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