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