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