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