/[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 708 - (hide annotations) (download)
Fri Sep 23 11:03:03 2011 UTC (2 years, 11 months ago) by ph10
File MIME type: text/plain
File size: 196232 byte(s)
File tidies for 8.20-RC2 release.

1 ph10 664 /*************************************************
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 ph10 691
123 ph10 664 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 ph10 677 int calllimit;
156 ph10 664 uschar notbol;
157     uschar noteol;
158     uschar notempty;
159     uschar notempty_atstart;
160     } jit_arguments;
161    
162     typedef struct executable_function {
163     void *executable_func;
164     pcre_jit_callback callback;
165     void *userdata;
166     } executable_function;
167    
168     typedef struct jump_list {
169     struct sljit_jump *jump;
170     struct jump_list *next;
171     } jump_list;
172    
173 zherczeg 696 enum stub_types { stack_alloc };
174 ph10 664
175     typedef struct stub_list {
176     enum stub_types type;
177     int data;
178     struct sljit_jump *start;
179     struct sljit_label *leave;
180     struct stub_list *next;
181     } stub_list;
182    
183     typedef int (SLJIT_CALL *jit_function)(jit_arguments *args);
184    
185     /* The following structure is the key data type for the recursive
186     code generator. It is allocated by compile_hotpath, and contains
187     the aguments for compile_fallbackpath. Must be the first member
188     of its descendants. */
189     typedef struct fallback_common {
190     /* Concatenation stack. */
191     struct fallback_common *prev;
192     jump_list *nextfallbacks;
193     /* Internal stack (for component operators). */
194     struct fallback_common *top;
195     jump_list *topfallbacks;
196     /* Opcode pointer. */
197     uschar *cc;
198     } fallback_common;
199    
200     typedef struct assert_fallback {
201     fallback_common common;
202     jump_list *condfailed;
203     /* Less than 0 (-1) if a frame is not needed. */
204     int framesize;
205     /* Points to our private memory word on the stack. */
206     int localptr;
207     /* For iterators. */
208     struct sljit_label *hotpath;
209     } assert_fallback;
210    
211     typedef struct bracket_fallback {
212     fallback_common common;
213     /* Where to coninue if an alternative is successfully matched. */
214     struct sljit_label *althotpath;
215     /* For rmin and rmax iterators. */
216     struct sljit_label *recursivehotpath;
217     /* For greedy ? operator. */
218     struct sljit_label *zerohotpath;
219     /* Contains the branches of a failed condition. */
220     union {
221     /* Both for OP_COND, OP_SCOND. */
222     jump_list *condfailed;
223     assert_fallback *assert;
224     /* For OP_ONCE. -1 if not needed. */
225     int framesize;
226     } u;
227     /* Points to our private memory word on the stack. */
228     int localptr;
229     } bracket_fallback;
230    
231     typedef struct bracketpos_fallback {
232     fallback_common common;
233     /* Points to our private memory word on the stack. */
234     int localptr;
235     /* Reverting stack is needed. */
236     int framesize;
237     /* Allocated stack size. */
238     int stacksize;
239     } bracketpos_fallback;
240    
241     typedef struct braminzero_fallback {
242     fallback_common common;
243     struct sljit_label *hotpath;
244     } braminzero_fallback;
245    
246     typedef struct iterator_fallback {
247     fallback_common common;
248     /* Next iteration. */
249     struct sljit_label *hotpath;
250     } iterator_fallback;
251    
252     typedef struct recurse_entry {
253     struct recurse_entry *next;
254     /* Contains the function entry. */
255     struct sljit_label *entry;
256     /* Collects the calls until the function is not created. */
257     jump_list *calls;
258     /* Points to the starting opcode. */
259     int start;
260     } recurse_entry;
261    
262     typedef struct recurse_fallback {
263     fallback_common common;
264     } recurse_fallback;
265    
266     typedef struct compiler_common {
267     struct sljit_compiler *compiler;
268     uschar *start;
269     int localsize;
270     int *localptrs;
271     const uschar *fcc;
272     sljit_w lcc;
273     int cbraptr;
274     int nltype;
275     int newline;
276     int bsr_nltype;
277     int endonly;
278     sljit_w ctypes;
279     struct sljit_label *acceptlabel;
280     stub_list *stubs;
281     recurse_entry *entries;
282     recurse_entry *currententry;
283     jump_list *accept;
284 ph10 677 jump_list *calllimit;
285 ph10 664 jump_list *stackalloc;
286     jump_list *revertframes;
287     jump_list *wordboundary;
288     jump_list *anynewline;
289     jump_list *hspace;
290     jump_list *vspace;
291     jump_list *casefulcmp;
292     jump_list *caselesscmp;
293     BOOL jscript_compat;
294     #ifdef SUPPORT_UTF8
295     BOOL utf8;
296     #ifdef SUPPORT_UCP
297     BOOL useucp;
298     #endif
299     jump_list *utf8readchar;
300     jump_list *utf8readtype8;
301     #endif
302     #ifdef SUPPORT_UCP
303     jump_list *getucd;
304     #endif
305     } compiler_common;
306    
307     /* For byte_sequence_compare. */
308    
309     typedef struct compare_context {
310     int length;
311     int sourcereg;
312     #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
313     int byteptr;
314     union {
315     int asint;
316     short asshort;
317     sljit_ub asbyte;
318     sljit_ub asbytes[4];
319     } c;
320     union {
321     int asint;
322     short asshort;
323     sljit_ub asbyte;
324     sljit_ub asbytes[4];
325     } oc;
326     #endif
327     } compare_context;
328    
329     enum {
330     frame_end = 0,
331 zherczeg 696 frame_setstrbegin = -1
332 ph10 664 };
333    
334     /* Used for accessing the elements of the stack. */
335     #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w))
336    
337     #define TMP1 SLJIT_TEMPORARY_REG1
338     #define TMP2 SLJIT_TEMPORARY_REG3
339     #define TMP3 SLJIT_TEMPORARY_EREG2
340     #define STR_PTR SLJIT_GENERAL_REG1
341     #define STR_END SLJIT_GENERAL_REG2
342     #define STACK_TOP SLJIT_TEMPORARY_REG2
343     #define STACK_LIMIT SLJIT_GENERAL_REG3
344     #define ARGUMENTS SLJIT_GENERAL_EREG1
345 zherczeg 695 #define CALL_COUNT SLJIT_GENERAL_EREG2
346 ph10 664 #define RETURN_ADDR SLJIT_TEMPORARY_EREG1
347    
348     /* Locals layout. */
349     /* These two locals can be used by the current opcode. */
350     #define LOCALS0 (0 * sizeof(sljit_w))
351     #define LOCALS1 (1 * sizeof(sljit_w))
352     /* Two local variables for possessive quantifiers (char1 cannot use them). */
353     #define POSSESSIVE0 (2 * sizeof(sljit_w))
354     #define POSSESSIVE1 (3 * sizeof(sljit_w))
355     /* Head of the saved local variables */
356     #define LOCALS_HEAD (4 * sizeof(sljit_w))
357     /* Head of the last recursion. */
358     #define RECURSIVE_HEAD (5 * sizeof(sljit_w))
359 ph10 677 /* Max limit of recursions. */
360     #define CALL_LIMIT (7 * sizeof(sljit_w))
361 ph10 664 /* Last known position of the requested byte. */
362 ph10 677 #define REQ_BYTE_PTR (8 * sizeof(sljit_w))
363 ph10 664 /* End pointer of the first line. */
364 ph10 677 #define FIRSTLINE_END (9 * sizeof(sljit_w))
365 ph10 664 /* The output vector is stored on the stack, and contains pointers
366     to characters. The vector data is divided into two groups: the first
367     group contains the start / end character pointers, and the second is
368     the start pointers when the end of the capturing group has not yet reached. */
369 ph10 677 #define OVECTOR_START (10 * sizeof(sljit_w))
370 ph10 664 #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w))
371     #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w))
372     #define PRIV(cc) (common->localptrs[(cc) - common->start])
373    
374     /* Shortcuts. */
375     #define DEFINE_COMPILER \
376     struct sljit_compiler *compiler = common->compiler
377     #define OP1(op, dst, dstw, src, srcw) \
378     sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
379     #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
380     sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
381     #define LABEL() \
382     sljit_emit_label(compiler)
383     #define JUMP(type) \
384     sljit_emit_jump(compiler, (type))
385     #define JUMPTO(type, label) \
386     sljit_set_label(sljit_emit_jump(compiler, (type)), (label))
387     #define JUMPHERE(jump) \
388     sljit_set_label((jump), sljit_emit_label(compiler))
389     #define CMP(type, src1, src1w, src2, src2w) \
390     sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
391     #define CMPTO(type, src1, src1w, src2, src2w, label) \
392     sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
393     #define COND_VALUE(op, dst, dstw, type) \
394     sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type))
395    
396     static uschar* bracketend(uschar* cc)
397     {
398     SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND));
399     do cc += GET(cc, 1); while (*cc == OP_ALT);
400     SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS);
401     cc += 1 + LINK_SIZE;
402     return cc;
403     }
404    
405 ph10 691 /* Functions whose might need modification for all new supported opcodes:
406 ph10 664 next_opcode
407     get_localspace
408     set_localptrs
409     get_framesize
410     init_frame
411     get_localsize
412     copy_locals
413     compile_hotpath
414     compile_fallbackpath
415     */
416    
417     static uschar *next_opcode(compiler_common *common, uschar *cc)
418     {
419     SLJIT_UNUSED_ARG(common);
420     switch(*cc)
421     {
422     case OP_SOD:
423     case OP_SOM:
424     case OP_SET_SOM:
425     case OP_NOT_WORD_BOUNDARY:
426     case OP_WORD_BOUNDARY:
427     case OP_NOT_DIGIT:
428     case OP_DIGIT:
429     case OP_NOT_WHITESPACE:
430     case OP_WHITESPACE:
431     case OP_NOT_WORDCHAR:
432     case OP_WORDCHAR:
433     case OP_ANY:
434     case OP_ALLANY:
435     case OP_ANYNL:
436     case OP_NOT_HSPACE:
437     case OP_HSPACE:
438     case OP_NOT_VSPACE:
439     case OP_VSPACE:
440     case OP_EXTUNI:
441     case OP_EODN:
442     case OP_EOD:
443     case OP_CIRC:
444     case OP_CIRCM:
445     case OP_DOLL:
446     case OP_DOLLM:
447     case OP_TYPESTAR:
448     case OP_TYPEMINSTAR:
449     case OP_TYPEPLUS:
450     case OP_TYPEMINPLUS:
451     case OP_TYPEQUERY:
452     case OP_TYPEMINQUERY:
453     case OP_TYPEPOSSTAR:
454     case OP_TYPEPOSPLUS:
455     case OP_TYPEPOSQUERY:
456     case OP_CRSTAR:
457     case OP_CRMINSTAR:
458     case OP_CRPLUS:
459     case OP_CRMINPLUS:
460     case OP_CRQUERY:
461     case OP_CRMINQUERY:
462     case OP_DEF:
463     case OP_BRAZERO:
464     case OP_BRAMINZERO:
465     case OP_BRAPOSZERO:
466     case OP_FAIL:
467     case OP_ACCEPT:
468     case OP_ASSERT_ACCEPT:
469     case OP_SKIPZERO:
470     return cc + 1;
471    
472     case OP_CHAR:
473     case OP_CHARI:
474     case OP_NOT:
475     case OP_NOTI:
476    
477     case OP_STAR:
478     case OP_MINSTAR:
479     case OP_PLUS:
480     case OP_MINPLUS:
481     case OP_QUERY:
482     case OP_MINQUERY:
483     case OP_POSSTAR:
484     case OP_POSPLUS:
485     case OP_POSQUERY:
486     case OP_STARI:
487     case OP_MINSTARI:
488     case OP_PLUSI:
489     case OP_MINPLUSI:
490     case OP_QUERYI:
491     case OP_MINQUERYI:
492     case OP_POSSTARI:
493     case OP_POSPLUSI:
494     case OP_POSQUERYI:
495     case OP_NOTSTAR:
496     case OP_NOTMINSTAR:
497     case OP_NOTPLUS:
498     case OP_NOTMINPLUS:
499     case OP_NOTQUERY:
500     case OP_NOTMINQUERY:
501     case OP_NOTPOSSTAR:
502     case OP_NOTPOSPLUS:
503     case OP_NOTPOSQUERY:
504     case OP_NOTSTARI:
505     case OP_NOTMINSTARI:
506     case OP_NOTPLUSI:
507     case OP_NOTMINPLUSI:
508     case OP_NOTQUERYI:
509     case OP_NOTMINQUERYI:
510     case OP_NOTPOSSTARI:
511     case OP_NOTPOSPLUSI:
512     case OP_NOTPOSQUERYI:
513     cc += 2;
514     #ifdef SUPPORT_UTF8
515     if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
516     #endif
517     return cc;
518    
519     case OP_UPTO:
520     case OP_MINUPTO:
521     case OP_EXACT:
522     case OP_POSUPTO:
523     case OP_UPTOI:
524     case OP_MINUPTOI:
525     case OP_EXACTI:
526     case OP_POSUPTOI:
527     case OP_NOTUPTO:
528     case OP_NOTMINUPTO:
529     case OP_NOTEXACT:
530     case OP_NOTPOSUPTO:
531     case OP_NOTUPTOI:
532     case OP_NOTMINUPTOI:
533     case OP_NOTEXACTI:
534     case OP_NOTPOSUPTOI:
535     cc += 4;
536     #ifdef SUPPORT_UTF8
537     if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
538     #endif
539     return cc;
540    
541     case OP_NOTPROP:
542     case OP_PROP:
543     case OP_TYPEUPTO:
544     case OP_TYPEMINUPTO:
545     case OP_TYPEEXACT:
546     case OP_TYPEPOSUPTO:
547     case OP_REF:
548     case OP_REFI:
549     case OP_CREF:
550     case OP_CLOSE:
551     cc += 3;
552     return cc;
553    
554     case OP_CRRANGE:
555     case OP_CRMINRANGE:
556     return cc + 5;
557    
558     case OP_CLASS:
559     case OP_NCLASS:
560     return cc + 33;
561    
562     #ifdef SUPPORT_UTF8
563     case OP_XCLASS:
564     return cc + GET(cc, 1);
565     #endif
566    
567     case OP_RECURSE:
568     case OP_ASSERT:
569     case OP_ASSERT_NOT:
570     case OP_ASSERTBACK:
571     case OP_ASSERTBACK_NOT:
572     case OP_REVERSE:
573     case OP_ONCE:
574     case OP_BRA:
575     case OP_BRAPOS:
576     case OP_COND:
577     case OP_SBRA:
578     case OP_SBRAPOS:
579     case OP_SCOND:
580     case OP_ALT:
581     case OP_KET:
582     case OP_KETRMAX:
583     case OP_KETRMIN:
584     case OP_KETRPOS:
585     return cc + 1 + LINK_SIZE;
586    
587     case OP_CBRA:
588     case OP_CBRAPOS:
589     case OP_SCBRA:
590     case OP_SCBRAPOS:
591     return cc + 1 + LINK_SIZE + 2;
592    
593     default:
594     return NULL;
595     }
596     }
597    
598     static int get_localspace(compiler_common *common, uschar *cc, uschar *ccend)
599     {
600     int localspace = 0;
601     uschar *alternative;
602     /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
603     while (cc < ccend)
604     {
605     switch(*cc)
606     {
607     case OP_ASSERT:
608     case OP_ASSERT_NOT:
609     case OP_ASSERTBACK:
610     case OP_ASSERTBACK_NOT:
611     case OP_ONCE:
612     case OP_BRAPOS:
613     case OP_SBRA:
614     case OP_SBRAPOS:
615     case OP_SCOND:
616     localspace += sizeof(sljit_w);
617     cc += 1 + LINK_SIZE;
618     break;
619    
620     case OP_CBRAPOS:
621     case OP_SCBRAPOS:
622     localspace += sizeof(sljit_w);
623     cc += 1 + LINK_SIZE + 2;
624     break;
625    
626     case OP_COND:
627     /* Might be a hidden SCOND. */
628     alternative = cc + GET(cc, 1);
629     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
630     localspace += sizeof(sljit_w);
631     cc += 1 + LINK_SIZE;
632     break;
633    
634     default:
635     cc = next_opcode(common, cc);
636     if (cc == NULL)
637     return -1;
638     break;
639     }
640     }
641     return localspace;
642     }
643    
644     static void set_localptrs(compiler_common *common, int localptr, uschar *ccend)
645     {
646     uschar *cc = common->start;
647     uschar *alternative;
648     while (cc < ccend)
649     {
650     switch(*cc)
651     {
652     case OP_ASSERT:
653     case OP_ASSERT_NOT:
654     case OP_ASSERTBACK:
655     case OP_ASSERTBACK_NOT:
656     case OP_ONCE:
657     case OP_BRAPOS:
658     case OP_SBRA:
659     case OP_SBRAPOS:
660     case OP_SCOND:
661     common->localptrs[cc - common->start] = localptr;
662     localptr += sizeof(sljit_w);
663     cc += 1 + LINK_SIZE;
664     break;
665    
666     case OP_CBRAPOS:
667     case OP_SCBRAPOS:
668     common->localptrs[cc - common->start] = localptr;
669     localptr += sizeof(sljit_w);
670     cc += 1 + LINK_SIZE + 2;
671     break;
672    
673     case OP_COND:
674     /* Might be a hidden SCOND. */
675     alternative = cc + GET(cc, 1);
676     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
677     {
678     common->localptrs[cc - common->start] = localptr;
679     localptr += sizeof(sljit_w);
680     }
681     cc += 1 + LINK_SIZE;
682     break;
683    
684     default:
685     cc = next_opcode(common, cc);
686     SLJIT_ASSERT(cc != NULL);
687     break;
688     }
689     }
690     }
691    
692     /* Returns with -1 if no need for frame. */
693     static int get_framesize(compiler_common *common, uschar *cc, BOOL recursive)
694     {
695     uschar *ccend = bracketend(cc);
696     uschar *end;
697     int length = 0;
698     BOOL possessive = FALSE;
699     BOOL needs_frame = FALSE;
700     BOOL setsom_found = FALSE;
701    
702     if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS))
703     {
704 zherczeg 696 length = 3;
705 ph10 664 possessive = TRUE;
706     }
707    
708     cc = next_opcode(common, cc);
709     SLJIT_ASSERT(cc != NULL);
710     while (cc < ccend)
711     switch(*cc)
712     {
713     case OP_SET_SOM:
714     case OP_RECURSE:
715     if (!setsom_found)
716     {
717     length += 2;
718     setsom_found = TRUE;
719     }
720     cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;
721     break;
722    
723     case OP_ASSERT:
724     case OP_ASSERT_NOT:
725     case OP_ASSERTBACK:
726     case OP_ASSERTBACK_NOT:
727     case OP_ONCE:
728     if (needs_frame || length > 0)
729     {
730     cc = bracketend(cc);
731     break;
732     }
733     /* Check whether a frame must be created. */
734     end = bracketend(cc);
735     while (cc < end)
736     {
737     if (*cc == OP_SET_SOM || *cc == OP_CBRA || *cc == OP_CBRAPOS
738     || *cc == OP_SCBRA || *cc == OP_SCBRAPOS || *cc == OP_RECURSE)
739     needs_frame = TRUE;
740     cc = next_opcode(common, cc);
741     SLJIT_ASSERT(cc != NULL);
742     }
743     break;
744    
745     case OP_CBRA:
746     case OP_CBRAPOS:
747     case OP_SCBRA:
748     case OP_SCBRAPOS:
749     length += 3;
750     cc += 1 + LINK_SIZE + 2;
751     break;
752    
753     default:
754     cc = next_opcode(common, cc);
755     SLJIT_ASSERT(cc != NULL);
756     break;
757     }
758    
759     /* Possessive quantifiers can use a special case. */
760     if (SLJIT_UNLIKELY(possessive) && !needs_frame && length == 3 + 2)
761     return -1;
762    
763     if (length > 0)
764     return length + 2;
765     return needs_frame ? 0 : -1;
766     }
767    
768     static void init_frame(compiler_common *common, uschar *cc, int stackpos, int stacktop, BOOL recursive)
769     {
770     /* TMP2 must contain STACK_TOP - (-STACK(stackpos)) */
771     DEFINE_COMPILER;
772     uschar *ccend = bracketend(cc);
773     BOOL setsom_found = FALSE;
774     int offset;
775    
776     if (stackpos < stacktop)
777     {
778     SLJIT_ASSERT(stackpos + 1 == stacktop);
779     return;
780     }
781    
782     stackpos = STACK(stackpos);
783     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD);
784     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0);
785     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacktop), TMP1, 0);
786    
787     if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS))
788     cc = next_opcode(common, cc);
789     SLJIT_ASSERT(cc != NULL);
790     while (cc < ccend)
791     switch(*cc)
792     {
793     case OP_SET_SOM:
794     case OP_RECURSE:
795     if (!setsom_found)
796     {
797     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
798     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin);
799     stackpos += (int)sizeof(sljit_w);
800     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
801     stackpos += (int)sizeof(sljit_w);
802     setsom_found = TRUE;
803     }
804     cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE;
805     break;
806    
807     case OP_ASSERT:
808     case OP_ASSERT_NOT:
809     case OP_ASSERTBACK:
810     case OP_ASSERTBACK_NOT:
811     case OP_ONCE:
812     cc = bracketend(cc);
813     break;
814    
815     case OP_CBRA:
816     case OP_CBRAPOS:
817     case OP_SCBRA:
818     case OP_SCBRAPOS:
819     offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
820     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
821     stackpos += (int)sizeof(sljit_w);
822     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
823     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
824     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
825     stackpos += (int)sizeof(sljit_w);
826     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
827     stackpos += (int)sizeof(sljit_w);
828    
829     cc += 1 + LINK_SIZE + 2;
830     break;
831    
832     default:
833     cc = next_opcode(common, cc);
834     SLJIT_ASSERT(cc != NULL);
835     break;
836     }
837    
838     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_end);
839     SLJIT_ASSERT(stackpos == STACK(stacktop + 1));
840     }
841    
842     static SLJIT_INLINE int get_localsize(compiler_common *common, uschar *cc, uschar *ccend)
843     {
844     int localsize = 2;
845     uschar *alternative;
846     /* Calculate the sum of the local variables. */
847     while (cc < ccend)
848     {
849     switch(*cc)
850     {
851     case OP_ASSERT:
852     case OP_ASSERT_NOT:
853     case OP_ASSERTBACK:
854     case OP_ASSERTBACK_NOT:
855     case OP_ONCE:
856     case OP_BRAPOS:
857     case OP_SBRA:
858     case OP_SBRAPOS:
859     case OP_SCOND:
860     localsize++;
861     cc += 1 + LINK_SIZE;
862     break;
863    
864     case OP_CBRA:
865     case OP_SCBRA:
866     localsize++;
867     cc += 1 + LINK_SIZE + 2;
868     break;
869    
870     case OP_CBRAPOS:
871     case OP_SCBRAPOS:
872     localsize += 2;
873     cc += 1 + LINK_SIZE + 2;
874     break;
875    
876     case OP_COND:
877     /* Might be a hidden SCOND. */
878     alternative = cc + GET(cc, 1);
879     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
880     localsize++;
881     cc += 1 + LINK_SIZE;
882     break;
883    
884     default:
885     cc = next_opcode(common, cc);
886     SLJIT_ASSERT(cc != NULL);
887     break;
888     }
889     }
890     SLJIT_ASSERT(cc == ccend);
891     return localsize;
892     }
893    
894     static void copy_locals(compiler_common *common, uschar *cc, uschar *ccend,
895     BOOL save, int stackptr, int stacktop)
896     {
897     DEFINE_COMPILER;
898     int srcw[2];
899     int count;
900     BOOL tmp1next = TRUE;
901     BOOL tmp1empty = TRUE;
902     BOOL tmp2empty = TRUE;
903     uschar *alternative;
904     enum {
905     start,
906     loop,
907     end
908     } status;
909    
910     status = save ? start : loop;
911     stackptr = STACK(stackptr - 2);
912     stacktop = STACK(stacktop - 1);
913    
914     if (!save)
915     {
916     stackptr += sizeof(sljit_w);
917     if (stackptr < stacktop)
918     {
919     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
920     stackptr += sizeof(sljit_w);
921     tmp1empty = FALSE;
922     }
923     if (stackptr < stacktop)
924     {
925     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
926     stackptr += sizeof(sljit_w);
927     tmp2empty = FALSE;
928     }
929     /* The tmp1next must be TRUE in either way. */
930     }
931    
932     while (status != end)
933     {
934     count = 0;
935     switch(status)
936     {
937     case start:
938     SLJIT_ASSERT(save);
939     count = 1;
940     srcw[0] = RECURSIVE_HEAD;
941     status = loop;
942     break;
943    
944     case loop:
945     if (cc >= ccend)
946     {
947     status = end;
948     break;
949     }
950    
951     switch(*cc)
952     {
953     case OP_ASSERT:
954     case OP_ASSERT_NOT:
955     case OP_ASSERTBACK:
956     case OP_ASSERTBACK_NOT:
957     case OP_ONCE:
958     case OP_BRAPOS:
959     case OP_SBRA:
960     case OP_SBRAPOS:
961     case OP_SCOND:
962     count = 1;
963     srcw[0] = PRIV(cc);
964     SLJIT_ASSERT(srcw[0] != 0);
965     cc += 1 + LINK_SIZE;
966     break;
967    
968     case OP_CBRA:
969     case OP_SCBRA:
970     count = 1;
971     srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
972     cc += 1 + LINK_SIZE + 2;
973     break;
974    
975     case OP_CBRAPOS:
976     case OP_SCBRAPOS:
977     count = 2;
978     srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
979     srcw[0] = PRIV(cc);
980     SLJIT_ASSERT(srcw[0] != 0);
981     cc += 1 + LINK_SIZE + 2;
982     break;
983    
984     case OP_COND:
985     /* Might be a hidden SCOND. */
986     alternative = cc + GET(cc, 1);
987     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
988     {
989     count = 1;
990     srcw[0] = PRIV(cc);
991     SLJIT_ASSERT(srcw[0] != 0);
992     }
993     cc += 1 + LINK_SIZE;
994     break;
995    
996     default:
997     cc = next_opcode(common, cc);
998     SLJIT_ASSERT(cc != NULL);
999     break;
1000     }
1001     break;
1002    
1003     case end:
1004     SLJIT_ASSERT_STOP();
1005     break;
1006     }
1007    
1008     while (count > 0)
1009     {
1010     count--;
1011     if (save)
1012     {
1013     if (tmp1next)
1014     {
1015     if (!tmp1empty)
1016     {
1017     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1018     stackptr += sizeof(sljit_w);
1019     }
1020     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
1021     tmp1empty = FALSE;
1022     tmp1next = FALSE;
1023     }
1024     else
1025     {
1026     if (!tmp2empty)
1027     {
1028     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1029     stackptr += sizeof(sljit_w);
1030     }
1031     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count]);
1032     tmp2empty = FALSE;
1033     tmp1next = TRUE;
1034     }
1035     }
1036     else
1037     {
1038     if (tmp1next)
1039     {
1040     SLJIT_ASSERT(!tmp1empty);
1041     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP1, 0);
1042     tmp1empty = stackptr >= stacktop;
1043     if (!tmp1empty)
1044     {
1045     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1046     stackptr += sizeof(sljit_w);
1047     }
1048     tmp1next = FALSE;
1049     }
1050     else
1051     {
1052     SLJIT_ASSERT(!tmp2empty);
1053     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), srcw[count], TMP2, 0);
1054     tmp2empty = stackptr >= stacktop;
1055     if (!tmp2empty)
1056     {
1057     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), stackptr);
1058     stackptr += sizeof(sljit_w);
1059     }
1060     tmp1next = TRUE;
1061     }
1062     }
1063     }
1064     }
1065    
1066     if (save)
1067     {
1068     if (tmp1next)
1069     {
1070     if (!tmp1empty)
1071     {
1072     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1073     stackptr += sizeof(sljit_w);
1074     }
1075     if (!tmp2empty)
1076     {
1077     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1078     stackptr += sizeof(sljit_w);
1079     }
1080     }
1081     else
1082     {
1083     if (!tmp2empty)
1084     {
1085     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP2, 0);
1086     stackptr += sizeof(sljit_w);
1087     }
1088     if (!tmp1empty)
1089     {
1090     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackptr, TMP1, 0);
1091     stackptr += sizeof(sljit_w);
1092     }
1093     }
1094     }
1095     SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty)));
1096     }
1097    
1098     static SLJIT_INLINE BOOL ispowerof2(unsigned int value)
1099     {
1100     return (value & (value - 1)) == 0;
1101     }
1102    
1103     static SLJIT_INLINE void set_jumps(jump_list *list, struct sljit_label *label)
1104     {
1105     while (list)
1106     {
1107     /* sljit_set_label is clever enough to do nothing
1108     if either the jump or the label is NULL */
1109     sljit_set_label(list->jump, label);
1110     list = list->next;
1111     }
1112     }
1113    
1114     static SLJIT_INLINE void add_jump(struct sljit_compiler *compiler, jump_list **list, struct sljit_jump* jump)
1115     {
1116     jump_list *list_item = sljit_alloc_memory(compiler, sizeof(jump_list));
1117     if (list_item)
1118     {
1119     list_item->next = *list;
1120     list_item->jump = jump;
1121     *list = list_item;
1122     }
1123     }
1124    
1125     static void add_stub(compiler_common *common, enum stub_types type, int data, struct sljit_jump *start)
1126     {
1127     DEFINE_COMPILER;
1128     stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list));
1129    
1130     if (list_item)
1131     {
1132     list_item->type = type;
1133     list_item->data = data;
1134     list_item->start = start;
1135     list_item->leave = LABEL();
1136     list_item->next = common->stubs;
1137     common->stubs = list_item;
1138     }
1139     }
1140    
1141     static void flush_stubs(compiler_common *common)
1142     {
1143     DEFINE_COMPILER;
1144     stub_list* list_item = common->stubs;
1145    
1146     while (list_item)
1147     {
1148     JUMPHERE(list_item->start);
1149     switch(list_item->type)
1150     {
1151     case stack_alloc:
1152     add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL));
1153     break;
1154     }
1155     JUMPTO(SLJIT_JUMP, list_item->leave);
1156     list_item = list_item->next;
1157     }
1158     common->stubs = NULL;
1159     }
1160    
1161 ph10 677 static SLJIT_INLINE void decrease_call_count(compiler_common *common)
1162     {
1163     DEFINE_COMPILER;
1164    
1165 zherczeg 695 OP2(SLJIT_SUB | SLJIT_SET_E, CALL_COUNT, 0, CALL_COUNT, 0, SLJIT_IMM, 1);
1166 ph10 677 add_jump(compiler, &common->calllimit, JUMP(SLJIT_C_ZERO));
1167     }
1168    
1169 ph10 664 static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
1170     {
1171     /* May destroy all locals and registers except TMP2. */
1172     DEFINE_COMPILER;
1173    
1174     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
1175     #ifdef DESTROY_REGISTERS
1176     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
1177     OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
1178     OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
1179     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0);
1180     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
1181     #endif
1182     add_stub(common, stack_alloc, 0, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0));
1183     }
1184    
1185     static SLJIT_INLINE void free_stack(compiler_common *common, int size)
1186     {
1187     DEFINE_COMPILER;
1188     OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_w));
1189     }
1190    
1191     static SLJIT_INLINE void reset_ovector(compiler_common *common, int length)
1192     {
1193     DEFINE_COMPILER;
1194     struct sljit_label *loop;
1195     int i;
1196     /* At this point we can freely use all temporary registers. */
1197     /* TMP1 returns with begin - 1. */
1198     OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, 1);
1199     if (length < 8)
1200     {
1201     for (i = 0; i < length; i++)
1202     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_TEMPORARY_REG1, 0);
1203     }
1204     else
1205     {
1206     OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START - sizeof(sljit_w));
1207     OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length);
1208     loop = LABEL();
1209     OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_w), SLJIT_TEMPORARY_REG1, 0);
1210     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1);
1211     JUMPTO(SLJIT_C_NOT_ZERO, loop);
1212     }
1213     }
1214    
1215 zherczeg 696 static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket)
1216 ph10 664 {
1217     DEFINE_COMPILER;
1218     struct sljit_label *loop;
1219     struct sljit_jump *earlyexit;
1220    
1221     /* At this point we can freely use all registers. */
1222 zherczeg 696 OP1(SLJIT_MOV, SLJIT_GENERAL_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
1223     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0);
1224    
1225 ph10 664 OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0);
1226     OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount));
1227     OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int));
1228     OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin));
1229     OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START);
1230     /* Unlikely, but possible */
1231     earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0);
1232     loop = LABEL();
1233     OP2(SLJIT_SUB, SLJIT_GENERAL_REG2, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), 0, SLJIT_TEMPORARY_REG1, 0);
1234     OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_GENERAL_REG1, 0, SLJIT_IMM, sizeof(sljit_w));
1235     /* Copy the integer value to the output buffer */
1236     OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_GENERAL_REG2, 0);
1237     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
1238     JUMPTO(SLJIT_C_NOT_ZERO, loop);
1239     JUMPHERE(earlyexit);
1240 zherczeg 696
1241     /* Calculate the return value, which is the maximum ovector value. */
1242     if (topbracket > 1)
1243     {
1244     OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START + topbracket * 2 * sizeof(sljit_w));
1245     OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1);
1246    
1247     /* OVECTOR(0) is never equal to SLJIT_GENERAL_REG3. */
1248     loop = LABEL();
1249     OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * sizeof(sljit_w)));
1250     OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1);
1251     CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_GENERAL_REG3, 0, loop);
1252     OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0);
1253     }
1254     else
1255     OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1);
1256 ph10 664 }
1257    
1258     static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, uschar* cc)
1259     {
1260     /* Detects if the character has an othercase. */
1261     unsigned int c;
1262    
1263     #ifdef SUPPORT_UTF8
1264     if (common->utf8)
1265     {
1266     GETCHAR(c, cc);
1267     if (c > 127)
1268     {
1269     #ifdef SUPPORT_UCP
1270     return c != UCD_OTHERCASE(c);
1271     #else
1272     return FALSE;
1273     #endif
1274     }
1275     }
1276     else
1277     #endif
1278     c = *cc;
1279     return common->fcc[c] != c;
1280     }
1281    
1282     static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c)
1283     {
1284     /* Returns with the othercase. */
1285     #ifdef SUPPORT_UTF8
1286     if (common->utf8 && c > 127)
1287     {
1288     #ifdef SUPPORT_UCP
1289     return UCD_OTHERCASE(c);
1290     #else
1291     return c;
1292     #endif
1293     }
1294     #endif
1295     return common->fcc[c];
1296     }
1297    
1298     static unsigned int char_get_othercase_bit(compiler_common *common, uschar* cc)
1299     {
1300     /* Detects if the character and its othercase has only 1 bit difference. */
1301     unsigned int c, oc, bit;
1302     #ifdef SUPPORT_UTF8
1303     int n;
1304     #endif
1305    
1306     #ifdef SUPPORT_UTF8
1307     if (common->utf8)
1308     {
1309     GETCHAR(c, cc);
1310     if (c <= 127)
1311     oc = common->fcc[c];
1312     else
1313     {
1314     #ifdef SUPPORT_UCP
1315     oc = UCD_OTHERCASE(c);
1316     #else
1317     oc = c;
1318     #endif
1319     }
1320     }
1321     else
1322     {
1323     c = *cc;
1324     oc = common->fcc[c];
1325     }
1326     #else
1327     c = *cc;
1328     oc = common->fcc[c];
1329     #endif
1330    
1331     SLJIT_ASSERT(c != oc);
1332    
1333     bit = c ^ oc;
1334     /* Optimized for English alphabet. */
1335     if (c <= 127 && bit == 0x20)
1336     return (0 << 8) | 0x20;
1337    
1338     /* Since c != oc, they must have at least 1 bit difference. */
1339     if (!ispowerof2(bit))
1340     return 0;
1341    
1342     #ifdef SUPPORT_UTF8
1343     if (common->utf8 && c > 127)
1344     {
1345     n = _pcre_utf8_table4[*cc & 0x3f];
1346     while ((bit & 0x3f) == 0)
1347     {
1348     n--;
1349     bit >>= 6;
1350     }
1351     return (n << 8) | bit;
1352     }
1353     #endif
1354     return (0 << 8) | bit;
1355     }
1356    
1357     static SLJIT_INLINE void check_input_end(compiler_common *common, jump_list **fallbacks)
1358     {
1359     DEFINE_COMPILER;
1360     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
1361     }
1362    
1363     static void read_char(compiler_common *common)
1364     {
1365     /* Reads the character into TMP1, updates STR_PTR.
1366     Does not check STR_END. TMP2 Destroyed. */
1367     DEFINE_COMPILER;
1368     #ifdef SUPPORT_UTF8
1369     struct sljit_jump *jump;
1370     #endif
1371    
1372     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1373     #ifdef SUPPORT_UTF8
1374     if (common->utf8)
1375     {
1376     /* Should not found a value between 128 and 192 here. */
1377     jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 192);
1378     add_jump(compiler, &common->utf8readchar, JUMP(SLJIT_FAST_CALL));
1379     JUMPHERE(jump);
1380     }
1381     #endif
1382     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1383     }
1384    
1385     static void peek_char(compiler_common *common)
1386     {
1387     /* Reads the character into TMP1, keeps STR_PTR.
1388     Does not check STR_END. TMP2 Destroyed. */
1389     DEFINE_COMPILER;
1390     #ifdef SUPPORT_UTF8
1391     struct sljit_jump *jump;
1392     #endif
1393    
1394     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1395     #ifdef SUPPORT_UTF8
1396     if (common->utf8)
1397     {
1398     /* Should not found a value between 128 and 192 here. */
1399     jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 192);
1400     add_jump(compiler, &common->utf8readchar, JUMP(SLJIT_FAST_CALL));
1401     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1402     JUMPHERE(jump);
1403     }
1404     #endif
1405     }
1406    
1407     static void read_char8_type(compiler_common *common)
1408     {
1409     /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
1410     DEFINE_COMPILER;
1411     #ifdef SUPPORT_UTF8
1412     struct sljit_jump *jump;
1413     #endif
1414    
1415     #ifdef SUPPORT_UTF8
1416     if (common->utf8)
1417     {
1418     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
1419     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1420     /* This can be an extra read in some situations, but hopefully
1421     it is a clever early read in most cases. */
1422     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1423     /* Should not found a value between 128 and 192 here. */
1424     jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 192);
1425     add_jump(compiler, &common->utf8readtype8, JUMP(SLJIT_FAST_CALL));
1426     JUMPHERE(jump);
1427     return;
1428     }
1429     #endif
1430     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1431     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1432     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
1433     }
1434    
1435     static void skip_char_back(compiler_common *common)
1436     {
1437     /* Goes one character back. Only affects STR_PTR. Does not check begin. */
1438     DEFINE_COMPILER;
1439     #ifdef SUPPORT_UTF8
1440     struct sljit_label *label;
1441    
1442     if (common->utf8)
1443     {
1444     label = LABEL();
1445     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1446     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1447     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0);
1448     CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label);
1449     return;
1450     }
1451     #endif
1452     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1453     }
1454    
1455     static void check_newlinechar(compiler_common *common, int nltype, jump_list **fallbacks, BOOL jumpiftrue)
1456     {
1457     /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
1458     DEFINE_COMPILER;
1459    
1460     if (nltype == NLTYPE_ANY)
1461     {
1462     add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
1463     add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1464     }
1465     else if (nltype == NLTYPE_ANYCRLF)
1466     {
1467     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR);
1468     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
1469     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
1470     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
1471     add_jump(compiler, fallbacks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
1472     }
1473     else
1474     {
1475     SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline <= 255);
1476     add_jump(compiler, fallbacks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
1477     }
1478     }
1479    
1480     #ifdef SUPPORT_UTF8
1481     static void do_utf8readchar(compiler_common *common)
1482     {
1483     /* Fast decoding an utf8 character. TMP1 contains the first byte
1484     of the character (>= 192). Return char value in TMP1, length - 1 in TMP2. */
1485     DEFINE_COMPILER;
1486     struct sljit_jump *jump;
1487    
1488     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1489     /* Searching for the first zero. */
1490     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
1491     jump = JUMP(SLJIT_C_NOT_ZERO);
1492     /* 2 byte sequence */
1493     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1494     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1495     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f);
1496     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
1497     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1498     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1499     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
1500     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1501     JUMPHERE(jump);
1502    
1503     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10);
1504     jump = JUMP(SLJIT_C_NOT_ZERO);
1505     /* 3 byte sequence */
1506     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1507     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f);
1508     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12);
1509     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1510     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1511     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1512     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2);
1513     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 2);
1514     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1515     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1516     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 2);
1517     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1518     JUMPHERE(jump);
1519    
1520     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x08);
1521     jump = JUMP(SLJIT_C_NOT_ZERO);
1522     /* 4 byte sequence */
1523     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1524     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07);
1525     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18);
1526     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1527     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
1528     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1529     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2);
1530     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1531     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1532     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1533     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 3);
1534     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 3);
1535     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1536     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1537     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 3);
1538     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1539     JUMPHERE(jump);
1540    
1541     /* 5 byte sequence */
1542     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
1543     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x03);
1544     OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 24);
1545     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1546     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 18);
1547     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1548     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2);
1549     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1550     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12);
1551     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1552     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 3);
1553     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1554     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1555     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1556     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 4);
1557     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 4);
1558     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
1559     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
1560     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 4);
1561     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1562     }
1563    
1564     static void do_utf8readtype8(compiler_common *common)
1565     {
1566     /* Fast decoding an utf8 character type. TMP2 contains the first byte
1567     of the character (>= 192) and TMP1 is destroyed. Return value in TMP1. */
1568     DEFINE_COMPILER;
1569     struct sljit_jump *jump;
1570     struct sljit_jump *compare;
1571    
1572     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1573    
1574     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
1575     jump = JUMP(SLJIT_C_NOT_ZERO);
1576     /* 2 byte sequence */
1577     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1578     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1579     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f);
1580     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6);
1581     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f);
1582     OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0);
1583     compare = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255);
1584     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes);
1585     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1586    
1587     JUMPHERE(compare);
1588     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1589     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1590     JUMPHERE(jump);
1591    
1592     /* We only have types for characters less than 256. */
1593     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_w)_pcre_utf8_char_sizes);
1594     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1595     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1596     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0);
1597     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1598     }
1599    
1600     #endif
1601    
1602     #ifdef SUPPORT_UCP
1603    
1604     /* UCD_BLOCK_SIZE must be 128 (see the assert below). */
1605     #define UCD_BLOCK_MASK 127
1606     #define UCD_BLOCK_SHIFT 7
1607    
1608     static void do_getucd(compiler_common *common)
1609     {
1610     /* Search the UCD record for the character comes in TMP1.
1611     Returns chartype in TMP1 and UCD offset in TMP2. */
1612     DEFINE_COMPILER;
1613    
1614     SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && sizeof(ucd_record) == 8);
1615    
1616     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1617     OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
1618     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)_pcre_ucd_stage1);
1619     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
1620     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
1621     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
1622     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_stage2);
1623     OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
1624     OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, chartype));
1625     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3);
1626     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1627     }
1628     #endif
1629    
1630     static SLJIT_INLINE struct sljit_label *mainloop_entry(compiler_common *common, BOOL hascrorlf, BOOL firstline)
1631     {
1632     DEFINE_COMPILER;
1633     struct sljit_label *mainloop;
1634     struct sljit_label *newlinelabel = NULL;
1635     struct sljit_jump *start;
1636     struct sljit_jump *end = NULL;
1637     struct sljit_jump *nl = NULL;
1638     jump_list *newline = NULL;
1639     BOOL newlinecheck = FALSE;
1640     BOOL readbyte = FALSE;
1641    
1642     if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY ||
1643     common->nltype == NLTYPE_ANYCRLF || common->newline > 255))
1644     newlinecheck = TRUE;
1645    
1646     if (firstline)
1647     {
1648     /* Search for the end of the first line. */
1649     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STR_PTR, 0);
1650     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_END, 0);
1651    
1652     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
1653     {
1654     mainloop = LABEL();
1655     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1656     end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1657     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -1);
1658     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 0);
1659     CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop);
1660     CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop);
1661     OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0, SLJIT_IMM, 1);
1662     }
1663     else
1664     {
1665     end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1666     mainloop = LABEL();
1667     /* Continual stores does not cause data dependency. */
1668     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0);
1669     read_char(common);
1670     check_newlinechar(common, common->nltype, &newline, TRUE);
1671     CMPTO(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0, mainloop);
1672     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0);
1673     set_jumps(newline, LABEL());
1674     }
1675    
1676     JUMPHERE(end);
1677     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
1678     }
1679    
1680     start = JUMP(SLJIT_JUMP);
1681    
1682     if (newlinecheck)
1683     {
1684     newlinelabel = LABEL();
1685     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1686     end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1687     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1688     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
1689     COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
1690     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1691     nl = JUMP(SLJIT_JUMP);
1692     }
1693    
1694     mainloop = LABEL();
1695    
1696     /* Increasing the STR_PTR here requires one less jump in the most common case. */
1697     #ifdef SUPPORT_UTF8
1698     if (common->utf8) readbyte = TRUE;
1699     #endif
1700     if (newlinecheck) readbyte = TRUE;
1701    
1702     if (readbyte)
1703     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1704    
1705     if (newlinecheck)
1706     CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel);
1707    
1708     #ifdef SUPPORT_UTF8
1709     if (common->utf8)
1710     {
1711     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
1712     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1713     }
1714     else
1715     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1716     #else
1717     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1718     #endif
1719     JUMPHERE(start);
1720    
1721     if (newlinecheck)
1722     {
1723     JUMPHERE(end);
1724     JUMPHERE(nl);
1725     }
1726    
1727     return mainloop;
1728     }
1729    
1730     static SLJIT_INLINE void fast_forward_first_byte(compiler_common *common, pcre_uint16 firstbyte, BOOL firstline)
1731     {
1732     DEFINE_COMPILER;
1733     struct sljit_label *start;
1734     struct sljit_jump *leave;
1735     struct sljit_jump *found;
1736     pcre_uint16 oc, bit;
1737    
1738     if (firstline)
1739     {
1740     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1741     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
1742     }
1743    
1744     start = LABEL();
1745     leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1746     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1747    
1748     if ((firstbyte & REQ_CASELESS) == 0)
1749     found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, firstbyte & 0xff);
1750     else
1751     {
1752     firstbyte &= 0xff;
1753     oc = common->fcc[firstbyte];
1754     bit = firstbyte ^ oc;
1755     if (ispowerof2(bit))
1756     {
1757     OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit);
1758     found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, firstbyte | bit);
1759     }
1760     else
1761     {
1762     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, firstbyte);
1763     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
1764     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
1765     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
1766     found = JUMP(SLJIT_C_NOT_ZERO);
1767     }
1768     }
1769    
1770     #ifdef SUPPORT_UTF8
1771     if (common->utf8)
1772     {
1773     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
1774     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1775     }
1776     else
1777     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1778     #else
1779     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1780     #endif
1781     JUMPTO(SLJIT_JUMP, start);
1782     JUMPHERE(found);
1783     JUMPHERE(leave);
1784    
1785     if (firstline)
1786     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1787     }
1788    
1789     static SLJIT_INLINE void fast_forward_newline(compiler_common *common, BOOL firstline)
1790     {
1791     DEFINE_COMPILER;
1792     struct sljit_label *loop;
1793     struct sljit_jump *lastchar;
1794     struct sljit_jump *firstchar;
1795     struct sljit_jump *leave;
1796     struct sljit_jump *foundcr = NULL;
1797     struct sljit_jump *notfoundnl;
1798     jump_list *newline = NULL;
1799    
1800     if (firstline)
1801     {
1802     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1803     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
1804     }
1805    
1806     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
1807     {
1808     lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1809     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1810     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
1811     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
1812     firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
1813    
1814     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);
1815     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
1816     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL);
1817     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
1818    
1819     loop = LABEL();
1820     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1821     leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1822     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -2);
1823     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), -1);
1824     CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop);
1825     CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop);
1826    
1827     JUMPHERE(leave);
1828     JUMPHERE(firstchar);
1829     JUMPHERE(lastchar);
1830    
1831     if (firstline)
1832     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1833     return;
1834     }
1835    
1836     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
1837     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
1838     firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
1839     skip_char_back(common);
1840    
1841     loop = LABEL();
1842     read_char(common);
1843     lastchar = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1844     if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
1845     foundcr = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
1846     check_newlinechar(common, common->nltype, &newline, FALSE);
1847     set_jumps(newline, loop);
1848    
1849     if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
1850     {
1851     leave = JUMP(SLJIT_JUMP);
1852     JUMPHERE(foundcr);
1853     notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1854     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1855     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
1856     COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL);
1857     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
1858     JUMPHERE(notfoundnl);
1859     JUMPHERE(leave);
1860     }
1861     JUMPHERE(lastchar);
1862     JUMPHERE(firstchar);
1863    
1864     if (firstline)
1865     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1866     }
1867    
1868     static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline)
1869     {
1870     DEFINE_COMPILER;
1871     struct sljit_label *start;
1872     struct sljit_jump *leave;
1873     struct sljit_jump *found;
1874    
1875     if (firstline)
1876     {
1877     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, STR_END, 0);
1878     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END);
1879     }
1880    
1881     start = LABEL();
1882     leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
1883     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
1884     #ifdef SUPPORT_UTF8
1885     if (common->utf8)
1886     OP1(SLJIT_MOV_UB, TMP3, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
1887     #endif
1888     OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
1889     OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
1890     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits);
1891     OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
1892     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
1893     found = JUMP(SLJIT_C_NOT_ZERO);
1894    
1895     #ifdef SUPPORT_UTF8
1896     if (common->utf8)
1897     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP3, 0);
1898     else
1899     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1900     #else
1901     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
1902     #endif
1903     JUMPTO(SLJIT_JUMP, start);
1904     JUMPHERE(found);
1905     JUMPHERE(leave);
1906    
1907     if (firstline)
1908     OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
1909     }
1910    
1911     static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uint16 reqbyte, BOOL has_firstbyte)
1912     {
1913     DEFINE_COMPILER;
1914     struct sljit_label *loop;
1915     struct sljit_jump *toolong;
1916     struct sljit_jump *alreadyfound;
1917     struct sljit_jump *found;
1918     struct sljit_jump *foundoc = NULL;
1919     struct sljit_jump *notfound;
1920     pcre_uint16 oc, bit;
1921    
1922     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_BYTE_PTR);
1923     OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX);
1924     toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0);
1925     alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0);
1926    
1927     if (has_firstbyte)
1928     OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, 1);
1929     else
1930     OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0);
1931    
1932     loop = LABEL();
1933     notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0);
1934    
1935     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), 0);
1936     if ((reqbyte & REQ_CASELESS) == 0)
1937     found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte & 0xff);
1938     else
1939     {
1940     reqbyte &= 0xff;
1941     oc = common->fcc[reqbyte];
1942     bit = reqbyte ^ oc;
1943     if (ispowerof2(bit))
1944     {
1945     OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit);
1946     found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte | bit);
1947     }
1948     else
1949     {
1950     found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte);
1951     foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc);
1952     }
1953     }
1954     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
1955     JUMPTO(SLJIT_JUMP, loop);
1956    
1957     JUMPHERE(found);
1958     if (foundoc)
1959     JUMPHERE(foundoc);
1960     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_BYTE_PTR, TMP1, 0);
1961     JUMPHERE(alreadyfound);
1962     JUMPHERE(toolong);
1963     return notfound;
1964     }
1965    
1966     static void do_revertframes(compiler_common *common)
1967     {
1968     DEFINE_COMPILER;
1969     struct sljit_jump *earlyexit;
1970     struct sljit_jump *jump;
1971     struct sljit_label *mainloop;
1972    
1973     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
1974     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD);
1975    
1976     /* Drop frames until we reach STACK_TOP. */
1977     earlyexit = CMP(SLJIT_C_LESS, TMP1, 0, STACK_TOP, 0);
1978     mainloop = LABEL();
1979     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0);
1980     jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
1981     OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_LOCALS_REG, 0);
1982     OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
1983     OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_w), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_w));
1984     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_w));
1985     JUMPTO(SLJIT_JUMP, mainloop);
1986    
1987     JUMPHERE(jump);
1988     jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end);
1989     /* End of dropping frames. */
1990     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
1991     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP1, 0);
1992     CMPTO(SLJIT_C_GREATER_EQUAL, TMP1, 0, STACK_TOP, 0, mainloop);
1993     JUMPHERE(earlyexit);
1994     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
1995    
1996     JUMPHERE(jump);
1997     jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin);
1998 zherczeg 696 /* Set string begin. */
1999 ph10 664 OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w));
2000     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
2001     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0);
2002     JUMPTO(SLJIT_JUMP, mainloop);
2003    
2004     JUMPHERE(jump);
2005     /* Unknown command. */
2006     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_w));
2007     JUMPTO(SLJIT_JUMP, mainloop);
2008     }
2009    
2010     static void check_wordboundary(compiler_common *common)
2011     {
2012     DEFINE_COMPILER;
2013     struct sljit_jump *beginend;
2014 ph10 670 #ifdef SUPPORT_UTF8
2015 ph10 664 struct sljit_jump *jump;
2016 ph10 670 #endif
2017 ph10 664
2018     SLJIT_ASSERT(ctype_word == 0x10);
2019    
2020     sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize);
2021     /* Get type of the previous char, and put it to LOCALS1. */
2022     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2023     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
2024     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0);
2025     beginend = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0);
2026     skip_char_back(common);
2027     read_char(common);
2028    
2029     /* Testing char type. */
2030     #ifdef SUPPORT_UCP
2031     if (common->useucp)
2032     {
2033     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
2034     jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
2035     add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2036     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
2037     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2038     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2039     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
2040     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2041     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2042     JUMPHERE(jump);
2043     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0);
2044     }
2045     else
2046     #endif
2047     {
2048     #ifdef SUPPORT_UTF8
2049     /* Here LOCALS1 has already been zeroed. */
2050     jump = NULL;
2051     if (common->utf8)
2052     jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2053     #endif
2054     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes);
2055     OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */);
2056     OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2057     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0);
2058     #ifdef SUPPORT_UTF8
2059     if (jump != NULL)
2060     JUMPHERE(jump);
2061     #endif
2062     }
2063     JUMPHERE(beginend);
2064    
2065     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2066     beginend = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2067     peek_char(common);
2068    
2069     /* Testing char type. This is a code duplication. */
2070     #ifdef SUPPORT_UCP
2071     if (common->useucp)
2072     {
2073     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1);
2074     jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
2075     add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2076     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
2077     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2078     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2079     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
2080     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2081     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2082     JUMPHERE(jump);
2083     }
2084     else
2085     #endif
2086     {
2087     #ifdef SUPPORT_UTF8
2088     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2089     jump = NULL;
2090     if (common->utf8)
2091     jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2092     #endif
2093     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes);
2094     OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */);
2095     OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
2096     #ifdef SUPPORT_UTF8
2097     if (jump != NULL)
2098     JUMPHERE(jump);
2099     #endif
2100     }
2101     JUMPHERE(beginend);
2102    
2103     OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2104     sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2105     }
2106    
2107     static void check_anynewline(compiler_common *common)
2108     {
2109     /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2110     DEFINE_COMPILER;
2111    
2112     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2113    
2114     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
2115     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
2116     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2117     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
2118     #ifdef SUPPORT_UTF8
2119     if (common->utf8)
2120     {
2121     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2122     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
2123     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
2124     }
2125     #endif
2126     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2127     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2128     }
2129    
2130     static void check_hspace(compiler_common *common)
2131     {
2132     /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2133     DEFINE_COMPILER;
2134    
2135     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2136    
2137     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
2138     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2139     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
2140     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2141     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
2142     #ifdef SUPPORT_UTF8
2143     if (common->utf8)
2144     {
2145     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2146     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
2147     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2148     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
2149     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2150     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
2151     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
2152     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2153     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
2154     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2155     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
2156     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2157     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
2158     }
2159     #endif
2160     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2161    
2162     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2163     }
2164    
2165     static void check_vspace(compiler_common *common)
2166     {
2167     /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2168     DEFINE_COMPILER;
2169    
2170     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2171    
2172     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
2173     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
2174     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2175     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
2176     #ifdef SUPPORT_UTF8
2177     if (common->utf8)
2178     {
2179     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2180     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
2181     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
2182     }
2183     #endif
2184     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2185    
2186     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2187     }
2188    
2189     #define CHAR1 STR_END
2190     #define CHAR2 STACK_TOP
2191    
2192     static void do_casefulcmp(compiler_common *common)
2193     {
2194     DEFINE_COMPILER;
2195     struct sljit_jump *jump;
2196     struct sljit_label *label;
2197    
2198     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2199     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
2200     OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0);
2201     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0);
2202     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2203     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2204    
2205     label = LABEL();
2206     OP1(SLJIT_MOVU_UB, CHAR1, 0, SLJIT_MEM1(TMP1), 1);
2207     OP1(SLJIT_MOVU_UB, CHAR2, 0, SLJIT_MEM1(STR_PTR), 1);
2208     jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
2209     OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
2210     JUMPTO(SLJIT_C_NOT_ZERO, label);
2211    
2212     JUMPHERE(jump);
2213     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2214     OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0);
2215     OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2216     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2217     }
2218    
2219     #define LCC_TABLE STACK_LIMIT
2220    
2221     static void do_caselesscmp(compiler_common *common)
2222     {
2223     DEFINE_COMPILER;
2224     struct sljit_jump *jump;
2225     struct sljit_label *label;
2226    
2227     sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize);
2228     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
2229    
2230     OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0);
2231     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0);
2232     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0);
2233     OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc);
2234     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
2235     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2236    
2237     label = LABEL();
2238     OP1(SLJIT_MOVU_UB, CHAR1, 0, SLJIT_MEM1(TMP1), 1);
2239     OP1(SLJIT_MOVU_UB, CHAR2, 0, SLJIT_MEM1(STR_PTR), 1);
2240     OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0);
2241     OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0);
2242     jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0);
2243     OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
2244     JUMPTO(SLJIT_C_NOT_ZERO, label);
2245    
2246     JUMPHERE(jump);
2247     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2248     OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0);
2249     OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
2250     OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2251     sljit_emit_fast_return(compiler, RETURN_ADDR, 0);
2252     }
2253    
2254     #undef LCC_TABLE
2255     #undef CHAR1
2256     #undef CHAR2
2257    
2258     #ifdef SUPPORT_UTF8
2259     #ifdef SUPPORT_UCP
2260    
2261     static uschar * SLJIT_CALL do_utf8caselesscmp(uschar *src1, jit_arguments *args, uschar *end1)
2262     {
2263     /* This function would be ineffective to do in JIT level. */
2264     int c1, c2;
2265     uschar *src2 = args->ptr;
2266     uschar *end2 = (uschar*)args->end;
2267    
2268     while (src1 < end1)
2269     {
2270     if (src2 >= end2)
2271     return 0;
2272     GETCHARINC(c1, src1);
2273     GETCHARINC(c2, src2);
2274     if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return 0;
2275     }
2276     return src2;
2277     }
2278    
2279     #endif
2280     #endif
2281    
2282     static uschar *byte_sequence_compare(compiler_common *common, BOOL caseless, uschar *cc,
2283     compare_context* context, jump_list **fallbacks)
2284     {
2285     DEFINE_COMPILER;
2286     unsigned int othercasebit = 0;
2287     uschar *othercasebyte = NULL;
2288     #ifdef SUPPORT_UTF8
2289     int utf8length;
2290     #endif
2291    
2292     if (caseless && char_has_othercase(common, cc))
2293     {
2294     othercasebit = char_get_othercase_bit(common, cc);
2295     SLJIT_ASSERT(othercasebit);
2296     /* Extracting bit difference info. */
2297     othercasebyte = cc + (othercasebit >> 8);
2298     othercasebit &= 0xff;
2299     }
2300    
2301     if (context->sourcereg == -1)
2302     {
2303     #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2304     if (context->length >= 4)
2305     OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2306     else if (context->length >= 2)
2307     OP1(SLJIT_MOV_SH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2308     else
2309     #endif
2310     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length);
2311     context->sourcereg = TMP2;
2312     }
2313    
2314     #ifdef SUPPORT_UTF8
2315     utf8length = 1;
2316     if (common->utf8 && *cc >= 0xc0)
2317     utf8length += _pcre_utf8_table4[*cc & 0x3f];
2318    
2319     do
2320     {
2321     #endif
2322    
2323     context->length--;
2324     #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2325    
2326     /* Unaligned read is supported. */
2327     if (othercasebit != 0 && othercasebyte == cc)
2328     {
2329     context->c.asbytes[context->byteptr] = *cc | othercasebit;
2330     context->oc.asbytes[context->byteptr] = othercasebit;
2331     }
2332     else
2333     {
2334     context->c.asbytes[context->byteptr] = *cc;
2335     context->oc.asbytes[context->byteptr] = 0;
2336     }
2337     context->byteptr++;
2338    
2339     if (context->byteptr >= 4 || context->length == 0 || (context->byteptr == 2 && context->length == 1))
2340     {
2341     if (context->length >= 4)
2342     OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2343     else if (context->length >= 2)
2344     OP1(SLJIT_MOV_SH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2345     else if (context->length >= 1)
2346     OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2347     context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
2348    
2349     switch(context->byteptr)
2350     {
2351     case 4:
2352     if (context->oc.asint != 0)
2353     OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint);
2354     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint));
2355     break;
2356    
2357     case 2:
2358     if (context->oc.asshort != 0)
2359     OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asshort);
2360     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asshort | context->oc.asshort));
2361     break;
2362    
2363     case 1:
2364     if (context->oc.asbyte != 0)
2365     OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte);
2366     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte));
2367     break;
2368    
2369     default:
2370     SLJIT_ASSERT_STOP();
2371     break;
2372     }
2373     context->byteptr = 0;
2374     }
2375 ph10 691
2376 ph10 664 #else
2377    
2378     /* Unaligned read is unsupported. */
2379     if (context->length > 0)
2380     OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length);
2381     context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1;
2382    
2383     if (othercasebit != 0 && othercasebyte == cc)
2384     {
2385     OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit);
2386     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit));
2387     }
2388     else
2389     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc));
2390    
2391     #endif
2392    
2393     cc++;
2394     #ifdef SUPPORT_UTF8
2395     utf8length--;
2396     }
2397     while (utf8length > 0);
2398     #endif
2399    
2400     return cc;
2401     }
2402    
2403     #ifdef SUPPORT_UTF8
2404    
2405     #define SET_TYPE_OFFSET(value) \
2406     if ((value) != typeoffset) \
2407     { \
2408     if ((value) > typeoffset) \
2409     OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
2410     else \
2411     OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
2412     } \
2413     typeoffset = (value);
2414    
2415     #define SET_CHAR_OFFSET(value) \
2416     if ((value) != charoffset) \
2417     { \
2418     if ((value) > charoffset) \
2419     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \
2420     else \
2421     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \
2422     } \
2423     charoffset = (value);
2424    
2425     static void compile_xclass_hotpath(compiler_common *common, uschar *cc, jump_list **fallbacks)
2426     {
2427     DEFINE_COMPILER;
2428     jump_list *found = NULL;
2429     jump_list **list = (*cc & XCL_NOT) == 0 ? &found : fallbacks;
2430     unsigned int c;
2431     int compares;
2432     struct sljit_jump *jump = NULL;
2433     uschar *ccbegin;
2434     #ifdef SUPPORT_UCP
2435     BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
2436     BOOL charsaved = FALSE;
2437     int typereg = TMP1, scriptreg = TMP1, typeoffset;
2438     #endif
2439     int charoffset, invertcmp, numberofcmps;
2440    
2441     /* Although SUPPORT_UTF8 must be defined, we are not necessary in utf8 mode. */
2442     check_input_end(common, fallbacks);
2443     read_char(common);
2444    
2445     if ((*cc++ & XCL_MAP) != 0)
2446     {
2447     OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
2448     if (common->utf8)
2449     jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
2450    
2451     OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
2452     OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
2453     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
2454     OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
2455     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
2456     add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO));
2457    
2458     if (common->utf8)
2459     JUMPHERE(jump);
2460     OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
2461     #ifdef SUPPORT_UCP
2462     charsaved = TRUE;
2463     #endif
2464     cc += 32;
2465     }
2466    
2467     /* Scanning the necessary info. */
2468     ccbegin = cc;
2469     compares = 0;
2470     while (*cc != XCL_END)
2471     {
2472     compares++;
2473     if (*cc == XCL_SINGLE)
2474     {
2475     cc += 2;
2476     #ifdef SUPPORT_UTF8
2477     if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
2478     #endif
2479     #ifdef SUPPORT_UCP
2480     needschar = TRUE;
2481     #endif
2482     }
2483     else if (*cc == XCL_RANGE)
2484     {
2485     cc += 2;
2486     #ifdef SUPPORT_UTF8
2487     if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
2488     #endif
2489     cc++;
2490     #ifdef SUPPORT_UTF8
2491     if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f];
2492     #endif
2493     #ifdef SUPPORT_UCP
2494     needschar = TRUE;
2495     #endif
2496     }
2497     #ifdef SUPPORT_UCP
2498     else
2499     {
2500     SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
2501     cc++;
2502     switch(*cc)
2503     {
2504     case PT_ANY:
2505     break;
2506    
2507     case PT_LAMP:
2508     case PT_GC:
2509     case PT_PC:
2510     case PT_ALNUM:
2511     needstype = TRUE;
2512     break;
2513    
2514     case PT_SC:
2515     needsscript = TRUE;
2516     break;
2517    
2518     case PT_SPACE:
2519     case PT_PXSPACE:
2520     case PT_WORD:
2521     needstype = TRUE;
2522     needschar = TRUE;
2523     break;
2524    
2525     default:
2526     SLJIT_ASSERT_STOP();
2527     break;
2528     }
2529     cc += 2;
2530     }
2531     #endif
2532     }
2533    
2534     #ifdef SUPPORT_UCP
2535     /* Simple register allocation. TMP1 is preferred if possible. */
2536     if (needstype || needsscript)
2537     {
2538     if (needschar && !charsaved)
2539     OP1(SLJIT_MOV, TMP3, 0, TMP1, 0);
2540     add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2541     if (needschar)
2542     {
2543     if (needstype)
2544     {
2545     OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
2546     typereg = RETURN_ADDR;
2547     }
2548    
2549     if (needsscript)
2550     scriptreg = TMP3;
2551     OP1(SLJIT_MOV, TMP1, 0, TMP3, 0);
2552     }
2553     else if (needstype && needsscript)
2554     scriptreg = TMP3;
2555     /* In all other cases only one of them was specified, and that can goes to TMP1. */
2556    
2557     if (needsscript)
2558     {
2559     if (scriptreg == TMP1)
2560     {
2561     OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, script));
2562     OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3);
2563     }
2564     else
2565     {
2566     OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3);
2567     OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, script));
2568     OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0);
2569     }
2570     }
2571     }
2572     #endif
2573    
2574     /* Generating code. */
2575     cc = ccbegin;
2576     charoffset = 0;
2577     numberofcmps = 0;
2578     #ifdef SUPPORT_UCP
2579     typeoffset = 0;
2580     #endif
2581    
2582     while (*cc != XCL_END)
2583     {
2584     compares--;
2585     invertcmp = (compares == 0 && list != fallbacks);
2586     jump = NULL;
2587    
2588     if (*cc == XCL_SINGLE)
2589     {
2590     cc ++;
2591     #ifdef SUPPORT_UTF8
2592     if (common->utf8)
2593     {
2594     GETCHARINC(c, cc);
2595     }
2596     else
2597     #endif
2598     c = *cc++;
2599    
2600     if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
2601     {
2602     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2603     COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2604     numberofcmps++;
2605     }
2606     else if (numberofcmps > 0)
2607     {
2608     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2609     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2610     jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2611     numberofcmps = 0;
2612     }
2613     else
2614     {
2615     jump = CMP(SLJIT_C_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
2616     numberofcmps = 0;
2617     }
2618     }
2619     else if (*cc == XCL_RANGE)
2620     {
2621     cc ++;
2622     #ifdef SUPPORT_UTF8
2623     if (common->utf8)
2624     {
2625     GETCHARINC(c, cc);
2626     }
2627     else
2628     #endif
2629     c = *cc++;
2630     SET_CHAR_OFFSET(c);
2631     #ifdef SUPPORT_UTF8
2632     if (common->utf8)
2633     {
2634     GETCHARINC(c, cc);
2635     }
2636     else
2637     #endif
2638     c = *cc++;
2639     if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
2640     {
2641     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2642     COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2643     numberofcmps++;
2644     }
2645     else if (numberofcmps > 0)
2646     {
2647     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset);
2648     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2649     jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2650     numberofcmps = 0;
2651     }
2652     else
2653     {
2654     jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, c - charoffset);
2655     numberofcmps = 0;
2656     }
2657     }
2658     #ifdef SUPPORT_UCP
2659     else
2660     {
2661     if (*cc == XCL_NOTPROP)
2662     invertcmp ^= 0x1;
2663     cc++;
2664     switch(*cc)
2665     {
2666     case PT_ANY:
2667     if (list != fallbacks)
2668     {
2669     if ((cc[-1] == XCL_NOTPROP && compares > 0) || (cc[-1] == XCL_PROP && compares == 0))
2670     continue;
2671     }
2672     else if (cc[-1] == XCL_NOTPROP)
2673     continue;
2674     jump = JUMP(SLJIT_JUMP);
2675     break;
2676    
2677     case PT_LAMP:
2678     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
2679     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2680     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
2681     COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL);
2682     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
2683     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
2684     jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2685     break;
2686    
2687     case PT_GC:
2688     c = _pcre_ucp_typerange[(int)cc[1] * 2];
2689     SET_TYPE_OFFSET(c);
2690     jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, _pcre_ucp_typerange[(int)cc[1] * 2 + 1] - c);
2691     break;
2692    
2693     case PT_PC:
2694     jump = CMP(SLJIT_C_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, (int)cc[1] - typeoffset);
2695     break;
2696    
2697     case PT_SC:
2698     jump = CMP(SLJIT_C_EQUAL ^ invertcmp, scriptreg, 0, SLJIT_IMM, (int)cc[1]);
2699     break;
2700    
2701     case PT_SPACE:
2702     case PT_PXSPACE:
2703     if (*cc == PT_SPACE)
2704     {
2705     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0);
2706     jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 11 - charoffset);
2707     }
2708     SET_CHAR_OFFSET(9);
2709     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9);
2710     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL);
2711     if (*cc == PT_SPACE)
2712     JUMPHERE(jump);
2713    
2714     SET_TYPE_OFFSET(ucp_Zl);
2715     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
2716     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2717     jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2718     break;
2719    
2720     case PT_WORD:
2721     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE - charoffset);
2722     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
2723     /* ... fall through */
2724    
2725     case PT_ALNUM:
2726     SET_TYPE_OFFSET(ucp_Ll);
2727     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
2728     COND_VALUE((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL);
2729     SET_TYPE_OFFSET(ucp_Nd);
2730     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
2731     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL);
2732     jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp);
2733     break;
2734     }
2735     cc += 2;
2736     }
2737     #endif
2738    
2739     if (jump != NULL)
2740     add_jump(compiler, compares > 0 ? list : fallbacks, jump);
2741     }
2742    
2743     if (found != NULL)
2744     set_jumps(found, LABEL());
2745     }
2746    
2747     #undef SET_TYPE_OFFSET
2748     #undef SET_CHAR_OFFSET
2749    
2750     #endif
2751    
2752     static uschar *compile_char1_hotpath(compiler_common *common, uschar type, uschar *cc, jump_list **fallbacks)
2753     {
2754     DEFINE_COMPILER;
2755     int length;
2756     unsigned int c, oc, bit;
2757     compare_context context;
2758     struct sljit_jump *jump[4];
2759     #ifdef SUPPORT_UTF8
2760 ph10 670 struct sljit_label *label;
2761 ph10 664 #ifdef SUPPORT_UCP
2762     uschar propdata[5];
2763     #endif
2764     #endif
2765    
2766     switch(type)
2767     {
2768     case OP_SOD:
2769     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2770     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
2771     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
2772     return cc;
2773    
2774     case OP_SOM:
2775     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
2776     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
2777     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, TMP1, 0));
2778     return cc;
2779    
2780     case OP_NOT_WORD_BOUNDARY:
2781     case OP_WORD_BOUNDARY:
2782     add_jump(compiler, &common->wordboundary, JUMP(SLJIT_FAST_CALL));
2783     add_jump(compiler, fallbacks, JUMP(type == OP_NOT_WORD_BOUNDARY ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
2784     return cc;
2785    
2786     case OP_NOT_DIGIT:
2787     case OP_DIGIT:
2788     check_input_end(common, fallbacks);
2789     read_char8_type(common);
2790     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
2791     add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
2792     return cc;
2793    
2794     case OP_NOT_WHITESPACE:
2795     case OP_WHITESPACE:
2796     check_input_end(common, fallbacks);
2797     read_char8_type(common);
2798     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
2799     add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
2800     return cc;
2801    
2802     case OP_NOT_WORDCHAR:
2803     case OP_WORDCHAR:
2804     check_input_end(common, fallbacks);
2805     read_char8_type(common);
2806     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
2807     add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO));
2808     return cc;
2809    
2810     case OP_ANY:
2811     check_input_end(common, fallbacks);
2812     read_char(common);
2813     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
2814     {
2815     jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
2816     jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2817     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2818     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff));
2819     JUMPHERE(jump[1]);
2820     JUMPHERE(jump[0]);
2821     }
2822     else
2823     check_newlinechar(common, common->nltype, fallbacks, TRUE);
2824     return cc;
2825    
2826     case OP_ALLANY:
2827     check_input_end(common, fallbacks);
2828     #ifdef SUPPORT_UTF8
2829     if (common->utf8)
2830     {
2831     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2832     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
2833     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
2834     return cc;
2835     }
2836     #endif
2837     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2838     return cc;
2839    
2840     #ifdef SUPPORT_UTF8
2841     #ifdef SUPPORT_UCP
2842     case OP_NOTPROP:
2843     case OP_PROP:
2844     propdata[0] = 0;
2845     propdata[1] = type == OP_NOTPROP ? XCL_NOTPROP : XCL_PROP;
2846     propdata[2] = cc[0];
2847     propdata[3] = cc[1];
2848     propdata[4] = XCL_END;
2849     compile_xclass_hotpath(common, propdata, fallbacks);
2850     return cc + 2;
2851     #endif
2852     #endif
2853    
2854     case OP_ANYNL:
2855     check_input_end(common, fallbacks);
2856     read_char(common);
2857     jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
2858     jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2859     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2860     jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
2861     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
2862     jump[3] = JUMP(SLJIT_JUMP);
2863     JUMPHERE(jump[0]);
2864     check_newlinechar(common, common->bsr_nltype, fallbacks, FALSE);
2865     JUMPHERE(jump[1]);
2866     JUMPHERE(jump[2]);
2867     JUMPHERE(jump[3]);
2868     return cc;
2869    
2870     case OP_NOT_HSPACE:
2871     case OP_HSPACE:
2872     check_input_end(common, fallbacks);
2873     read_char(common);
2874     add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
2875     add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
2876     return cc;
2877    
2878     case OP_NOT_VSPACE:
2879     case OP_VSPACE:
2880     check_input_end(common, fallbacks);
2881     read_char(common);
2882     add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
2883     add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO));
2884     return cc;
2885    
2886     #ifdef SUPPORT_UCP
2887     case OP_EXTUNI:
2888     check_input_end(common, fallbacks);
2889     read_char(common);
2890     add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2891     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
2892     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc));
2893    
2894     label = LABEL();
2895     jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2896     OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
2897     read_char(common);
2898     add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL));
2899     OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc);
2900     CMPTO(SLJIT_C_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Mn - ucp_Mc, label);
2901    
2902     OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
2903     JUMPHERE(jump[0]);
2904     return cc;
2905     #endif
2906    
2907     case OP_EODN:
2908     jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
2909     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
2910     {
2911     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
2912     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2913     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
2914     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
2915     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
2916     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
2917     }
2918     else if (common->nltype == NLTYPE_FIXED)
2919     {
2920     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 1);
2921     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2922     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0));
2923     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline));
2924     }
2925     else
2926     {
2927     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
2928     jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
2929     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
2930     OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
2931     jump[2] = JUMP(SLJIT_C_GREATER);
2932     add_jump(compiler, fallbacks, JUMP(SLJIT_C_LESS));
2933     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 1);
2934     jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL);
2935     add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP));
2936    
2937     JUMPHERE(jump[1]);
2938     if (common->nltype == NLTYPE_ANYCRLF)
2939     {
2940     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 1);
2941     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0));
2942     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL));
2943     }
2944     else
2945     {
2946     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, STR_PTR, 0);
2947     read_char(common);
2948     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
2949     add_jump(compiler, &common->anynewline, JUMP(SLJIT_FAST_CALL));
2950     add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
2951     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1);
2952     }
2953     JUMPHERE(jump[2]);
2954     JUMPHERE(jump[3]);
2955     }
2956     JUMPHERE(jump[0]);
2957     return cc;
2958    
2959     case OP_EOD:
2960     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0));
2961     return cc;
2962    
2963     case OP_CIRC:
2964     OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
2965     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
2966     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0));
2967     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
2968     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
2969     return cc;
2970    
2971     case OP_CIRCM:
2972     OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
2973     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
2974     jump[1] = CMP(SLJIT_C_GREATER, STR_PTR, 0, TMP1, 0);
2975     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, notbol));
2976     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
2977     jump[0] = JUMP(SLJIT_JUMP);
2978     JUMPHERE(jump[1]);
2979    
2980     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, end));
2981     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP2, 0, STR_PTR, 0));
2982    
2983     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
2984     {
2985     OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
2986     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0));
2987     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -2);
2988     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), -1);
2989     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
2990     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
2991     }
2992     else
2993     {
2994     skip_char_back(common);
2995     read_char(common);
2996     check_newlinechar(common, common->nltype, fallbacks, FALSE);
2997     }
2998     JUMPHERE(jump[0]);
2999     return cc;
3000    
3001     case OP_DOLL:
3002     OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3003     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
3004     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3005    
3006     if (!common->endonly)
3007     compile_char1_hotpath(common, OP_EODN, cc, fallbacks);
3008     else
3009     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0));
3010     return cc;
3011    
3012     case OP_DOLLM:
3013     jump[1] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0);
3014     OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
3015     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol));
3016     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3017     jump[0] = JUMP(SLJIT_JUMP);
3018     JUMPHERE(jump[1]);
3019    
3020     if (common->nltype == NLTYPE_FIXED && common->newline > 255)
3021     {
3022     OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2);
3023     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0));
3024     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
3025     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1);
3026     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff));
3027     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff));
3028     }
3029     else
3030     {
3031     peek_char(common);
3032     check_newlinechar(common, common->nltype, fallbacks, FALSE);
3033     }
3034     JUMPHERE(jump[0]);
3035     return cc;
3036    
3037     case OP_CHAR:
3038     case OP_CHARI:
3039     length = 1;
3040     #ifdef SUPPORT_UTF8
3041     if (common->utf8 && *cc >= 0xc0) length += _pcre_utf8_table4[*cc & 0x3f];
3042     #endif
3043     if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)
3044     {
3045     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, length);
3046     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3047    
3048     context.length = length;
3049     context.sourcereg = -1;
3050     #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3051     context.byteptr = 0;
3052     #endif
3053     return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks);
3054     }
3055     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
3056     read_char(common);
3057     #ifdef SUPPORT_UTF8
3058     if (common->utf8)
3059     {
3060     GETCHAR(c, cc);
3061     }
3062     else
3063     #endif
3064     c = *cc;
3065     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c);
3066     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3067     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c));
3068     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
3069     add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
3070     return cc + length;
3071    
3072     case OP_NOT:
3073     case OP_NOTI:
3074     length = 1;
3075     #ifdef SUPPORT_UTF8
3076     if (common->utf8)
3077     {
3078     if (*cc >= 0xc0) length += _pcre_utf8_table4[*cc & 0x3f];
3079    
3080     check_input_end(common, fallbacks);
3081     GETCHAR(c, cc);
3082    
3083     if (c <= 127)
3084     {
3085     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
3086     OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes);
3087     if (type == OP_NOT || !char_has_othercase(common, cc))
3088     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3089     else
3090     {
3091     /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
3092     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x20);
3093     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | 0x20));
3094     }
3095     /* Skip the variable-length character. */
3096     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
3097     return cc + length;
3098     }
3099     else
3100     read_char(common);
3101     }
3102     else
3103     #endif
3104     {
3105     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1);
3106     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3107     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -1);
3108     c = *cc;
3109     }
3110    
3111     if (type == OP_NOT || !char_has_othercase(common, cc))
3112     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3113     else
3114     {
3115     oc = char_othercase(common, c);
3116     bit = c ^ oc;
3117     if (ispowerof2(bit))
3118     {
3119     OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit);
3120     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | bit));
3121     }
3122     else
3123     {
3124     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c));
3125     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc));
3126     }
3127     }
3128     return cc + length;
3129    
3130     case OP_CLASS:
3131     case OP_NCLASS:
3132     check_input_end(common, fallbacks);
3133     read_char(common);
3134     #ifdef SUPPORT_UTF8
3135     jump[0] = NULL;
3136     if (common->utf8)
3137     {
3138     jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255);
3139     if (type == OP_CLASS)
3140     {
3141     add_jump(compiler, fallbacks, jump[0]);
3142     jump[0] = NULL;
3143     }
3144     }
3145     #endif
3146     OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7);
3147     OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
3148     OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc);
3149     OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
3150     OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
3151     add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO));
3152     #ifdef SUPPORT_UTF8
3153     if (jump[0] != NULL)
3154     JUMPHERE(jump[0]);
3155     #endif
3156     return cc + 32;
3157    
3158     #ifdef SUPPORT_UTF8
3159     case OP_XCLASS:
3160     compile_xclass_hotpath(common, cc + LINK_SIZE, fallbacks);
3161     return cc + GET(cc, 0) - 1;
3162     #endif
3163    
3164     case OP_REVERSE:
3165     length = GET(cc, 0);
3166     SLJIT_ASSERT(length > 0);
3167     OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
3168     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
3169     #ifdef SUPPORT_UTF8
3170     if (common->utf8)
3171     {
3172     OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length);
3173     label = LABEL();
3174     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0));
3175     skip_char_back(common);
3176     OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
3177     JUMPTO(SLJIT_C_NOT_ZERO, label);
3178     return cc + LINK_SIZE;
3179     }
3180     #endif
3181     OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, length);
3182     add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0));
3183     return cc + LINK_SIZE;
3184     }
3185     SLJIT_ASSERT_STOP();
3186     return cc;
3187     }
3188    
3189     static SLJIT_INLINE uschar *compile_charn_hotpath(compiler_common *common, uschar *cc, uschar *ccend, jump_list **fallbacks)
3190     {
3191     /* This function consumes at least one input character. */
3192     /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
3193     DEFINE_COMPILER;
3194     uschar *ccbegin = cc;
3195     compare_context context;
3196     int size;
3197    
3198     context.length = 0;
3199     do
3200     {
3201     if (cc >= ccend)
3202     break;
3203    
3204     if (*cc == OP_CHAR)
3205     {
3206     size = 1;
3207     #ifdef SUPPORT_UTF8
3208     if (common->utf8 && cc[1] >= 0xc0)
3209     size += _pcre_utf8_table4[cc[1] & 0x3f];
3210     #endif
3211     }
3212     else if (*cc == OP_CHARI)
3213     {
3214     size = 1;
3215     #ifdef SUPPORT_UTF8
3216     if (common->utf8)
3217     {
3218     if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
3219     size = 0;
3220     else if (cc[1] >= 0xc0)
3221     size += _pcre_utf8_table4[cc[1] & 0x3f];
3222     }
3223 ph10 691 else
3224 ph10 664 #endif
3225     if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0)
3226     size = 0;
3227     }
3228     else
3229     size = 0;
3230    
3231     cc += 1 + size;
3232     context.length += size;
3233     }
3234     while (size > 0 && context.length <= 128);
3235    
3236     cc = ccbegin;
3237     if (context.length > 0)
3238     {
3239     /* We have a fixed-length byte sequence. */
3240     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, context.length);
3241     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3242    
3243     context.sourcereg = -1;
3244     #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3245     context.byteptr = 0;
3246     #endif
3247     do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, fallbacks); while (context.length > 0);
3248     return cc;
3249     }
3250    
3251     /* A non-fixed length character will be checked if length == 0. */
3252     return compile_char1_hotpath(common, *cc, cc + 1, fallbacks);
3253     }
3254    
3255     static struct sljit_jump *compile_ref_checks(compiler_common *common, uschar *cc, jump_list **fallbacks)
3256     {
3257     DEFINE_COMPILER;
3258     int offset = GET2(cc, 1) << 1;
3259    
3260     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
3261     if (!common->jscript_compat)
3262     {
3263     if (fallbacks == NULL)
3264     {
3265     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1));
3266     COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL);
3267     OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3268     COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL);
3269     return JUMP(SLJIT_C_NOT_ZERO);
3270     }
3271     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
3272     }
3273     return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3274     }
3275    
3276     /* Forward definitions. */
3277     static void compile_hotpath(compiler_common *, uschar *, uschar *, fallback_common *);
3278     static void compile_fallbackpath(compiler_common *, struct fallback_common *);
3279    
3280     #define PUSH_FALLBACK(size, ccstart, error) \
3281     do \
3282     { \
3283     fallback = sljit_alloc_memory(compiler, (size)); \
3284     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3285     return error; \
3286     memset(fallback, 0, size); \
3287     fallback->prev = parent->top; \
3288     fallback->cc = (ccstart); \
3289     parent->top = fallback; \
3290     } \
3291     while (0)
3292    
3293     #define PUSH_FALLBACK_NOVALUE(size, ccstart) \
3294     do \
3295     { \
3296     fallback = sljit_alloc_memory(compiler, (size)); \
3297     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3298     return; \
3299     memset(fallback, 0, size); \
3300     fallback->prev = parent->top; \
3301     fallback->cc = (ccstart); \
3302     parent->top = fallback; \
3303     } \
3304     while (0)
3305    
3306     #define FALLBACK_AS(type) ((type*)fallback)
3307    
3308     static uschar *compile_ref_hotpath(compiler_common *common, uschar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail)
3309     {
3310     DEFINE_COMPILER;
3311     int offset = GET2(cc, 1) << 1;
3312     struct sljit_jump *jump = NULL;
3313    
3314     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
3315     if (withchecks && !common->jscript_compat)
3316     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
3317    
3318     #ifdef SUPPORT_UTF8
3319     #ifdef SUPPORT_UCP
3320     if (common->utf8 && *cc == OP_REFI)
3321     {
3322     SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3);
3323     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
3324     if (withchecks)
3325     jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0);
3326    
3327     /* Needed to save important temporary registers. */
3328     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0);
3329     OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0);
3330     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, ptr), STR_PTR, 0);
3331     sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf8caselesscmp));
3332     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0);
3333     add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
3334     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
3335     }
3336     else
3337     #endif
3338     #endif
3339     {
3340     OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0);
3341     if (withchecks)
3342     jump = JUMP(SLJIT_C_ZERO);
3343     OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
3344    
3345     add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0));
3346     add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL));
3347     add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0));
3348     }
3349    
3350     if (jump != NULL)
3351     {
3352     if (emptyfail)
3353     add_jump(compiler, fallbacks, jump);
3354     else
3355     JUMPHERE(jump);
3356     }
3357     return cc + 3;
3358     }
3359    
3360     static SLJIT_INLINE uschar *compile_ref_iterator_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
3361     {
3362     DEFINE_COMPILER;
3363     fallback_common *fallback;
3364     uschar type;
3365     struct sljit_label *label;
3366     struct sljit_jump *zerolength;
3367     struct sljit_jump *jump = NULL;
3368     uschar *ccbegin = cc;
3369     int min = 0, max = 0;
3370     BOOL minimize;
3371    
3372     PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL);
3373    
3374     type = cc[3];
3375     minimize = (type & 0x1) != 0;
3376     switch(type)
3377     {
3378     case OP_CRSTAR:
3379     case OP_CRMINSTAR:
3380     min = 0;
3381     max = 0;
3382     cc += 4;
3383     break;
3384     case OP_CRPLUS:
3385     case OP_CRMINPLUS:
3386     min = 1;
3387     max = 0;
3388     cc += 4;
3389     break;
3390     case OP_CRQUERY:
3391     case OP_CRMINQUERY:
3392     min = 0;
3393     max = 1;
3394     cc += 4;
3395     break;
3396     case OP_CRRANGE:
3397     case OP_CRMINRANGE:
3398     min = GET2(cc, 3 + 1);
3399     max = GET2(cc, 3 + 3);
3400     cc += 8;
3401     break;
3402     default:
3403     SLJIT_ASSERT_STOP();
3404     break;
3405     }
3406    
3407     if (!minimize)
3408     {
3409     if (min == 0)
3410     {
3411     allocate_stack(common, 2);
3412     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3413     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
3414     /* Temporary release of STR_PTR. */
3415     OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3416     zerolength = compile_ref_checks(common, ccbegin, NULL);
3417     /* Restore if not zero length. */
3418     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3419     }
3420     else
3421     {
3422     allocate_stack(common, 1);
3423     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3424     zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);
3425     }
3426    
3427     if (min > 1 || max > 1)
3428     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, 0);
3429    
3430     label = LABEL();
3431     compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, FALSE, FALSE);
3432    
3433     if (min > 1 || max > 1)
3434     {
3435     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0);
3436     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
3437     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, TMP1, 0);
3438     if (min > 1)
3439     CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, label);
3440     if (max > 1)
3441     {
3442     jump = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, max);
3443     allocate_stack(common, 1);
3444     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3445     JUMPTO(SLJIT_JUMP, label);
3446     JUMPHERE(jump);
3447     }
3448     }
3449    
3450     if (max == 0)
3451     {
3452     /* Includes min > 1 case as well. */
3453     allocate_stack(common, 1);
3454     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3455     JUMPTO(SLJIT_JUMP, label);
3456     }
3457    
3458     JUMPHERE(zerolength);
3459     FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
3460 ph10 677
3461     decrease_call_count(common);
3462 ph10 664 return cc;
3463     }
3464    
3465     allocate_stack(common, 2);
3466     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3467     if (type != OP_CRMINSTAR)
3468     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 0);
3469    
3470     if (min == 0)
3471     {
3472     zerolength = compile_ref_checks(common, ccbegin, NULL);
3473     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3474     jump = JUMP(SLJIT_JUMP);
3475     }
3476     else
3477     zerolength = compile_ref_checks(common, ccbegin, &fallback->topfallbacks);
3478    
3479     FALLBACK_AS(iterator_fallback)->hotpath = LABEL();
3480     if (max > 0)
3481     add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, max));
3482    
3483     compile_ref_hotpath(common, ccbegin, &fallback->topfallbacks, TRUE, TRUE);
3484     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3485    
3486     if (min > 1)
3487     {
3488     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3489     OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
3490     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
3491     CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, min, FALLBACK_AS(iterator_fallback)->hotpath);
3492     }
3493     else if (max > 0)
3494     OP2(SLJIT_ADD, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, 1);
3495    
3496     if (jump != NULL)
3497     JUMPHERE(jump);
3498     JUMPHERE(zerolength);
3499 ph10 677
3500     decrease_call_count(common);
3501 ph10 664 return cc;
3502     }
3503    
3504     static SLJIT_INLINE uschar *compile_recurse_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
3505     {
3506     DEFINE_COMPILER;
3507     fallback_common *fallback;
3508     recurse_entry *entry = common->entries;
3509     recurse_entry *prev = NULL;
3510     int start = GET(cc, 1);
3511    
3512     PUSH_FALLBACK(sizeof(recurse_fallback), cc, NULL);
3513     while (entry != NULL)
3514     {
3515     if (entry->start == start)
3516     break;
3517     prev = entry;
3518     entry = entry->next;
3519     }
3520    
3521     if (entry == NULL)
3522     {
3523     entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));
3524     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3525     return NULL;
3526     entry->next = NULL;
3527     entry->entry = NULL;
3528     entry->calls = NULL;
3529     entry->start = start;
3530    
3531     if (prev != NULL)
3532     prev->next = entry;
3533     else
3534     common->entries = entry;
3535     }
3536    
3537     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0));
3538     allocate_stack(common, 1);
3539     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
3540    
3541     if (entry->entry == NULL)
3542     add_jump(compiler, &entry->calls, JUMP(SLJIT_FAST_CALL));
3543     else
3544     JUMPTO(SLJIT_FAST_CALL, entry->entry);
3545     /* Leave if the match is failed. */
3546     add_jump(compiler, &fallback->topfallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0));
3547     return cc + 1 + LINK_SIZE;
3548     }
3549    
3550     static uschar *compile_assert_hotpath(compiler_common *common, uschar *cc, assert_fallback *fallback, BOOL conditional)
3551     {
3552     DEFINE_COMPILER;
3553     int framesize;
3554     int localptr;
3555     fallback_common altfallback;
3556     uschar *ccbegin;
3557     uschar opcode;
3558     uschar bra = OP_BRA;
3559     jump_list *tmp = NULL;
3560     jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks;
3561     jump_list **found;
3562     /* Saving previous accept variables. */
3563     struct sljit_label *save_acceptlabel = common->acceptlabel;
3564     struct sljit_jump *jump;
3565     struct sljit_jump *brajump = NULL;
3566     jump_list *save_accept = common->accept;
3567    
3568     if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
3569     {
3570     SLJIT_ASSERT(!conditional);
3571     bra = *cc;
3572     cc++;
3573     }
3574     localptr = PRIV(cc);
3575     SLJIT_ASSERT(localptr != 0);
3576     framesize = get_framesize(common, cc, FALSE);
3577     fallback->framesize = framesize;
3578     fallback->localptr = localptr;
3579     opcode = *cc;
3580     SLJIT_ASSERT(opcode >= OP_ASSERT && opcode <= OP_ASSERTBACK_NOT);
3581     found = (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) ? &tmp : target;
3582     ccbegin = cc;
3583     cc += GET(cc, 1);
3584    
3585     if (bra == OP_BRAMINZERO)
3586     {
3587     /* This is a braminzero fallback path. */
3588     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3589     free_stack(common, 1);
3590     brajump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3591     }
3592    
3593     if (framesize < 0)
3594     {
3595     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
3596     allocate_stack(common, 1);
3597     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3598     }
3599     else
3600     {
3601     allocate_stack(common, framesize + 2);
3602     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3603     OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + 1));
3604     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
3605     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3606     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
3607     init_frame(common, ccbegin, framesize + 1, 2, FALSE);
3608     }
3609    
3610     memset(&altfallback, 0, sizeof(fallback_common));
3611     while (1)
3612     {
3613     common->acceptlabel = NULL;
3614     common->accept = NULL;
3615     altfallback.top = NULL;
3616     altfallback.topfallbacks = NULL;
3617    
3618     if (*ccbegin == OP_ALT)
3619     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3620    
3621     altfallback.cc = ccbegin;
3622     compile_hotpath(common, ccbegin + 1 + LINK_SIZE, cc, &altfallback);
3623     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3624     {
3625     common->acceptlabel = save_acceptlabel;
3626     common->accept = save_accept;
3627     return NULL;
3628     }
3629     common->acceptlabel = LABEL();
3630     if (common->accept != NULL)
3631     set_jumps(common->accept, common->acceptlabel);
3632    
3633     if (framesize < 0)
3634     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3635    
3636     if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT)
3637     {
3638     /* We know that STR_PTR was stored on the top of the stack. */
3639     if (conditional)
3640     {
3641     if (framesize < 0)
3642     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3643     else
3644     {
3645     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3646     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), (framesize + 1) * sizeof(sljit_w));
3647     }
3648     }
3649     else if (bra == OP_BRAZERO)
3650     {
3651     if (framesize < 0)
3652     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3653     else
3654     {
3655     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3656     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
3657     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
3658     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_w));
3659     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
3660     }
3661     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3662     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3663     }
3664     else if (bra == OP_BRAMINZERO)
3665     {
3666     if (framesize >= 0)
3667     {
3668     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3669     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
3670     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
3671     }
3672     }
3673     }
3674     add_jump(compiler, found, JUMP(SLJIT_JUMP));
3675    
3676     compile_fallbackpath(common, altfallback.top);
3677     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
3678     {
3679     common->acceptlabel = save_acceptlabel;
3680     common->accept = save_accept;
3681     return NULL;
3682     }
3683     set_jumps(altfallback.topfallbacks, LABEL());
3684    
3685     if (*cc != OP_ALT)
3686     break;
3687    
3688     ccbegin = cc;
3689     cc += GET(cc, 1);
3690     }
3691     /* None of them matched. */
3692    
3693     if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
3694     {
3695     /* Assert is failed. */
3696     if (conditional || bra == OP_BRAZERO)
3697     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3698     if (framesize < 0)
3699     {
3700     /* The topmost item should be 0. */
3701     if (bra == OP_BRAZERO)
3702     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3703     else
3704     free_stack(common, 1);
3705     }
3706     else
3707     {
3708     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3709     if (framesize > 0)
3710     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
3711     /* The topmost item should be 0. */
3712     if (bra == OP_BRAZERO)
3713     {
3714     free_stack(common, framesize + 1);
3715     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3716     }
3717     else
3718     free_stack(common, framesize + 2);
3719     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
3720     if (framesize > 0)
3721     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0);
3722     }
3723     jump = JUMP(SLJIT_JUMP);
3724     if (bra != OP_BRAZERO)
3725     add_jump(compiler, target, jump);
3726    
3727     /* Assert is successful. */
3728     set_jumps(tmp, LABEL());
3729     if (framesize < 0)
3730     {
3731     /* We know that STR_PTR was stored on the top of the stack. */
3732     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0);
3733     /* Keep the STR_PTR on the top of the stack. */
3734     if (bra == OP_BRAZERO)
3735     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3736     else if (bra == OP_BRAMINZERO)
3737     {
3738     OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
3739     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3740     }
3741     }
3742     else
3743     {
3744     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3745     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), (framesize + 1) * sizeof(sljit_w));
3746     if (bra == OP_BRAZERO)
3747     {
3748     allocate_stack(common, 1);
3749     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
3750     }
3751     else if (bra == OP_BRAMINZERO)
3752     {
3753     allocate_stack(common, 1);
3754     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3755     }
3756     }
3757    
3758     if (bra == OP_BRAZERO)
3759     {
3760     fallback->hotpath = LABEL();
3761     sljit_set_label(jump, fallback->hotpath);
3762     }
3763     else if (bra == OP_BRAMINZERO)
3764     {
3765     JUMPTO(SLJIT_JUMP, fallback->hotpath);
3766     JUMPHERE(brajump);
3767     if (framesize >= 0)
3768     {
3769     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3770     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
3771     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w));
3772     }
3773     set_jumps(fallback->common.topfallbacks, LABEL());
3774     }
3775     }
3776     else
3777     {
3778     /* AssertNot is successful. */
3779     if (framesize < 0)
3780     {
3781     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3782     if (bra != OP_BRA)
3783     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3784     else
3785     free_stack(common, 1);
3786     }
3787     else
3788     {
3789     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3790     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3791     if (framesize > 0)
3792     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2));
3793     /* The topmost item should be 0. */
3794     if (bra != OP_BRA)
3795     {
3796     free_stack(common, framesize + 1);
3797     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
3798     }
3799     else
3800     free_stack(common, framesize + 2);
3801     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0);
3802     if (framesize > 0)
3803     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0);
3804     }
3805    
3806     if (bra == OP_BRAZERO)
3807     fallback->hotpath = LABEL();
3808     else if (bra == OP_BRAMINZERO)
3809     {
3810     JUMPTO(SLJIT_JUMP, fallback->hotpath);
3811     JUMPHERE(brajump);
3812     }
3813    
3814     if (bra != OP_BRA)
3815     {
3816     SLJIT_ASSERT(found == &fallback->common.topfallbacks);
3817     set_jumps(fallback->common.topfallbacks, LABEL());
3818     fallback->common.topfallbacks = NULL;
3819     }
3820     }
3821    
3822     common->acceptlabel = save_acceptlabel;
3823     common->accept = save_accept;
3824     return cc + 1 + LINK_SIZE;
3825     }
3826    
3827     /*
3828     Handling bracketed expressions is probably the most complex part.
3829    
3830     Stack layout naming characters:
3831     S - Push the current STR_PTR
3832     0 - Push a 0 (NULL)
3833     A - Push the current STR_PTR. Needed for restoring the STR_PTR
3834     before the next alternative. Not pushed if there are no alternatives.
3835     M - Any values pushed by the current alternative. Can be empty, or anything.
3836 zherczeg 696 C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.
3837 ph10 664 L - Push the previous local (pointed by localptr) to the stack
3838     () - opional values stored on the stack
3839     ()* - optonal, can be stored multiple times
3840    
3841     The following list shows the regular expression templates, their PCRE byte codes
3842     and stack layout supported by pcre-sljit.
3843    
3844     (?:) OP_BRA | OP_KET A M
3845     () OP_CBRA | OP_KET C M
3846     (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*
3847     OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*
3848     (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*
3849     OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*
3850     ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*
3851     OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*
3852     ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*
3853     OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*
3854     (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )
3855     (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )
3856     ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )
3857     ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )
3858     (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*
3859     OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*
3860     (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*
3861     OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*
3862     ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*
3863     OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*
3864     ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*
3865     OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*
3866    
3867    
3868     Stack layout naming characters:
3869     A - Push the alternative index (starting from 0) on the stack.
3870     Not pushed if there is no alternatives.
3871     M - Any values pushed by the current alternative. Can be empty, or anything.
3872    
3873     The next list shows the possible content of a bracket:
3874     (|) OP_*BRA | OP_ALT ... M A
3875     (?()|) OP_*COND | OP_ALT M A
3876     (?>|) OP_ONCE | OP_ALT ... [stack trace] M A
3877     Or nothing, if trace is unnecessary
3878     */
3879    
3880     static uschar *compile_bracket_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
3881     {
3882     DEFINE_COMPILER;
3883     fallback_common *fallback;
3884     uschar opcode;
3885     int localptr = 0;
3886     int offset = 0;
3887     int stacksize;
3888     uschar *ccbegin;
3889     uschar *hotpath;
3890     uschar bra = OP_BRA;
3891     uschar ket;
3892     assert_fallback *assert;
3893     BOOL has_alternatives;
3894     struct sljit_jump *jump;
3895     struct sljit_jump *skip;
3896     struct sljit_label *rmaxlabel = NULL;
3897     struct sljit_jump *braminzerojump = NULL;
3898    
3899     PUSH_FALLBACK(sizeof(bracket_fallback), cc, NULL);
3900    
3901     if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO)
3902     {
3903     bra = *cc;
3904     cc++;
3905     opcode = *cc;
3906     }
3907    
3908     opcode = *cc;
3909     ccbegin = cc;
3910     if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF)
3911     {
3912     /* Drop this bracket_fallback. */
3913     parent->top = fallback->prev;
3914     return bracketend(cc);
3915     }
3916    
3917     ket = *(bracketend(cc) - 1 - LINK_SIZE);
3918     SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN);
3919     SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX)));
3920     cc += GET(cc, 1);
3921     has_alternatives = *cc == OP_ALT || opcode == OP_COND || opcode == OP_SCOND;
3922     if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
3923     opcode = OP_SCOND;
3924    
3925     if (opcode == OP_CBRA || opcode == OP_SCBRA)
3926     {
3927     /* Capturing brackets has a pre-allocated space. */
3928     offset = GET2(ccbegin, 1 + LINK_SIZE);
3929     localptr = OVECTOR_PRIV(offset);
3930     offset <<= 1;
3931     FALLBACK_AS(bracket_fallback)->localptr = localptr;
3932     }
3933     else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND)
3934     {
3935     /* Other brackets simply allocate the next entry. */
3936     localptr = PRIV(ccbegin);
3937     SLJIT_ASSERT(localptr != 0);
3938     FALLBACK_AS(bracket_fallback)->localptr = localptr;
3939     if (opcode == OP_ONCE)
3940     FALLBACK_AS(bracket_fallback)->u.framesize = get_framesize(common, ccbegin, FALSE);
3941     }
3942    
3943     /* Instructions before the first alternative. */
3944     stacksize = 0;
3945     if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
3946     stacksize++;
3947     if (bra == OP_BRAZERO)
3948     stacksize++;
3949    
3950     if (stacksize > 0)
3951     allocate_stack(common, stacksize);
3952    
3953     stacksize = 0;
3954     if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO))
3955     {
3956     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
3957     stacksize++;
3958     }
3959    
3960     if (bra == OP_BRAZERO)
3961     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
3962    
3963     if (bra == OP_BRAMINZERO)
3964     {
3965     /* This is a fallback path! (Since the hot-path of OP_BRAMINZERO matches to the empty string) */
3966     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
3967     if (ket != OP_KETRMIN)
3968     {
3969     free_stack(common, 1);
3970     braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3971     }
3972     else
3973     {
3974     if (opcode == OP_ONCE || opcode >= OP_SBRA)
3975     {
3976     jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3977     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3978     /* Nothing stored during the first run. */
3979     skip = JUMP(SLJIT_JUMP);
3980     JUMPHERE(jump);
3981     /* Checking zero-length iteration. */
3982     if (opcode != OP_ONCE || FALLBACK_AS(bracket_fallback)->u.framesize < 0)
3983     {
3984     /* When we come from outside, localptr contains the previous STR_PTR. */
3985     braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3986     }
3987     else
3988     {
3989     /* Except when the whole stack frame must be saved. */
3990     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
3991     braminzerojump = CMP(SLJIT_C_EQUAL, STR_PTR, 0, SLJIT_MEM1(TMP1), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w));
3992     }
3993     JUMPHERE(skip);
3994     }
3995     else
3996     {
3997     jump = CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_IMM, 0);
3998     OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
3999     JUMPHERE(jump);
4000     }
4001     }
4002     }
4003    
4004     if (ket == OP_KETRMIN)
4005     FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();
4006    
4007     if (ket == OP_KETRMAX)
4008     {
4009     rmaxlabel = LABEL();
4010     if (has_alternatives && opcode != OP_ONCE && opcode < OP_SBRA)
4011     FALLBACK_AS(bracket_fallback)->althotpath = rmaxlabel;
4012     }
4013    
4014     /* Handling capturing brackets and alternatives. */
4015     if (opcode == OP_ONCE)
4016     {
4017     if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)
4018     {
4019     /* Neither capturing brackets nor recursions are not found in the block. */
4020     if (ket == OP_KETRMIN)
4021     {
4022     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4023     allocate_stack(common, 2);
4024     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4025     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4026     OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w));
4027     }
4028     else if (ket == OP_KETRMAX || has_alternatives)
4029     {
4030     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4031     allocate_stack(common, 1);
4032     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4033     }
4034     else
4035     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4036     }
4037     else
4038     {
4039     if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives)
4040     {
4041     allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 2);
4042     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4043     OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize + 1));
4044     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4045     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4046     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
4047     init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize + 1, 2, FALSE);
4048     }
4049     else
4050     {
4051     allocate_stack(common, FALLBACK_AS(bracket_fallback)->u.framesize + 1);
4052     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4053     OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(FALLBACK_AS(bracket_fallback)->u.framesize));
4054     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4055     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4056     init_frame(common, ccbegin, FALLBACK_AS(bracket_fallback)->u.framesize, 1, FALSE);
4057     }
4058     }
4059     }
4060     else if (opcode == OP_CBRA || opcode == OP_SCBRA)
4061     {
4062     /* Saving the previous values. */
4063 zherczeg 696 allocate_stack(common, 3);
4064 ph10 664 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
4065     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
4066     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4067     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4068 zherczeg 696 OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4069 ph10 664 OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
4070 zherczeg 695 OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
4071 ph10 664 }
4072     else if (opcode == OP_SBRA || opcode == OP_SCOND)
4073     {
4074     /* Saving the previous value. */
4075     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4076     allocate_stack(common, 1);
4077     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0);
4078     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
4079     }
4080     else if (has_alternatives)
4081     {
4082     /* Pushing the starting string pointer. */
4083     allocate_stack(common, 1);
4084     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4085     }
4086    
4087     /* Generating code for the first alternative. */
4088     hotpath = ccbegin + 1 + LINK_SIZE;
4089     if (offset != 0)
4090     hotpath += 2;
4091     if (opcode == OP_COND || opcode == OP_SCOND)
4092     {
4093     if (*hotpath == OP_CREF)
4094     {
4095     add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed),
4096     CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR((GET2(hotpath, 1) << 1)), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)));
4097     hotpath += 3;
4098     }
4099     else
4100     {
4101     SLJIT_ASSERT(*hotpath >= OP_ASSERT && *hotpath <= OP_ASSERTBACK_NOT);
4102     /* Similar code as PUSH_FALLBACK macro. */
4103     assert = sljit_alloc_memory(compiler, sizeof(assert_fallback));
4104     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4105     return NULL;
4106     memset(assert, 0, sizeof(assert_fallback));
4107     assert->common.cc = hotpath;
4108     FALLBACK_AS(bracket_fallback)->u.assert = assert;
4109     hotpath = compile_assert_hotpath(common, hotpath, assert, TRUE);
4110     }
4111     }
4112    
4113     compile_hotpath(common, hotpath, cc, fallback);
4114     if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
4115     return NULL;
4116    
4117     if (opcode == OP_ONCE)
4118     {
4119     if (FALLBACK_AS(bracket_fallback)->u.framesize < 0)
4120     {
4121     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4122     /* TMP2 which is set here used by OP_KETRMAX below. */
4123     if (ket == OP_KETRMAX)
4124     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0);
4125     else if (ket == OP_KETRMIN)
4126     {
4127     /* Move the STR_PTR to the localptr. */
4128     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0);
4129     }
4130     }
4131     else if (ket == OP_KETRMAX)
4132     {
4133     /* TMP2 which is set here used by OP_KETRMAX below. */
4134     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4135     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w));
4136     }
4137     }
4138    
4139     stacksize = 0;
4140     if (ket != OP_KET || bra != OP_BRA)
4141     stacksize++;
4142     if (has_alternatives && opcode != OP_ONCE)
4143     stacksize++;
4144    
4145     if (stacksize > 0)
4146     allocate_stack(common, stacksize);
4147    
4148     stacksize = 0;
4149     if (ket != OP_KET)
4150     {
4151     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0);
4152     stacksize++;
4153     }
4154     else if (bra != OP_BRA)
4155     {
4156     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
4157     stacksize++;
4158     }
4159    
4160     if (has_alternatives)
4161     {
4162     if (opcode != OP_ONCE)
4163     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
4164     if (ket != OP_KETRMAX)
4165     FALLBACK_AS(bracket_fallback)->althotpath = LABEL();
4166     }
4167    
4168     /* Must be after the hotpath label. */
4169     if (offset != 0)
4170     {
4171     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4172     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0);
4173     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0);
4174     }
4175    
4176     if (ket == OP_KETRMAX)
4177     {
4178     if (opcode == OP_ONCE || opcode >= OP_SBRA)
4179     {
4180     if (has_alternatives)
4181     FALLBACK_AS(bracket_fallback)->althotpath = LABEL();
4182     /* Checking zero-length iteration. */
4183     if (opcode != OP_ONCE)
4184     CMPTO(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STR_PTR, 0, rmaxlabel);
4185     else
4186     /* TMP2 must contain the starting STR_PTR. */
4187     CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, rmaxlabel);
4188     }
4189     else
4190     JUMPTO(SLJIT_JUMP, rmaxlabel);
4191     FALLBACK_AS(bracket_fallback)->recursivehotpath = LABEL();
4192     }
4193    
4194     if (bra == OP_BRAZERO)
4195     FALLBACK_AS(bracket_fallback)->zerohotpath = LABEL();
4196    
4197     if (bra == OP_BRAMINZERO)
4198     {
4199     /* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */
4200     JUMPTO(SLJIT_JUMP, ((braminzero_fallback*)parent)->hotpath);
4201     if (braminzerojump != NULL)
4202     {
4203     JUMPHERE(braminzerojump);
4204     /* We need to release the end pointer to perform the
4205     fallback for the zero-length iteration. When
4206     framesize is < 0, OP_ONCE will do the release itself. */
4207     if (opcode == OP_ONCE && FALLBACK_AS(bracket_fallback)->u.framesize >= 0)
4208     {
4209     OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4210     add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL));
4211     }
4212     else if (ket == OP_KETRMIN && opcode != OP_ONCE)
4213     free_stack(common, 1);
4214     }
4215     /* Continue to the normal fallback. */
4216     }
4217    
4218 ph10 677 if ((ket != OP_KET && bra != OP_BRAMINZERO) || bra == OP_BRAZERO)
4219     decrease_call_count(common);
4220    
4221 ph10 664 /* Skip the other alternatives. */
4222     while (*cc == OP_ALT)
4223     cc += GET(cc, 1);
4224     cc += 1 + LINK_SIZE;
4225     return cc;
4226     }
4227    
4228     static uschar *compile_bracketpos_hotpath(compiler_common *common, uschar *cc, fallback_common *parent)
4229     {
4230     DEFINE_COMPILER;
4231     fallback_common *fallback;
4232     uschar opcode;
4233     int localptr;
4234     int cbraprivptr = 0;
4235     int framesize;
4236     int stacksize;
4237     int offset = 0;
4238     BOOL zero = FALSE;
4239     uschar *ccbegin = NULL;
4240     int stack;
4241     struct sljit_label *loop = NULL;
4242     struct jump_list *emptymatch = NULL;
4243    
4244     PUSH_FALLBACK(sizeof(bracketpos_fallback), cc, NULL);
4245     if (*cc == OP_BRAPOSZERO)
4246     {
4247     zero = TRUE;
4248     cc++;
4249     }
4250    
4251     opcode = *cc;
4252     localptr = PRIV(cc);
4253     SLJIT_ASSERT(localptr != 0);
4254     FALLBACK_AS(bracketpos_fallback)->localptr = localptr;
4255     switch(opcode)
4256     {
4257     case OP_BRAPOS:
4258     case OP_SBRAPOS:
4259     ccbegin = cc + 1 + LINK_SIZE;
4260     break;
4261    
4262     case OP_CBRAPOS:
4263     case OP_SCBRAPOS:
4264     offset = GET2(cc, 1 + LINK_SIZE);
4265     cbraprivptr = OVECTOR_PRIV(offset);
4266     offset <<= 1;
4267     ccbegin = cc + 1 + LINK_SIZE + 2;
4268     break;
4269    
4270     default:
4271     SLJIT_ASSERT_STOP();
4272     break;
4273     }
4274    
4275     framesize = get_framesize(common, cc, FALSE);
4276     FALLBACK_AS(bracketpos_fallback)->framesize = framesize;
4277     if (framesize < 0)
4278     {
4279 zherczeg 696 stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1;
4280 ph10 664 if (!zero)
4281     stacksize++;
4282     FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;
4283     allocate_stack(common, stacksize);
4284     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, STACK_TOP, 0);
4285    
4286     if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS)
4287     {
4288     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset));
4289     OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1));
4290     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0);
4291     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0);
4292     }
4293     else
4294     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
4295    
4296     if (!zero)
4297     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 1);
4298     }
4299     else
4300     {
4301     stacksize = framesize + 1;
4302     if (!zero)
4303     stacksize++;
4304     if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
4305     stacksize++;
4306     FALLBACK_AS(bracketpos_fallback)->stacksize = stacksize;
4307     allocate_stack(common, stacksize);
4308    
4309     OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr);
4310     OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1));
4311     OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP2, 0);
4312     stack = 0;
4313     if (!zero)
4314     {
4315     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1);
4316     stack++;
4317     }
4318     if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS)
4319     {
4320     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0);
4321     stack++;
4322     }
4323     OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0);
4324