/[pcre]/code/trunk/pcre_jit_compile.c
ViewVC logotype

Contents of /code/trunk/pcre_jit_compile.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.5