/[pcre]/code/trunk/pcre_jit_compile.c
ViewVC logotype

Contents of /code/trunk/pcre_jit_compile.c

Parent Directory Parent Directory | Revision Log Revision Log


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