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