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