/[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 688 - (show annotations) (download)
Fri Sep 9 09:35:48 2011 UTC (3 years, 1 month ago) by ph10
File MIME type: text/plain
File size: 197150 byte(s)
Tidy up interface from pcre_study() to JIT, and ignore a minimum length of 0.

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

webmaster@exim.org
ViewVC Help
Powered by ViewVC 1.1.12