/[pcre]/code/branches/pcre16/pcre_jit_compile.c
ViewVC logotype

Contents of /code/branches/pcre16/pcre_jit_compile.c

Parent Directory Parent Directory | Revision Log Revision Log


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