/[pcre]/code/trunk/pcre_jit_compile.c
ViewVC logotype

Contents of /code/trunk/pcre_jit_compile.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 664 - (show annotations) (download)
Mon Aug 22 14:54:38 2011 UTC (2 years, 8 months ago) by ph10
File MIME type: text/plain
File size: 195687 byte(s)
Commit all the changes for JIT support, but without any documentation yet.

1 /*************************************************
2 * Perl-Compatible Regular Expressions *
3 *************************************************/
4
5 /* PCRE is a library of functions to support regular expressions whose syntax
6 and semantics are as close as possible to those of the Perl 5 language.
7
8 Written by Philip Hazel
9 Copyright (c) 1997-2008 University of Cambridge
10
11 The machine code generator part (this module) was written by Zoltan Herczeg
12 Copyright (c) 2010-2011
13
14 -----------------------------------------------------------------------------
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions are met:
17
18 * Redistributions of source code must retain the above copyright notice,
19 this list of conditions and the following disclaimer.
20
21 * Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in the
23 documentation and/or other materials provided with the distribution.
24
25 * Neither the name of the University of Cambridge nor the names of its
26 contributors may be used to endorse or promote products derived from
27 this software without specific prior written permission.
28
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
40 -----------------------------------------------------------------------------
41 */
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46
47 #include "pcre_internal.h"
48
49 #ifdef SUPPORT_JIT
50
51 /* All-in-one: Since we use the JIT compiler only from here,
52 we just include it. This way we don't need to touch the build
53 system files. */
54
55 #define SLJIT_CONFIG_AUTO 1
56 #define SLJIT_VERBOSE 0
57 #define SLJIT_DEBUG 0
58
59 #include "sljit/sljitLir.c"
60
61 #if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
62 #error "Unsupported architecture"
63 #endif
64
65 /* Allocate memory on the stack. Fast, but limited size. */
66 #define LOCAL_SPACE_SIZE 32768
67
68 #define STACK_GROWTH_RATE 8192
69
70 /* Enable to check that the allocation could destroy temporaries. */
71 #if defined SLJIT_DEBUG && SLJIT_DEBUG
72 #define DESTROY_REGISTERS 1
73 #endif
74
75 /*
76 Short summary about the backtracking mechanism empolyed by the jit code generator:
77
78 The code generator follows the recursive nature of the PERL compatible regular
79 expressions. The basic blocks of regular expressions are condition checkers
80 whose execute different commands depending on the result of the condition check.
81 The relationship between the operators can be horizontal (concatenation) and
82 vertical (sub-expression) (See struct fallback_common for more details).
83
84 'ab' - 'a' and 'b' regexps are concatenated
85 'a+' - 'a' is the sub-expression of the '+' operator
86
87 The condition checkers are boolean (true/false) checkers. Machine code is generated
88 for the checker itself and for the actions depending on the result of the checker.
89 The 'true' case is called as the hot path (expected path), and the other is called as
90 the 'fallback' path. Branch instructions are expesive for all CPUs, so we avoid taken
91 branches on the hot path.
92
93 Greedy star operator (*) :
94 Hot path: match happens.
95 Fallback path: match failed.
96 Non-greedy star operator (*?) :
97 Hot path: no need to perform a match.
98 Fallback path: match is required.
99
100 The following example shows how the code generated for a capturing bracket
101 with two alternatives. Let A, B, C, D are arbirary regular expressions, and
102 we have the following regular expression:
103
104 A(B|C)D
105
106 The generated code will be the following:
107
108 A hot path
109 '(' hot path (pushing arguments to the stack)
110 B hot path
111 ')' hot path (pushing arguments to the stack)
112 D hot path
113 return with successful match
114
115 D fallback path
116 ')' fallback path (If we arrived from "C" jump to the fallback of "C")
117 B fallback path
118 C expected path
119 jump to D hot path
120 C fallback path
121 A fallback path
122
123 Notice, that the order of fallback code paths are the opposite of the fast
124 code paths. In this way the topmost value on the stack is always belong
125 to the current fallback code path. The fallback code path must check
126 whether there is a next alternative. If so, it needs to jump back to
127 the hot path eventually. Otherwise it needs to clear out its own stack
128 frame and continue the execution on the fallback code paths.
129 */
130
131 /*
132 Saved stack frames:
133
134 Atomic blocks and asserts require reloading the values of local variables
135 when the fallback mechanism performed. Because of OP_RECURSE, the locals
136 are not necessarly known in compile time, thus we need a dynamic restore
137 mechanism.
138
139 The stack frames are stored in a chain list, and have the following format:
140 ([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]
141
142 Thus we can restore the locals to a particular point in the stack.
143 */
144
145 typedef struct jit_arguments {
146 /* Pointers first. */
147 struct sljit_stack *stack;
148 PCRE_SPTR str;
149 PCRE_SPTR begin;
150 PCRE_SPTR end;
151 int *offsets;
152 uschar *ptr;
153 /* Everything else after. */
154 int offsetcount;
155 uschar notbol;
156 uschar noteol;
157 uschar notempty;
158 uschar notempty_atstart;
159 } jit_arguments;
160
161 typedef struct executable_function {
162 void *executable_func;
163 pcre_jit_callback callback;
164 void *userdata;
165 } executable_function;
166
167 typedef struct jump_list {
168 struct sljit_jump *jump;
169 struct jump_list *next;
170 } jump_list;
171
172 enum stub_types { stack_alloc, max_index };
173
174 typedef struct stub_list {
175 enum stub_types type;
176 int data;
177 struct sljit_jump *start;
178 struct sljit_label *leave;
179 struct stub_list *next;
180 } stub_list;
181
182 typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);
183
184 /* The following structure is the key data type for the recursive
185 code generator. It is allocated by compile_hotpath, and contains
186 the aguments for compile_fallbackpath. Must be the first member
187 of its descendants. */
188 typedef struct fallback_common {
189 /* Concatenation stack. */
190 struct fallback_common *prev;
191 jump_list *nextfallbacks;
192 /* Internal stack (for component operators). */
193 struct fallback_common *top;
194 jump_list *topfallbacks;
195 /* Opcode pointer. */
196 uschar *cc;
197 } fallback_common;
198
199 typedef struct assert_fallback {
200 fallback_common common;
201 jump_list *condfailed;
202 /* Less than 0 (-1) if a frame is not needed. */
203 int framesize;
204 /* Points to our private memory word on the stack. */
205 int localptr;
206 /* For iterators. */
207 struct sljit_label *hotpath;
208 } assert_fallback;
209
210 typedef struct bracket_fallback {
211 fallback_common common;
212 /* Where to coninue if an alternative is successfully matched. */
213 struct sljit_label *althotpath;
214 /* For rmin and rmax iterators. */
215 struct sljit_label *recursivehotpath;
216 /* For greedy ? operator. */
217 struct sljit_label *zerohotpath;
218 /* Contains the branches of a failed condition. */
219 union {
220 /* Both for OP_COND, OP_SCOND. */
221 jump_list *condfailed;
222 assert_fallback *assert;
223 /* For OP_ONCE. -1 if not needed. */
224 int framesize;
225 } u;
226 /* Points to our private memory word on the stack. */
227 int localptr;
228 } bracket_fallback;
229
230 typedef struct bracketpos_fallback {
231 fallback_common common;
232 /* Points to our private memory word on the stack. */
233 int localptr;
234 /* Reverting stack is needed. */
235 int framesize;
236 /* Allocated stack size. */
237 int stacksize;
238 } bracketpos_fallback;
239
240 typedef struct braminzero_fallback {
241 fallback_common common;
242 struct sljit_label *hotpath;
243 } braminzero_fallback;
244
245 typedef struct iterator_fallback {
246 fallback_common common;
247 /* Next iteration. */
248 struct sljit_label *hotpath;
249 } iterator_fallback;
250
251 typedef struct recurse_entry {
252 struct recurse_entry *next;
253 /* Contains the function entry. */
254 struct sljit_label *entry;
255 /* Collects the calls until the function is not created. */
256 jump_list *calls;
257 /* Points to the starting opcode. */
258 int start;
259 } recurse_entry;
260
261 typedef struct recurse_fallback {
262 fallback_common common;
263 } recurse_fallback;
264
265 typedef struct compiler_common {
266 struct sljit_compiler *compiler;
267 uschar *start;
268 int localsize;
269 int *localptrs;
270 const uschar *fcc;
271 sljit_w lcc;
272 int cbraptr;
273 int nltype;
274 int newline;
275 int bsr_nltype;
276 int endonly;
277 sljit_w ctypes;
278 struct sljit_label *acceptlabel;
279 stub_list *stubs;
280 recurse_entry *entries;
281 recurse_entry *currententry;
282 jump_list *accept;
283 jump_list *stackalloc;
284 jump_list *revertframes;
285 jump_list *wordboundary;
286 jump_list *anynewline;
287 jump_list *hspace;
288 jump_list *vspace;
289 jump_list *casefulcmp;
290 jump_list *caselesscmp;
291 BOOL jscript_compat;
292 #ifdef SUPPORT_UTF8
293 BOOL utf8;
294 #ifdef SUPPORT_UCP
295 BOOL useucp;
296 #endif
297 jump_list *utf8readchar;
298 jump_list *utf8readtype8;
299 #endif
300 #ifdef SUPPORT_UCP
301 jump_list *getucd;
302 #endif
303 } compiler_common;
304
305 /* For byte_sequence_compare. */
306
307 typedef struct compare_context {
308 int length;
309 int sourcereg;
310 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
311 int byteptr;
312 union {
313 int asint;
314 short asshort;
315 sljit_ub asbyte;
316 sljit_ub asbytes[4];
317 } c;
318 union {
319 int asint;
320 short asshort;
321 sljit_ub asbyte;
322 sljit_ub asbytes[4];
323 } oc;
324 #endif
325 } compare_context;
326
327 enum {
328 frame_end = 0,
329 frame_setmaxindex = -1,
330 frame_setstrbegin = -2
331 };
332
333 /* Used for accessing the elements of the stack. */
334 #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w))
335
336 #define TMP1 SLJIT_TEMPORARY_REG1
337 #define TMP2 SLJIT_TEMPORARY_REG3
338 #define TMP3 SLJIT_TEMPORARY_EREG2
339 #define STR_PTR SLJIT_GENERAL_REG1
340 #define STR_END SLJIT_GENERAL_REG2
341 #define STACK_TOP SLJIT_TEMPORARY_REG2
342 #define STACK_LIMIT SLJIT_GENERAL_REG3
343 #define ARGUMENTS SLJIT_GENERAL_EREG1
344 #define MAX_INDEX SLJIT_GENERAL_EREG2
345 #define RETURN_ADDR SLJIT_TEMPORARY_EREG1
346
347 /* Locals layout. */
348 /* These two locals can be used by the current opcode. */
349 #define LOCALS0 (0 * sizeof(sljit_w))
350 #define LOCALS1 (1 * sizeof(sljit_w))
351 /* Two local variables for possessive quantifiers (char1 cannot use them). */
352 #define POSSESSIVE0 (2 * sizeof(sljit_w))
353 #define POSSESSIVE1 (3 * sizeof(sljit_w))
354 /* Head of the saved local variables */
355 #define LOCALS_HEAD (4 * sizeof(sljit_w))
356 /* Head of the last recursion. */
357 #define RECURSIVE_HEAD (5 * sizeof(sljit_w))
358 /* Last known position of the requested byte. */
359 #define REQ_BYTE_PTR (6 * sizeof(sljit_w))
360 /* End pointer of the first line. */
361 #define FIRSTLINE_END (7 * sizeof(sljit_w))
362 /* The output vector is stored on the stack, and contains pointers
363 to characters. The vector data is divided into two groups: the first
364 group contains the start / end character pointers, and the second is
365 the start pointers when the end of the capturing group has not yet reached. */
366 #define OVECTOR_START (8 * sizeof(sljit_w))
367 #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w))
368 #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w))
369 #define PRIV(cc) (common->localptrs[(cc) - common->start])
370
371 /* Shortcuts. */
372 #define DEFINE_COMPILER \
373 struct sljit_compiler *compiler = common->compiler
374 #define OP1(op, dst, dstw, src, srcw) \
375 sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
376 #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
377 sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
378 #define LABEL() \
379 sljit_emit_label(compiler)
380 #define JUMP(type) \
381 sljit_emit_jump(compiler, (type))
382 #define JUMPTO(type, label) \
383 sljit_set_label(sljit_emit_jump(compiler, (type)), (label))
384 #define JUMPHERE(jump) \
385 sljit_set_label((jump), sljit_emit_label(compiler))
386 #define CMP(type, src1, src1w, src2, src2w) \
387 sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
388 #define CMPTO(type, src1, src1w, src2, src2w, label) \
389 sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
390 #define COND_VALUE(op, dst, dstw, type) \
391 sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type))
392
393 static uschar* bracketend(uschar* cc)
394 {
395 SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
396 do cc += GET(cc, 1); while (*cc == OP_ALT);
397 SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
398 cc += 1 + LINK_SIZE;
399 return cc;
400 }
401
402 /* Functions whose might need modification for all new supported opcodes:
403 next_opcode
404 get_localspace
405 set_localptrs
406 get_framesize
407 init_frame
408 get_localsize
409 copy_locals
410 compile_hotpath
411 compile_fallbackpath
412 */
413
414 static uschar *next_opcode(compiler_common *common, uschar *cc)
415 {
416 SLJIT_UNUSED_ARG(common);
417 switch(*cc)
418 {
419 case OP_SOD:
420 case OP_SOM:
421 case OP_SET_SOM:
422 case OP_NOT_WORD_BOUNDARY:
423 case OP_WORD_BOUNDARY:
424 case OP_NOT_DIGIT:
425 case OP_DIGIT:
426 case OP_NOT_WHITESPACE:
427 case OP_WHITESPACE:
428 case OP_NOT_WORDCHAR:
429 case OP_WORDCHAR:
430 case OP_ANY:
431 case OP_ALLANY:
432 case OP_ANYNL:
433 case OP_NOT_HSPACE:
434 case OP_HSPACE:
435 case OP_NOT_VSPACE:
436 case OP_VSPACE:
437 case OP_EXTUNI:
438 case OP_EODN:
439 case OP_EOD:
440 case OP_CIRC:
441 case OP_CIRCM:
442 case OP_DOLL:
443 case OP_DOLLM:
444 case OP_TYPESTAR:
445 case OP_TYPEMINSTAR:
446 case OP_TYPEPLUS:
447 case OP_TYPEMINPLUS:
448 case OP_TYPEQUERY:
449 case OP_TYPEMINQUERY:
450 case OP_TYPEPOSSTAR:
451 case OP_TYPEPOSPLUS:
452 case OP_TYPEPOSQUERY:
453 case OP_CRSTAR:
454 case OP_CRMINSTAR:
455 case OP_CRPLUS:
456 case OP_CRMINPLUS:
457 case OP_CRQUERY:
458 case OP_CRMINQUERY:
459 case OP_DEF:
460 case OP_BRAZERO:
461 case OP_BRAMINZERO:
462 case OP_BRAPOSZERO:
463 case OP_FAIL:
464 case OP_ACCEPT:
465 case OP_ASSERT_ACCEPT:
466 case OP_SKIPZERO:
467 return cc + 1;
468
469 case OP_CHAR:
470 case OP_CHARI:
471 case OP_NOT:
472 case OP_NOTI:
473
474 case OP_STAR:
475 case OP_MINSTAR:
476 case OP_PLUS:
477 case OP_MINPLUS:
478 case OP_QUERY:
479 case OP_MINQUERY:
480 case OP_POSSTAR:
481 case OP_POSPLUS:
482 case OP_POSQUERY:
483 case OP_STARI:
484 case OP_MINSTARI:
485 case OP_PLUSI:
486 case OP_MINPLUSI:
487 case OP_QUERYI:
488 case OP_MINQUERYI:
489 case OP_POSSTARI:
490 case OP_POSPLUSI:
491 case OP_POSQUERYI:
492 case OP_NOTSTAR:
493 case OP_NOTMINSTAR:
494 case OP_NOTPLUS:
495 case OP_NOTMINPLUS:
496 case OP_NOTQUERY:
497 case OP_NOTMINQUERY:
498 case OP_NOTPOSSTAR:
499 case OP_NOTPOSPLUS:
500 case OP_NOTPOSQUERY:
501 case OP_NOTSTARI:
502 case OP_NOTMINSTARI:
503 case OP_NOTPLUSI:
504 case OP_NOTMINPLUSI:
505 case OP_NOTQUERYI:
506 case OP_NOTMINQUERYI:
507 case OP_NOTPOSSTARI:
508 case OP_NOTPOSPLUSI:
509 case OP_NOTPOSQUERYI:
510 cc += 2;
511 #ifdef SUPPORT_UTF8
512 if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
513 #endif
514 return cc;
515
516 case OP_UPTO:
517 case OP_MINUPTO:
518 case OP_EXACT:
519 case OP_POSUPTO:
520 case OP_UPTOI:
521 case OP_MINUPTOI:
522 case OP_EXACTI:
523 case OP_POSUPTOI:
524 case OP_NOTUPTO:
525 case OP_NOTMINUPTO:
526 case OP_NOTEXACT:
527 case OP_NOTPOSUPTO:
528 case OP_NOTUPTOI:
529 case OP_NOTMINUPTOI:
530 case OP_NOTEXACTI:
531 case OP_NOTPOSUPTOI:
532 cc += 4;
533 #ifdef SUPPORT_UTF8
534 if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
535 #endif
536 return cc;
537
538 case OP_NOTPROP:
539 case OP_PROP:
540 case OP_TYPEUPTO:
541 case OP_TYPEMINUPTO:
542 case OP_TYPEEXACT:
543 case OP_TYPEPOSUPTO:
544 case OP_REF:
545 case OP_REFI:
546 case OP_CREF:
547 case OP_CLOSE:
548 cc += 3;
549 return cc;
550
551 case OP_CRRANGE:
552 case OP_CRMINRANGE:
553 return cc + 5;
554
555 case OP_CLASS:
556 case OP_NCLASS:
557 return cc + 33;
558
559 #ifdef SUPPORT_UTF8
560 case OP_XCLASS:
561 return cc + GET(cc, 1);
562 #endif
563
564 case OP_RECURSE:
565 case OP_ASSERT:
566 case OP_ASSERT_NOT:
567 case OP_ASSERTBACK:
568 case OP_ASSERTBACK_NOT:
569 case OP_REVERSE:
570 case OP_ONCE:
571 case OP_BRA:
572 case OP_BRAPOS:
573 case OP_COND:
574 case OP_SBRA:
575 case OP_SBRAPOS:
576 case OP_SCOND:
577 case OP_ALT:
578 case OP_KET:
579 case OP_KETRMAX:
580 case OP_KETRMIN:
581 case OP_KETRPOS:
582 return cc + 1 + LINK_SIZE;
583
584 case OP_CBRA:
585 case OP_CBRAPOS:
586 case OP_SCBRA:
587 case OP_SCBRAPOS:
588 return cc + 1 + LINK_SIZE + 2;
589
590 default:
591 return NULL;
592 }
593 }
594
595 static int get_localspace(compiler_common *common, uschar *cc, uschar *ccend)
596 {
597 int localspace = 0;
598 uschar *alternative;
599 /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
600 while (cc < ccend)
601 {
602 switch(*cc)
603 {
604 case OP_ASSERT:
605 case OP_ASSERT_NOT:
606 case OP_ASSERTBACK:
607 case OP_ASSERTBACK_NOT:
608 case OP_ONCE:
609 case OP_BRAPOS:
610 case OP_SBRA:
611 case OP_SBRAPOS:
612 case OP_SCOND:
613 localspace += sizeof(sljit_w);
614 cc += 1 + LINK_SIZE;
615 break;
616
617 case OP_CBRAPOS:
618 case OP_SCBRAPOS:
619 localspace += sizeof(sljit_w);
620 cc += 1 + LINK_SIZE + 2;
621 break;
622
623 case OP_COND:
624 /* Might be a hidden SCOND. */
625 alternative = cc + GET(cc, 1);
626 if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
627 localspace += sizeof(sljit_w);
628 cc += 1 + LINK_SIZE;
629 break;
630
631 default:
632 cc = next_opcode(common, cc);
633 if (cc == NULL)
634 return -1;
635 break;
636 }
637 }
638 return localspace;
639 }
640
641 static void set_localptrs(compiler_common *common, int localptr, uschar *ccend)
642 {
643 uschar *cc = common->start;
644 uschar *alternative;
645 while (cc < ccend)
646 {
647 switch(*cc)
648 {
649 case OP_ASSERT:
650 case OP_ASSERT_NOT:
651 case OP_ASSERTBACK:
652 case OP_ASSERTBACK_NOT:
653 case OP_ONCE:
654 case OP_BRAPOS:
655 case OP_SBRA:
656 case OP_SBRAPOS:
657 case OP_SCOND:
658 common->localptrs[cc - common->start] = localptr;
659 localptr += sizeof(sljit_w);
660 cc += 1 + LINK_SIZE;
661 break;
662
663 case OP_CBRAPOS:
664 case OP_SCBRAPOS:
665 common->localptrs[cc - common->start] = localptr;
666 localptr += sizeof(sljit_w);
667 cc += 1 + LINK_SIZE + 2;
668 break;
669
670 case OP_COND:
671 /* Might be a hidden SCOND. */
672 alternative = cc + GET(cc, 1);
673 if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
674 {
675 common->localptrs[cc - common->start] = localptr;
676 localptr += sizeof(sljit_w);
677 }
678 cc += 1 + LINK_SIZE;
679 break;
680
681 default:
682 cc = next_opcode(common, cc);
683 SLJIT_ASSERT(cc != NULL);
684 break;
685 }
686 }
687 }
688
689 /* Returns with -1 if no need for frame. */
690 static int get_framesize(compiler_common *common, uschar *cc, BOOL recursive)
691 {
692 uschar *ccend = bracketend(cc);
693 uschar *end;
694 int length = 0;
695 BOOL possessive = FALSE;
696 BOOL needs_frame = FALSE;
697 BOOL needs_maxindex = FALSE;
698 BOOL setsom_found = FALSE;
699
700 if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))
701 {
702 length = 3 + 2;
703 needs_maxindex = TRUE;
704 possessive = TRUE;
705 }
706
707 cc = next_opcode(common, cc);
708 SLJIT_ASSERT(cc != NULL);
709 while (cc < ccend)
710 switch(*cc)
711 {
712 case OP_SET_SOM:
713 case OP_RECURSE:
714 if (!setsom_found)
715 {
716 length += 2;
717 setsom_found = TRUE;
718 }
719 cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;
720 break;
721
722 case OP_ASSERT:
723 case OP_ASSERT_NOT:
724 case OP_ASSERTBACK:
725 case OP_ASSERTBACK_NOT:
726 case OP_ONCE:
727 if (needs_frame || length > 0)
728 {
729 cc = bracketend(cc);
730 break;
731 }
732 /* Check whether a frame must be created. */
733 end = bracketend(cc);
734 while (cc < end)
735 {
736 if (*cc == OP_SET_SOM || *cc == OP_CBRA || *cc == OP_CBRAPOS
737 || *cc == OP_SCBRA || *cc == OP_SCBRAPOS || *cc == OP_RECURSE)
738 needs_frame = TRUE;
739 cc = next_opcode(common, cc);
740 SLJIT_ASSERT(cc != NULL);
741 }
742 break;
743
744 case OP_CBRA:
745 case OP_CBRAPOS:
746 case OP_SCBRA:
747 case OP_SCBRAPOS:
748 if (!needs_maxindex)
749 {
750 needs_maxindex = TRUE;
751 length += 2;
752 }
753 length += 3;
754 cc += 1 + LINK_SIZE + 2;
755 break;
756
757 default:
758 cc = next_opcode(common, cc);
759 SLJIT_ASSERT(cc != NULL);
760 break;
761 }
762
763 /* Possessive quantifiers can use a special case. */
764 if (SLJIT_UNLIKELY(possessive) && !needs_frame && length == 3 + 2)
765 return -1;
766
767 if (length > 0)
768 return length + 2;
769 return needs_frame ? 0 : -1;
770 }
771
772 static void init_frame(compiler_common *common, uschar *cc, int stackpos, int stacktop, BOOL recursive)
773 {
774 /* TMP2 must contain STACK_TOP - (-STACK(stackpos)) */
775 DEFINE_COMPILER;
776 uschar *ccend = bracketend(cc);
777 BOOL needs_maxindex = FALSE;
778 BOOL setsom_found = FALSE;
779 int offset;
780
781 if (stackpos < stacktop)
782 {
783 SLJIT_ASSERT(stackpos + 1 == stacktop);
784 return;
785 }
786
787 stackpos = STACK(stackpos);
788 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD);
789 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0);
790 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacktop), TMP1, 0);
791
792 if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS))
793 cc = next_opcode(common, cc);
794 SLJIT_ASSERT(cc != NULL);
795 while (cc < ccend)
796 switch(*cc)
797 {
798 case OP_SET_SOM:
799 case OP_RECURSE:
800 if (!setsom_found)
801 {
802 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
803 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin);
804 stackpos += (int)sizeof(sljit_w);
805 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
806 stackpos += (int)sizeof(sljit_w);
807 setsom_found = TRUE;
808 }
809 cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;
810 break;
811
812 case OP_ASSERT:
813 case OP_ASSERT_NOT:
814 case OP_ASSERTBACK:
815 case OP_ASSERTBACK_NOT:
816 case OP_ONCE:
817 cc = bracketend(cc);
818 break;
819
820 case OP_CBRA:
821 case OP_CBRAPOS:
822 case OP_SCBRA:
823 case OP_SCBRAPOS:
824 if (!needs_maxindex)
825 {
826 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmaxindex);
827 stackpos += (int)sizeof(sljit_w);
828 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, MAX_INDEX, 0);
829 stackpos += (int)sizeof(sljit_w);
830 needs_maxindex = TRUE;
831 }
832 offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
833 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
834 stackpos += (int)sizeof(sljit_w);
835 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
836 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
837 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
838 stackpos += (int)sizeof(sljit_w);
839 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
840 stackpos += (int)sizeof(sljit_w);
841
842 cc += 1 + LINK_SIZE + 2;
843 break;
844
845 default:
846 cc = next_opcode(common, cc);
847 SLJIT_ASSERT(cc != NULL);
848 break;
849 }
850
851 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_end);
852 SLJIT_ASSERT(stackpos == STACK(stacktop + 1));
853 }
854
855 static SLJIT_INLINE int get_localsize(compiler_common *common, uschar *cc, uschar *ccend)
856 {
857 int localsize = 2;
858 uschar *alternative;
859 /* Calculate the sum of the local variables. */
860 while (cc < ccend)
861 {
862 switch(*cc)
863 {
864 case OP_ASSERT:
865 case OP_ASSERT_NOT:
866 case OP_ASSERTBACK:
867 case OP_ASSERTBACK_NOT:
868 case OP_ONCE:
869 case OP_BRAPOS:
870 case OP_SBRA:
871 case OP_SBRAPOS:
872 case OP_SCOND:
873 localsize++;
874 cc += 1 + LINK_SIZE;
875 break;
876
877 case OP_CBRA:
878 case OP_SCBRA:
879 localsize++;
880 cc += 1 + LINK_SIZE + 2;
881 break;
882
883 case OP_CBRAPOS:
884 case OP_SCBRAPOS:
885 localsize += 2;
886 cc += 1 + LINK_SIZE + 2;
887 break;
888
889 case OP_COND:
890 /* Might be a hidden SCOND. */
891 alternative = cc + GET(cc, 1);
892 if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
893 localsize++;
894 cc += 1 + LINK_SIZE;
895 break;
896
897 default:
898 cc = next_opcode(common, cc);
899 SLJIT_ASSERT(cc != NULL);
900 break;
901 }
902 }
903 SLJIT_ASSERT(cc == ccend);
904 return localsize;
905 }
906
907 static void copy_locals(compiler_common *common, uschar *cc, uschar *ccend,
908 BOOL save, int stackptr, int stacktop)
909 {
910 DEFINE_COMPILER;
911 int srcw[2];
912 int count;
913 BOOL tmp1next = TRUE;
914 BOOL tmp1empty = TRUE;
915 BOOL tmp2empty = TRUE;
916 uschar *alternative;
917 enum {
918 start,
919 loop,
920 end
921 } status;
922
923 status = save ? start : loop;
924 stackptr = STACK(stackptr - 2);
925 stacktop = STACK(stacktop - 1);
926
927 if (!save)
928 {
929 stackptr += sizeof(sljit_w);
930 if (stackptr < stacktop)
931 {
932 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
933 stackptr += sizeof(sljit_w);
934 tmp1empty = FALSE;
935 }
936 if (stackptr < stacktop)
937 {
938 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
939 stackptr += sizeof(sljit_w);
940 tmp2empty = FALSE;
941 }
942 /* The tmp1next must be TRUE in either way. */
943 }
944
945 while (status != end)
946 {
947 count = 0;
948 switch(status)
949 {
950 case start:
951 SLJIT_ASSERT(save);
952 count = 1;
953 srcw[0] = RECURSIVE_HEAD;
954 status = loop;
955 break;
956
957 case loop:
958 if (cc >= ccend)
959 {
960 status = end;
961 break;
962 }
963
964 switch(*cc)
965 {
966 case OP_ASSERT:
967 case OP_ASSERT_NOT:
968 case OP_ASSERTBACK:
969 case OP_ASSERTBACK_NOT:
970 case OP_ONCE:
971 case OP_BRAPOS:
972 case OP_SBRA:
973 case OP_SBRAPOS:
974 case OP_SCOND:
975 count = 1;
976 srcw[0] = PRIV(cc);
977 SLJIT_ASSERT(srcw[0] != 0);
978 cc += 1 + LINK_SIZE;
979 break;
980
981 case OP_CBRA:
982 case OP_SCBRA:
983 count = 1;
984 srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
985 cc += 1 + LINK_SIZE + 2;
986 break;
987
988 case OP_CBRAPOS:
989 case OP_SCBRAPOS:
990 count = 2;
991 srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
992 srcw[0] = PRIV(cc);
993 SLJIT_ASSERT(srcw[0] != 0);
994 cc += 1 + LINK_SIZE + 2;
995 break;
996
997 case OP_COND:
998 /* Might be a hidden SCOND. */
999 alternative = cc + GET(cc, 1);
1000 if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
1001 {
1002 count = 1;
1003 srcw[0] = PRIV(cc);
1004 SLJIT_ASSERT(srcw[0] != 0);
1005 }
1006 cc += 1 + LINK_SIZE;
1007 break;
1008
1009 default:
1010 cc = next_opcode(common, cc);
1011 SLJIT_ASSERT(cc != NULL);
1012 break;
1013 }
1014 break;
1015
1016 case end:
1017 SLJIT_ASSERT_STOP();
1018 break;
1019 }
1020
1021 while (count > 0)
1022 {
1023 count--;
1024 if (save)
1025 {
1026 if (tmp1next)
1027 {
1028 if (!tmp1empty)
1029 {
1030 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1031 stackptr += sizeof(sljit_w);
1032 }
1033 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
1034 tmp1empty = FALSE;
1035 tmp1next = FALSE;
1036 }
1037 else
1038 {
1039 if (!tmp2empty)
1040 {
1041 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1042 stackptr += sizeof(sljit_w);
1043 }
1044 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
1045 tmp2empty = FALSE;
1046 tmp1next = TRUE;
1047 }
1048 }
1049 else
1050 {
1051 if (tmp1next)
1052 {
1053 SLJIT_ASSERT(!tmp1empty);
1054 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP1, 0);
1055 tmp1empty = stackptr >= stacktop;
1056 if (!tmp1empty)
1057 {
1058 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1059 stackptr += sizeof(sljit_w);
1060 }
1061 tmp1next = FALSE;
1062 }
1063 else
1064 {
1065 SLJIT_ASSERT(!tmp2empty);
1066 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP2, 0);
1067 tmp2empty = stackptr >= stacktop;
1068 if (!tmp2empty)
1069 {
1070 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1071 stackptr += sizeof(sljit_w);
1072 }
1073 tmp1next = TRUE;
1074 }
1075 }
1076 }
1077 }
1078
1079 if (save)
1080 {
1081 if (tmp1next)
1082 {
1083 if (!tmp1empty)
1084 {
1085 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1086 stackptr += sizeof(sljit_w);
1087 }
1088 if (!tmp2empty)
1089 {
1090 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1091 stackptr += sizeof(sljit_w);
1092 }
1093 }
1094 else
1095 {
1096 if (!tmp2empty)
1097 {
1098 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1099 stackptr += sizeof(sljit_w);
1100 }
1101 if (!tmp1empty)
1102 {
1103 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1104 stackptr += sizeof(sljit_w);
1105 }
1106 }
1107 }
1108 SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty)));
1109 }
1110
1111 static SLJIT_INLINE BOOL ispowerof2(unsigned int value)
1112 {
1113 return (value & (value - 1)) == 0;
1114 }
1115
1116 static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label)
1117 {
1118 while (list)
1119 {
1120 /* sljit_set_label is clever enough to do nothing
1121 if either the jump or the label is NULL */
1122 sljit_set_label(list->jump, label);
1123 list = list->next;
1124 }
1125 }
1126
1127 static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump* jump)
1128 {
1129 jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list));
1130 if (list_item)
1131 {
1132 list_item->next = *list;
1133 list_item->jump = jump;
1134 *list = list_item;
1135 }
1136 }
1137
1138 static void add_stub(compiler_common *common, enum stub_types type, int data, struct sljit_jump *start)
1139 {
1140 DEFINE_COMPILER;
1141 stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list));
1142
1143 if (list_item)
1144 {
1145 list_item->type = type;
1146 list_item->data = data;
1147 list_item->start = start;
1148 list_item->leave = LABEL();
1149 list_item->next = common->stubs;
1150 common->stubs = list_item;
1151 }
1152 }
1153
1154 static void flush_stubs(compiler_common *common)
1155 {
1156 DEFINE_COMPILER;
1157 stub_list* list_item = common->stubs;
1158
1159 while (list_item)
1160 {
1161 JUMPHERE(list_item->start);
1162 switch(list_item->type)
1163 {
1164 case stack_alloc:
1165 add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));
1166 break;
1167
1168 case max_index:
1169 OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, list_item->data);
1170 break;
1171 }
1172 JUMPTO(SLJIT_JUMP, list_item->leave);
1173 list_item = list_item->next;
1174 }
1175 common->stubs = NULL;
1176 }
1177
1178 static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
1179 {
1180 /* May destroy all locals and registers except TMP2. */
1181 DEFINE_COMPILER;
1182
1183 OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
1184 #ifdef DESTROY_REGISTERS
1185 OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
1186 OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
1187 OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
1188 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0);
1189 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
1190 #endif
1191 add_stub(common, stack_alloc, 0, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0));
1192 }
1193
1194 static SLJIT_INLINE void free_stack(compiler_common *common, int size)
1195 {
1196 DEFINE_COMPILER;
1197 OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
1198 }
1199
1200 static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)
1201 {
1202 DEFINE_COMPILER;
1203 struct sljit_label *loop;
1204 int i;
1205 /* At this point we can freely use all temporary registers. */
1206 /* TMP1 returns with begin - 1. */
1207 OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, 1);
1208 OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, 1);
1209 if (length < 8)
1210 {
1211 for (i = 0; i < length; i++)
1212 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_TEMPORARY_REG1, 0);
1213 }
1214 else
1215 {
1216 OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START - sizeof(sljit_w));
1217 OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length);
1218 loop = LABEL();
1219 OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0);
1220 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1);
1221 JUMPTO(SLJIT_C_NOT_ZERO, loop);
1222 }
1223 }
1224
1225 static SLJIT_INLINE void copy_ovector(compiler_common *common)
1226 {
1227 DEFINE_COMPILER;
1228 struct sljit_label *loop;
1229 struct sljit_jump *earlyexit;
1230
1231 /* At this point we can freely use all registers. */
1232 OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0);
1233 OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount));
1234 OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
1235 OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin));
1236 OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START);
1237 /* Unlikely, but possible */
1238 earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0);
1239 loop = LABEL();
1240 OP2(SLJIT_SUB, SLJIT_GENERAL_REG2, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), 0, SLJIT_TEMPORARY_REG1, 0);
1241 OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_GENERAL_REG1, 0, SLJIT_IMM, sizeof(sljit_w));
1242 /* Copy the integer value to the output buffer */
1243 OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_GENERAL_REG2, 0);
1244 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
1245 JUMPTO(SLJIT_C_NOT_ZERO, loop);
1246 JUMPHERE(earlyexit);
1247 }
1248
1249 static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, uschar* cc)
1250 {
1251 /* Detects if the character has an othercase. */
1252 unsigned int c;
1253
1254 #ifdef SUPPORT_UTF8
1255 if (common->utf8)
1256 {
1257 GETCHAR(c, cc);
1258 if (c > 127)
1259 {
1260 #ifdef SUPPORT_UCP
1261 return c != UCD_OTHERCASE(c);
1262 #else
1263 return FALSE;
1264 #endif
1265 }
1266 }
1267 else
1268 #endif
1269 c = *cc;
1270 return common->fcc[c] != c;
1271 }
1272
1273 static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c)
1274 {
1275 /* Returns with the othercase. */
1276 #ifdef SUPPORT_UTF8
1277 if (common->utf8 && c > 127)
1278 {
1279 #ifdef SUPPORT_UCP
1280 return UCD_OTHERCASE(c);
1281 #else
1282 return c;
1283 #endif
1284 }
1285 #endif
1286 return common->fcc[c];
1287 }
1288
1289 static unsigned int char_get_othercase_bit(compiler_common *common, uschar* cc)
1290 {
1291 /* Detects if the character and its othercase has only 1 bit difference. */
1292 unsigned int c, oc, bit;
1293 #ifdef SUPPORT_UTF8
1294 int n;
1295 #endif
1296
1297 #ifdef SUPPORT_UTF8
1298 if (common->utf8)
1299 {
1300 GETCHAR(c, cc);
1301 if (c <= 127)
1302 oc = common->fcc[c];
1303 else
1304 {
1305 #ifdef SUPPORT_UCP
1306 oc = UCD_OTHERCASE(c);
1307 #else
1308 oc = c;
1309 #endif
1310 }
1311 }
1312 else
1313 {
1314 c = *cc;
1315 oc = common->fcc[c];
1316 }
1317 #else
1318 c = *cc;
1319 oc = common->fcc[c];
1320 #endif
1321
1322 SLJIT_ASSERT(c != oc);
1323
1324 bit = c ^ oc;
1325 /* Optimized for English alphabet. */
1326 if (c <= 127 && bit == 0x20)
1327 return (0 << 8) | 0x20;
1328
1329 /* Since c != oc, they must have at least 1 bit difference. */
1330 if (!ispowerof2(bit))
1331 return 0;
1332
1333 #ifdef SUPPORT_UTF8
1334 if (common->utf8 && c > 127)
1335 {
1336 n = _pcre_utf8_table4[*cc & 0x3f];
1337 while ((bit & 0x3f) == 0)
1338 {
1339 n--;
1340 bit >>= 6;
1341 }
1342 return (n << 8) | bit;
1343 }
1344 #endif
1345 return (0 << 8) | bit;
1346 }
1347
1348 static SLJIT_INLINE void check_input_end(compiler_common *common, jump_list **fallbacks)
1349 {
1350 DEFINE_COMPILER;
1351 add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
1352 }
1353
1354 static void read_char(compiler_common *common)
1355 {
1356 /* Reads the character into TMP1, updates STR_PTR.
1357 Does not check STR_END. TMP2 Destroyed. */
1358 DEFINE_COMPILER;
1359 #ifdef SUPPORT_UTF8
1360 struct sljit_jump *jump;
1361 #endif
1362
1363 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1364 #ifdef SUPPORT_UTF8
1365 if (common->utf8)
1366 {
1367 /* Should not found a value between 128 and 192 here. */
1368 jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 192);
1369 add_jump(compiler, &common->utf8readchar, JUMP(SLJIT_FAST_CALL));
1370 JUMPHERE(jump);
1371 }
1372 #endif
1373 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1374 }
1375
1376 static void peek_char(compiler_common *common)
1377 {
1378 /* Reads the character into TMP1, keeps STR_PTR.
1379 Does not check STR_END. TMP2 Destroyed. */
1380 DEFINE_COMPILER;
1381 #ifdef SUPPORT_UTF8
1382 struct sljit_jump *jump;
1383 #endif
1384
1385 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1386 #ifdef SUPPORT_UTF8
1387 if (common->utf8)
1388 {
1389 /* Should not found a value between 128 and 192 here. */
1390 jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 192);
1391 add_jump(compiler, &common->utf8readchar, JUMP(SLJIT_FAST_CALL));
1392 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1393 JUMPHERE(jump);
1394 }
1395 #endif
1396 }
1397
1398 static void read_char8_type(compiler_common *common)
1399 {
1400 /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
1401 DEFINE_COMPILER;
1402 #ifdef SUPPORT_UTF8
1403 struct sljit_jump *jump;
1404 #endif
1405
1406 #ifdef SUPPORT_UTF8
1407 if (common->utf8)
1408 {
1409 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
1410 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1411 /* This can be an extra read in some situations, but hopefully
1412 it is a clever early read in most cases. */
1413 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1414 /* Should not found a value between 128 and 192 here. */
1415 jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 192);
1416 add_jump(compiler, &common->utf8readtype8, JUMP(SLJIT_FAST_CALL));
1417 JUMPHERE(jump);
1418 return;
1419 }
1420 #endif
1421 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1422 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1423 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
1424 }
1425
1426 static void skip_char_back(compiler_common *common)
1427 {
1428 /* Goes one character back. Only affects STR_PTR. Does not check begin. */
1429 DEFINE_COMPILER;
1430 #ifdef SUPPORT_UTF8
1431 struct sljit_label *label;
1432
1433 if (common->utf8)
1434 {
1435 label = LABEL();
1436 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1437 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1438 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
1439 CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);
1440 return;
1441 }
1442 #endif
1443 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1444 }
1445
1446 static void check_newlinechar(compiler_common *common, int nltype, jump_list **fallbacks, BOOL jumpiftrue)
1447 {
1448 /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
1449 DEFINE_COMPILER;
1450
1451 if (nltype == NLTYPE_ANY)
1452 {
1453 add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
1454 add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1455 }
1456 else if (nltype == NLTYPE_ANYCRLF)
1457 {
1458 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR);
1459 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
1460 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
1461 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
1462 add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1463 }
1464 else
1465 {
1466 SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline <= 255);
1467 add_jump(compiler, fallbacks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
1468 }
1469 }
1470
1471 #ifdef SUPPORT_UTF8
1472 static void do_utf8readchar(compiler_common *common)
1473 {
1474 /* Fast decoding an utf8 character. TMP1 contains the first byte
1475 of the character (>= 192). Return char value in TMP1, length - 1 in TMP2. */
1476 DEFINE_COMPILER;
1477 struct sljit_jump *jump;
1478
1479 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1480 /* Searching for the first zero. */
1481 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
1482 jump = JUMP(SLJIT_C_NOT_ZERO);
1483 /* 2 byte sequence */
1484 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1485 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1486 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f);
1487 OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
1488 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1489 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1490 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
1491 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1492 JUMPHERE(jump);
1493
1494 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10);
1495 jump = JUMP(SLJIT_C_NOT_ZERO);
1496 /* 3 byte sequence */
1497 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1498 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f);
1499 OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12);
1500 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1501 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1502 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1503 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2);
1504 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 2);
1505 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1506 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1507 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 2);
1508 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1509 JUMPHERE(jump);
1510
1511 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x08);
1512 jump = JUMP(SLJIT_C_NOT_ZERO);
1513 /* 4 byte sequence */
1514 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1515 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07);
1516 OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18);
1517 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1518 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
1519 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1520 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2);
1521 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1522 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1523 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1524 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 3);
1525 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 3);
1526 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1527 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1528 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 3);
1529 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1530 JUMPHERE(jump);
1531
1532 /* 5 byte sequence */
1533 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1534 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x03);
1535 OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 24);
1536 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1537 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 18);
1538 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1539 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2);
1540 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1541 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
1542 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1543 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 3);
1544 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1545 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1546 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1547 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 4);
1548 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 4);
1549 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1550 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1551 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 4);
1552 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1553 }
1554
1555 static void do_utf8readtype8(compiler_common *common)
1556 {
1557 /* Fast decoding an utf8 character type. TMP2 contains the first byte
1558 of the character (>= 192) and TMP1 is destroyed. Return value in TMP1. */
1559 DEFINE_COMPILER;
1560 struct sljit_jump *jump;
1561 struct sljit_jump *compare;
1562
1563 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1564
1565 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
1566 jump = JUMP(SLJIT_C_NOT_ZERO);
1567 /* 2 byte sequence */
1568 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1569 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1570 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f);
1571 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1572 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
1573 OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
1574 compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
1575 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1576 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1577
1578 JUMPHERE(compare);
1579 OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1580 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1581 JUMPHERE(jump);
1582
1583 /* We only have types for characters less than 256. */
1584 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_w)_pcre_utf8_char_sizes);
1585 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1586 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1587 OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1588 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1589 }
1590
1591 #endif
1592
1593 #ifdef SUPPORT_UCP
1594
1595 /* UCD_BLOCK_SIZE must be 128 (see the assert below). */
1596 #define UCD_BLOCK_MASK 127
1597 #define UCD_BLOCK_SHIFT 7
1598
1599 static void do_getucd(compiler_common *common)
1600 {
1601 /* Search the UCD record for the character comes in TMP1.
1602 Returns chartype in TMP1 and UCD offset in TMP2. */
1603 DEFINE_COMPILER;
1604
1605 SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);
1606
1607 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1608 OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
1609 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)_pcre_ucd_stage1);
1610 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
1611 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
1612 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
1613 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_stage2);
1614 OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
1615 OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, chartype));
1616 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
1617 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1618 }
1619 #endif
1620
1621 static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline)
1622 {
1623 DEFINE_COMPILER;
1624 struct sljit_label *mainloop;
1625 struct sljit_label *newlinelabel = NULL;
1626 struct sljit_jump *start;
1627 struct sljit_jump *end = NULL;
1628 struct sljit_jump *nl = NULL;
1629 jump_list *newline = NULL;
1630 BOOL newlinecheck = FALSE;
1631 BOOL readbyte = FALSE;
1632
1633 if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY ||
1634 common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
1635 newlinecheck = TRUE;
1636
1637 if (firstline)
1638 {
1639 /* Search for the end of the first line. */
1640 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0);
1641 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_END, 0);
1642
1643 if (common->nltype == NLTYPE_FIXED && common->newline > 255)
1644 {
1645 mainloop = LABEL();
1646 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1647 end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1648 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -1);
1649 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
1650 CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
1651 CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
1652 OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0, SLJIT_IMM, 1);
1653 }
1654 else
1655 {
1656 end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1657 mainloop = LABEL();
1658 /* Continual stores does not cause data dependency. */
1659 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0);
1660 read_char(common);
1661 check_newlinechar(common, common->nltype, &newline, TRUE);
1662 CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
1663 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0);
1664 set_jumps(newline, LABEL());
1665 }
1666
1667 JUMPHERE(end);
1668 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
1669 }
1670
1671 start = JUMP(SLJIT_JUMP);
1672
1673 if (newlinecheck)
1674 {
1675 newlinelabel = LABEL();
1676 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1677 end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1678 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1679 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
1680 COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
1681 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1682 nl = JUMP(SLJIT_JUMP);
1683 }
1684
1685 mainloop = LABEL();
1686
1687 /* Increasing the STR_PTR here requires one less jump in the most common case. */
1688 #ifdef SUPPORT_UTF8
1689 if (common->utf8) readbyte = TRUE;
1690 #endif
1691 if (newlinecheck) readbyte = TRUE;
1692
1693 if (readbyte)
1694 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1695
1696 if (newlinecheck)
1697 CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);
1698
1699 #ifdef SUPPORT_UTF8
1700 if (common->utf8)
1701 {
1702 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
1703 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1704 }
1705 else
1706 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1707 #else
1708 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1709 #endif
1710 JUMPHERE(start);
1711
1712 if (newlinecheck)
1713 {
1714 JUMPHERE(end);
1715 JUMPHERE(nl);
1716 }
1717
1718 return mainloop;
1719 }
1720
1721 static SLJIT_INLINE void fast_forward_first_byte(compiler_common *common, pcre_uint16 firstbyte, BOOL firstline)
1722 {
1723 DEFINE_COMPILER;
1724 struct sljit_label *start;
1725 struct sljit_jump *leave;
1726 struct sljit_jump *found;
1727 pcre_uint16 oc, bit;
1728
1729 if (firstline)
1730 {
1731 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1732 OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
1733 }
1734
1735 start = LABEL();
1736 leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1737 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1738
1739 if ((firstbyte & REQ_CASELESS) == 0)
1740 found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, firstbyte & 0xff);
1741 else
1742 {
1743 firstbyte &= 0xff;
1744 oc = common->fcc[firstbyte];
1745 bit = firstbyte ^ oc;
1746 if (ispowerof2(bit))
1747 {
1748 OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit);
1749 found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, firstbyte | bit);
1750 }
1751 else
1752 {
1753 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, firstbyte);
1754 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
1755 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
1756 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
1757 found = JUMP(SLJIT_C_NOT_ZERO);
1758 }
1759 }
1760
1761 #ifdef SUPPORT_UTF8
1762 if (common->utf8)
1763 {
1764 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
1765 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1766 }
1767 else
1768 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1769 #else
1770 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1771 #endif
1772 JUMPTO(SLJIT_JUMP, start);
1773 JUMPHERE(found);
1774 JUMPHERE(leave);
1775
1776 if (firstline)
1777 OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1778 }
1779
1780 static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline)
1781 {
1782 DEFINE_COMPILER;
1783 struct sljit_label *loop;
1784 struct sljit_jump *lastchar;
1785 struct sljit_jump *firstchar;
1786 struct sljit_jump *leave;
1787 struct sljit_jump *foundcr = NULL;
1788 struct sljit_jump *notfoundnl;
1789 jump_list *newline = NULL;
1790
1791 if (firstline)
1792 {
1793 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1794 OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
1795 }
1796
1797 if (common->nltype == NLTYPE_FIXED && common->newline > 255)
1798 {
1799 lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1800 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1801 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
1802 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
1803 firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
1804
1805 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);
1806 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
1807 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL);
1808 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1809
1810 loop = LABEL();
1811 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1812 leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1813 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -2);
1814 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), -1);
1815 CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop);
1816 CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop);
1817
1818 JUMPHERE(leave);
1819 JUMPHERE(firstchar);
1820 JUMPHERE(lastchar);
1821
1822 if (firstline)
1823 OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1824 return;
1825 }
1826
1827 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1828 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
1829 firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
1830 skip_char_back(common);
1831
1832 loop = LABEL();
1833 read_char(common);
1834 lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1835 if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
1836 foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
1837 check_newlinechar(common, common->nltype, &newline, FALSE);
1838 set_jumps(newline, loop);
1839
1840 if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
1841 {
1842 leave = JUMP(SLJIT_JUMP);
1843 JUMPHERE(foundcr);
1844 notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1845 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1846 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
1847 COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
1848 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1849 JUMPHERE(notfoundnl);
1850 JUMPHERE(leave);
1851 }
1852 JUMPHERE(lastchar);
1853 JUMPHERE(firstchar);
1854
1855 if (firstline)
1856 OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1857 }
1858
1859 static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline)
1860 {
1861 DEFINE_COMPILER;
1862 struct sljit_label *start;
1863 struct sljit_jump *leave;
1864 struct sljit_jump *found;
1865
1866 if (firstline)
1867 {
1868 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1869 OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
1870 }
1871
1872 start = LABEL();
1873 leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1874 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1875 #ifdef SUPPORT_UTF8
1876 if (common->utf8)
1877 OP1(SLJIT_MOV_UB, TMP3, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
1878 #endif
1879 OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
1880 OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
1881 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits);
1882 OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
1883 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
1884 found = JUMP(SLJIT_C_NOT_ZERO);
1885
1886 #ifdef SUPPORT_UTF8
1887 if (common->utf8)
1888 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP3, 0);
1889 else
1890 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1891 #else
1892 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1893 #endif
1894 JUMPTO(SLJIT_JUMP, start);
1895 JUMPHERE(found);
1896 JUMPHERE(leave);
1897
1898 if (firstline)
1899 OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1900 }
1901
1902 static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uint16 reqbyte, BOOL has_firstbyte)
1903 {
1904 DEFINE_COMPILER;
1905 struct sljit_label *loop;
1906 struct sljit_jump *toolong;
1907 struct sljit_jump *alreadyfound;
1908 struct sljit_jump *found;
1909 struct sljit_jump *foundoc = NULL;
1910 struct sljit_jump *notfound;
1911 pcre_uint16 oc, bit;
1912
1913 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_BYTE_PTR);
1914 OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX);
1915 toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0);
1916 alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0);
1917
1918 if (has_firstbyte)
1919 OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, 1);
1920 else
1921 OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0);
1922
1923 loop = LABEL();
1924 notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0);
1925
1926 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), 0);
1927 if ((reqbyte & REQ_CASELESS) == 0)
1928 found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte & 0xff);
1929 else
1930 {
1931 reqbyte &= 0xff;
1932 oc = common->fcc[reqbyte];
1933 bit = reqbyte ^ oc;
1934 if (ispowerof2(bit))
1935 {
1936 OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit);
1937 found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte | bit);
1938 }
1939 else
1940 {
1941 found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte);
1942 foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc);
1943 }
1944 }
1945 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1946 JUMPTO(SLJIT_JUMP, loop);
1947
1948 JUMPHERE(found);
1949 if (foundoc)
1950 JUMPHERE(foundoc);
1951 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_BYTE_PTR, TMP1, 0);
1952 JUMPHERE(alreadyfound);
1953 JUMPHERE(toolong);
1954 return notfound;
1955 }
1956
1957 static void do_revertframes(compiler_common *common)
1958 {
1959 DEFINE_COMPILER;
1960 struct sljit_jump *earlyexit;
1961 struct sljit_jump *jump;
1962 struct sljit_label *mainloop;
1963
1964 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1965 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD);
1966
1967 /* Drop frames until we reach STACK_TOP. */
1968 earlyexit = CMP(SLJIT_C_LESS, TMP1, 0, STACK_TOP, 0);
1969 mainloop = LABEL();
1970 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);
1971 jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
1972 OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_LOCALS_REG, 0);
1973 OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
1974 OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w));
1975 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w));
1976 JUMPTO(SLJIT_JUMP, mainloop);
1977
1978 JUMPHERE(jump);
1979 jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
1980 /* End of dropping frames. */
1981 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
1982 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP1, 0);
1983 CMPTO(SLJIT_C_GREATER_EQUAL, TMP1, 0, STACK_TOP, 0, mainloop);
1984 JUMPHERE(earlyexit);
1985 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1986
1987 JUMPHERE(jump);
1988 jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setmaxindex);
1989 /* Set max index. */
1990 OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
1991 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
1992 JUMPTO(SLJIT_JUMP, mainloop);
1993
1994 JUMPHERE(jump);
1995 jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin);
1996 /* Set max index. */
1997 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
1998 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
1999 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
2000 JUMPTO(SLJIT_JUMP, mainloop);
2001
2002 JUMPHERE(jump);
2003 /* Unknown command. */
2004 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
2005 JUMPTO(SLJIT_JUMP, mainloop);
2006 }
2007
2008 static void check_wordboundary(compiler_common *common)
2009 {
2010 DEFINE_COMPILER;
2011 struct sljit_jump *beginend;
2012 struct sljit_jump *jump;
2013
2014 SLJIT_ASSERT(ctype_word == 0x10);
2015
2016 sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize);
2017 /* Get type of the previous char, and put it to LOCALS1. */
2018 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2019 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
2020 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0);
2021 beginend = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
2022 skip_char_back(common);
2023 read_char(common);
2024
2025 /* Testing char type. */
2026 #ifdef SUPPORT_UCP
2027 if (common->useucp)
2028 {
2029 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
2030 jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
2031 add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2032 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
2033 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2034 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2035 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
2036 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2037 COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2038 JUMPHERE(jump);
2039 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
2040 }
2041 else
2042 #endif
2043 {
2044 #ifdef SUPPORT_UTF8
2045 /* Here LOCALS1 has already been zeroed. */
2046 jump = NULL;
2047 if (common->utf8)
2048 jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2049 #endif
2050 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
2051 OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */);
2052 OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2053 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
2054 #ifdef SUPPORT_UTF8
2055 if (jump != NULL)
2056 JUMPHERE(jump);
2057 #endif
2058 }
2059 JUMPHERE(beginend);
2060
2061 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2062 beginend = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2063 peek_char(common);
2064
2065 /* Testing char type. This is a code duplication. */
2066 #ifdef SUPPORT_UCP
2067 if (common->useucp)
2068 {
2069 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
2070 jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
2071 add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2072 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
2073 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2074 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2075 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
2076 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2077 COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2078 JUMPHERE(jump);
2079 }
2080 else
2081 #endif
2082 {
2083 #ifdef SUPPORT_UTF8
2084 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2085 jump = NULL;
2086 if (common->utf8)
2087 jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2088 #endif
2089 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);
2090 OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */);
2091 OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
2092 #ifdef SUPPORT_UTF8
2093 if (jump != NULL)
2094 JUMPHERE(jump);
2095 #endif
2096 }
2097 JUMPHERE(beginend);
2098
2099 OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2100 sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2101 }
2102
2103 static void check_anynewline(compiler_common *common)
2104 {
2105 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2106 DEFINE_COMPILER;
2107
2108 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2109
2110 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
2111 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
2112 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2113 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
2114 #ifdef SUPPORT_UTF8
2115 if (common->utf8)
2116 {
2117 COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2118 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
2119 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
2120 }
2121 #endif
2122 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2123 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2124 }
2125
2126 static void check_hspace(compiler_common *common)
2127 {
2128 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2129 DEFINE_COMPILER;
2130
2131 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2132
2133 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
2134 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2135 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
2136 COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2137 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
2138 #ifdef SUPPORT_UTF8
2139 if (common->utf8)
2140 {
2141 COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2142 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
2143 COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2144 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
2145 COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2146 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
2147 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
2148 COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2149 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
2150 COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2151 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
2152 COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2153 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
2154 }
2155 #endif
2156 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2157
2158 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2159 }
2160
2161 static void check_vspace(compiler_common *common)
2162 {
2163 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2164 DEFINE_COMPILER;
2165
2166 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2167
2168 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
2169 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
2170 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2171 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
2172 #ifdef SUPPORT_UTF8
2173 if (common->utf8)
2174 {
2175 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2176 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
2177 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
2178 }
2179 #endif
2180 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2181
2182 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2183 }
2184
2185 #define CHAR1 STR_END
2186 #define CHAR2 STACK_TOP
2187
2188 static void do_casefulcmp(compiler_common *common)
2189 {
2190 DEFINE_COMPILER;
2191 struct sljit_jump *jump;
2192 struct sljit_label *label;
2193
2194 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2195 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
2196 OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);
2197 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0);
2198 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2199 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2200
2201 label = LABEL();
2202 OP1(SLJIT_MOVU_UB, CHAR1, 0, SLJIT_MEM1(TMP1), 1);
2203 OP1(SLJIT_MOVU_UB, CHAR2, 0, SLJIT_MEM1(STR_PTR), 1);
2204 jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
2205 OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
2206 JUMPTO(SLJIT_C_NOT_ZERO, label);
2207
2208 JUMPHERE(jump);
2209 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2210 OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0);
2211 OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2212 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2213 }
2214
2215 #define LCC_TABLE STACK_LIMIT
2216
2217 static void do_caselesscmp(compiler_common *common)
2218 {
2219 DEFINE_COMPILER;
2220 struct sljit_jump *jump;
2221 struct sljit_label *label;
2222
2223 sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2224 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
2225
2226 OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0);
2227 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0);
2228 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0);
2229 OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc);
2230 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2231 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2232
2233 label = LABEL();
2234 OP1(SLJIT_MOVU_UB, CHAR1, 0, SLJIT_MEM1(TMP1), 1);
2235 OP1(SLJIT_MOVU_UB, CHAR2, 0, SLJIT_MEM1(STR_PTR), 1);
2236 OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
2237 OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
2238 jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
2239 OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
2240 JUMPTO(SLJIT_C_NOT_ZERO, label);
2241
2242 JUMPHERE(jump);
2243 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2244 OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0);
2245 OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2246 OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2247 sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2248 }
2249
2250 #undef LCC_TABLE
2251 #undef CHAR1
2252 #undef CHAR2
2253
2254 #ifdef SUPPORT_UTF8
2255 #ifdef SUPPORT_UCP
2256
2257 static uschar * SLJIT_CALL do_utf8caselesscmp(uschar *src1, jit_arguments *args, uschar *end1)
2258 {
2259 /* This function would be ineffective to do in JIT level. */
2260 int c1, c2;
2261 uschar *src2 = args->ptr;
2262 uschar *end2 = (uschar*)args->end;
2263
2264 while (src1 < end1)
2265 {
2266 if (src2 >= end2)
2267 return 0;
2268 GETCHARINC(c1, src1);
2269 GETCHARINC(c2, src2);
2270 if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return 0;
2271 }
2272 return src2;
2273 }
2274
2275 #endif
2276 #endif
2277
2278 static uschar *byte_sequence_compare(compiler_common *common, BOOL caseless, uschar *cc,
2279 compare_context* context, jump_list **fallbacks)
2280 {
2281 DEFINE_COMPILER;
2282 unsigned int othercasebit = 0;
2283 uschar *othercasebyte = NULL;
2284 #ifdef SUPPORT_UTF8
2285 int utf8length;
2286 #endif
2287
2288 if (caseless && char_has_othercase(common, cc))
2289 {
2290 othercasebit = char_get_othercase_bit(common, cc);
2291 SLJIT_ASSERT(othercasebit);
2292 /* Extracting bit difference info. */
2293 othercasebyte = cc + (othercasebit >> 8);
2294 othercasebit &= 0xff;
2295 }
2296
2297 if (context->sourcereg == -1)
2298 {
2299 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2300 if (context->length >= 4)
2301 OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2302 else if (context->length >= 2)
2303 OP1(SLJIT_MOV_SH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2304 else
2305 #endif
2306 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2307 context->sourcereg = TMP2;
2308 }
2309
2310 #ifdef SUPPORT_UTF8
2311 utf8length = 1;
2312 if (common->utf8 && *cc >= 0xc0)
2313 utf8length += _pcre_utf8_table4[*cc & 0x3f];
2314
2315 do
2316 {
2317 #endif
2318
2319 context->length--;
2320 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2321
2322 /* Unaligned read is supported. */
2323 if (othercasebit != 0 && othercasebyte == cc)
2324 {
2325 context->c.asbytes[context->byteptr] = *cc | othercasebit;
2326 context->oc.asbytes[context->byteptr] = othercasebit;
2327 }
2328 else
2329 {
2330 context->c.asbytes[context->byteptr] = *cc;
2331 context->oc.asbytes[context->byteptr] = 0;
2332 }
2333 context->byteptr++;
2334
2335 if (context->byteptr >= 4 || context->length == 0 || (context->byteptr == 2 && context->length == 1))
2336 {
2337 if (context->length >= 4)
2338 OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2339 else if (context->length >= 2)
2340 OP1(SLJIT_MOV_SH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2341 else if (context->length >= 1)
2342 OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2343 context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
2344
2345 switch(context->byteptr)
2346 {
2347 case 4:
2348 if (context->oc.asint != 0)
2349 OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);
2350 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));
2351 break;
2352
2353 case 2:
2354 if (context->oc.asshort != 0)
2355 OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asshort);
2356 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asshort | context->oc.asshort));
2357 break;
2358
2359 case 1:
2360 if (context->oc.asbyte != 0)
2361 OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);
2362 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));
2363 break;
2364
2365 default:
2366 SLJIT_ASSERT_STOP();
2367 break;
2368 }
2369 context->byteptr = 0;
2370 }
2371
2372 #else
2373
2374 /* Unaligned read is unsupported. */
2375 if (context->length > 0)
2376 OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2377 context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
2378
2379 if (othercasebit != 0 && othercasebyte == cc)
2380 {
2381 OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);
2382 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));
2383 }
2384 else
2385 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));
2386
2387 #endif
2388
2389 cc++;
2390 #ifdef SUPPORT_UTF8
2391 utf8length--;
2392 }
2393 while (utf8length > 0);
2394 #endif
2395
2396 return cc;
2397 }
2398
2399 #ifdef SUPPORT_UTF8
2400
2401 #define SET_TYPE_OFFSET(value) \
2402 if ((value) != typeoffset) \
2403 { \
2404 if ((value) > typeoffset) \
2405 OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
2406 else \
2407 OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
2408 } \
2409 typeoffset = (value);
2410
2411 #define SET_CHAR_OFFSET(value) \
2412 if ((value) != charoffset) \
2413 { \
2414 if ((value) > charoffset) \
2415 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \
2416 else \
2417 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \
2418 } \
2419 charoffset = (value);
2420
2421 static void compile_xclass_hotpath(compiler_common *common, uschar *cc, jump_list **fallbacks)
2422 {
2423 DEFINE_COMPILER;
2424 jump_list *found = NULL;
2425 jump_list **list = (*cc & XCL_NOT) == 0 ? &found : fallbacks;
2426 unsigned int c;
2427 int compares;
2428 struct sljit_jump *jump = NULL;
2429 uschar *ccbegin;
2430 #ifdef SUPPORT_UCP
2431 BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
2432 BOOL charsaved = FALSE;
2433 int typereg = TMP1, scriptreg = TMP1, typeoffset;
2434 #endif
2435 int charoffset, invertcmp, numberofcmps;
2436
2437 /* Although SUPPORT_UTF8 must be defined, we are not necessary in utf8 mode. */
2438 check_input_end(common, fallbacks);
2439 read_char(common);
2440
2441 if ((*cc++ & XCL_MAP) != 0)
2442 {
2443 OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
2444 if (common->utf8)
2445 jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2446
2447 OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
2448 OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
2449 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
2450 OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
2451 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
2452 add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO));
2453
2454 if (common->utf8)
2455 JUMPHERE(jump);
2456 OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
2457 #ifdef SUPPORT_UCP
2458 charsaved = TRUE;
2459 #endif
2460 cc += 32;
2461 }
2462
2463 /* Scanning the necessary info. */
2464 ccbegin = cc;
2465 compares = 0;
2466 while (*cc != XCL_END)
2467 {
2468 compares++;
2469 if (*cc == XCL_SINGLE)
2470 {
2471 cc += 2;
2472 #ifdef SUPPORT_UTF8
2473 if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
2474 #endif
2475 #ifdef SUPPORT_UCP
2476 needschar = TRUE;
2477 #endif
2478 }
2479 else if (*cc == XCL_RANGE)
2480 {
2481 cc += 2;
2482 #ifdef SUPPORT_UTF8
2483 if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
2484 #endif
2485 cc++;
2486 #ifdef SUPPORT_UTF8
2487 if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
2488 #endif
2489 #ifdef SUPPORT_UCP
2490 needschar = TRUE;
2491 #endif
2492 }
2493 #ifdef SUPPORT_UCP
2494 else
2495 {
2496 SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
2497 cc++;
2498 switch(*cc)
2499 {
2500 case PT_ANY:
2501 break;
2502
2503 case PT_LAMP:
2504 case PT_GC:
2505 case PT_PC:
2506 case PT_ALNUM:
2507 needstype = TRUE;
2508 break;
2509
2510 case PT_SC:
2511 needsscript = TRUE;
2512 break;
2513
2514 case PT_SPACE:
2515 case PT_PXSPACE:
2516 case PT_WORD:
2517 needstype = TRUE;
2518 needschar = TRUE;
2519 break;
2520
2521 default:
2522 SLJIT_ASSERT_STOP();
2523 break;
2524 }
2525 cc += 2;
2526 }
2527 #endif
2528 }
2529
2530 #ifdef SUPPORT_UCP
2531 /* Simple register allocation. TMP1 is preferred if possible. */
2532 if (needstype || needsscript)
2533 {
2534 if (needschar && !charsaved)
2535 OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
2536 add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2537 if (needschar)
2538 {
2539 if (needstype)
2540 {
2541 OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
2542 typereg = RETURN_ADDR;
2543 }
2544
2545 if (needsscript)
2546 scriptreg = TMP3;
2547 OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
2548 }
2549 else if (needstype && needsscript)
2550 scriptreg = TMP3;
2551 /* In all other cases only one of them was specified, and that can goes to TMP1. */
2552
2553 if (needsscript)
2554 {
2555 if (scriptreg == TMP1)
2556 {
2557 OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, script));
2558 OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3);
2559 }
2560 else
2561 {
2562 OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
2563 OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, script));
2564 OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0);
2565 }
2566 }
2567 }
2568 #endif
2569
2570 /* Generating code. */
2571 cc = ccbegin;
2572 charoffset = 0;
2573 numberofcmps = 0;
2574 #ifdef SUPPORT_UCP
2575 typeoffset = 0;
2576 #endif
2577
2578 while (*cc != XCL_END)
2579 {
2580 compares--;
2581 invertcmp = (compares == 0 && list != fallbacks);
2582 jump = NULL;
2583
2584 if (*cc == XCL_SINGLE)
2585 {
2586 cc ++;
2587 #ifdef SUPPORT_UTF8
2588 if (common->utf8)
2589 {
2590 GETCHARINC(c, cc);
2591 }
2592 else
2593 #endif
2594 c = *cc++;
2595
2596 if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
2597 {
2598 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2599 COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2600 numberofcmps++;
2601 }
2602 else if (numberofcmps > 0)
2603 {
2604 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2605 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2606 jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2607 numberofcmps = 0;
2608 }
2609 else
2610 {
2611 jump = CMP(SLJIT_C_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
2612 numberofcmps = 0;
2613 }
2614 }
2615 else if (*cc == XCL_RANGE)
2616 {
2617 cc ++;
2618 #ifdef SUPPORT_UTF8
2619 if (common->utf8)
2620 {
2621 GETCHARINC(c, cc);
2622 }
2623 else
2624 #endif
2625 c = *cc++;
2626 SET_CHAR_OFFSET(c);
2627 #ifdef SUPPORT_UTF8
2628 if (common->utf8)
2629 {
2630 GETCHARINC(c, cc);
2631 }
2632 else
2633 #endif
2634 c = *cc++;
2635 if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
2636 {
2637 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2638 COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2639 numberofcmps++;
2640 }
2641 else if (numberofcmps > 0)
2642 {
2643 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2644 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2645 jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2646 numberofcmps = 0;
2647 }
2648 else
2649 {
2650 jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
2651 numberofcmps = 0;
2652 }
2653 }
2654 #ifdef SUPPORT_UCP
2655 else
2656 {
2657 if (*cc == XCL_NOTPROP)
2658 invertcmp ^= 0x1;
2659 cc++;
2660 switch(*cc)
2661 {
2662 case PT_ANY:
2663 if (list != fallbacks)
2664 {
2665 if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0))
2666 continue;
2667 }
2668 else if (cc[-1] == XCL_NOTPROP)
2669 continue;
2670 jump = JUMP(SLJIT_JUMP);
2671 break;
2672
2673 case PT_LAMP:
2674 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
2675 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2676 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
2677 COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2678 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
2679 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2680 jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2681 break;
2682
2683 case PT_GC:
2684 c = _pcre_ucp_typerange[(int)cc[1] * 2];
2685 SET_TYPE_OFFSET(c);
2686 jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, _pcre_ucp_typerange[(int)cc[1] * 2 + 1] - c);
2687 break;
2688
2689 case PT_PC:
2690 jump = CMP(SLJIT_C_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset);
2691 break;
2692
2693 case PT_SC:
2694 jump = CMP(SLJIT_C_EQUAL ^ invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]);
2695 break;
2696
2697 case PT_SPACE:
2698 case PT_PXSPACE:
2699 if (*cc == PT_SPACE)
2700 {
2701 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2702 jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 11 - charoffset);
2703 }
2704 SET_CHAR_OFFSET(9);
2705 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9);
2706 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2707 if (*cc == PT_SPACE)
2708 JUMPHERE(jump);
2709
2710 SET_TYPE_OFFSET(ucp_Zl);
2711 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
2712 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2713 jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2714 break;
2715
2716 case PT_WORD:
2717 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE - charoffset);
2718 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2719 /* ... fall through */
2720
2721 case PT_ALNUM:
2722 SET_TYPE_OFFSET(ucp_Ll);
2723 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2724 COND_VALUE((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2725 SET_TYPE_OFFSET(ucp_Nd);
2726 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2727 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2728 jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2729 break;
2730 }
2731 cc += 2;
2732 }
2733 #endif
2734
2735 if (jump != NULL)
2736 add_jump(compiler, compares > 0 ? list : fallbacks, jump);
2737 }
2738
2739 if (found != NULL)
2740 set_jumps(found, LABEL());
2741 }
2742
2743 #undef SET_TYPE_OFFSET
2744 #undef SET_CHAR_OFFSET
2745
2746 #endif
2747
2748 static uschar *compile_char1_hotpath(compiler_common *common, uschar type, uschar *cc, jump_list **fallbacks)
2749 {
2750 DEFINE_COMPILER;
2751 int length;
2752 unsigned int c, oc, bit;
2753 compare_context context;
2754 struct sljit_label *label;
2755 struct sljit_jump *jump[4];
2756 #ifdef SUPPORT_UTF8
2757 #ifdef SUPPORT_UCP
2758 uschar propdata[5];
2759 #endif
2760 #endif
2761
2762 switch(type)
2763 {
2764 case OP_SOD:
2765 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2766 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
2767 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
2768 return cc;
2769
2770 case OP_SOM:
2771 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2772 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
2773 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
2774 return cc;
2775
2776 case OP_NOT_WORD_BOUNDARY:
2777 case OP_WORD_BOUNDARY:
2778 add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
2779 add_jump(compiler, fallbacks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
2780 return cc;
2781
2782 case OP_NOT_DIGIT:
2783 case OP_DIGIT:
2784 check_input_end(common, fallbacks);
2785 read_char8_type(common);
2786 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
2787 add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
2788 return cc;
2789
2790 case OP_NOT_WHITESPACE:
2791 case OP_WHITESPACE:
2792 check_input_end(common, fallbacks);
2793 read_char8_type(common);
2794 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
2795 add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
2796 return cc;
2797
2798 case OP_NOT_WORDCHAR:
2799 case OP_WORDCHAR:
2800 check_input_end(common, fallbacks);
2801 read_char8_type(common);
2802 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
2803 add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
2804 return cc;
2805
2806 case OP_ANY:
2807 check_input_end(common, fallbacks);
2808 read_char(common);
2809 if (common->nltype == NLTYPE_FIXED && common->newline > 255)
2810 {
2811 jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
2812 jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2813 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2814 add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));
2815 JUMPHERE(jump[1]);
2816 JUMPHERE(jump[0]);
2817 }
2818 else
2819 check_newlinechar(common, common->nltype, fallbacks, TRUE);
2820 return cc;
2821
2822 case OP_ALLANY:
2823 check_input_end(common, fallbacks);
2824 #ifdef SUPPORT_UTF8
2825 if (common->utf8)
2826 {
2827 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2828 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
2829 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
2830 return cc;
2831 }
2832 #endif
2833 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2834 return cc;
2835
2836 #ifdef SUPPORT_UTF8
2837 #ifdef SUPPORT_UCP
2838 case OP_NOTPROP:
2839 case OP_PROP:
2840 propdata[0] = 0;
2841 propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;
2842 propdata[2] = cc[0];
2843 propdata[3] = cc[1];
2844 propdata[4] = XCL_END;
2845 compile_xclass_hotpath(common, propdata, fallbacks);
2846 return cc + 2;
2847 #endif
2848 #endif
2849
2850 case OP_ANYNL:
2851 check_input_end(common, fallbacks);
2852 read_char(common);
2853 jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
2854 jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2855 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2856 jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
2857 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2858 jump[3] = JUMP(SLJIT_JUMP);
2859 JUMPHERE(jump[0]);
2860 check_newlinechar(common, common->bsr_nltype, fallbacks, FALSE);
2861 JUMPHERE(jump[1]);
2862 JUMPHERE(jump[2]);
2863 JUMPHERE(jump[3]);
2864 return cc;
2865
2866 case OP_NOT_HSPACE:
2867 case OP_HSPACE:
2868 check_input_end(common, fallbacks);
2869 read_char(common);
2870 add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
2871 add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
2872 return cc;
2873
2874 case OP_NOT_VSPACE:
2875 case OP_VSPACE:
2876 check_input_end(common, fallbacks);
2877 read_char(common);
2878 add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
2879 add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
2880 return cc;
2881
2882 #ifdef SUPPORT_UCP
2883 case OP_EXTUNI:
2884 check_input_end(common, fallbacks);
2885 read_char(common);
2886 add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2887 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
2888 add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc));
2889
2890 label = LABEL();
2891 jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2892 OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
2893 read_char(common);
2894 add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2895 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
2896 CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc, label);
2897
2898 OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
2899 JUMPHERE(jump[0]);
2900 return cc;
2901 #endif
2902
2903 case OP_EODN:
2904 jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2905 if (common->nltype == NLTYPE_FIXED && common->newline > 255)
2906 {
2907 OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
2908 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2909 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
2910 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
2911 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
2912 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
2913 }
2914 else if (common->nltype == NLTYPE_FIXED)
2915 {
2916 OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 1);
2917 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2918 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
2919 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
2920 }
2921 else
2922 {
2923 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2924 jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
2925 OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
2926 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
2927 jump[2] = JUMP(SLJIT_C_GREATER);
2928 add_jump(compiler, fallbacks, JUMP(SLJIT_C_LESS));
2929 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 1);
2930 jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
2931 add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP));
2932
2933 JUMPHERE(jump[1]);
2934 if (common->nltype == NLTYPE_ANYCRLF)
2935 {
2936 OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 1);
2937 add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0));
2938 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
2939 }
2940 else
2941 {
2942 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0);
2943 read_char(common);
2944 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
2945 add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
2946 add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
2947 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2948 }
2949 JUMPHERE(jump[2]);
2950 JUMPHERE(jump[3]);
2951 }
2952 JUMPHERE(jump[0]);
2953 return cc;
2954
2955 case OP_EOD:
2956 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
2957 return cc;
2958
2959 case OP_CIRC:
2960 OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
2961 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
2962 add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0));
2963 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
2964 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
2965 return cc;
2966
2967 case OP_CIRCM:
2968 OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
2969 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
2970 jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0);
2971 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
2972 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
2973 jump[0] = JUMP(SLJIT_JUMP);
2974 JUMPHERE(jump[1]);
2975
2976 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, end));
2977 add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP2, 0, STR_PTR, 0));
2978
2979 if (common->nltype == NLTYPE_FIXED && common->newline > 255)
2980 {
2981 OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
2982 add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0));
2983 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -2);
2984 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), -1);
2985 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
2986 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
2987 }
2988 else
2989 {
2990 skip_char_back(common);
2991 read_char(common);
2992 check_newlinechar(common, common->nltype, fallbacks, FALSE);
2993 }
2994 JUMPHERE(jump[0]);
2995 return cc;
2996
2997 case OP_DOLL:
2998 OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
2999 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
3000 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3001
3002 if (!common->endonly)
3003 compile_char1_hotpath(common, OP_EODN, cc, fallbacks);
3004 else
3005 add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
3006 return cc;
3007
3008 case OP_DOLLM:
3009 jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
3010 OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3011 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
3012 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3013 jump[0] = JUMP(SLJIT_JUMP);
3014 JUMPHERE(jump[1]);
3015
3016 if (common->nltype == NLTYPE_FIXED && common->newline > 255)
3017 {
3018 OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
3019 add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0));
3020 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
3021 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
3022 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
3023 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
3024 }
3025 else
3026 {
3027 peek_char(common);
3028 check_newlinechar(common, common->nltype, fallbacks, FALSE);
3029 }
3030 JUMPHERE(jump[0]);
3031 return cc;
3032
3033 case OP_CHAR:
3034 case OP_CHARI:
3035 length = 1;
3036 #ifdef SUPPORT_UTF8
3037 if (common->utf8 && *cc >= 0xc0) length += _pcre_utf8_table4[*cc & 0x3f];
3038 #endif
3039 if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)
3040 {
3041 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, length);
3042 add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3043
3044 context.length = length;
3045 context.sourcereg = -1;
3046 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3047 context.byteptr = 0;
3048 #endif
3049 return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks);
3050 }
3051 add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
3052 read_char(common);
3053 #ifdef SUPPORT_UTF8
3054 if (common->utf8)
3055 {
3056 GETCHAR(c, cc);
3057 }
3058 else
3059 #endif
3060 c = *cc;
3061 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c);
3062 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3063 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c));
3064 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
3065 add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
3066 return cc + length;
3067
3068 case OP_NOT:
3069 case OP_NOTI:
3070 length = 1;
3071 #ifdef SUPPORT_UTF8
3072 if (common->utf8)
3073 {
3074 if (*cc >= 0xc0) length += _pcre_utf8_table4[*cc & 0x3f];
3075
3076 check_input_end(common, fallbacks);
3077 GETCHAR(c, cc);
3078
3079 if (c <= 127)
3080 {
3081 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
3082 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
3083 if (type == OP_NOT || !char_has_othercase(common, cc))
3084 add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3085 else
3086 {
3087 /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
3088 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x20);
3089 add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | 0x20));
3090 }
3091 /* Skip the variable-length character. */
3092 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
3093 return cc + length;
3094 }
3095 else
3096 read_char(common);
3097 }
3098 else
3099 #endif
3100 {
3101 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
3102 add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3103 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -1);
3104 c = *cc;
3105 }
3106
3107 if (type == OP_NOT || !char_has_othercase(common, cc))
3108 add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3109 else
3110 {
3111 oc = char_othercase(common, c);
3112 bit = c ^ oc;
3113 if (ispowerof2(bit))
3114 {
3115 OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
3116 add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
3117 }
3118 else
3119 {
3120 add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3121 add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc));
3122 }
3123 }
3124 return cc + length;
3125
3126 case OP_CLASS:
3127 case OP_NCLASS:
3128 check_input_end(common, fallbacks);
3129 read_char(common);
3130 #ifdef SUPPORT_UTF8
3131 jump[0] = NULL;
3132 if (common->utf8)
3133 {
3134 jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
3135 if (type == OP_CLASS)
3136 {
3137 add_jump(compiler, fallbacks, jump[0]);
3138 jump[0] = NULL;
3139 }
3140 }
3141 #endif
3142 OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
3143 OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
3144 OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
3145 OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
3146 OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
3147 add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
3148 #ifdef SUPPORT_UTF8
3149 if (jump[0] != NULL)
3150 JUMPHERE(jump[0]);
3151 #endif
3152 return cc + 32;
3153
3154 #ifdef SUPPORT_UTF8
3155 case OP_XCLASS:
3156 compile_xclass_hotpath(common, cc + LINK_SIZE, fallbacks);
3157 return cc + GET(cc, 0) - 1;
3158 #endif
3159
3160 case OP_REVERSE:
3161 length = GET(cc, 0);
3162 SLJIT_ASSERT(length > 0);
3163 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
3164 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
3165 #ifdef SUPPORT_UTF8
3166 if (common->utf8)
3167 {
3168 OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
3169 label = LABEL();
3170 add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0));
3171 skip_char_back(common);
3172 OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
3173 JUMPTO(SLJIT_C_NOT_ZERO, label);
3174 return cc + LINK_SIZE;
3175 }
3176 #endif
3177 OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, length);
3178 add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0));
3179 return cc + LINK_SIZE;
3180 }
3181 SLJIT_ASSERT_STOP();
3182 return cc;
3183 }
3184
3185 static SLJIT_INLINE uschar *compile_charn_hotpath(compiler_common *common, uschar *cc, uschar *ccend, jump_list **fallbacks)
3186 {
3187 /* This function consumes at least one input character. */
3188 /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
3189 DEFINE_COMPILER;
3190 uschar *ccbegin = cc;
3191 compare_context context;
3192 int size;
3193
3194 context.length = 0;
3195 do
3196 {
3197 if (cc >= ccend)
3198 break;
3199
3200 if (*cc == OP_CHAR)
3201 {
3202 size = 1;
3203 #ifdef SUPPORT_UTF8
3204 if (common->utf8 && cc[1] >= 0xc0)
3205 size += _pcre_utf8_table4[cc[1] & 0x3f];
3206 #endif
3207 }
3208 else if (*cc == OP_CHARI)
3209 {
3210 size = 1;
3211 #ifdef SUPPORT_UTF8
3212 if (common->utf8)
3213 {
3214 if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
3215 size = 0;
3216 else if (cc[1] >= 0xc0)
3217 size += _pcre_utf8_table4[cc[1] & 0x3f];
3218 }
3219 else
3220 #endif
3221 if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
3222 size = 0;
3223 }
3224 else
3225 size = 0;
3226
3227 cc += 1 + size;
3228 context.length += size;
3229 }
3230 while (size > 0 && context.length <= 128);
3231
3232 cc = ccbegin;
3233 if (context.length > 0)
3234 {
3235 /* We have a fixed-length byte sequence. */
3236 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);
3237 add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3238
3239 context.sourcereg = -1;
3240 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3241 context.byteptr = 0;
3242 #endif
3243 do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, fallbacks); while (context.length > 0);
3244 return cc;
3245 }
3246
3247 /* A non-fixed length character will be checked if length == 0. */
3248 return compile_char1_hotpath(common, *cc, cc + 1, fallbacks);
3249 }
3250
3251 static struct sljit_jump *compile_ref_checks(compiler_common *common, uschar *cc, jump_list **fallbacks)
3252 {
3253 DEFINE_COMPILER;
3254 int offset = GET2(cc, 1) << 1;
3255
3256 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
3257 if (!common->jscript_compat)
3258 {
3259 if (fallbacks == NULL)
3260 {
3261 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
3262 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3263 OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3264 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
3265 return JUMP(SLJIT_C_NOT_ZERO);
3266 }
3267 add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
3268 }
3269 return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3270 }
3271
3272 /* Forward definitions. */
3273 static void compile_hotpath(compiler_common *, uschar *, uschar *, fallback_common *);
3274 static void compile_fallbackpath(compiler_common *, struct fallback_common *);
3275
3276 #define PUSH_FALLBACK(size, ccstart, error) \
3277 do \
3278 { \
3279 fallback = sljit_alloc_memory(compiler, (size)); \
3280 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3281 return error; \
3282 memset(fallback, 0, size); \
3283 fallback->prev = parent->top; \
3284 fallback->cc = (ccstart); \
3285 parent->top = fallback; \
3286 } \
3287 while (0)
3288
3289 #define PUSH_FALLBACK_NOVALUE(size, ccstart) \
3290 do \
3291 { \
3292 fallback = sljit_alloc_memory(compiler, (size)); \
3293 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3294 return; \
3295 memset(fallback, 0, size); \
3296 fallback->prev = parent->top; \
3297 fallback->cc = (ccstart); \
3298 parent->top = fallback; \
3299 } \
3300 while (0)
3301
3302 #define FALLBACK_AS(type) ((type*)fallback)
3303
3304 static uschar *compile_ref_hotpath(compiler_common *common, uschar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail)
3305 {
3306 DEFINE_COMPILER;
3307 int offset = GET2(cc, 1) << 1;
3308 struct sljit_jump *jump = NULL;
3309
3310 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
3311 if (withchecks && !common->jscript_compat)
3312 add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
3313
3314 #ifdef SUPPORT_UTF8
3315 #ifdef SUPPORT_UCP
3316 if (common->utf8 && *cc == OP_REFI)
3317 {
3318 SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3);
3319 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3320 if (withchecks)
3321 jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0);
3322
3323 /* Needed to save important temporary registers. */
3324 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
3325 OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0);
3326 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, ptr), STR_PTR, 0);
3327 sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf8caselesscmp));
3328 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
3329 add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
3330 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
3331 }
3332 else
3333 #endif
3334 #endif
3335 {
3336 OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);
3337 if (withchecks)
3338 jump = JUMP(SLJIT_C_ZERO);
3339 OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
3340
3341 add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3342 add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
3343 add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3344 }
3345
3346 if (jump != NULL)
3347 {
3348 if (emptyfail)
3349 add_jump(compiler, fallbacks, jump);
3350 else
3351 JUMPHERE(jump);
3352 }
3353 return cc + 3;
3354 }
3355
3356 static SLJIT_INLINE uschar *compile_ref_iterator_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
3357 {
3358 DEFINE_COMPILER;
3359 fallback_common *fallback;
3360 uschar type;
3361 struct sljit_label *label;
3362 struct sljit_jump *zerolength;
3363 struct sljit_jump *jump = NULL;
3364 uschar *ccbegin = cc;
3365 int min = 0, max = 0;
3366 BOOL minimize;
3367
3368 PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL);
3369
3370 type = cc[3];
3371 minimize = (type & 0x1) != 0;
3372 switch(type)
3373 {
3374 case OP_CRSTAR:
3375 case OP_CRMINSTAR:
3376 min = 0;
3377 max = 0;
3378 cc += 4;
3379 break;
3380 case OP_CRPLUS:
3381 case OP_CRMINPLUS:
3382 min = 1;
3383 max = 0;
3384 cc += 4;
3385 break;
3386 case OP_CRQUERY:
3387 case OP_CRMINQUERY:
3388 min = 0;
3389 max = 1;
3390 cc += 4;
3391 break;
3392 case OP_CRRANGE:
3393 case OP_CRMINRANGE:
3394 min = GET2(cc, 3 + 1);
3395 max = GET2(cc, 3 + 3);
3396 cc += 8;
3397 break;
3398 default:
3399 SLJIT_ASSERT_STOP();
3400 break;
3401 }
3402
3403 if (!minimize)
3404 {
3405 if (min == 0)
3406 {
3407 allocate_stack(common, 2);
3408 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3409 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
3410 /* Temporary release of STR_PTR. */
3411 OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3412 zerolength = compile_ref_checks(common, ccbegin, NULL);
3413 /* Restore if not zero length. */
3414 OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3415 }
3416 else
3417 {
3418 allocate_stack(common, 1);
3419 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3420 zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);
3421 }
3422
3423 if (min > 1 || max > 1)
3424 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
3425
3426 label = LABEL();
3427 compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, FALSE, FALSE);
3428
3429 if (min > 1 || max > 1)
3430 {
3431 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
3432 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
3433 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
3434 if (min > 1)
3435 CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label);
3436 if (max > 1)
3437 {
3438 jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);
3439 allocate_stack(common, 1);
3440 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3441 JUMPTO(SLJIT_JUMP, label);
3442 JUMPHERE(jump);
3443 }
3444 }
3445
3446 if (max == 0)
3447 {
3448 /* Includes min > 1 case as well. */
3449 allocate_stack(common, 1);
3450 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3451 JUMPTO(SLJIT_JUMP, label);
3452 }
3453
3454 JUMPHERE(zerolength);
3455 FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
3456 return cc;
3457 }
3458
3459 allocate_stack(common, 2);
3460 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3461 if (type != OP_CRMINSTAR)
3462 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
3463
3464 if (min == 0)
3465 {
3466 zerolength = compile_ref_checks(common, ccbegin, NULL);
3467 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3468 jump = JUMP(SLJIT_JUMP);
3469 }
3470 else
3471 zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);
3472
3473 FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
3474 if (max > 0)
3475 add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));
3476
3477 compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, TRUE, TRUE);
3478 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3479
3480 if (min > 1)
3481 {
3482 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3483 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
3484 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
3485 CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, FALLBACK_AS(iterator_fallback)->hotpath);
3486 }
3487 else if (max > 0)
3488 OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
3489
3490 if (jump != NULL)
3491 JUMPHERE(jump);
3492 JUMPHERE(zerolength);
3493 return cc;
3494 }
3495
3496 static SLJIT_INLINE uschar *compile_recurse_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
3497 {
3498 DEFINE_COMPILER;
3499 fallback_common *fallback;
3500 recurse_entry *entry = common->entries;
3501 recurse_entry *prev = NULL;
3502 int start = GET(cc, 1);
3503
3504 PUSH_FALLBACK(sizeof(recurse_fallback), cc, NULL);
3505 while (entry != NULL)
3506 {
3507 if (entry->start == start)
3508 break;
3509 prev = entry;
3510 entry = entry->next;
3511 }
3512
3513 if (entry == NULL)
3514 {
3515 entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));
3516 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3517 return NULL;
3518 entry->next = NULL;
3519 entry->entry = NULL;
3520 entry->calls = NULL;
3521 entry->start = start;
3522
3523 if (prev != NULL)
3524 prev->next = entry;
3525 else
3526 common->entries = entry;
3527 }
3528
3529 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
3530 allocate_stack(common, 1);
3531 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
3532
3533 if (entry->entry == NULL)
3534 add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL));
3535 else
3536 JUMPTO(SLJIT_FAST_CALL, entry->entry);
3537 /* Leave if the match is failed. */
3538 add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0));
3539 return cc + 1 + LINK_SIZE;
3540 }
3541
3542 static uschar *compile_assert_hotpath(compiler_common *common, uschar *cc, assert_fallback *fallback, BOOL conditional)
3543 {
3544 DEFINE_COMPILER;
3545 int framesize;
3546 int localptr;
3547 fallback_common altfallback;
3548 uschar *ccbegin;
3549 uschar opcode;
3550 uschar bra = OP_BRA;
3551 jump_list *tmp = NULL;
3552 jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks;
3553 jump_list **found;
3554 /* Saving previous accept variables. */
3555 struct sljit_label *save_acceptlabel = common->acceptlabel;
3556 struct sljit_jump *jump;
3557 struct sljit_jump *brajump = NULL;
3558 jump_list *save_accept = common->accept;
3559
3560 if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
3561 {
3562 SLJIT_ASSERT(!conditional);
3563 bra = *cc;
3564 cc++;
3565 }
3566 localptr = PRIV(cc);
3567 SLJIT_ASSERT(localptr != 0);
3568 framesize = get_framesize(common, cc, FALSE);
3569 fallback->framesize = framesize;
3570 fallback->localptr = localptr;
3571 opcode = *cc;
3572 SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);
3573 found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;
3574 ccbegin = cc;
3575 cc += GET(cc, 1);
3576
3577 if (bra == OP_BRAMINZERO)
3578 {
3579 /* This is a braminzero fallback path. */
3580 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3581 free_stack(common, 1);
3582 brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3583 }
3584
3585 if (framesize < 0)
3586 {
3587 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
3588 allocate_stack(common, 1);
3589 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3590 }
3591 else
3592 {
3593 allocate_stack(common, framesize + 2);
3594 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3595 OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + 1));
3596 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
3597 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3598 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
3599 init_frame(common, ccbegin, framesize + 1, 2, FALSE);
3600 }
3601
3602 memset(&altfallback, 0, sizeof(fallback_common));
3603 while (1)
3604 {
3605 common->acceptlabel = NULL;
3606 common->accept = NULL;
3607 altfallback.top = NULL;
3608 altfallback.topfallbacks = NULL;
3609
3610 if (*ccbegin == OP_ALT)
3611 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3612
3613 altfallback.cc = ccbegin;
3614 compile_hotpath(common, ccbegin + 1 + LINK_SIZE, cc, &altfallback);
3615 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3616 {
3617 common->acceptlabel = save_acceptlabel;
3618 common->accept = save_accept;
3619 return NULL;
3620 }
3621 common->acceptlabel = LABEL();
3622 if (common->accept != NULL)
3623 set_jumps(common->accept, common->acceptlabel);
3624
3625 if (framesize < 0)
3626 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3627
3628 if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
3629 {
3630 /* We know that STR_PTR was stored on the top of the stack. */
3631 if (conditional)
3632 {
3633 if (framesize < 0)
3634 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3635 else
3636 {
3637 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3638 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), (framesize + 1) * sizeof(sljit_w));
3639 }
3640 }
3641 else if (bra == OP_BRAZERO)
3642 {
3643 if (framesize < 0)
3644 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3645 else
3646 {
3647 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3648 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
3649 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
3650 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_w));
3651 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
3652 }
3653 OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3654 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3655 }
3656 else if (bra == OP_BRAMINZERO)
3657 {
3658 if (framesize >= 0)
3659 {
3660 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3661 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
3662 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
3663 }
3664 }
3665 }
3666 add_jump(compiler, found, JUMP(SLJIT_JUMP));
3667
3668 compile_fallbackpath(common, altfallback.top);
3669 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3670 {
3671 common->acceptlabel = save_acceptlabel;
3672 common->accept = save_accept;
3673 return NULL;
3674 }
3675 set_jumps(altfallback.topfallbacks, LABEL());
3676
3677 if (*cc != OP_ALT)
3678 break;
3679
3680 ccbegin = cc;
3681 cc += GET(cc, 1);
3682 }
3683 /* None of them matched. */
3684
3685 if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
3686 {
3687 /* Assert is failed. */
3688 if (conditional || bra == OP_BRAZERO)
3689 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3690 if (framesize < 0)
3691 {
3692 /* The topmost item should be 0. */
3693 if (bra == OP_BRAZERO)
3694 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3695 else
3696 free_stack(common, 1);
3697 }
3698 else
3699 {
3700 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3701 if (framesize > 0)
3702 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
3703 /* The topmost item should be 0. */
3704 if (bra == OP_BRAZERO)
3705 {
3706 free_stack(common, framesize + 1);
3707 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3708 }
3709 else
3710 free_stack(common, framesize + 2);
3711 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
3712 if (framesize > 0)
3713 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0);
3714 }
3715 jump = JUMP(SLJIT_JUMP);
3716 if (bra != OP_BRAZERO)
3717 add_jump(compiler, target, jump);
3718
3719 /* Assert is successful. */
3720 set_jumps(tmp, LABEL());
3721 if (framesize < 0)
3722 {
3723 /* We know that STR_PTR was stored on the top of the stack. */
3724 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3725 /* Keep the STR_PTR on the top of the stack. */
3726 if (bra == OP_BRAZERO)
3727 OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3728 else if (bra == OP_BRAMINZERO)
3729 {
3730 OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3731 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3732 }
3733 }
3734 else
3735 {
3736 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3737 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), (framesize + 1) * sizeof(sljit_w));
3738 if (bra == OP_BRAZERO)
3739 {
3740 allocate_stack(common, 1);
3741 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3742 }
3743 else if (bra == OP_BRAMINZERO)
3744 {
3745 allocate_stack(common, 1);
3746 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3747 }
3748 }
3749
3750 if (bra == OP_BRAZERO)
3751 {
3752 fallback->hotpath = LABEL();
3753 sljit_set_label(jump, fallback->hotpath);
3754 }
3755 else if (bra == OP_BRAMINZERO)
3756 {
3757 JUMPTO(SLJIT_JUMP, fallback->hotpath);
3758 JUMPHERE(brajump);
3759 if (framesize >= 0)
3760 {
3761 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3762 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
3763 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
3764 }
3765 set_jumps(fallback->common.topfallbacks, LABEL());
3766 }
3767 }
3768 else
3769 {
3770 /* AssertNot is successful. */
3771 if (framesize < 0)
3772 {
3773 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3774 if (bra != OP_BRA)
3775 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3776 else
3777 free_stack(common, 1);
3778 }
3779 else
3780 {
3781 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3782 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3783 if (framesize > 0)
3784 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
3785 /* The topmost item should be 0. */
3786 if (bra != OP_BRA)
3787 {
3788 free_stack(common, framesize + 1);
3789 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3790 }
3791 else
3792 free_stack(common, framesize + 2);
3793 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
3794 if (framesize > 0)
3795 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0);
3796 }
3797
3798 if (bra == OP_BRAZERO)
3799 fallback->hotpath = LABEL();
3800 else if (bra == OP_BRAMINZERO)
3801 {
3802 JUMPTO(SLJIT_JUMP, fallback->hotpath);
3803 JUMPHERE(brajump);
3804 }
3805
3806 if (bra != OP_BRA)
3807 {
3808 SLJIT_ASSERT(found == &fallback->common.topfallbacks);
3809 set_jumps(fallback->common.topfallbacks, LABEL());
3810 fallback->common.topfallbacks = NULL;
3811 }
3812 }
3813
3814 common->acceptlabel = save_acceptlabel;
3815 common->accept = save_accept;
3816 return cc + 1 + LINK_SIZE;
3817 }
3818
3819 /*
3820 Handling bracketed expressions is probably the most complex part.
3821
3822 Stack layout naming characters:
3823 S - Push the current STR_PTR
3824 0 - Push a 0 (NULL)
3825 A - Push the current STR_PTR. Needed for restoring the STR_PTR
3826 before the next alternative. Not pushed if there are no alternatives.
3827 M - Any values pushed by the current alternative. Can be empty, or anything.
3828 C - Push the previous OVECTOR(i), OVECTOR(i+1), MAX_INDEX and OVECTOR_PRIV(i) to the stack.
3829 L - Push the previous local (pointed by localptr) to the stack
3830 () - opional values stored on the stack
3831 ()* - optonal, can be stored multiple times
3832
3833 The following list shows the regular expression templates, their PCRE byte codes
3834 and stack layout supported by pcre-sljit.
3835
3836 (?:) OP_BRA | OP_KET A M
3837 () OP_CBRA | OP_KET C M
3838 (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*
3839 OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*
3840 (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*
3841 OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*
3842 ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*
3843 OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*
3844 ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*
3845 OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*
3846 (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )
3847 (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )
3848 ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )
3849 ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )
3850 (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*
3851 OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*
3852 (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*
3853 OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*
3854 ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*
3855 OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*
3856 ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*
3857 OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*
3858
3859
3860 Stack layout naming characters:
3861 A - Push the alternative index (starting from 0) on the stack.
3862 Not pushed if there is no alternatives.
3863 M - Any values pushed by the current alternative. Can be empty, or anything.
3864
3865 The next list shows the possible content of a bracket:
3866 (|) OP_*BRA | OP_ALT ... M A
3867 (?()|) OP_*COND | OP_ALT M A
3868 (?>|) OP_ONCE | OP_ALT ... [stack trace] M A
3869 Or nothing, if trace is unnecessary
3870 */
3871
3872 static uschar *compile_bracket_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
3873 {
3874 DEFINE_COMPILER;
3875 fallback_common *fallback;
3876 uschar opcode;
3877 int localptr = 0;
3878 int offset = 0;
3879 int stacksize;
3880 uschar *ccbegin;
3881 uschar *hotpath;
3882 uschar bra = OP_BRA;
3883 uschar ket;
3884 assert_fallback *assert;
3885 BOOL has_alternatives;
3886 struct sljit_jump *jump;
3887 struct sljit_jump *skip;
3888 struct sljit_label *rmaxlabel = NULL;
3889 struct sljit_jump *braminzerojump = NULL;
3890
3891 PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL);
3892
3893 if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
3894 {
3895 bra = *cc;
3896 cc++;
3897 opcode = *cc;
3898 }
3899
3900 opcode = *cc;
3901 ccbegin = cc;
3902 if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
3903 {
3904 /* Drop this bracket_fallback. */
3905 parent->top = fallback->prev;
3906 return bracketend(cc);
3907 }
3908
3909 ket = *(bracketend(cc) - 1 - LINK_SIZE);
3910 SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
3911 SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));
3912 cc += GET(cc, 1);
3913 has_alternatives = *cc == OP_ALT || opcode == OP_COND || opcode == OP_SCOND;
3914 if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
3915 opcode = OP_SCOND;
3916
3917 if (opcode == OP_CBRA || opcode == OP_SCBRA)
3918 {
3919 /* Capturing brackets has a pre-allocated space. */
3920 offset = GET2(ccbegin, 1 + LINK_SIZE);
3921 localptr = OVECTOR_PRIV(offset);
3922 offset <<= 1;
3923 FALLBACK_AS(bracket_fallback)->localptr = localptr;
3924 }
3925 else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)
3926 {
3927 /* Other brackets simply allocate the next entry. */
3928 localptr = PRIV(ccbegin);
3929 SLJIT_ASSERT(localptr != 0);
3930 FALLBACK_AS(bracket_fallback)->localptr = localptr;
3931 if (opcode == OP_ONCE)
3932 FALLBACK_AS(bracket_fallback)->u.framesize = get_framesize(common, ccbegin, FALSE);
3933 }
3934
3935 /* Instructions before the first alternative. */
3936 stacksize = 0;
3937 if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
3938 stacksize++;
3939 if (bra == OP_BRAZERO)
3940 stacksize++;
3941
3942 if (stacksize > 0)
3943 allocate_stack(common, stacksize);
3944
3945 stacksize = 0;
3946 if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
3947 {
3948 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
3949 stacksize++;
3950 }
3951
3952 if (bra == OP_BRAZERO)
3953 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
3954
3955 if (bra == OP_BRAMINZERO)
3956 {
3957 /* This is a fallback path! (Since the hot-path of OP_BRAMINZERO matches to the empty string) */
3958 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3959 if (ket != OP_KETRMIN)
3960 {
3961 free_stack(common, 1);
3962 braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3963 }
3964 else
3965 {
3966 if (opcode == OP_ONCE || opcode >= OP_SBRA)
3967 {
3968 jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3969 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3970 /* Nothing stored during the first run. */
3971 skip = JUMP(SLJIT_JUMP);
3972 JUMPHERE(jump);
3973 /* Checking zero-length iteration. */
3974 if (opcode != OP_ONCE || FALLBACK_AS(bracket_fallback)->u.framesize < 0)
3975 {
3976 /* When we come from outside, localptr contains the previous STR_PTR. */
3977 braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3978 }
3979 else
3980 {
3981 /* Except when the whole stack frame must be saved. */
3982 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3983 braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w));
3984 }
3985 JUMPHERE(skip);
3986 }
3987 else
3988 {
3989 jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3990 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3991 JUMPHERE(jump);
3992 }
3993 }
3994 }
3995
3996 if (ket == OP_KETRMIN)
3997 FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();
3998
3999 if (ket == OP_KETRMAX)
4000 {
4001 rmaxlabel = LABEL();
4002 if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)
4003 FALLBACK_AS(bracket_fallback)->althotpath = rmaxlabel;
4004 }
4005
4006 /* Handling capturing brackets and alternatives. */
4007 if (opcode == OP_ONCE)
4008 {
4009 if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)
4010 {
4011 /* Neither capturing brackets nor recursions are not found in the block. */
4012 if (ket == OP_KETRMIN)
4013 {
4014 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4015 allocate_stack(common, 2);
4016 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4017 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4018 OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
4019 }
4020 else if (ket == OP_KETRMAX || has_alternatives)
4021 {
4022 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4023 allocate_stack(common, 1);
4024 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4025 }
4026 else
4027 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4028 }
4029 else
4030 {
4031 if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives)
4032 {
4033 allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 2);
4034 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4035 OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize + 1));
4036 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4037 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4038 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
4039 init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize + 1, 2, FALSE);
4040 }
4041 else
4042 {
4043 allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 1);
4044 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4045 OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize));
4046 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4047 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4048 init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize, 1, FALSE);
4049 }
4050 }
4051 }
4052 else if (opcode == OP_CBRA || opcode == OP_SCBRA)
4053 {
4054 /* Saving the previous values. */
4055 allocate_stack(common, 4);
4056 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
4057 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
4058 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4059 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4060 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4061 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), MAX_INDEX, 0);
4062 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
4063 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), TMP1, 0);
4064 /* Update MAX_INDEX if necessary. */
4065 add_stub(common, max_index, (offset >> 1) + 1, CMP(SLJIT_C_LESS, MAX_INDEX, 0, SLJIT_IMM, (offset >> 1) + 1));
4066 }
4067 else if (opcode == OP_SBRA || opcode == OP_SCOND)
4068 {
4069 /* Saving the previous value. */
4070 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4071 allocate_stack(common, 1);
4072 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
4073 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
4074 }
4075 else if (has_alternatives)
4076 {
4077 /* Pushing the starting string pointer. */
4078 allocate_stack(common, 1);
4079 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4080 }
4081
4082 /* Generating code for the first alternative. */
4083 hotpath = ccbegin + 1 + LINK_SIZE;
4084 if (offset != 0)
4085 hotpath += 2;
4086 if (opcode == OP_COND || opcode == OP_SCOND)
4087 {
4088 if (*hotpath == OP_CREF)
4089 {
4090 add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed),
4091 CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR((GET2(hotpath, 1) << 1)), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
4092 hotpath += 3;
4093 }
4094 else
4095 {
4096 SLJIT_ASSERT(*hotpath >= OP_ASSERT && *hotpath <= OP_ASSERTBACK_NOT);
4097 /* Similar code as PUSH_FALLBACK macro. */
4098 assert = sljit_alloc_memory(compiler, sizeof(assert_fallback));
4099 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4100 return NULL;
4101 memset(assert, 0, sizeof(assert_fallback));
4102 assert->common.cc = hotpath;
4103 FALLBACK_AS(bracket_fallback)->u.assert = assert;
4104 hotpath = compile_assert_hotpath(common, hotpath, assert, TRUE);
4105 }
4106 }
4107
4108 compile_hotpath(common, hotpath, cc, fallback);
4109 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4110 return NULL;
4111
4112 if (opcode == OP_ONCE)
4113 {
4114 if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)
4115 {
4116 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4117 /* TMP2 which is set here used by OP_KETRMAX below. */
4118 if (ket == OP_KETRMAX)
4119 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
4120 else if (ket == OP_KETRMIN)
4121 {
4122 /* Move the STR_PTR to the localptr. */
4123 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
4124 }
4125 }
4126 else if (ket == OP_KETRMAX)
4127 {
4128 /* TMP2 which is set here used by OP_KETRMAX below. */
4129 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4130 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w));
4131 }
4132 }
4133
4134 stacksize = 0;
4135 if (ket != OP_KET || bra != OP_BRA)
4136 stacksize++;
4137 if (has_alternatives && opcode != OP_ONCE)
4138 stacksize++;
4139
4140 if (stacksize > 0)
4141 allocate_stack(common, stacksize);
4142
4143 stacksize = 0;
4144 if (ket != OP_KET)
4145 {
4146 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
4147 stacksize++;
4148 }
4149 else if (bra != OP_BRA)
4150 {
4151 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
4152 stacksize++;
4153 }
4154
4155 if (has_alternatives)
4156 {
4157 if (opcode != OP_ONCE)
4158 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
4159 if (ket != OP_KETRMAX)
4160 FALLBACK_AS(bracket_fallback)->althotpath = LABEL();
4161 }
4162
4163 /* Must be after the hotpath label. */
4164 if (offset != 0)
4165 {
4166 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4167 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
4168 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
4169 }
4170
4171 if (ket == OP_KETRMAX)
4172 {
4173 if (opcode == OP_ONCE || opcode >= OP_SBRA)
4174 {
4175 if (has_alternatives)
4176 FALLBACK_AS(bracket_fallback)->althotpath = LABEL();
4177 /* Checking zero-length iteration. */
4178 if (opcode != OP_ONCE)
4179 CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel);
4180 else
4181 /* TMP2 must contain the starting STR_PTR. */
4182 CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel);
4183 }
4184 else
4185 JUMPTO(SLJIT_JUMP, rmaxlabel);
4186 FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();
4187 }
4188
4189 if (bra == OP_BRAZERO)
4190 FALLBACK_AS(bracket_fallback)->zerohotpath = LABEL();
4191
4192 if (bra == OP_BRAMINZERO)
4193 {
4194 /* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */
4195 JUMPTO(SLJIT_JUMP, ((braminzero_fallback*)parent)->hotpath);
4196 if (braminzerojump != NULL)
4197 {
4198 JUMPHERE(braminzerojump);
4199 /* We need to release the end pointer to perform the
4200 fallback for the zero-length iteration. When
4201 framesize is < 0, OP_ONCE will do the release itself. */
4202 if (opcode == OP_ONCE && FALLBACK_AS(bracket_fallback)->u.framesize >= 0)
4203 {
4204 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4205 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
4206 }
4207 else if (ket == OP_KETRMIN && opcode != OP_ONCE)
4208 free_stack(common, 1);
4209 }
4210 /* Continue to the normal fallback. */
4211 }
4212
4213 /* Skip the other alternatives. */
4214 while (*cc == OP_ALT)
4215 cc += GET(cc, 1);
4216 cc += 1 + LINK_SIZE;
4217 return cc;
4218 }
4219
4220 static uschar *compile_bracketpos_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
4221 {
4222 DEFINE_COMPILER;
4223 fallback_common *fallback;
4224 uschar opcode;
4225 int localptr;
4226 int cbraprivptr = 0;
4227 int framesize;
4228 int stacksize;
4229 int offset = 0;
4230 BOOL zero = FALSE;
4231 uschar *ccbegin = NULL;
4232 int stack;
4233 struct sljit_label *loop = NULL;
4234 struct jump_list *emptymatch = NULL;
4235
4236 PUSH_FALLBACK(sizeof(bracketpos_fallback), cc, NULL);
4237 if (*cc == OP_BRAPOSZERO)
4238 {
4239 zero = TRUE;
4240 cc++;
4241 }
4242
4243 opcode = *cc;
4244 localptr = PRIV(cc);
4245 SLJIT_ASSERT(localptr != 0);
4246 FALLBACK_AS(bracketpos_fallback)->localptr = localptr;
4247 switch(opcode)
4248 {
4249 case OP_BRAPOS:
4250 case OP_SBRAPOS:
4251 ccbegin = cc + 1 + LINK_SIZE;
4252 break;
4253
4254 case OP_CBRAPOS:
4255 case OP_SCBRAPOS:
4256 offset = GET2(cc, 1 + LINK_SIZE);
4257 cbraprivptr = OVECTOR_PRIV(offset);
4258 offset <<= 1;
4259 ccbegin = cc + 1 + LINK_SIZE + 2;
4260 break;
4261
4262 default:
4263 SLJIT_ASSERT_STOP();
4264 break;
4265 }
4266
4267 framesize = get_framesize(common, cc, FALSE);
4268 FALLBACK_AS(bracketpos_fallback)->framesize = framesize;
4269 if (framesize < 0)
4270 {
4271 stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 3 : 1;
4272 if (!zero)
4273 stacksize++;
4274 FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;
4275 allocate_stack(common, stacksize);
4276 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4277
4278 if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4279 {
4280 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
4281 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
4282 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4283 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4284 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), MAX_INDEX, 0);
4285 }
4286 else
4287 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4288
4289 if (!zero)
4290 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 1);
4291 }
4292 else
4293 {
4294 stacksize = framesize + 1;
4295 if (!zero)
4296 stacksize++;
4297 if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
4298 stacksize++;
4299 FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;
4300 allocate_stack(common, stacksize);
4301
4302 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4303 OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1));
4304 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4305 stack = 0;
4306 if (!zero)
4307 {
4308 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1);
4309 stack++;
4310 }
4311 if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
4312 {
4313 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0);
4314 stack++;
4315 }
4316 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0);
4317 init_frame(common, cc, stacksize - 1, stacksize - framesize, FALSE);
4318 }
4319
4320 if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4321 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
4322
4323 loop = LABEL();
4324 while (*cc != OP_KETRPOS)
4325 {
4326 fallback->top = NULL;
4327 fallback->topfallbacks = NULL;
4328 cc += GET(cc, 1);
4329
4330 compile_hotpath(common, ccbegin, cc, fallback);
4331 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4332 return NULL;
4333
4334 if (framesize < 0)
4335 {
4336 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4337
4338 if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4339 {
4340 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
4341 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
4342 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
4343 add_stub(common, max_index, (offset >> 1) + 1, CMP(SLJIT_C_LESS, MAX_INDEX, 0, SLJIT_IMM, (offset >> 1) + 1));
4344 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
4345 }
4346 else
4347 {
4348 if (opcode == OP_SBRAPOS)
4349 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4350 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4351 }
4352
4353 if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
4354 add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0));
4355
4356 if (!zero)
4357 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
4358 }
4359 else
4360 {
4361 if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4362 {
4363 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
4364 if (!zero)
4365 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4366 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
4367 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
4368 add_stub(common, max_index, (offset >> 1) + 1, CMP(SLJIT_C_LESS, MAX_INDEX, 0, SLJIT_IMM, (offset >> 1) + 1));
4369 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0);
4370 }
4371 else
4372 {
4373 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4374 if (opcode == OP_SBRAPOS)
4375 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w));
4376 OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w), STR_PTR, 0);
4377 }
4378
4379 if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS)
4380 add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0));
4381
4382 /* TMP2 must be set above. */
4383 if (!zero)
4384 {
4385 if (framesize < 0)
4386 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0);
4387 else
4388 OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0);
4389 }
4390 }
4391 JUMPTO(SLJIT_JUMP, loop);
4392 flush_stubs(common);
4393
4394 compile_fallbackpath(common, fallback->top);
4395 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4396 return NULL;
4397 set_jumps(fallback->topfallbacks, LABEL());
4398
4399 if (framesize < 0)
4400 {
4401 if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4402 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
4403 else
4404 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4405 }
4406 else
4407 {
4408 if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4409 {
4410 if (*cc == OP_KETRPOS)
4411 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4412 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr);
4413 }
4414 else
4415 {
4416 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4417 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w));
4418 }
4419 }
4420
4421 if (*cc == OP_KETRPOS)
4422 break;
4423 ccbegin = cc + 1 + LINK_SIZE;
4424 }
4425
4426 fallback->topfallbacks = NULL;
4427 if (!zero)
4428 {
4429 if (framesize < 0)
4430 add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0));
4431 else /* TMP2 is set to [localptr] above. */
4432 add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0));
4433 }
4434
4435 /* None of them matched. */
4436 set_jumps(emptymatch, LABEL());
4437 return cc + 1 + LINK_SIZE;
4438 }
4439
4440 static SLJIT_INLINE uschar *get_iterator_parameters(compiler_common *common, uschar *cc, uschar *opcode, uschar *type, int *arg1, int *arg2, uschar **end)
4441 {
4442 int class_len;
4443
4444 *opcode = *cc;
4445 if (*opcode >= OP_STAR && *opcode <= OP_POSUPTO)
4446 {
4447 cc++;
4448 *type = OP_CHAR;
4449 }
4450 else if (*opcode >= OP_STARI && *opcode <= OP_POSUPTOI)
4451 {
4452 cc++;
4453 *type = OP_CHARI;
4454 *opcode -= OP_STARI - OP_STAR;
4455 }
4456 else if (*opcode >= OP_NOTSTAR && *opcode <= OP_NOTPOSUPTO)
4457 {
4458 cc++;
4459 *type = OP_NOT;
4460 *opcode -= OP_NOTSTAR - OP_STAR;
4461 }
4462 else if (*opcode >= OP_NOTSTARI && *opcode <= OP_NOTPOSUPTOI)
4463 {
4464 cc++;
4465 *type = OP_NOTI;
4466 *opcode -= OP_NOTSTARI - OP_STAR;
4467 }
4468 else if (*opcode >= OP_TYPESTAR && *opcode <= OP_TYPEPOSUPTO)
4469 {
4470 cc++;
4471 *opcode -= OP_TYPESTAR - OP_STAR;
4472 *type = 0;
4473 }
4474 else
4475 {
4476 SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS);
4477 *type = *opcode;
4478 cc++;
4479 class_len = (*type < OP_XCLASS) ? 33 : GET(cc, 0);
4480 *opcode = cc[class_len - 1];
4481 if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY)
4482 {
4483 *opcode -= OP_CRSTAR - OP_STAR;
4484 if (end != NULL)
4485 *end = cc + class_len;
4486 }
4487 else
4488 {
4489 SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE);
4490 *arg1 = GET2(cc, (class_len + 2));
4491 *arg2 = GET2(cc, class_len);
4492
4493 if (*arg2 == 0)
4494 {
4495 SLJIT_ASSERT(*arg1 != 0);
4496 *opcode = (*opcode == OP_CRRANGE) ? OP_UPTO : OP_MINUPTO;
4497 }
4498 if (*arg1 == *arg2)
4499 *opcode = OP_EXACT;
4500
4501 if (end != NULL)
4502 *end = cc + class_len + 4;
4503 }
4504 return cc;
4505 }
4506
4507 if (*opcode == OP_UPTO || *opcode == OP_MINUPTO || *opcode == OP_EXACT || *opcode == OP_POSUPTO)
4508 {
4509 *arg1 = GET2(cc, 0);
4510 cc += 2;
4511 }
4512
4513 if (*type == 0)
4514 {
4515 *type = *cc;
4516 if (end != NULL)
4517 *end = next_opcode(common, cc);
4518 cc++;
4519 return cc;
4520 }
4521
4522 if (end != NULL)
4523 {
4524 *end = cc + 1;
4525 #ifdef SUPPORT_UTF8
4526 if (common->utf8 && *cc >= 0xc0) *end += _pcre_utf8_table4[*cc & 0x3f];
4527 #endif
4528 }
4529 return cc;
4530 }
4531
4532 static uschar *compile_iterator_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
4533 {
4534 DEFINE_COMPILER;
4535 fallback_common *fallback;
4536 uschar opcode;
4537 uschar type;
4538 int arg1 = -1, arg2 = -1;
4539 uschar* end;
4540 jump_list *nomatch = NULL;
4541 struct sljit_jump *jump = NULL;
4542 struct sljit_label *label;
4543
4544 PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL);
4545
4546 cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end);
4547
4548 switch(opcode)
4549 {
4550 case OP_STAR:
4551 case OP_PLUS:
4552 case OP_UPTO:
4553 case OP_CRRANGE:
4554 if (type == OP_ANYNL || type == OP_EXTUNI)
4555 {
4556 if (opcode == OP_STAR || opcode == OP_UPTO)
4557 {
4558 allocate_stack(common, 2);
4559 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4560 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
4561 }
4562 else
4563 {
4564 allocate_stack(common, 1);
4565 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4566 }
4567 if (opcode == OP_UPTO || opcode == OP_CRRANGE)
4568 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
4569
4570 label = LABEL();
4571 compile_char1_hotpath(common, type, cc, &fallback->topfallbacks);
4572 if (opcode == OP_UPTO || opcode == OP_CRRANGE)
4573 {
4574 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
4575 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
4576 if (opcode == OP_CRRANGE && arg2 > 0)
4577 CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2, label);
4578 if (opcode == OP_UPTO || (opcode == OP_CRRANGE && arg1 > 0))
4579 jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, arg1);
4580 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
4581 }
4582
4583 allocate_stack(common, 1);
4584 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4585 JUMPTO(SLJIT_JUMP, label);
4586 if (jump != NULL)
4587 JUMPHERE(jump);
4588 }
4589 else
4590 {
4591 allocate_stack(common, 2);
4592 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4593 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
4594 label = LABEL();
4595 compile_char1_hotpath(common, type, cc, &nomatch);
4596 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4597 if (opcode <= OP_PLUS || (opcode == OP_CRRANGE && arg1 == 0))
4598 {
4599 OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
4600 JUMPTO(SLJIT_JUMP, label);
4601 }
4602 else
4603 {
4604 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
4605 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
4606 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
4607 CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
4608 }
4609 set_jumps(nomatch, LABEL());
4610 if (opcode == OP_PLUS || opcode == OP_CRRANGE)
4611 add_jump(compiler, &fallback->topfallbacks,
4612 CMP(SLJIT_C_LESS, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, opcode == OP_PLUS ? 2 : arg2 + 1));
4613 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
4614 }
4615 FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
4616 break;
4617
4618 case OP_MINSTAR:
4619 case OP_MINPLUS:
4620 allocate_stack(common, 1);
4621 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4622 if (opcode == OP_MINPLUS)
4623 add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
4624 FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
4625 break;
4626
4627 case OP_MINUPTO:
4628 case OP_CRMINRANGE:
4629 allocate_stack(common, 2);
4630 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4631 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
4632 if (opcode == OP_CRMINRANGE)
4633 add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
4634 FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
4635 break;
4636
4637 case OP_QUERY:
4638 case OP_MINQUERY:
4639 allocate_stack(common, 1);
4640 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4641 if (opcode == OP_QUERY)
4642 compile_char1_hotpath(common, type, cc, &fallback->topfallbacks);
4643 FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
4644 break;
4645
4646 case OP_EXACT:
4647 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
4648 label = LABEL();
4649 compile_char1_hotpath(common, type, cc, &fallback->topfallbacks);
4650 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
4651 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
4652 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
4653 CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
4654 break;
4655
4656 case OP_POSSTAR:
4657 case OP_POSPLUS:
4658 case OP_POSUPTO:
4659 if (opcode != OP_POSSTAR)
4660 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 1);
4661 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
4662 label = LABEL();
4663 compile_char1_hotpath(common, type, cc, &nomatch);
4664 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
4665 if (opcode != OP_POSUPTO)
4666 {
4667 if (opcode == OP_POSPLUS)
4668 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2);
4669 JUMPTO(SLJIT_JUMP, label);
4670 }
4671 else
4672 {
4673 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
4674 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
4675 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
4676 CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 1, label);
4677 }
4678 set_jumps(nomatch, LABEL());
4679 if (opcode == OP_POSPLUS)
4680 add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_LESS, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 2));
4681 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
4682 break;
4683
4684 case OP_POSQUERY:
4685 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
4686 compile_char1_hotpath(common, type, cc, &nomatch);
4687 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STR_PTR, 0);
4688 set_jumps(nomatch, LABEL());
4689 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1);
4690 break;
4691
4692 default:
4693 SLJIT_ASSERT_STOP();
4694 break;
4695 }
4696
4697 return end;
4698 }
4699
4700 static SLJIT_INLINE uschar *compile_fail_accept_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
4701 {
4702 DEFINE_COMPILER;
4703 fallback_common *fallback;
4704
4705 PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL);
4706
4707 if (*cc == OP_FAIL)
4708 {
4709 add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
4710 return cc + 1;
4711 }
4712
4713 if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL)
4714 {
4715 /* No need to check notempty conditions. */
4716 if (common->acceptlabel == NULL)
4717 add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
4718 else
4719 JUMPTO(SLJIT_JUMP, common->acceptlabel);
4720 return cc + 1;
4721 }
4722
4723 if (common->acceptlabel == NULL)
4724 add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)));
4725 else
4726 CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->acceptlabel);
4727 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
4728 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
4729 add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
4730 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
4731 if (common->acceptlabel == NULL)
4732 add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0));
4733 else
4734 CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->acceptlabel);
4735 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
4736 if (common->acceptlabel == NULL)
4737 add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0));
4738 else
4739 CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel);
4740 add_jump(compiler, &fallback->topfallbacks, JUMP(SLJIT_JUMP));
4741 return cc + 1;
4742 }
4743
4744 static SLJIT_INLINE uschar *compile_close_hotpath(compiler_common *common, uschar *cc)
4745 {
4746 DEFINE_COMPILER;
4747 struct sljit_jump *jump;
4748 int offset = GET2(cc, 1);
4749
4750 /* Data will be discarded anyway... */
4751 if (common->currententry != NULL)
4752 return cc + 3;
4753
4754 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset));
4755 offset <<= 1;
4756 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
4757 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
4758 offset = (offset >> 1) + 1;
4759 jump = CMP(SLJIT_C_GREATER_EQUAL, MAX_INDEX, 0, SLJIT_IMM, offset);
4760 OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, offset);
4761 JUMPHERE(jump);
4762 return cc + 3;
4763 }
4764
4765 static void compile_hotpath(compiler_common *common, uschar *cc, uschar *ccend, fallback_common *parent)
4766 {
4767 DEFINE_COMPILER;
4768 fallback_common *fallback;
4769
4770 while (cc < ccend)
4771 {
4772 switch(*cc)
4773 {
4774 case OP_SOD:
4775 case OP_SOM:
4776 case OP_NOT_WORD_BOUNDARY:
4777 case OP_WORD_BOUNDARY:
4778 case OP_NOT_DIGIT:
4779 case OP_DIGIT:
4780 case OP_NOT_WHITESPACE:
4781 case OP_WHITESPACE:
4782 case OP_NOT_WORDCHAR:
4783 case OP_WORDCHAR:
4784 case OP_ANY:
4785 case OP_ALLANY:
4786 case OP_NOTPROP:
4787 case OP_PROP:
4788 case OP_ANYNL:
4789 case OP_NOT_HSPACE:
4790 case OP_HSPACE:
4791 case OP_NOT_VSPACE:
4792 case OP_VSPACE:
4793 case OP_EXTUNI:
4794 case OP_EODN:
4795 case OP_EOD:
4796 case OP_CIRC:
4797 case OP_CIRCM:
4798 case OP_DOLL:
4799 case OP_DOLLM:
4800 case OP_NOT:
4801 case OP_NOTI:
4802 case OP_REVERSE:
4803 cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
4804 break;
4805
4806 case OP_SET_SOM:
4807 PUSH_FALLBACK_NOVALUE(sizeof(fallback_common), cc);
4808 allocate_stack(common, 1);
4809 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
4810 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
4811 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4812 cc++;
4813 break;
4814
4815 case OP_CHAR:
4816 case OP_CHARI:
4817 cc = compile_charn_hotpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
4818 break;
4819
4820 case OP_STAR:
4821 case OP_MINSTAR:
4822 case OP_PLUS:
4823 case OP_MINPLUS:
4824 case OP_QUERY:
4825 case OP_MINQUERY:
4826 case OP_UPTO:
4827 case OP_MINUPTO:
4828 case OP_EXACT:
4829 case OP_POSSTAR:
4830 case OP_POSPLUS:
4831 case OP_POSQUERY:
4832 case OP_POSUPTO:
4833 case OP_STARI:
4834 case OP_MINSTARI:
4835 case OP_PLUSI:
4836 case OP_MINPLUSI:
4837 case OP_QUERYI:
4838 case OP_MINQUERYI:
4839 case OP_UPTOI:
4840 case OP_MINUPTOI:
4841 case OP_EXACTI:
4842 case OP_POSSTARI:
4843 case OP_POSPLUSI:
4844 case OP_POSQUERYI:
4845 case OP_POSUPTOI:
4846 case OP_NOTSTAR:
4847 case OP_NOTMINSTAR:
4848 case OP_NOTPLUS:
4849 case OP_NOTMINPLUS:
4850 case OP_NOTQUERY:
4851 case OP_NOTMINQUERY:
4852 case OP_NOTUPTO:
4853 case OP_NOTMINUPTO:
4854 case OP_NOTEXACT:
4855 case OP_NOTPOSSTAR:
4856 case OP_NOTPOSPLUS:
4857 case OP_NOTPOSQUERY:
4858 case OP_NOTPOSUPTO:
4859 case OP_NOTSTARI:
4860 case OP_NOTMINSTARI:
4861 case OP_NOTPLUSI:
4862 case OP_NOTMINPLUSI:
4863 case OP_NOTQUERYI:
4864 case OP_NOTMINQUERYI:
4865 case OP_NOTUPTOI:
4866 case OP_NOTMINUPTOI:
4867 case OP_NOTEXACTI:
4868 case OP_NOTPOSSTARI:
4869 case OP_NOTPOSPLUSI:
4870 case OP_NOTPOSQUERYI:
4871 case OP_NOTPOSUPTOI:
4872 case OP_TYPESTAR:
4873 case OP_TYPEMINSTAR:
4874 case OP_TYPEPLUS:
4875 case OP_TYPEMINPLUS:
4876 case OP_TYPEQUERY:
4877 case OP_TYPEMINQUERY:
4878 case OP_TYPEUPTO:
4879 case OP_TYPEMINUPTO:
4880 case OP_TYPEEXACT:
4881 case OP_TYPEPOSSTAR:
4882 case OP_TYPEPOSPLUS:
4883 case OP_TYPEPOSQUERY:
4884 case OP_TYPEPOSUPTO:
4885 cc = compile_iterator_hotpath(common, cc, parent);
4886 break;
4887
4888 case OP_CLASS:
4889 case OP_NCLASS:
4890 if (cc[33] >= OP_CRSTAR && cc[33] <= OP_CRMINRANGE)
4891 cc = compile_iterator_hotpath(common, cc, parent);
4892 else
4893 cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
4894 break;
4895
4896 #ifdef SUPPORT_UTF8
4897 case OP_XCLASS:
4898 if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE)
4899 cc = compile_iterator_hotpath(common, cc, parent);
4900 else
4901 cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks);
4902 break;
4903 #endif
4904
4905 case OP_REF:
4906 case OP_REFI:
4907 if (cc[3] >= OP_CRSTAR && cc[3] <= OP_CRMINRANGE)
4908 cc = compile_ref_iterator_hotpath(common, cc, parent);
4909 else
4910 cc = compile_ref_hotpath(common, cc, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks, TRUE, FALSE);
4911 break;
4912
4913 case OP_RECURSE:
4914 cc = compile_recurse_hotpath(common, cc, parent);
4915 break;
4916
4917 case OP_ASSERT:
4918 case OP_ASSERT_NOT:
4919 case OP_ASSERTBACK:
4920 case OP_ASSERTBACK_NOT:
4921 PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc);
4922 cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE);
4923 break;
4924
4925 case OP_BRAMINZERO:
4926 PUSH_FALLBACK_NOVALUE(sizeof(braminzero_fallback), cc);
4927 cc = bracketend(cc + 1);
4928 if (*(cc - 1 - LINK_SIZE) != OP_KETRMIN)
4929 {
4930 allocate_stack(common, 1);
4931 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4932 }
4933 else
4934 {
4935 allocate_stack(common, 2);
4936 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
4937 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0);
4938 }
4939 FALLBACK_AS(braminzero_fallback)->hotpath = LABEL();
4940 break;
4941
4942 case OP_ONCE:
4943 case OP_BRA:
4944 case OP_CBRA:
4945 case OP_COND:
4946 case OP_SBRA:
4947 case OP_SCBRA:
4948 case OP_SCOND:
4949 cc = compile_bracket_hotpath(common, cc, parent);
4950 break;
4951
4952 case OP_BRAZERO:
4953 if (cc[1] > OP_ASSERTBACK_NOT)
4954 cc = compile_bracket_hotpath(common, cc, parent);
4955 else
4956 {
4957 PUSH_FALLBACK_NOVALUE(sizeof(assert_fallback), cc);
4958 cc = compile_assert_hotpath(common, cc, FALLBACK_AS(assert_fallback), FALSE);
4959 }
4960 break;
4961
4962 case OP_BRAPOS:
4963 case OP_CBRAPOS:
4964 case OP_SBRAPOS:
4965 case OP_SCBRAPOS:
4966 case OP_BRAPOSZERO:
4967 cc = compile_bracketpos_hotpath(common, cc, parent);
4968 break;
4969
4970 case OP_FAIL:
4971 case OP_ACCEPT:
4972 case OP_ASSERT_ACCEPT:
4973 cc = compile_fail_accept_hotpath(common, cc, parent);
4974 break;
4975
4976 case OP_CLOSE:
4977 cc = compile_close_hotpath(common, cc);
4978 break;
4979
4980 case OP_SKIPZERO:
4981 cc = bracketend(cc + 1);
4982 break;
4983
4984 default:
4985 SLJIT_ASSERT_STOP();
4986 return;
4987 }
4988 if (cc == NULL)
4989 return;
4990 }
4991 SLJIT_ASSERT(cc == ccend);
4992 }
4993
4994 #undef PUSH_FALLBACK
4995 #undef PUSH_FALLBACK_NOVALUE
4996 #undef FALLBACK_AS
4997
4998 #define COMPILE_FALLBACKPATH(current) \
4999 do \
5000 { \
5001 compile_fallbackpath(common, (current)); \
5002 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
5003 return; \
5004 } \
5005 while (0)
5006
5007 #define CURRENT_AS(type) ((type*)current)
5008
5009 static void compile_iterator_fallbackpath(compiler_common *common, struct fallback_common *current)
5010 {
5011 DEFINE_COMPILER;
5012 uschar *cc = current->cc;
5013 uschar opcode;
5014 uschar type;
5015 int arg1 = -1, arg2 = -1;
5016 struct sljit_label *label = NULL;
5017 struct sljit_jump *jump = NULL;
5018
5019 cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, NULL);
5020
5021 switch(opcode)
5022 {
5023 case OP_STAR:
5024 case OP_PLUS:
5025 case OP_UPTO:
5026 case OP_CRRANGE:
5027 if (type == OP_ANYNL || type == OP_EXTUNI)
5028 {
5029 set_jumps(current->topfallbacks, LABEL());
5030 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5031 free_stack(common, 1);
5032 CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);
5033 }
5034 else
5035 {
5036 if (opcode == OP_STAR || opcode == OP_UPTO)
5037 arg2 = 0;
5038 else if (opcode == OP_PLUS)
5039 arg2 = 1;
5040 jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, arg2 + 1);
5041 OP2(SLJIT_SUB, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
5042 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5043 skip_char_back(common);
5044 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5045 JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
5046 if (opcode == OP_PLUS || opcode == OP_CRRANGE)
5047 set_jumps(current->topfallbacks, LABEL());
5048 JUMPHERE(jump);
5049 free_stack(common, 2);
5050 }
5051 break;
5052
5053 case OP_MINSTAR:
5054 case OP_MINPLUS:
5055 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5056 if (opcode == OP_MINPLUS)
5057 {
5058 set_jumps(current->topfallbacks, LABEL());
5059 current->topfallbacks = NULL;
5060 }
5061 compile_char1_hotpath(common, type, cc, &current->topfallbacks);
5062 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5063 JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
5064 set_jumps(current->topfallbacks, LABEL());
5065 free_stack(common, 1);
5066 break;
5067
5068 case OP_MINUPTO:
5069 case OP_CRMINRANGE:
5070 if (opcode == OP_CRMINRANGE)
5071 {
5072 set_jumps(current->topfallbacks, LABEL());
5073 current->topfallbacks = NULL;
5074 label = LABEL();
5075 }
5076 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5077 compile_char1_hotpath(common, type, cc, &current->topfallbacks);
5078
5079 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5080 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5081 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
5082 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
5083
5084 if (opcode == OP_CRMINRANGE)
5085 CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg2 + 1, label);
5086
5087 if (opcode == OP_CRMINRANGE && arg1 == 0)
5088 JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
5089 else
5090 CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, arg1 + 2, CURRENT_AS(iterator_fallback)->hotpath);
5091
5092 set_jumps(current->topfallbacks, LABEL());
5093 free_stack(common, 2);
5094 break;
5095
5096 case OP_QUERY:
5097 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5098 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5099 CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);
5100 jump = JUMP(SLJIT_JUMP);
5101 set_jumps(current->topfallbacks, LABEL());
5102 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5103 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5104 JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
5105 JUMPHERE(jump);
5106 free_stack(common, 1);
5107 break;
5108
5109 case OP_MINQUERY:
5110 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5111 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5112 jump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
5113 compile_char1_hotpath(common, type, cc, &current->topfallbacks);
5114 JUMPTO(SLJIT_JUMP, CURRENT_AS(iterator_fallback)->hotpath);
5115 set_jumps(current->topfallbacks, LABEL());
5116 JUMPHERE(jump);
5117 free_stack(common, 1);
5118 break;
5119
5120 case OP_EXACT:
5121 case OP_POSPLUS:
5122 set_jumps(current->topfallbacks, LABEL());
5123 break;
5124
5125 case OP_POSSTAR:
5126 case OP_POSQUERY:
5127 case OP_POSUPTO:
5128 break;
5129
5130 default:
5131 SLJIT_ASSERT_STOP();
5132 break;
5133 }
5134 }
5135
5136 static void compile_ref_iterator_fallbackpath(compiler_common *common, struct fallback_common *current)
5137 {
5138 DEFINE_COMPILER;
5139 uschar *cc = current->cc;
5140 uschar type;
5141
5142 type = cc[3];
5143 if ((type & 0x1) == 0)
5144 {
5145 set_jumps(current->topfallbacks, LABEL());
5146 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5147 free_stack(common, 1);
5148 CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);
5149 return;
5150 }
5151
5152 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5153 CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(iterator_fallback)->hotpath);
5154 set_jumps(current->topfallbacks, LABEL());
5155 free_stack(common, 2);
5156 }
5157
5158 static void compile_recurse_fallbackpath(compiler_common *common, struct fallback_common *current)
5159 {
5160 DEFINE_COMPILER;
5161
5162 set_jumps(current->topfallbacks, LABEL());
5163 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5164 free_stack(common, 1);
5165 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
5166 }
5167
5168 static void compile_assert_fallbackpath(compiler_common *common, struct fallback_common *current)
5169 {
5170 DEFINE_COMPILER;
5171 uschar *cc = current->cc;
5172 uschar bra = OP_BRA;
5173 struct sljit_jump *jump;
5174 struct sljit_jump *brajump = NULL;
5175
5176 SLJIT_ASSERT(*cc != OP_BRAMINZERO);
5177 if (*cc == OP_BRAZERO)
5178 {
5179 bra = *cc;
5180 cc++;
5181 }
5182
5183 if (bra == OP_BRAZERO)
5184 {
5185 SLJIT_ASSERT(current->topfallbacks == NULL);
5186 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5187 }
5188
5189 if (CURRENT_AS(assert_fallback)->framesize < 0)
5190 {
5191 set_jumps(current->topfallbacks, LABEL());
5192
5193 if (bra == OP_BRAZERO)
5194 {
5195 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5196 CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_fallback)->hotpath);
5197 free_stack(common, 1);
5198 }
5199 return;
5200 }
5201
5202 if (bra == OP_BRAZERO)
5203 {
5204 if (*cc == OP_ASSERT_NOT || *cc == OP_ASSERTBACK_NOT)
5205 {
5206 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5207 CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(assert_fallback)->hotpath);
5208 free_stack(common, 1);
5209 return;
5210 }
5211 free_stack(common, 1);
5212 brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
5213 }
5214
5215 if (*cc == OP_ASSERT || *cc == OP_ASSERTBACK)
5216 {
5217 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr);
5218 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5219
5220 set_jumps(current->topfallbacks, LABEL());
5221 }
5222 else
5223 {
5224 jump = JUMP(SLJIT_JUMP);
5225
5226 set_jumps(current->topfallbacks, LABEL());
5227 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr);
5228 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5229 JUMPHERE(jump);
5230 }
5231 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(assert_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(assert_fallback)->framesize * sizeof(sljit_w));
5232
5233 if (bra == OP_BRAZERO)
5234 {
5235 /* We know there is enough place on the stack. */
5236 OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
5237 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
5238 JUMPTO(SLJIT_JUMP, CURRENT_AS(assert_fallback)->hotpath);
5239 JUMPHERE(brajump);
5240 }
5241 }
5242
5243 static void compile_bracket_fallbackpath(compiler_common *common, struct fallback_common *current)
5244 {
5245 DEFINE_COMPILER;
5246 int opcode;
5247 int offset = 0;
5248 int localptr = CURRENT_AS(bracket_fallback)->localptr;
5249 int stacksize;
5250 int count;
5251 uschar *cc = current->cc;
5252 uschar *ccbegin;
5253 uschar *ccprev;
5254 jump_list *jumplist = NULL;
5255 jump_list *jumplistitem = NULL;
5256 uschar bra = OP_BRA;
5257 uschar ket;
5258 assert_fallback *assert;
5259 struct sljit_jump *brazero = NULL;
5260 struct sljit_jump *once = NULL;
5261 struct sljit_jump *cond = NULL;
5262 struct sljit_label *rminlabel = NULL;
5263
5264 if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
5265 {
5266 bra = *cc;
5267 cc++;
5268 }
5269
5270 opcode = *cc;
5271 ccbegin = cc;
5272 ket = *(bracketend(ccbegin) - 1 - LINK_SIZE);
5273 cc += GET(cc, 1);
5274 if (opcode == OP_CBRA || opcode == OP_SCBRA)
5275 offset = (GET2(ccbegin, 1 + LINK_SIZE)) << 1;
5276 if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
5277 opcode = OP_SCOND;
5278
5279 if (ket == OP_KETRMAX)
5280 {
5281 if (bra != OP_BRAZERO)
5282 free_stack(common, 1);
5283 else
5284 {
5285 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5286 free_stack(common, 1);
5287 brazero = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0);
5288 }
5289 }
5290 else if (ket == OP_KETRMIN)
5291 {
5292 if (bra != OP_BRAMINZERO)
5293 {
5294 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5295 if (opcode >= OP_SBRA || opcode == OP_ONCE)
5296 {
5297 /* Checking zero-length iteration. */
5298 if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize < 0)
5299 CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, CURRENT_AS(bracket_fallback)->recursivehotpath);
5300 else
5301 {
5302 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5303 CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (CURRENT_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w), CURRENT_AS(bracket_fallback)->recursivehotpath);
5304 }
5305 if (opcode != OP_ONCE)
5306 free_stack(common, 1);
5307 }
5308 else
5309 JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->recursivehotpath);
5310 }
5311 rminlabel = LABEL();
5312 }
5313 else if (bra == OP_BRAZERO)
5314 {
5315 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5316 free_stack(common, 1);
5317 brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
5318 }
5319
5320 if (opcode == OP_ONCE)
5321 {
5322 if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)
5323 {
5324 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5325 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5326 }
5327 once = JUMP(SLJIT_JUMP);
5328 }
5329 else if (*cc == OP_ALT)
5330 {
5331 /* Build a jump list. Get the last successfully matched branch index. */
5332 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5333 free_stack(common, 1);
5334 count = 1;
5335 do
5336 {
5337 /* Append as the last item. */
5338 if (jumplist != NULL)
5339 {
5340 jumplistitem->next = sljit_alloc_memory(compiler, sizeof(jump_list));
5341 jumplistitem = jumplistitem->next;
5342 }
5343 else
5344 {
5345 jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
5346 jumplist = jumplistitem;
5347 }
5348
5349 if (SLJIT_UNLIKELY(!jumplistitem))
5350 return;
5351
5352 jumplistitem->next = NULL;
5353 jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, count++);
5354 cc += GET(cc, 1);
5355 }
5356 while (*cc == OP_ALT);
5357
5358 cc = ccbegin + GET(ccbegin, 1);
5359 }
5360 else if (opcode == OP_COND || opcode == OP_SCOND)
5361 {
5362 /* Always one. */
5363 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5364 free_stack(common, 1);
5365
5366 jumplistitem = sljit_alloc_memory(compiler, sizeof(jump_list));
5367 if (SLJIT_UNLIKELY(!jumplistitem))
5368 return;
5369 jumplist = jumplistitem;
5370 jumplistitem->next = NULL;
5371 jumplistitem->jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 1);
5372 }
5373
5374 COMPILE_FALLBACKPATH(current->top);
5375 if (current->topfallbacks)
5376 set_jumps(current->topfallbacks, LABEL());
5377
5378 if (opcode == OP_COND || opcode == OP_SCOND)
5379 {
5380 /* Conditional block always has at most one alternative. */
5381 if (ccbegin[1 + LINK_SIZE] >= OP_ASSERT && ccbegin[1 + LINK_SIZE] <= OP_ASSERTBACK_NOT)
5382 {
5383 assert = CURRENT_AS(bracket_fallback)->u.assert;
5384 if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK))
5385 {
5386 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr);
5387 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5388 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));
5389 }
5390 cond = JUMP(SLJIT_JUMP);
5391 set_jumps(CURRENT_AS(bracket_fallback)->u.assert->condfailed, LABEL());
5392 }
5393 else
5394 {
5395 cond = JUMP(SLJIT_JUMP);
5396 set_jumps(CURRENT_AS(bracket_fallback)->u.condfailed, LABEL());
5397 }
5398 }
5399
5400 if (*cc == OP_ALT || opcode == OP_COND || opcode == OP_SCOND)
5401 {
5402 count = 1;
5403 do
5404 {
5405 current->top = NULL;
5406 current->topfallbacks = NULL;
5407 current->nextfallbacks = NULL;
5408 if (*cc == OP_ALT)
5409 {
5410 ccprev = cc + 1 + LINK_SIZE;
5411 cc += GET(cc, 1);
5412 if (opcode != OP_COND && opcode != OP_SCOND)
5413 {
5414 if (localptr != 0 && opcode != OP_ONCE)
5415 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5416 else
5417 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5418 }
5419 compile_hotpath(common, ccprev, cc, current);
5420 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
5421 return;
5422 }
5423
5424 /* Instructions after the current alternative is succesfully matched. */
5425 /* There is a similar code in compile_bracket_hotpath. */
5426 if (opcode == OP_ONCE)
5427 {
5428 if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)
5429 {
5430 if (ket == OP_KETRMAX)
5431 {
5432 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5433 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), (CURRENT_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w));
5434 }
5435 }
5436 else
5437 {
5438 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5439 /* The register which is set here used by OP_KETRMAX below. */
5440 if (ket == OP_KETRMAX)
5441 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
5442 else if (ket == OP_KETRMIN)
5443 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
5444 }
5445 }
5446
5447 stacksize = 0;
5448 if (opcode != OP_ONCE)
5449 stacksize++;
5450 if (ket != OP_KET || bra != OP_BRA)
5451 stacksize++;
5452
5453 if (stacksize > 0) {
5454 if (opcode != OP_ONCE || CURRENT_AS(bracket_fallback)->u.framesize >= 0)
5455 allocate_stack(common, stacksize);
5456 else
5457 {
5458 /* We know we have place at least for one item on the top of the stack. */
5459 SLJIT_ASSERT(stacksize == 1);
5460 OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
5461 }
5462 }
5463
5464 stacksize = 0;
5465 if (ket != OP_KET || bra != OP_BRA)
5466 {
5467 if (ket != OP_KET)
5468 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
5469 else
5470 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
5471 stacksize++;
5472 }
5473
5474 if (opcode != OP_ONCE)
5475 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++);
5476
5477 if (offset != 0)
5478 {
5479 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
5480 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
5481 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
5482 }
5483
5484 JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->althotpath);
5485
5486 if (opcode != OP_ONCE)
5487 {
5488 SLJIT_ASSERT(jumplist);
5489 JUMPHERE(jumplist->jump);
5490 jumplist = jumplist->next;
5491 }
5492
5493 COMPILE_FALLBACKPATH(current->top);
5494 if (current->topfallbacks)
5495 set_jumps(current->topfallbacks, LABEL());
5496 SLJIT_ASSERT(!current->nextfallbacks);
5497 }
5498 while (*cc == OP_ALT);
5499 SLJIT_ASSERT(!jumplist);
5500
5501 if (cond != NULL)
5502 {
5503 SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND);
5504 assert = CURRENT_AS(bracket_fallback)->u.assert;
5505 if (assert->framesize >= 0 && (ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT))
5506 {
5507 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr);
5508 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5509 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->localptr, SLJIT_MEM1(STACK_TOP), assert->framesize * sizeof(sljit_w));
5510 }
5511 JUMPHERE(cond);
5512 }
5513
5514 /* Free the STR_PTR. */
5515 if (localptr == 0)
5516 free_stack(common, 1);
5517 }
5518
5519 if (offset != 0)
5520 {
5521 /* Using both tmp register is better for instruction scheduling. */
5522 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5523 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5524 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
5525 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
5526 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(3));
5527 OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
5528 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
5529 free_stack(common, 4);
5530 }
5531 else if (opcode == OP_SBRA || opcode == OP_SCOND)
5532 {
5533 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), STACK(0));
5534 free_stack(common, 1);
5535 }
5536 else if (opcode == OP_ONCE)
5537 {
5538 cc = ccbegin + GET(ccbegin, 1);
5539 if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)
5540 {
5541 /* Reset head and drop saved frame. */
5542 stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1;
5543 if (CURRENT_AS(bracket_fallback)->u.framesize > 0)
5544 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(stacksize));
5545 free_stack(common, CURRENT_AS(bracket_fallback)->u.framesize + stacksize);
5546 if (CURRENT_AS(bracket_fallback)->u.framesize > 0)
5547 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP1, 0);
5548 }
5549 else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN))
5550 {
5551 /* The STR_PTR must be released. */
5552 free_stack(common, 1);
5553 }
5554
5555 JUMPHERE(once);
5556 /* Restore previous localptr */
5557 if (CURRENT_AS(bracket_fallback)->u.framesize >= 0)
5558 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracket_fallback)->u.framesize * sizeof(sljit_w));
5559 else if (ket == OP_KETRMIN)
5560 {
5561 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5562 /* See the comment below. */
5563 free_stack(common, 2);
5564 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
5565 }
5566 }
5567
5568 if (ket == OP_KETRMAX)
5569 {
5570 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5571 CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0, CURRENT_AS(bracket_fallback)->recursivehotpath);
5572 if (bra == OP_BRAZERO)
5573 {
5574 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5575 JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->zerohotpath);
5576 JUMPHERE(brazero);
5577 }
5578 free_stack(common, 1);
5579 }
5580 else if (ket == OP_KETRMIN)
5581 {
5582 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5583
5584 /* OP_ONCE removes everything in case of a fallback, so we don't
5585 need to explicitly release the STR_PTR. The extra release would
5586 affect badly the free_stack(2) above. */
5587 if (opcode != OP_ONCE)
5588 free_stack(common, 1);
5589 CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0, rminlabel);
5590 if (opcode == OP_ONCE)
5591 free_stack(common, bra == OP_BRAMINZERO ? 2 : 1);
5592 else if (bra == OP_BRAMINZERO)
5593 free_stack(common, 1);
5594 }
5595 else if (bra == OP_BRAZERO)
5596 {
5597 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5598 JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_fallback)->zerohotpath);
5599 JUMPHERE(brazero);
5600 }
5601 }
5602
5603 static void compile_bracketpos_fallbackpath(compiler_common *common, struct fallback_common *current)
5604 {
5605 DEFINE_COMPILER;
5606 int offset;
5607 struct sljit_jump *jump;
5608
5609 if (CURRENT_AS(bracketpos_fallback)->framesize < 0)
5610 {
5611 if (*current->cc == OP_CBRAPOS || *current->cc == OP_SCBRAPOS)
5612 {
5613 offset = (GET2(current->cc, 1 + LINK_SIZE)) << 1;
5614 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5615 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
5616 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0);
5617 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0);
5618 OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
5619 }
5620 set_jumps(current->topfallbacks, LABEL());
5621 free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize);
5622 return;
5623 }
5624
5625 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr);
5626 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5627
5628 if (current->topfallbacks)
5629 {
5630 jump = JUMP(SLJIT_JUMP);
5631 set_jumps(current->topfallbacks, LABEL());
5632 /* Drop the stack frame and restore LOCALS_HEAD. */
5633 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(CURRENT_AS(bracketpos_fallback)->stacksize - CURRENT_AS(bracketpos_fallback)->framesize));
5634 free_stack(common, CURRENT_AS(bracketpos_fallback)->stacksize);
5635 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP1, 0);
5636 JUMPHERE(jump);
5637 }
5638 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), CURRENT_AS(bracketpos_fallback)->localptr, SLJIT_MEM1(STACK_TOP), CURRENT_AS(bracketpos_fallback)->framesize * sizeof(sljit_w));
5639 }
5640
5641 static void compile_braminzero_fallbackpath(compiler_common *common, struct fallback_common *current)
5642 {
5643 assert_fallback fallback;
5644
5645 current->top = NULL;
5646 current->topfallbacks = NULL;
5647 current->nextfallbacks = NULL;
5648 if (current->cc[1] > OP_ASSERTBACK_NOT)
5649 {
5650 /* Manual call of compile_bracket_hotpath and compile_bracket_fallbackpath. */
5651 compile_bracket_hotpath(common, current->cc, current);
5652 compile_bracket_fallbackpath(common, current->top);
5653 }
5654 else
5655 {
5656 memset(&fallback, 0, sizeof(fallback));
5657 fallback.common.cc = current->cc;
5658 fallback.hotpath = CURRENT_AS(braminzero_fallback)->hotpath;
5659 /* Manual call of compile_assert_hotpath. */
5660 compile_assert_hotpath(common, current->cc, &fallback, FALSE);
5661 }
5662 SLJIT_ASSERT(!current->nextfallbacks && !current->topfallbacks);
5663 }
5664
5665 static void compile_fallbackpath(compiler_common *common, struct fallback_common *current)
5666 {
5667 DEFINE_COMPILER;
5668
5669 while (current)
5670 {
5671 if (current->nextfallbacks != NULL)
5672 set_jumps(current->nextfallbacks, LABEL());
5673 switch(*current->cc)
5674 {
5675 case OP_SET_SOM:
5676 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5677 free_stack(common, 1);
5678 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP1, 0);
5679 break;
5680
5681 case OP_STAR:
5682 case OP_MINSTAR:
5683 case OP_PLUS:
5684 case OP_MINPLUS:
5685 case OP_QUERY:
5686 case OP_MINQUERY:
5687 case OP_UPTO:
5688 case OP_MINUPTO:
5689 case OP_EXACT:
5690 case OP_POSSTAR:
5691 case OP_POSPLUS:
5692 case OP_POSQUERY:
5693 case OP_POSUPTO:
5694 case OP_STARI:
5695 case OP_MINSTARI:
5696 case OP_PLUSI:
5697 case OP_MINPLUSI:
5698 case OP_QUERYI:
5699 case OP_MINQUERYI:
5700 case OP_UPTOI:
5701 case OP_MINUPTOI:
5702 case OP_EXACTI:
5703 case OP_POSSTARI:
5704 case OP_POSPLUSI:
5705 case OP_POSQUERYI:
5706 case OP_POSUPTOI:
5707 case OP_NOTSTAR:
5708 case OP_NOTMINSTAR:
5709 case OP_NOTPLUS:
5710 case OP_NOTMINPLUS:
5711 case OP_NOTQUERY:
5712 case OP_NOTMINQUERY:
5713 case OP_NOTUPTO:
5714 case OP_NOTMINUPTO:
5715 case OP_NOTEXACT:
5716 case OP_NOTPOSSTAR:
5717 case OP_NOTPOSPLUS:
5718 case OP_NOTPOSQUERY:
5719 case OP_NOTPOSUPTO:
5720 case OP_NOTSTARI:
5721 case OP_NOTMINSTARI:
5722 case OP_NOTPLUSI:
5723 case OP_NOTMINPLUSI:
5724 case OP_NOTQUERYI:
5725 case OP_NOTMINQUERYI:
5726 case OP_NOTUPTOI:
5727 case OP_NOTMINUPTOI:
5728 case OP_NOTEXACTI:
5729 case OP_NOTPOSSTARI:
5730 case OP_NOTPOSPLUSI:
5731 case OP_NOTPOSQUERYI:
5732 case OP_NOTPOSUPTOI:
5733 case OP_TYPESTAR:
5734 case OP_TYPEMINSTAR:
5735 case OP_TYPEPLUS:
5736 case OP_TYPEMINPLUS:
5737 case OP_TYPEQUERY:
5738 case OP_TYPEMINQUERY:
5739 case OP_TYPEUPTO:
5740 case OP_TYPEMINUPTO:
5741 case OP_TYPEEXACT:
5742 case OP_TYPEPOSSTAR:
5743 case OP_TYPEPOSPLUS:
5744 case OP_TYPEPOSQUERY:
5745 case OP_TYPEPOSUPTO:
5746 case OP_CLASS:
5747 case OP_NCLASS:
5748 case OP_XCLASS:
5749 compile_iterator_fallbackpath(common, current);
5750 break;
5751
5752 case OP_REF:
5753 case OP_REFI:
5754 compile_ref_iterator_fallbackpath(common, current);
5755 break;
5756
5757 case OP_RECURSE:
5758 compile_recurse_fallbackpath(common, current);
5759 break;
5760
5761 case OP_ASSERT:
5762 case OP_ASSERT_NOT:
5763 case OP_ASSERTBACK:
5764 case OP_ASSERTBACK_NOT:
5765 compile_assert_fallbackpath(common, current);
5766 break;
5767
5768 case OP_ONCE:
5769 case OP_BRA:
5770 case OP_CBRA:
5771 case OP_COND:
5772 case OP_SBRA:
5773 case OP_SCBRA:
5774 case OP_SCOND:
5775 compile_bracket_fallbackpath(common, current);
5776 break;
5777
5778 case OP_BRAZERO:
5779 if (current->cc[1] > OP_ASSERTBACK_NOT)
5780 compile_bracket_fallbackpath(common, current);
5781 else
5782 compile_assert_fallbackpath(common, current);
5783 break;
5784
5785 case OP_BRAPOS:
5786 case OP_CBRAPOS:
5787 case OP_SBRAPOS:
5788 case OP_SCBRAPOS:
5789 case OP_BRAPOSZERO:
5790 compile_bracketpos_fallbackpath(common, current);
5791 break;
5792
5793 case OP_BRAMINZERO:
5794 compile_braminzero_fallbackpath(common, current);
5795 break;
5796
5797 case OP_FAIL:
5798 case OP_ACCEPT:
5799 case OP_ASSERT_ACCEPT:
5800 set_jumps(current->topfallbacks, LABEL());
5801 break;
5802
5803 default:
5804 SLJIT_ASSERT_STOP();
5805 break;
5806 }
5807 current = current->prev;
5808 }
5809 }
5810
5811 static SLJIT_INLINE void compile_recurse(compiler_common *common)
5812 {
5813 DEFINE_COMPILER;
5814 uschar *cc = common->start + common->currententry->start;
5815 uschar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : 2);
5816 uschar *ccend = bracketend(cc);
5817 int localsize = get_localsize(common, ccbegin, ccend);
5818 int framesize = get_framesize(common, cc, TRUE);
5819 int alternativesize;
5820 BOOL needsframe;
5821 fallback_common altfallback;
5822 struct sljit_jump *jump;
5823
5824 SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA || *cc == OP_CBRAPOS || *cc == OP_SCBRA || *cc == OP_SCBRAPOS);
5825 needsframe = framesize >= 0;
5826 if (!needsframe)
5827 framesize = 0;
5828 alternativesize = *(cc + GET(cc, 1)) == OP_ALT ? 1 : 0;
5829
5830 SLJIT_ASSERT(common->currententry->entry == NULL);
5831 common->currententry->entry = LABEL();
5832 set_jumps(common->currententry->calls, common->currententry->entry);
5833
5834 sljit_emit_fast_enter(compiler, TMP2, 0, 1, 5, 5, common->localsize);
5835 allocate_stack(common, localsize + framesize + alternativesize);
5836 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(localsize + framesize + alternativesize - 1), TMP2, 0);
5837 copy_locals(common, ccbegin, ccend, TRUE, localsize + framesize + alternativesize, framesize + alternativesize);
5838 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD, STACK_TOP, 0);
5839 if (framesize > 0)
5840 {
5841 OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + alternativesize - 1));
5842 init_frame(common, cc, framesize + alternativesize - 1, alternativesize, FALSE);
5843 }
5844
5845 if (alternativesize > 0)
5846 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
5847
5848 memset(&altfallback, 0, sizeof(fallback_common));
5849 common->acceptlabel = NULL;
5850 common->accept = NULL;
5851 altfallback.cc = ccbegin;
5852 cc += GET(cc, 1);
5853 while (1)
5854 {
5855 altfallback.top = NULL;
5856 altfallback.topfallbacks = NULL;
5857
5858 if (altfallback.cc != ccbegin)
5859 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
5860
5861 compile_hotpath(common, altfallback.cc, cc, &altfallback);
5862 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
5863 return;
5864
5865 add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP));
5866
5867 compile_fallbackpath(common, altfallback.top);
5868 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
5869 return;
5870 set_jumps(altfallback.topfallbacks, LABEL());
5871
5872 if (*cc != OP_ALT)
5873 break;
5874
5875 altfallback.cc = cc + 1 + LINK_SIZE;
5876 cc += GET(cc, 1);
5877 }
5878 /* None of them matched. */
5879 OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0);
5880 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, SLJIT_MEM1(STACK_TOP), STACK(alternativesize));
5881 jump = JUMP(SLJIT_JUMP);
5882
5883 set_jumps(common->accept, LABEL());
5884 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD);
5885 if (needsframe)
5886 {
5887 OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
5888 OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (localsize + framesize + alternativesize) * sizeof(sljit_w));
5889 add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
5890 OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (localsize + framesize + alternativesize) * sizeof(sljit_w));
5891 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP3, 0);
5892 }
5893 OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 1);
5894
5895 JUMPHERE(jump);
5896 copy_locals(common, ccbegin, ccend, FALSE, localsize + framesize + alternativesize, framesize + alternativesize);
5897 free_stack(common, localsize + framesize + alternativesize);
5898 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), sizeof(sljit_w));
5899 OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
5900 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), RECURSIVE_HEAD, TMP2, 0);
5901 sljit_emit_fast_return(compiler, SLJIT_MEM1(STACK_TOP), 0);
5902 }
5903
5904 #undef COMPILE_FALLBACKPATH
5905 #undef CURRENT_AS
5906
5907 void
5908 _pcre_jit_compile(const real_pcre *re, pcre_extra *extra)
5909 {
5910 struct sljit_compiler *compiler;
5911 fallback_common rootfallback;
5912 compiler_common common_data;
5913 compiler_common *common = &common_data;
5914 const unsigned char *tables = re->tables;
5915 pcre_study_data *study = (extra->flags & PCRE_EXTRA_STUDY_DATA) != 0 ? extra->study_data : NULL;
5916 uschar *ccend;
5917 executable_function *function;
5918 void *executable_func;
5919 struct sljit_label *leave;
5920 struct sljit_label *mainloop = NULL;
5921 struct sljit_label *empty_match_found;
5922 struct sljit_label *empty_match_fallback;
5923 struct sljit_jump *alloc_error;
5924 struct sljit_jump *reqbyte_notfound = NULL;
5925 struct sljit_jump *empty_match;
5926
5927 if (!tables)
5928 tables = _pcre_default_tables;
5929
5930 memset(&rootfallback, 0, sizeof(fallback_common));
5931 rootfallback.cc = (uschar *)re + re->name_table_offset + re->name_count * re->name_entry_size;
5932
5933 common->compiler = NULL;
5934 common->start = rootfallback.cc;
5935 common->cbraptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_w);
5936 common->fcc = tables + fcc_offset;
5937 common->lcc = (sljit_w)(tables + lcc_offset);
5938 common->nltype = NLTYPE_FIXED;
5939 switch(re->options & PCRE_NEWLINE_BITS)
5940 {
5941 case 0: common->newline = NEWLINE; break; /* Compile-time default */
5942 case PCRE_NEWLINE_CR: common->newline = CHAR_CR; break;
5943 case PCRE_NEWLINE_LF: common->newline = CHAR_NL; break;
5944 case PCRE_NEWLINE_CR+
5945 PCRE_NEWLINE_LF: common->newline = (CHAR_CR << 8) | CHAR_NL; break;
5946 case PCRE_NEWLINE_ANY: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANY; break;
5947 case PCRE_NEWLINE_ANYCRLF: common->newline = (CHAR_CR << 8) | CHAR_NL; common->nltype = NLTYPE_ANYCRLF; break;
5948 default: return;
5949 }
5950 if ((re->options & PCRE_BSR_ANYCRLF) != 0)
5951 common->bsr_nltype = NLTYPE_ANYCRLF;
5952 else if ((re->options & PCRE_BSR_UNICODE) != 0)
5953 common->bsr_nltype = NLTYPE_ANY;
5954 else
5955 {
5956 #ifdef BSR_ANYCRLF
5957 common->bsr_nltype = NLTYPE_ANYCRLF;
5958 #else
5959 common->bsr_nltype = NLTYPE_ANY;
5960 #endif
5961 }
5962 common->endonly = (re->options & PCRE_DOLLAR_ENDONLY) != 0;
5963 common->ctypes = (sljit_w)(tables + ctypes_offset);
5964 common->acceptlabel = NULL;
5965 common->stubs = NULL;
5966 common->entries = NULL;
5967 common->currententry = NULL;
5968 common->accept = NULL;
5969 common->stackalloc = NULL;
5970 common->revertframes = NULL;
5971 common->wordboundary = NULL;
5972 common->anynewline = NULL;
5973 common->hspace = NULL;
5974 common->vspace = NULL;
5975 common->casefulcmp = NULL;
5976 common->caselesscmp = NULL;
5977 common->jscript_compat = (re->options & PCRE_JAVASCRIPT_COMPAT) != 0;
5978 #ifdef SUPPORT_UTF8
5979 common->utf8 = (re->options & PCRE_UTF8) != 0;
5980 #ifdef SUPPORT_UCP
5981 common->useucp = (re->options & PCRE_UCP) != 0;
5982 #endif
5983 common->utf8readchar = NULL;
5984 common->utf8readtype8 = NULL;
5985 #endif
5986 #ifdef SUPPORT_UCP
5987 common->getucd = NULL;
5988 #endif
5989 ccend = bracketend(rootfallback.cc);
5990 SLJIT_ASSERT(*rootfallback.cc == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
5991 common->localsize = get_localspace(common, rootfallback.cc, ccend);
5992 if (common->localsize < 0)
5993 return;
5994 common->localsize += common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w);
5995 if (common->localsize > SLJIT_MAX_LOCAL_SIZE)
5996 return;
5997 common->localptrs = (int*)SLJIT_MALLOC((ccend - rootfallback.cc) * sizeof(int));
5998 if (!common->localptrs)
5999 return;
6000 memset(common->localptrs, 0, (ccend - rootfallback.cc) * sizeof(int));
6001 set_localptrs(common, common->cbraptr + (re->top_bracket + 1) * sizeof(sljit_w), ccend);
6002
6003 compiler = sljit_create_compiler();
6004 if (!compiler)
6005 {
6006 SLJIT_FREE(common->localptrs);
6007 return;
6008 }
6009 common->compiler = compiler;
6010
6011 /* Main pcre_jit_exec entry. */
6012 sljit_emit_enter(compiler, 1, 5, 5, common->localsize);
6013
6014 /* Register init. */
6015 reset_ovector(common, (re->top_bracket + 1) * 2);
6016 if ((re->flags & PCRE_REQCHSET) != 0)
6017 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_BYTE_PTR, SLJIT_TEMPORARY_REG1, 0);
6018 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, SLJIT_IMM, 0);
6019
6020 OP1(SLJIT_MOV, ARGUMENTS, 0, SLJIT_GENERAL_REG1, 0);
6021 OP1(SLJIT_MOV, TMP1, 0, SLJIT_GENERAL_REG1, 0);
6022 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
6023 OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, end));
6024 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
6025 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base));
6026 OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit));
6027
6028 /* Main part of the matching */
6029 if ((re->options & PCRE_ANCHORED) == 0)
6030 {
6031 mainloop = mainloop_entry(common, (re->flags & PCRE_HASCRORLF) != 0, (re->options & PCRE_FIRSTLINE) != 0);
6032 /* Forward search if possible. */
6033 if ((re->flags & PCRE_FIRSTSET) != 0)
6034 fast_forward_first_byte(common, re->first_byte, (re->options & PCRE_FIRSTLINE) != 0);
6035 else if ((re->flags & PCRE_STARTLINE) != 0)
6036 fast_forward_newline(common, (re->options & PCRE_FIRSTLINE) != 0);
6037 else if ((re->flags & PCRE_STARTLINE) == 0 && study != NULL && (study->flags & PCRE_STUDY_MAPPED) != 0)
6038 fast_forward_start_bits(common, (sljit_uw)study->start_bits, (re->options & PCRE_FIRSTLINE) != 0);
6039 }
6040 if ((re->flags & PCRE_REQCHSET) != 0)
6041 reqbyte_notfound = search_requested_char(common, re->req_byte, (re->flags & PCRE_FIRSTSET) != 0);
6042
6043 /* Store the current STR_PTR in OVECTOR(0). */
6044 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), STR_PTR, 0);
6045
6046 compile_hotpath(common, rootfallback.cc, ccend, &rootfallback);
6047 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
6048 {
6049 sljit_free_compiler(compiler);
6050 SLJIT_FREE(common->localptrs);
6051 return;
6052 }
6053
6054 empty_match = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
6055 empty_match_found = LABEL();
6056
6057 common->acceptlabel = LABEL();
6058 if (common->accept != NULL)
6059 set_jumps(common->accept, common->acceptlabel);
6060
6061 /* This means we have a match. Update the ovector. */
6062 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0);
6063
6064 leave = LABEL();
6065 copy_ovector(common);
6066 OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, MAX_INDEX, 0);
6067 sljit_emit_return(compiler, SLJIT_UNUSED, 0);
6068
6069 empty_match_fallback = LABEL();
6070 compile_fallbackpath(common, rootfallback.top);
6071 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
6072 {
6073 sljit_free_compiler(compiler);
6074 SLJIT_FREE(common->localptrs);
6075 return;
6076 }
6077
6078 SLJIT_ASSERT(rootfallback.prev == NULL);
6079
6080 /* Check we have remaining characters. */
6081 OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
6082
6083 if ((re->options & PCRE_ANCHORED) == 0)
6084 {
6085 if ((re->options & PCRE_FIRSTLINE) == 0)
6086 {
6087 if (study != NULL && study->minlength > 1)
6088 {
6089 OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, study->minlength);
6090 CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_END, 0, mainloop);
6091 }
6092 else
6093 CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
6094 }
6095 else
6096 {
6097 if (study != NULL && study->minlength > 1)
6098 {
6099 OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, study->minlength);
6100 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
6101 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER);
6102 OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
6103 COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_GREATER_EQUAL);
6104 JUMPTO(SLJIT_C_ZERO, mainloop);
6105 }
6106 else
6107 CMPTO(SLJIT_C_LESS, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, mainloop);
6108 }
6109 }
6110
6111 if (reqbyte_notfound != NULL)
6112 JUMPHERE(reqbyte_notfound);
6113 /* Copy OVECTOR(1) to OVECTOR(0) */
6114 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
6115 OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, PCRE_ERROR_NOMATCH);
6116 JUMPTO(SLJIT_JUMP, leave);
6117
6118 flush_stubs(common);
6119
6120 JUMPHERE(empty_match);
6121 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
6122 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty));
6123 CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_fallback);
6124 OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart));
6125 CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, empty_match_found);
6126 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
6127 CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found);
6128 JUMPTO(SLJIT_JUMP, empty_match_fallback);
6129
6130 common->currententry = common->entries;
6131 while (common->currententry != NULL)
6132 {
6133 /* Might add new entries. */
6134 compile_recurse(common);
6135 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
6136 {
6137 sljit_free_compiler(compiler);
6138 SLJIT_FREE(common->localptrs);
6139 return;
6140 }
6141 flush_stubs(common);
6142 common->currententry = common->currententry->next;
6143 }
6144
6145 /* Allocating stack, returns with PCRE_ERROR_NOMEMORY if fails. */
6146 /* This is a (really) rare case. */
6147 set_jumps(common->stackalloc, LABEL());
6148 /* RETURN_ADDR is not a saved register. */
6149 sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize);
6150 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
6151 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
6152 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
6153 OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top), STACK_TOP, 0);
6154 OP2(SLJIT_ADD, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit), SLJIT_IMM, STACK_GROWTH_RATE);
6155
6156 sljit_emit_ijump(compiler, SLJIT_CALL2, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
6157 alloc_error = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
6158 OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
6159 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack));
6160 OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, top));
6161 OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(struct sljit_stack, limit));
6162 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
6163 sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
6164
6165 /* Allocation failed. */
6166 JUMPHERE(alloc_error);
6167 /* We break the return address cache here, but this is a really rare case. */
6168 OP1(SLJIT_MOV, MAX_INDEX, 0, SLJIT_IMM, PCRE_ERROR_NOMEMORY);
6169 JUMPTO(SLJIT_JUMP, leave);
6170
6171 if (common->revertframes != NULL)
6172 {
6173 set_jumps(common->revertframes, LABEL());
6174 do_revertframes(common);
6175 }
6176 if (common->wordboundary != NULL)
6177 {
6178 set_jumps(common->wordboundary, LABEL());
6179 check_wordboundary(common);
6180 }
6181 if (common->anynewline != NULL)
6182 {
6183 set_jumps(common->anynewline, LABEL());
6184 check_anynewline(common);
6185 }
6186 if (common->hspace != NULL)
6187 {
6188 set_jumps(common->hspace, LABEL());
6189 check_hspace(common);
6190 }
6191 if (common->vspace != NULL)
6192 {
6193 set_jumps(common->vspace, LABEL());
6194 check_vspace(common);
6195 }
6196 if (common->casefulcmp != NULL)
6197 {
6198 set_jumps(common->casefulcmp, LABEL());
6199 do_casefulcmp(common);
6200 }
6201 if (common->caselesscmp != NULL)
6202 {
6203 set_jumps(common->caselesscmp, LABEL());
6204 do_caselesscmp(common);
6205 }
6206 #ifdef SUPPORT_UTF8
6207 if (common->utf8readchar != NULL)
6208 {
6209 set_jumps(common->utf8readchar, LABEL());
6210 do_utf8readchar(common);
6211 }
6212 if (common->utf8readtype8 != NULL)
6213 {
6214 set_jumps(common->utf8readtype8, LABEL());
6215 do_utf8readtype8(common);
6216 }
6217 #endif
6218 #ifdef SUPPORT_UCP
6219 if (common->getucd != NULL)
6220 {
6221 set_jumps(common->getucd, LABEL());
6222 do_getucd(common);
6223 }
6224 #endif
6225
6226 SLJIT_FREE(common->localptrs);
6227 executable_func = sljit_generate_code(compiler);
6228 sljit_free_compiler(compiler);
6229 if (executable_func == NULL)
6230 return;
6231
6232 function = SLJIT_MALLOC(sizeof(executable_function));
6233 if (function == NULL)
6234 {
6235 /* This case is highly unlikely since we just recently
6236 freed a lot of memory. Although not impossible. */
6237 sljit_free_code(executable_func);
6238 return;
6239 }
6240
6241 function->executable_func = executable_func;
6242 function->callback = NULL;
6243 function->userdata = NULL;
6244 extra->executable_jit = function;
6245 extra->flags |= PCRE_EXTRA_EXECUTABLE_JIT;
6246 }
6247
6248 static int jit_machine_stack_exec(jit_arguments *arguments, executable_function *function)
6249 {
6250 union {
6251 void* executable_func;
6252 jit_function call_executable_func;
6253 } convert_executable_func;
6254 uschar local_area[LOCAL_SPACE_SIZE];
6255 struct sljit_stack local_stack;
6256
6257 local_stack.top = (sljit_w)&local_area;
6258 local_stack.base = local_stack.top;
6259 local_stack.limit = local_stack.base + LOCAL_SPACE_SIZE;
6260 local_stack.max_limit = local_stack.limit;
6261 arguments->stack = &local_stack;
6262 convert_executable_func.executable_func = function->executable_func;
6263 return convert_executable_func.call_executable_func(arguments);
6264 }
6265
6266 int
6267 _pcre_jit_exec(const real_pcre *re, void *executable_func,
6268 PCRE_SPTR subject, int length, int start_offset, int options, int *offsets,
6269 int offsetcount)
6270 {
6271 executable_function *function = (executable_function*)executable_func;
6272 union {
6273 void* executable_func;
6274 jit_function call_executable_func;
6275 } convert_executable_func;
6276 jit_arguments arguments;
6277 int maxoffsetcount;
6278 int retval;
6279
6280 /* Sanity checks should be handled by pcre_exec. */
6281 arguments.stack = NULL;
6282 arguments.str = subject + start_offset;
6283 arguments.begin = subject;
6284 arguments.end = subject + length;
6285 arguments.notbol = (options & PCRE_NOTBOL) != 0;
6286 arguments.noteol = (options & PCRE_NOTEOL) != 0;
6287 arguments.notempty = (options & PCRE_NOTEMPTY) != 0;
6288 arguments.notempty_atstart = (options & PCRE_NOTEMPTY_ATSTART) != 0;
6289 arguments.offsets = offsets;
6290
6291 /* pcre_exec() rounds offsetcount to a multiple of 3, and then uses only 2/3 of
6292 the output vector for storing captured strings, with the remainder used as
6293 workspace. We don't need the workspace here. For compatibility, we limit the
6294 number of captured strings in the same way as pcre_exec(), so that the user
6295 gets the same result with and without JIT. */
6296
6297 offsetcount = ((offsetcount - (offsetcount % 3)) * 2)/3;
6298 maxoffsetcount = (re->top_bracket + 1) * 2;
6299 if (offsetcount > maxoffsetcount)
6300 offsetcount = maxoffsetcount;
6301 arguments.offsetcount = offsetcount;
6302
6303 if (function->callback)
6304 arguments.stack = (struct sljit_stack*)function->callback(function->userdata);
6305 else
6306 arguments.stack = (struct sljit_stack*)function->userdata;
6307
6308 if (arguments.stack == NULL)
6309 retval = jit_machine_stack_exec(&arguments, function);
6310 else
6311 {
6312 convert_executable_func.executable_func = function->executable_func;
6313 retval = convert_executable_func.call_executable_func(&arguments);
6314 }
6315
6316 if (retval * 2 > offsetcount)
6317 retval = 0;
6318 return retval;
6319 }
6320
6321 void
6322 _pcre_jit_free(void *executable_func)
6323 {
6324 executable_function *function = (executable_function*)executable_func;
6325 sljit_free_code(function->executable_func);
6326 SLJIT_FREE(function);
6327 }
6328
6329 PCRE_EXP_DECL pcre_jit_stack *
6330 pcre_jit_stack_alloc(int startsize, int maxsize)
6331 {
6332 if (startsize < 1 || maxsize < 1)
6333 return NULL;
6334 if (startsize > maxsize)
6335 startsize = maxsize;
6336 startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
6337 maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
6338 return (pcre_jit_stack*)sljit_allocate_stack(startsize, maxsize);
6339 }
6340
6341 PCRE_EXP_DECL void
6342 pcre_jit_stack_free(pcre_jit_stack *stack)
6343 {
6344 sljit_free_stack((struct sljit_stack*)stack);
6345 }
6346
6347 PCRE_EXP_DECL void
6348 pcre_assign_jit_callback(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
6349 {
6350 executable_function *function;
6351 if ((extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) != 0 && extra->executable_jit != NULL)
6352 {
6353 function = (executable_function*)extra->executable_jit;
6354 function->callback = callback;
6355 function->userdata = userdata;
6356 }
6357 }
6358
6359 #else /* SUPPORT_JIT */
6360
6361 /* These are dummy functions to avoid linking errors when JIT support is not
6362 being compiled. */
6363
6364 PCRE_EXP_DECL pcre_jit_stack *
6365 pcre_jit_stack_alloc(int startsize, int maxsize)
6366 {
6367 (void)startsize;
6368 (void)maxsize;
6369 return NULL;
6370 }
6371
6372 PCRE_EXP_DECL void
6373 pcre_jit_stack_free(pcre_jit_stack *stack)
6374 {
6375 (void)stack;
6376 }
6377
6378 PCRE_EXP_DECL void
6379 pcre_assign_jit_callback(pcre_extra *extra, pcre_jit_callback callback, void *userdata)
6380 {
6381 (void)extra;
6382 (void)callback;
6383 (void)userdata;
6384 }
6385
6386 #endif
6387
6388 /* End of pcre_jit_compile.c */

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12