/[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 676 - (show annotations) (download)
Sat Aug 27 15:53:04 2011 UTC (3 years, 2 months ago) by ph10
File MIME type: text/plain
File size: 195735 byte(s)
Give PCRE_ERROR_JIT_STACKLIMIT when JIT runs out of stack.

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

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12