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

  ViewVC Help
Powered by ViewVC 1.1.5