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