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

  ViewVC Help
Powered by ViewVC 1.1.5