/[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 708 - (show annotations) (download)
Fri Sep 23 11:03:03 2011 UTC (2 years, 7 months ago) by ph10
File MIME type: text/plain
File size: 196232 byte(s)
File tidies for 8.20-RC2 release.

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

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12