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