1 /*************************************************
2 * Perl-Compatible Regular Expressions *
3 *************************************************/
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.
8 Written by Philip Hazel
9 Copyright (c) 1997-2012 University of Cambridge
11 The machine code generator part (this module) was written by Zoltan Herczeg
12 Copyright (c) 2010-2012
14 -----------------------------------------------------------------------------
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions are met:
18 * Redistributions of source code must retain the above copyright notice,
19 this list of conditions and the following disclaimer.
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.
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.
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 -----------------------------------------------------------------------------
45 #include "pcre_internal.h"
49 /* All-in-one: Since we use the JIT compiler only from here,
50 we just include it. This way we don't need to touch the build
53 #define SLJIT_MALLOC(size) (PUBL(malloc))(size)
54 #define SLJIT_FREE(ptr) (PUBL(free))(ptr)
55 #define SLJIT_CONFIG_AUTO 1
56 #define SLJIT_CONFIG_STATIC 1
57 #define SLJIT_VERBOSE 0
60 #include "sljit/sljitLir.c"
62 #if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
63 #error Unsupported architecture
66 /* Allocate memory on the stack. Fast, but limited size. */
67 #define LOCAL_SPACE_SIZE 32768
69 #define STACK_GROWTH_RATE 8192
71 /* Enable to check that the allocation could destroy temporaries. */
72 #if defined SLJIT_DEBUG && SLJIT_DEBUG
73 #define DESTROY_REGISTERS 1
77 Short summary about the backtracking mechanism empolyed by the jit code generator:
79 The code generator follows the recursive nature of the PERL compatible regular
80 expressions. The basic blocks of regular expressions are condition checkers
81 whose execute different commands depending on the result of the condition check.
82 The relationship between the operators can be horizontal (concatenation) and
83 vertical (sub-expression) (See struct backtrack_common for more details).
85 'ab' - 'a' and 'b' regexps are concatenated
86 'a+' - 'a' is the sub-expression of the '+' operator
88 The condition checkers are boolean (true/false) checkers. Machine code is generated
89 for the checker itself and for the actions depending on the result of the checker.
90 The 'true' case is called as the try path (expected path), and the other is called as
91 the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken
92 branches on the try path.
94 Greedy star operator (*) :
95 Try path: match happens.
96 Backtrack path: match failed.
97 Non-greedy star operator (*?) :
98 Try path: no need to perform a match.
99 Backtrack path: match is required.
101 The following example shows how the code generated for a capturing bracket
102 with two alternatives. Let A, B, C, D are arbirary regular expressions, and
103 we have the following regular expression:
107 The generated code will be the following:
110 '(' try path (pushing arguments to the stack)
112 ')' try path (pushing arguments to the stack)
114 return with successful match
117 ')' backtrack path (If we arrived from "C" jump to the backtrack of "C")
124 Notice, that the order of backtrack code paths are the opposite of the fast
125 code paths. In this way the topmost value on the stack is always belong
126 to the current backtrack code path. The backtrack path must check
127 whether there is a next alternative. If so, it needs to jump back to
128 the try path eventually. Otherwise it needs to clear out its own stack
129 frame and continue the execution on the backtrack code paths.
135 Atomic blocks and asserts require reloading the values of local variables
136 when the backtrack mechanism performed. Because of OP_RECURSE, the locals
137 are not necessarly known in compile time, thus we need a dynamic restore
140 The stack frames are stored in a chain list, and have the following format:
141 ([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]
143 Thus we can restore the locals to a particular point in the stack.
146 typedef struct jit_arguments
{
147 /* Pointers first. */
148 struct sljit_stack
*stack
;
149 const pcre_uchar
*str
;
150 const pcre_uchar
*begin
;
151 const pcre_uchar
*end
;
153 pcre_uchar
*uchar_ptr
;
154 pcre_uchar
*mark_ptr
;
155 /* Everything else after. */
161 pcre_uint8 notempty_atstart
;
164 typedef struct executable_functions
{
165 void *executable_funcs
[JIT_NUMBER_OF_COMPILE_MODES
];
166 PUBL(jit_callback
) callback
;
168 sljit_uw executable_sizes
[JIT_NUMBER_OF_COMPILE_MODES
];
169 } executable_functions
;
171 typedef struct jump_list
{
172 struct sljit_jump
*jump
;
173 struct jump_list
*next
;
176 enum stub_types
{ stack_alloc
};
178 typedef struct stub_list
{
179 enum stub_types type
;
181 struct sljit_jump
*start
;
182 struct sljit_label
*leave
;
183 struct stub_list
*next
;
186 typedef int (SLJIT_CALL
*jit_function
)(jit_arguments
*args
);
188 /* The following structure is the key data type for the recursive
189 code generator. It is allocated by compile_trypath, and contains
190 the aguments for compile_backtrackpath. Must be the first member
191 of its descendants. */
192 typedef struct backtrack_common
{
193 /* Concatenation stack. */
194 struct backtrack_common
*prev
;
195 jump_list
*nextbacktracks
;
196 /* Internal stack (for component operators). */
197 struct backtrack_common
*top
;
198 jump_list
*topbacktracks
;
199 /* Opcode pointer. */
203 typedef struct assert_backtrack
{
204 backtrack_common common
;
205 jump_list
*condfailed
;
206 /* Less than 0 (-1) if a frame is not needed. */
208 /* Points to our private memory word on the stack. */
211 struct sljit_label
*trypath
;
214 typedef struct bracket_backtrack
{
215 backtrack_common common
;
216 /* Where to coninue if an alternative is successfully matched. */
217 struct sljit_label
*alttrypath
;
218 /* For rmin and rmax iterators. */
219 struct sljit_label
*recursivetrypath
;
220 /* For greedy ? operator. */
221 struct sljit_label
*zerotrypath
;
222 /* Contains the branches of a failed condition. */
224 /* Both for OP_COND, OP_SCOND. */
225 jump_list
*condfailed
;
226 assert_backtrack
*assert;
227 /* For OP_ONCE. -1 if not needed. */
230 /* Points to our private memory word on the stack. */
234 typedef struct bracketpos_backtrack
{
235 backtrack_common common
;
236 /* Points to our private memory word on the stack. */
238 /* Reverting stack is needed. */
240 /* Allocated stack size. */
242 } bracketpos_backtrack
;
244 typedef struct braminzero_backtrack
{
245 backtrack_common common
;
246 struct sljit_label
*trypath
;
247 } braminzero_backtrack
;
249 typedef struct iterator_backtrack
{
250 backtrack_common common
;
251 /* Next iteration. */
252 struct sljit_label
*trypath
;
253 } iterator_backtrack
;
255 typedef struct recurse_entry
{
256 struct recurse_entry
*next
;
257 /* Contains the function entry. */
258 struct sljit_label
*entry
;
259 /* Collects the calls until the function is not created. */
261 /* Points to the starting opcode. */
265 typedef struct recurse_backtrack
{
266 backtrack_common common
;
269 typedef struct compiler_common
{
270 struct sljit_compiler
*compiler
;
273 /* Opcode local area direct map. */
276 /* OVector starting point. Must be divisible by 2. */
278 /* Last known position of the requested byte. */
280 /* Head of the last recursion. */
282 /* First inspected character for partial matching. */
284 /* Starting pointer for partial soft matches. */
286 /* End pointer of the first line. */
288 /* Points to the marked string. */
292 const pcre_uint8
*fcc
;
303 sljit_w name_entry_size
;
305 /* Labels and jump lists. */
306 struct sljit_label
*partialmatchlabel
;
307 struct sljit_label
*leavelabel
;
308 struct sljit_label
*acceptlabel
;
310 recurse_entry
*entries
;
311 recurse_entry
*currententry
;
312 jump_list
*partialmatch
;
315 jump_list
*calllimit
;
316 jump_list
*stackalloc
;
317 jump_list
*revertframes
;
318 jump_list
*wordboundary
;
319 jump_list
*anynewline
;
322 jump_list
*casefulcmp
;
323 jump_list
*caselesscmp
;
330 jump_list
*utfreadchar
;
332 jump_list
*utfreadtype8
;
334 #endif /* SUPPORT_UTF */
336 jump_list
*getunichartype
;
337 jump_list
*getunichartype_2
;
338 jump_list
*getunicharscript
;
342 /* For byte_sequence_compare. */
344 typedef struct compare_context
{
347 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
354 sljit_ub asuchars
[4];
356 #ifdef COMPILE_PCRE16
357 sljit_uh asuchars
[2];
366 sljit_ub asuchars
[4];
368 #ifdef COMPILE_PCRE16
369 sljit_uh asuchars
[2];
378 frame_setstrbegin
= -1,
382 /* Undefine sljit macros. */
385 /* Used for accessing the elements of the stack. */
386 #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w))
388 #define TMP1 SLJIT_TEMPORARY_REG1
389 #define TMP2 SLJIT_TEMPORARY_REG3
390 #define TMP3 SLJIT_TEMPORARY_EREG2
391 #define STR_PTR SLJIT_SAVED_REG1
392 #define STR_END SLJIT_SAVED_REG2
393 #define STACK_TOP SLJIT_TEMPORARY_REG2
394 #define STACK_LIMIT SLJIT_SAVED_REG3
395 #define ARGUMENTS SLJIT_SAVED_EREG1
396 #define CALL_COUNT SLJIT_SAVED_EREG2
397 #define RETURN_ADDR SLJIT_TEMPORARY_EREG1
400 /* These two locals can be used by the current opcode. */
401 #define LOCALS0 (0 * sizeof(sljit_w))
402 #define LOCALS1 (1 * sizeof(sljit_w))
403 /* Two local variables for possessive quantifiers (char1 cannot use them). */
404 #define POSSESSIVE0 (2 * sizeof(sljit_w))
405 #define POSSESSIVE1 (3 * sizeof(sljit_w))
406 /* Max limit of recursions. */
407 #define CALL_LIMIT (4 * sizeof(sljit_w))
408 /* The output vector is stored on the stack, and contains pointers
409 to characters. The vector data is divided into two groups: the first
410 group contains the start / end character pointers, and the second is
411 the start pointers when the end of the capturing group has not yet reached. */
412 #define OVECTOR_START (common->ovector_start)
413 #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w))
414 #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w))
415 #define PRIV_DATA(cc) (common->localptrs[(cc) - common->start])
418 #define MOV_UCHAR SLJIT_MOV_UB
419 #define MOVU_UCHAR SLJIT_MOVU_UB
421 #ifdef COMPILE_PCRE16
422 #define MOV_UCHAR SLJIT_MOV_UH
423 #define MOVU_UCHAR SLJIT_MOVU_UH
425 #error Unsupported compiling mode
430 #define DEFINE_COMPILER \
431 struct sljit_compiler *compiler = common->compiler
432 #define OP1(op, dst, dstw, src, srcw) \
433 sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
434 #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
435 sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
437 sljit_emit_label(compiler)
439 sljit_emit_jump(compiler, (type))
440 #define JUMPTO(type, label) \
441 sljit_set_label(sljit_emit_jump(compiler, (type)), (label))
442 #define JUMPHERE(jump) \
443 sljit_set_label((jump), sljit_emit_label(compiler))
444 #define CMP(type, src1, src1w, src2, src2w) \
445 sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
446 #define CMPTO(type, src1, src1w, src2, src2w, label) \
447 sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
448 #define COND_VALUE(op, dst, dstw, type) \
449 sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type))
450 #define GET_LOCAL_BASE(dst, dstw, offset) \
451 sljit_get_local_base(compiler, (dst), (dstw), (offset))
453 static pcre_uchar
* bracketend(pcre_uchar
* cc
)
455 SLJIT_ASSERT((*cc
>= OP_ASSERT
&& *cc
<= OP_ASSERTBACK_NOT
) || (*cc
>= OP_ONCE
&& *cc
<= OP_SCOND
));
456 do cc
+= GET(cc
, 1); while (*cc
== OP_ALT
);
457 SLJIT_ASSERT(*cc
>= OP_KET
&& *cc
<= OP_KETRPOS
);
462 /* Functions whose might need modification for all new supported opcodes:
471 compile_backtrackpath
474 static pcre_uchar
*next_opcode(compiler_common
*common
, pcre_uchar
*cc
)
476 SLJIT_UNUSED_ARG(common
);
482 case OP_NOT_WORD_BOUNDARY
:
483 case OP_WORD_BOUNDARY
:
486 case OP_NOT_WHITESPACE
:
488 case OP_NOT_WORDCHAR
:
509 case OP_TYPEMINQUERY
:
512 case OP_TYPEPOSQUERY
:
526 case OP_ASSERT_ACCEPT
:
532 if (common
->utf
) return NULL
;
572 case OP_NOTMINQUERYI
:
575 case OP_NOTPOSQUERYI
:
578 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
600 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
624 return cc
+ 1 + 2 * IMM2_SIZE
;
628 return cc
+ 1 + 32 / sizeof(pcre_uchar
);
630 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
632 return cc
+ GET(cc
, 1);
639 case OP_ASSERTBACK_NOT
:
654 return cc
+ 1 + LINK_SIZE
;
660 return cc
+ 1 + LINK_SIZE
+ IMM2_SIZE
;
663 return cc
+ 1 + 2 + cc
[1];
670 static int get_localspace(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
)
673 pcre_uchar
*alternative
;
674 /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
680 common
->has_set_som
= TRUE
;
687 case OP_ASSERTBACK_NOT
:
694 localspace
+= sizeof(sljit_w
);
700 localspace
+= sizeof(sljit_w
);
701 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
705 /* Might be a hidden SCOND. */
706 alternative
= cc
+ GET(cc
, 1);
707 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
708 localspace
+= sizeof(sljit_w
);
713 /* Set its value only once. */
714 if (common
->recursive_head
== 0)
716 common
->recursive_head
= common
->ovector_start
;
717 common
->ovector_start
+= sizeof(sljit_w
);
723 if (common
->mark_ptr
== 0)
725 common
->mark_ptr
= common
->ovector_start
;
726 common
->ovector_start
+= sizeof(sljit_w
);
732 cc
= next_opcode(common
, cc
);
741 static void set_localptrs(compiler_common
*common
, int localptr
, pcre_uchar
*ccend
)
743 pcre_uchar
*cc
= common
->start
;
744 pcre_uchar
*alternative
;
752 case OP_ASSERTBACK_NOT
:
759 common
->localptrs
[cc
- common
->start
] = localptr
;
760 localptr
+= sizeof(sljit_w
);
766 common
->localptrs
[cc
- common
->start
] = localptr
;
767 localptr
+= sizeof(sljit_w
);
768 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
772 /* Might be a hidden SCOND. */
773 alternative
= cc
+ GET(cc
, 1);
774 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
776 common
->localptrs
[cc
- common
->start
] = localptr
;
777 localptr
+= sizeof(sljit_w
);
783 cc
= next_opcode(common
, cc
);
784 SLJIT_ASSERT(cc
!= NULL
);
790 /* Returns with -1 if no need for frame. */
791 static int get_framesize(compiler_common
*common
, pcre_uchar
*cc
, BOOL recursive
)
793 pcre_uchar
*ccend
= bracketend(cc
);
795 BOOL possessive
= FALSE
;
796 BOOL setsom_found
= recursive
;
797 BOOL setmark_found
= recursive
;
799 if (!recursive
&& (*cc
== OP_CBRAPOS
|| *cc
== OP_SCBRAPOS
))
805 cc
= next_opcode(common
, cc
);
806 SLJIT_ASSERT(cc
!= NULL
);
811 SLJIT_ASSERT(common
->has_set_som
);
821 SLJIT_ASSERT(common
->mark_ptr
!= 0);
825 setmark_found
= TRUE
;
831 if (common
->has_set_som
&& !setsom_found
)
836 if (common
->mark_ptr
!= 0 && !setmark_found
)
839 setmark_found
= TRUE
;
849 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
853 cc
= next_opcode(common
, cc
);
854 SLJIT_ASSERT(cc
!= NULL
);
858 /* Possessive quantifiers can use a special case. */
859 if (SLJIT_UNLIKELY(possessive
) && length
== 3)
867 static void init_frame(compiler_common
*common
, pcre_uchar
*cc
, int stackpos
, int stacktop
, BOOL recursive
)
870 pcre_uchar
*ccend
= bracketend(cc
);
871 BOOL setsom_found
= recursive
;
872 BOOL setmark_found
= recursive
;
875 /* >= 1 + shortest item size (2) */
876 SLJIT_UNUSED_ARG(stacktop
);
877 SLJIT_ASSERT(stackpos
>= stacktop
+ 2);
879 stackpos
= STACK(stackpos
);
880 if (recursive
|| (*cc
!= OP_CBRAPOS
&& *cc
!= OP_SCBRAPOS
))
881 cc
= next_opcode(common
, cc
);
882 SLJIT_ASSERT(cc
!= NULL
);
887 SLJIT_ASSERT(common
->has_set_som
);
890 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
891 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setstrbegin
);
892 stackpos
+= (int)sizeof(sljit_w
);
893 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
894 stackpos
+= (int)sizeof(sljit_w
);
901 SLJIT_ASSERT(common
->mark_ptr
!= 0);
904 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
905 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setmark
);
906 stackpos
+= (int)sizeof(sljit_w
);
907 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
908 stackpos
+= (int)sizeof(sljit_w
);
909 setmark_found
= TRUE
;
915 if (common
->has_set_som
&& !setsom_found
)
917 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
918 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setstrbegin
);
919 stackpos
+= (int)sizeof(sljit_w
);
920 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
921 stackpos
+= (int)sizeof(sljit_w
);
924 if (common
->mark_ptr
!= 0 && !setmark_found
)
926 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
927 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setmark
);
928 stackpos
+= (int)sizeof(sljit_w
);
929 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
930 stackpos
+= (int)sizeof(sljit_w
);
931 setmark_found
= TRUE
;
940 offset
= (GET2(cc
, 1 + LINK_SIZE
)) << 1;
941 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, OVECTOR(offset
));
942 stackpos
+= (int)sizeof(sljit_w
);
943 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
944 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
945 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
946 stackpos
+= (int)sizeof(sljit_w
);
947 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP2
, 0);
948 stackpos
+= (int)sizeof(sljit_w
);
950 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
954 cc
= next_opcode(common
, cc
);
955 SLJIT_ASSERT(cc
!= NULL
);
959 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_end
);
960 SLJIT_ASSERT(stackpos
== STACK(stacktop
));
963 static SLJIT_INLINE
int get_localsize(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
)
966 pcre_uchar
*alternative
;
967 /* Calculate the sum of the local variables. */
975 case OP_ASSERTBACK_NOT
:
989 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
995 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
999 /* Might be a hidden SCOND. */
1000 alternative
= cc
+ GET(cc
, 1);
1001 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
1003 cc
+= 1 + LINK_SIZE
;
1007 cc
= next_opcode(common
, cc
);
1008 SLJIT_ASSERT(cc
!= NULL
);
1012 SLJIT_ASSERT(cc
== ccend
);
1016 static void copy_locals(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
,
1017 BOOL save
, int stackptr
, int stacktop
)
1022 BOOL tmp1next
= TRUE
;
1023 BOOL tmp1empty
= TRUE
;
1024 BOOL tmp2empty
= TRUE
;
1025 pcre_uchar
*alternative
;
1032 status
= save
? start
: loop
;
1033 stackptr
= STACK(stackptr
- 2);
1034 stacktop
= STACK(stacktop
- 1);
1038 stackptr
+= sizeof(sljit_w
);
1039 if (stackptr
< stacktop
)
1041 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1042 stackptr
+= sizeof(sljit_w
);
1045 if (stackptr
< stacktop
)
1047 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1048 stackptr
+= sizeof(sljit_w
);
1051 /* The tmp1next must be TRUE in either way. */
1054 while (status
!= end
)
1060 SLJIT_ASSERT(save
&& common
->recursive_head
!= 0);
1062 srcw
[0] = common
->recursive_head
;
1078 case OP_ASSERTBACK_NOT
:
1086 srcw
[0] = PRIV_DATA(cc
);
1087 SLJIT_ASSERT(srcw
[0] != 0);
1088 cc
+= 1 + LINK_SIZE
;
1094 srcw
[0] = OVECTOR_PRIV(GET2(cc
, 1 + LINK_SIZE
));
1095 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
1101 srcw
[1] = OVECTOR_PRIV(GET2(cc
, 1 + LINK_SIZE
));
1102 srcw
[0] = PRIV_DATA(cc
);
1103 SLJIT_ASSERT(srcw
[0] != 0);
1104 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
1108 /* Might be a hidden SCOND. */
1109 alternative
= cc
+ GET(cc
, 1);
1110 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
1113 srcw
[0] = PRIV_DATA(cc
);
1114 SLJIT_ASSERT(srcw
[0] != 0);
1116 cc
+= 1 + LINK_SIZE
;
1120 cc
= next_opcode(common
, cc
);
1121 SLJIT_ASSERT(cc
!= NULL
);
1127 SLJIT_ASSERT_STOP();
1140 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP1
, 0);
1141 stackptr
+= sizeof(sljit_w
);
1143 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
]);
1151 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP2
, 0);
1152 stackptr
+= sizeof(sljit_w
);
1154 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
]);
1163 SLJIT_ASSERT(!tmp1empty
);
1164 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
], TMP1
, 0);
1165 tmp1empty
= stackptr
>= stacktop
;
1168 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1169 stackptr
+= sizeof(sljit_w
);
1175 SLJIT_ASSERT(!tmp2empty
);
1176 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
], TMP2
, 0);
1177 tmp2empty
= stackptr
>= stacktop
;
1180 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1181 stackptr
+= sizeof(sljit_w
);
1195 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP1
, 0);
1196 stackptr
+= sizeof(sljit_w
);
1200 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP2
, 0);
1201 stackptr
+= sizeof(sljit_w
);
1208 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP2
, 0);
1209 stackptr
+= sizeof(sljit_w
);
1213 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP1
, 0);
1214 stackptr
+= sizeof(sljit_w
);
1218 SLJIT_ASSERT(cc
== ccend
&& stackptr
== stacktop
&& (save
|| (tmp1empty
&& tmp2empty
)));
1221 static SLJIT_INLINE BOOL
ispowerof2(unsigned int value
)
1223 return (value
& (value
- 1)) == 0;
1226 static SLJIT_INLINE
void set_jumps(jump_list
*list
, struct sljit_label
*label
)
1230 /* sljit_set_label is clever enough to do nothing
1231 if either the jump or the label is NULL */
1232 sljit_set_label(list
->jump
, label
);
1237 static SLJIT_INLINE
void add_jump(struct sljit_compiler
*compiler
, jump_list
**list
, struct sljit_jump
* jump
)
1239 jump_list
*list_item
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
1242 list_item
->next
= *list
;
1243 list_item
->jump
= jump
;
1248 static void add_stub(compiler_common
*common
, enum stub_types type
, int data
, struct sljit_jump
*start
)
1251 stub_list
* list_item
= sljit_alloc_memory(compiler
, sizeof(stub_list
));
1255 list_item
->type
= type
;
1256 list_item
->data
= data
;
1257 list_item
->start
= start
;
1258 list_item
->leave
= LABEL();
1259 list_item
->next
= common
->stubs
;
1260 common
->stubs
= list_item
;
1264 static void flush_stubs(compiler_common
*common
)
1267 stub_list
* list_item
= common
->stubs
;
1271 JUMPHERE(list_item
->start
);
1272 switch(list_item
->type
)
1275 add_jump(compiler
, &common
->stackalloc
, JUMP(SLJIT_FAST_CALL
));
1278 JUMPTO(SLJIT_JUMP
, list_item
->leave
);
1279 list_item
= list_item
->next
;
1281 common
->stubs
= NULL
;
1284 static SLJIT_INLINE
void decrease_call_count(compiler_common
*common
)
1288 OP2(SLJIT_SUB
| SLJIT_SET_E
, CALL_COUNT
, 0, CALL_COUNT
, 0, SLJIT_IMM
, 1);
1289 add_jump(compiler
, &common
->calllimit
, JUMP(SLJIT_C_ZERO
));
1292 static SLJIT_INLINE
void allocate_stack(compiler_common
*common
, int size
)
1294 /* May destroy all locals and registers except TMP2. */
1297 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, size
* sizeof(sljit_w
));
1298 #ifdef DESTROY_REGISTERS
1299 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 12345);
1300 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
1301 OP1(SLJIT_MOV
, RETURN_ADDR
, 0, TMP1
, 0);
1302 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, TMP1
, 0);
1303 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP1
, 0);
1305 add_stub(common
, stack_alloc
, 0, CMP(SLJIT_C_GREATER
, STACK_TOP
, 0, STACK_LIMIT
, 0));
1308 static SLJIT_INLINE
void free_stack(compiler_common
*common
, int size
)
1311 OP2(SLJIT_SUB
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, size
* sizeof(sljit_w
));
1314 static SLJIT_INLINE
void reset_ovector(compiler_common
*common
, int length
)
1317 struct sljit_label
*loop
;
1319 /* At this point we can freely use all temporary registers. */
1320 /* TMP1 returns with begin - 1. */
1321 OP2(SLJIT_SUB
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_MEM1(SLJIT_SAVED_REG1
), SLJIT_OFFSETOF(jit_arguments
, begin
), SLJIT_IMM
, IN_UCHARS(1));
1324 for (i
= 0; i
< length
; i
++)
1325 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(i
), SLJIT_TEMPORARY_REG1
, 0);
1329 GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2
, 0, OVECTOR_START
- sizeof(sljit_w
));
1330 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, length
);
1332 OP1(SLJIT_MOVU
, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), sizeof(sljit_w
), SLJIT_TEMPORARY_REG1
, 0);
1333 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, 1);
1334 JUMPTO(SLJIT_C_NOT_ZERO
, loop
);
1338 static SLJIT_INLINE
void copy_ovector(compiler_common
*common
, int topbracket
)
1341 struct sljit_label
*loop
;
1342 struct sljit_jump
*earlyexit
;
1344 /* At this point we can freely use all registers. */
1345 OP1(SLJIT_MOV
, SLJIT_SAVED_REG3
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1));
1346 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1), STR_PTR
, 0);
1348 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG1
, 0, ARGUMENTS
, 0);
1349 if (common
->mark_ptr
!= 0)
1350 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
1351 OP1(SLJIT_MOV_SI
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1
), SLJIT_OFFSETOF(jit_arguments
, offsetcount
));
1352 if (common
->mark_ptr
!= 0)
1353 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_TEMPORARY_REG1
), SLJIT_OFFSETOF(jit_arguments
, mark_ptr
), SLJIT_TEMPORARY_REG3
, 0);
1354 OP2(SLJIT_SUB
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1
), SLJIT_OFFSETOF(jit_arguments
, offsets
), SLJIT_IMM
, sizeof(int));
1355 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
1356 GET_LOCAL_BASE(SLJIT_SAVED_REG1
, 0, OVECTOR_START
);
1357 /* Unlikely, but possible */
1358 earlyexit
= CMP(SLJIT_C_EQUAL
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_IMM
, 0);
1360 OP2(SLJIT_SUB
, SLJIT_SAVED_REG2
, 0, SLJIT_MEM1(SLJIT_SAVED_REG1
), 0, SLJIT_TEMPORARY_REG1
, 0);
1361 OP2(SLJIT_ADD
, SLJIT_SAVED_REG1
, 0, SLJIT_SAVED_REG1
, 0, SLJIT_IMM
, sizeof(sljit_w
));
1362 /* Copy the integer value to the output buffer */
1363 #ifdef COMPILE_PCRE16
1364 OP2(SLJIT_ASHR
, SLJIT_SAVED_REG2
, 0, SLJIT_SAVED_REG2
, 0, SLJIT_IMM
, 1);
1366 OP1(SLJIT_MOVU_SI
, SLJIT_MEM1(SLJIT_TEMPORARY_REG3
), sizeof(int), SLJIT_SAVED_REG2
, 0);
1367 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_TEMPORARY_REG2
, 0, SLJIT_IMM
, 1);
1368 JUMPTO(SLJIT_C_NOT_ZERO
, loop
);
1369 JUMPHERE(earlyexit
);
1371 /* Calculate the return value, which is the maximum ovector value. */
1374 GET_LOCAL_BASE(SLJIT_TEMPORARY_REG1
, 0, OVECTOR_START
+ topbracket
* 2 * sizeof(sljit_w
));
1375 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_IMM
, topbracket
+ 1);
1377 /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */
1379 OP1(SLJIT_MOVU
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1
), -(2 * (sljit_w
)sizeof(sljit_w
)));
1380 OP2(SLJIT_SUB
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_TEMPORARY_REG2
, 0, SLJIT_IMM
, 1);
1381 CMPTO(SLJIT_C_EQUAL
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_SAVED_REG3
, 0, loop
);
1382 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_TEMPORARY_REG2
, 0);
1385 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 1);
1388 static SLJIT_INLINE
void return_with_partial_match(compiler_common
*common
, struct sljit_label
*leave
)
1392 SLJIT_COMPILE_ASSERT(STR_END
== SLJIT_SAVED_REG2
, str_end_must_be_saved_reg2
);
1393 SLJIT_ASSERT(common
->start_used_ptr
!= 0 && (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
? common
->hit_start
!= 0 : common
->hit_start
== 0));
1395 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG2
, 0, ARGUMENTS
, 0);
1396 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_PARTIAL
);
1397 OP1(SLJIT_MOV_SI
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), SLJIT_OFFSETOF(jit_arguments
, offsetcount
));
1398 CMPTO(SLJIT_C_LESS
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, 2, leave
);
1400 /* Store match begin and end. */
1401 OP1(SLJIT_MOV
, SLJIT_SAVED_REG1
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), SLJIT_OFFSETOF(jit_arguments
, begin
));
1402 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), SLJIT_OFFSETOF(jit_arguments
, offsets
));
1403 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mode
== JIT_PARTIAL_HARD_COMPILE
? common
->start_used_ptr
: common
->hit_start
);
1404 OP2(SLJIT_SUB
, SLJIT_SAVED_REG2
, 0, STR_END
, 0, SLJIT_SAVED_REG1
, 0);
1405 #ifdef COMPILE_PCRE16
1406 OP2(SLJIT_ASHR
, SLJIT_SAVED_REG2
, 0, SLJIT_SAVED_REG2
, 0, SLJIT_IMM
, 1);
1408 OP1(SLJIT_MOV_SI
, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), sizeof(int), SLJIT_SAVED_REG2
, 0);
1410 OP2(SLJIT_SUB
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_TEMPORARY_REG3
, 0, SLJIT_SAVED_REG1
, 0);
1411 #ifdef COMPILE_PCRE16
1412 OP2(SLJIT_ASHR
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, 1);
1414 OP1(SLJIT_MOV_SI
, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), 0, SLJIT_TEMPORARY_REG3
, 0);
1416 JUMPTO(SLJIT_JUMP
, leave
);
1419 static SLJIT_INLINE
void check_start_used_ptr(compiler_common
*common
)
1421 /* May destroy TMP1. */
1423 struct sljit_jump
*jump
;
1425 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
1427 /* The value of -1 must be kept for start_used_ptr! */
1428 OP2(SLJIT_ADD
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, SLJIT_IMM
, 1);
1429 /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting
1430 is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */
1431 jump
= CMP(SLJIT_C_LESS_EQUAL
, TMP1
, 0, STR_PTR
, 0);
1432 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1435 else if (common
->mode
== JIT_PARTIAL_HARD_COMPILE
)
1437 jump
= CMP(SLJIT_C_LESS_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1438 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1443 static SLJIT_INLINE BOOL
char_has_othercase(compiler_common
*common
, pcre_uchar
* cc
)
1445 /* Detects if the character has an othercase. */
1455 return c
!= UCD_OTHERCASE(c
);
1460 #ifndef COMPILE_PCRE8
1461 return common
->fcc
[c
] != c
;
1467 return MAX_255(c
) ? common
->fcc
[c
] != c
: FALSE
;
1470 static SLJIT_INLINE
unsigned int char_othercase(compiler_common
*common
, unsigned int c
)
1472 /* Returns with the othercase. */
1474 if (common
->utf
&& c
> 127)
1477 return UCD_OTHERCASE(c
);
1483 return TABLE_GET(c
, common
->fcc
, c
);
1486 static unsigned int char_get_othercase_bit(compiler_common
*common
, pcre_uchar
* cc
)
1488 /* Detects if the character and its othercase has only 1 bit difference. */
1489 unsigned int c
, oc
, bit
;
1490 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1499 oc
= common
->fcc
[c
];
1503 oc
= UCD_OTHERCASE(c
);
1512 oc
= TABLE_GET(c
, common
->fcc
, c
);
1516 oc
= TABLE_GET(c
, common
->fcc
, c
);
1519 SLJIT_ASSERT(c
!= oc
);
1522 /* Optimized for English alphabet. */
1523 if (c
<= 127 && bit
== 0x20)
1524 return (0 << 8) | 0x20;
1526 /* Since c != oc, they must have at least 1 bit difference. */
1527 if (!ispowerof2(bit
))
1530 #ifdef COMPILE_PCRE8
1533 if (common
->utf
&& c
> 127)
1535 n
= GET_EXTRALEN(*cc
);
1536 while ((bit
& 0x3f) == 0)
1541 return (n
<< 8) | bit
;
1543 #endif /* SUPPORT_UTF */
1544 return (0 << 8) | bit
;
1546 #else /* COMPILE_PCRE8 */
1548 #ifdef COMPILE_PCRE16
1550 if (common
->utf
&& c
> 65535)
1552 if (bit
>= (1 << 10))
1555 return (bit
< 256) ? ((2 << 8) | bit
) : ((3 << 8) | (bit
>> 8));
1557 #endif /* SUPPORT_UTF */
1558 return (bit
< 256) ? ((0 << 8) | bit
) : ((1 << 8) | (bit
>> 8));
1559 #endif /* COMPILE_PCRE16 */
1561 #endif /* COMPILE_PCRE8 */
1564 static void check_partial(compiler_common
*common
, BOOL force
)
1566 /* Checks whether a partial matching is occured. Does not modify registers. */
1568 struct sljit_jump
*jump
= NULL
;
1570 SLJIT_ASSERT(!force
|| common
->mode
!= JIT_COMPILE
);
1572 if (common
->mode
== JIT_COMPILE
)
1576 jump
= CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1577 else if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
1578 jump
= CMP(SLJIT_C_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, SLJIT_IMM
, -1);
1580 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
1581 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
1584 if (common
->partialmatchlabel
!= NULL
)
1585 JUMPTO(SLJIT_JUMP
, common
->partialmatchlabel
);
1587 add_jump(compiler
, &common
->partialmatch
, JUMP(SLJIT_JUMP
));
1594 static struct sljit_jump
*check_str_end(compiler_common
*common
)
1596 /* Does not affect registers. Usually used in a tight spot. */
1598 struct sljit_jump
*jump
;
1599 struct sljit_jump
*nohit
;
1600 struct sljit_jump
*return_value
;
1602 if (common
->mode
== JIT_COMPILE
)
1603 return CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
1605 jump
= CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
1606 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
1608 nohit
= CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1609 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
1611 return_value
= JUMP(SLJIT_JUMP
);
1615 return_value
= CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1616 if (common
->partialmatchlabel
!= NULL
)
1617 JUMPTO(SLJIT_JUMP
, common
->partialmatchlabel
);
1619 add_jump(compiler
, &common
->partialmatch
, JUMP(SLJIT_JUMP
));
1622 return return_value
;
1625 static void detect_partial_match(compiler_common
*common
, jump_list
**backtracks
)
1628 struct sljit_jump
*jump
;
1630 if (common
->mode
== JIT_COMPILE
)
1632 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0));
1636 /* Partial matching mode. */
1637 jump
= CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
1638 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0));
1639 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
1641 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
1642 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
1646 if (common
->partialmatchlabel
!= NULL
)
1647 JUMPTO(SLJIT_JUMP
, common
->partialmatchlabel
);
1649 add_jump(compiler
, &common
->partialmatch
, JUMP(SLJIT_JUMP
));
1654 static void read_char(compiler_common
*common
)
1656 /* Reads the character into TMP1, updates STR_PTR.
1657 Does not check STR_END. TMP2 Destroyed. */
1660 struct sljit_jump
*jump
;
1663 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
1667 #ifdef COMPILE_PCRE8
1668 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
1670 #ifdef COMPILE_PCRE16
1671 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
1673 #endif /* COMPILE_PCRE8 */
1674 add_jump(compiler
, &common
->utfreadchar
, JUMP(SLJIT_FAST_CALL
));
1678 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1681 static void peek_char(compiler_common
*common
)
1683 /* Reads the character into TMP1, keeps STR_PTR.
1684 Does not check STR_END. TMP2 Destroyed. */
1687 struct sljit_jump
*jump
;
1690 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
1694 #ifdef COMPILE_PCRE8
1695 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
1697 #ifdef COMPILE_PCRE16
1698 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
1700 #endif /* COMPILE_PCRE8 */
1701 add_jump(compiler
, &common
->utfreadchar
, JUMP(SLJIT_FAST_CALL
));
1702 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
1708 static void read_char8_type(compiler_common
*common
)
1710 /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
1712 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
1713 struct sljit_jump
*jump
;
1719 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), 0);
1720 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1721 #ifdef COMPILE_PCRE8
1722 /* This can be an extra read in some situations, but hopefully
1723 it is needed in most cases. */
1724 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
1725 jump
= CMP(SLJIT_C_LESS
, TMP2
, 0, SLJIT_IMM
, 0xc0);
1726 add_jump(compiler
, &common
->utfreadtype8
, JUMP(SLJIT_FAST_CALL
));
1729 #ifdef COMPILE_PCRE16
1730 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
1731 jump
= CMP(SLJIT_C_GREATER
, TMP2
, 0, SLJIT_IMM
, 255);
1732 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
1734 /* Skip low surrogate if necessary. */
1735 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0xfc00);
1736 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP2
, 0, SLJIT_IMM
, 0xd800);
1737 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
1738 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 1);
1739 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
1741 #endif /* COMPILE_PCRE8 */
1745 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), 0);
1746 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1747 #ifdef COMPILE_PCRE16
1748 /* The ctypes array contains only 256 values. */
1749 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
1750 jump
= CMP(SLJIT_C_GREATER
, TMP2
, 0, SLJIT_IMM
, 255);
1752 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
1753 #ifdef COMPILE_PCRE16
1758 static void skip_char_back(compiler_common
*common
)
1760 /* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */
1762 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1763 struct sljit_label
*label
;
1768 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -IN_UCHARS(1));
1769 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1770 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xc0);
1771 CMPTO(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0x80, label
);
1775 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
1778 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -IN_UCHARS(1));
1779 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1780 /* Skip low surrogate if necessary. */
1781 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
1782 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xdc00);
1783 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
1784 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
1785 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
1789 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1792 static void check_newlinechar(compiler_common
*common
, int nltype
, jump_list
**backtracks
, BOOL jumpiftrue
)
1794 /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
1797 if (nltype
== NLTYPE_ANY
)
1799 add_jump(compiler
, &common
->anynewline
, JUMP(SLJIT_FAST_CALL
));
1800 add_jump(compiler
, backtracks
, JUMP(jumpiftrue
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
1802 else if (nltype
== NLTYPE_ANYCRLF
)
1804 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
1805 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
1806 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
1807 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
1808 add_jump(compiler
, backtracks
, JUMP(jumpiftrue
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
1812 SLJIT_ASSERT(nltype
== NLTYPE_FIXED
&& common
->newline
< 256);
1813 add_jump(compiler
, backtracks
, CMP(jumpiftrue
? SLJIT_C_EQUAL
: SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, common
->newline
));
1819 #ifdef COMPILE_PCRE8
1820 static void do_utfreadchar(compiler_common
*common
)
1822 /* Fast decoding a UTF-8 character. TMP1 contains the first byte
1823 of the character (>= 0xc0). Return char value in TMP1, length - 1 in TMP2. */
1825 struct sljit_jump
*jump
;
1827 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1828 /* Searching for the first zero. */
1829 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x20);
1830 jump
= JUMP(SLJIT_C_NOT_ZERO
);
1831 /* Two byte sequence. */
1832 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
1833 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1834 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x1f);
1835 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 6);
1836 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1837 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1838 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
1839 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1842 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x10);
1843 jump
= JUMP(SLJIT_C_NOT_ZERO
);
1844 /* Three byte sequence. */
1845 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
1846 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x0f);
1847 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 12);
1848 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1849 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 6);
1850 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1851 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(2));
1852 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
1853 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1854 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1855 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(2));
1856 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1859 /* Four byte sequence. */
1860 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
1861 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x07);
1862 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 18);
1863 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1864 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 12);
1865 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1866 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(2));
1867 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1868 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 6);
1869 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1870 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(3));
1871 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(3));
1872 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1873 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1874 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(3));
1875 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1878 static void do_utfreadtype8(compiler_common
*common
)
1880 /* Fast decoding a UTF-8 character type. TMP2 contains the first byte
1881 of the character (>= 0xc0). Return value in TMP1. */
1883 struct sljit_jump
*jump
;
1884 struct sljit_jump
*compare
;
1886 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1888 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP2
, 0, SLJIT_IMM
, 0x20);
1889 jump
= JUMP(SLJIT_C_NOT_ZERO
);
1890 /* Two byte sequence. */
1891 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
1892 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1893 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x1f);
1894 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 6);
1895 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x3f);
1896 OP2(SLJIT_OR
, TMP2
, 0, TMP2
, 0, TMP1
, 0);
1897 compare
= CMP(SLJIT_C_GREATER
, TMP2
, 0, SLJIT_IMM
, 255);
1898 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
1899 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1902 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
1903 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1906 /* We only have types for characters less than 256. */
1907 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
1908 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
1909 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
1910 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1913 #else /* COMPILE_PCRE8 */
1915 #ifdef COMPILE_PCRE16
1916 static void do_utfreadchar(compiler_common
*common
)
1918 /* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char
1919 of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */
1921 struct sljit_jump
*jump
;
1923 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1924 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xdc00);
1925 /* Do nothing, only return. */
1926 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1929 /* Combine two 16 bit characters. */
1930 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
1931 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1932 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x3ff);
1933 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 10);
1934 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3ff);
1935 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1936 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
1937 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x10000);
1938 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1940 #endif /* COMPILE_PCRE16 */
1942 #endif /* COMPILE_PCRE8 */
1944 #endif /* SUPPORT_UTF */
1948 static sljit_w SLJIT_CALL
getunichartype(sljit_w c
)
1950 return (sljit_w
)(unsigned int)UCD_CHARTYPE((unsigned int)c
);
1953 static sljit_w SLJIT_CALL
getunicharscript(sljit_w c
)
1955 return (sljit_w
)(unsigned int)UCD_SCRIPT((unsigned int)c
);
1958 static void do_getunichartype(compiler_common
*common
)
1960 /* Character comes in TMP1. Returns chartype in TMP1 */
1963 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1964 /* Save registers */
1965 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, STACK_TOP
, 0);
1966 sljit_emit_ijump(compiler
, SLJIT_CALL1
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(getunichartype
));
1967 /* Restore registers */
1968 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
1969 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1972 static void do_getunichartype_2(compiler_common
*common
)
1974 /* Character comes in TMP1. Returns chartype in TMP1 */
1977 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1978 /* Save registers */
1979 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, STACK_TOP
, 0);
1980 sljit_emit_ijump(compiler
, SLJIT_CALL1
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(getunichartype
));
1981 /* Restore registers */
1982 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
1983 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1986 static void do_getunicharscript(compiler_common
*common
)
1988 /* Character comes in TMP1. Returns chartype in TMP1 */
1991 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1992 /* Save registers */
1993 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, STACK_TOP
, 0);
1994 sljit_emit_ijump(compiler
, SLJIT_CALL1
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(getunicharscript
));
1995 /* Restore registers */
1996 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
1997 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2001 static SLJIT_INLINE
struct sljit_label
*mainloop_entry(compiler_common
*common
, BOOL hascrorlf
, BOOL firstline
)
2004 struct sljit_label
*mainloop
;
2005 struct sljit_label
*newlinelabel
= NULL
;
2006 struct sljit_jump
*start
;
2007 struct sljit_jump
*end
= NULL
;
2008 struct sljit_jump
*nl
= NULL
;
2010 struct sljit_jump
*singlechar
;
2012 jump_list
*newline
= NULL
;
2013 BOOL newlinecheck
= FALSE
;
2014 BOOL readuchar
= FALSE
;
2016 if (!(hascrorlf
|| firstline
) && (common
->nltype
== NLTYPE_ANY
||
2017 common
->nltype
== NLTYPE_ANYCRLF
|| common
->newline
> 255))
2018 newlinecheck
= TRUE
;
2022 /* Search for the end of the first line. */
2023 SLJIT_ASSERT(common
->first_line_end
!= 0);
2024 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, STR_PTR
, 0);
2025 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, STR_END
, 0);
2027 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
2030 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2031 end
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2032 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-1));
2033 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
2034 CMPTO(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff, mainloop
);
2035 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff, mainloop
);
2036 OP2(SLJIT_SUB
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2040 end
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2042 /* Continual stores does not cause data dependency. */
2043 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, STR_PTR
, 0);
2045 check_newlinechar(common
, common
->nltype
, &newline
, TRUE
);
2046 CMPTO(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0, mainloop
);
2047 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, STR_PTR
, 0);
2048 set_jumps(newline
, LABEL());
2052 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
2055 start
= JUMP(SLJIT_JUMP
);
2059 newlinelabel
= LABEL();
2060 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2061 end
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2062 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2063 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, common
->newline
& 0xff);
2064 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
2065 #ifdef COMPILE_PCRE16
2066 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2068 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2069 nl
= JUMP(SLJIT_JUMP
);
2074 /* Increasing the STR_PTR here requires one less jump in the most common case. */
2076 if (common
->utf
) readuchar
= TRUE
;
2078 if (newlinecheck
) readuchar
= TRUE
;
2081 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2084 CMPTO(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff, newlinelabel
);
2086 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2087 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
2090 singlechar
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
2091 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
2092 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2093 JUMPHERE(singlechar
);
2096 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
2099 singlechar
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
2100 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
2101 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xd800);
2102 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
2103 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2104 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2105 JUMPHERE(singlechar
);
2119 static SLJIT_INLINE
void fast_forward_first_char(compiler_common
*common
, pcre_uchar first_char
, BOOL caseless
, BOOL firstline
)
2122 struct sljit_label
*start
;
2123 struct sljit_jump
*leave
;
2124 struct sljit_jump
*found
;
2129 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, STR_END
, 0);
2130 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
2134 leave
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2135 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2140 oc
= TABLE_GET(first_char
, common
->fcc
, first_char
);
2141 #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
2142 if (first_char
> 127 && common
->utf
)
2143 oc
= UCD_OTHERCASE(first_char
);
2146 if (first_char
== oc
)
2147 found
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, first_char
);
2150 bit
= first_char
^ oc
;
2151 if (ispowerof2(bit
))
2153 OP2(SLJIT_OR
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, bit
);
2154 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, first_char
| bit
);
2158 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, first_char
);
2159 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
2160 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, oc
);
2161 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
2162 found
= JUMP(SLJIT_C_NOT_ZERO
);
2166 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2167 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
2170 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0, start
);
2171 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
2172 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2175 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
2178 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800, start
);
2179 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
2180 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xd800);
2181 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
2182 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2183 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2186 JUMPTO(SLJIT_JUMP
, start
);
2191 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
2194 static SLJIT_INLINE
void fast_forward_newline(compiler_common
*common
, BOOL firstline
)
2197 struct sljit_label
*loop
;
2198 struct sljit_jump
*lastchar
;
2199 struct sljit_jump
*firstchar
;
2200 struct sljit_jump
*leave
;
2201 struct sljit_jump
*foundcr
= NULL
;
2202 struct sljit_jump
*notfoundnl
;
2203 jump_list
*newline
= NULL
;
2207 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, STR_END
, 0);
2208 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
2211 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
2213 lastchar
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2214 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
2215 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
2216 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
2217 firstchar
= CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP2
, 0);
2219 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(2));
2220 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, STR_PTR
, 0, TMP1
, 0);
2221 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_GREATER_EQUAL
);
2222 #ifdef COMPILE_PCRE16
2223 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 1);
2225 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
2228 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2229 leave
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2230 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-2));
2231 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-1));
2232 CMPTO(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff, loop
);
2233 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff, loop
);
2236 JUMPHERE(firstchar
);
2240 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
2244 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
2245 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
2246 firstchar
= CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP2
, 0);
2247 skip_char_back(common
);
2251 lastchar
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2252 if (common
->nltype
== NLTYPE_ANY
|| common
->nltype
== NLTYPE_ANYCRLF
)
2253 foundcr
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
2254 check_newlinechar(common
, common
->nltype
, &newline
, FALSE
);
2255 set_jumps(newline
, loop
);
2257 if (common
->nltype
== NLTYPE_ANY
|| common
->nltype
== NLTYPE_ANYCRLF
)
2259 leave
= JUMP(SLJIT_JUMP
);
2261 notfoundnl
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2262 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2263 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
2264 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
2265 #ifdef COMPILE_PCRE16
2266 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2268 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2269 JUMPHERE(notfoundnl
);
2273 JUMPHERE(firstchar
);
2276 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
2279 static SLJIT_INLINE
void fast_forward_start_bits(compiler_common
*common
, sljit_uw start_bits
, BOOL firstline
)
2282 struct sljit_label
*start
;
2283 struct sljit_jump
*leave
;
2284 struct sljit_jump
*found
;
2285 #ifndef COMPILE_PCRE8
2286 struct sljit_jump
*jump
;
2291 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, STR_END
, 0);
2292 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
2296 leave
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2297 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2300 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
2302 #ifndef COMPILE_PCRE8
2303 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 255);
2304 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 255);
2307 OP2(SLJIT_AND
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x7);
2308 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3);
2309 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), start_bits
);
2310 OP2(SLJIT_SHL
, TMP2
, 0, SLJIT_IMM
, 1, TMP2
, 0);
2311 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, TMP2
, 0);
2312 found
= JUMP(SLJIT_C_NOT_ZERO
);
2316 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
2318 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2319 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
2322 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0, start
);
2323 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
2324 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2327 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
2330 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800, start
);
2331 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
2332 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xd800);
2333 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
2334 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2335 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2338 JUMPTO(SLJIT_JUMP
, start
);
2343 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
2346 static SLJIT_INLINE
struct sljit_jump
*search_requested_char(compiler_common
*common
, pcre_uchar req_char
, BOOL caseless
, BOOL has_firstchar
)
2349 struct sljit_label
*loop
;
2350 struct sljit_jump
*toolong
;
2351 struct sljit_jump
*alreadyfound
;
2352 struct sljit_jump
*found
;
2353 struct sljit_jump
*foundoc
= NULL
;
2354 struct sljit_jump
*notfound
;
2357 SLJIT_ASSERT(common
->req_char_ptr
!= 0);
2358 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->req_char_ptr
);
2359 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, REQ_BYTE_MAX
);
2360 toolong
= CMP(SLJIT_C_LESS
, TMP1
, 0, STR_END
, 0);
2361 alreadyfound
= CMP(SLJIT_C_LESS
, STR_PTR
, 0, TMP2
, 0);
2364 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2366 OP1(SLJIT_MOV
, TMP1
, 0, STR_PTR
, 0);
2369 notfound
= CMP(SLJIT_C_GREATER_EQUAL
, TMP1
, 0, STR_END
, 0);
2371 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(TMP1
), 0);
2375 oc
= TABLE_GET(req_char
, common
->fcc
, req_char
);
2376 #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
2377 if (req_char
> 127 && common
->utf
)
2378 oc
= UCD_OTHERCASE(req_char
);
2382 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, req_char
);
2385 bit
= req_char
^ oc
;
2386 if (ispowerof2(bit
))
2388 OP2(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, bit
);
2389 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, req_char
| bit
);
2393 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, req_char
);
2394 foundoc
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, oc
);
2397 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(1));
2398 JUMPTO(SLJIT_JUMP
, loop
);
2403 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->req_char_ptr
, TMP1
, 0);
2404 JUMPHERE(alreadyfound
);
2409 static void do_revertframes(compiler_common
*common
)
2412 struct sljit_jump
*jump
;
2413 struct sljit_label
*mainloop
;
2415 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2416 OP1(SLJIT_MOV
, TMP1
, 0, STACK_TOP
, 0);
2417 GET_LOCAL_BASE(TMP3
, 0, 0);
2419 /* Drop frames until we reach STACK_TOP. */
2421 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), 0);
2422 jump
= CMP(SLJIT_C_SIG_LESS_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_end
);
2423 OP2(SLJIT_ADD
, TMP2
, 0, TMP2
, 0, TMP3
, 0);
2424 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP2
), 0, SLJIT_MEM1(TMP1
), sizeof(sljit_w
));
2425 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP2
), sizeof(sljit_w
), SLJIT_MEM1(TMP1
), 2 * sizeof(sljit_w
));
2426 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3 * sizeof(sljit_w
));
2427 JUMPTO(SLJIT_JUMP
, mainloop
);
2430 jump
= CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_end
);
2431 /* End of dropping frames. */
2432 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2435 jump
= CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_setstrbegin
);
2436 /* Set string begin. */
2437 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), sizeof(sljit_w
));
2438 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 2 * sizeof(sljit_w
));
2439 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), TMP2
, 0);
2440 JUMPTO(SLJIT_JUMP
, mainloop
);
2443 if (common
->mark_ptr
!= 0)
2445 jump
= CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_setmark
);
2446 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), sizeof(sljit_w
));
2447 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 2 * sizeof(sljit_w
));
2448 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP2
, 0);
2449 JUMPTO(SLJIT_JUMP
, mainloop
);
2454 /* Unknown command. */
2455 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 2 * sizeof(sljit_w
));
2456 JUMPTO(SLJIT_JUMP
, mainloop
);
2459 static void check_wordboundary(compiler_common
*common
)
2462 struct sljit_jump
*skipread
;
2463 #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF
2464 struct sljit_jump
*jump
;
2467 SLJIT_COMPILE_ASSERT(ctype_word
== 0x10, ctype_word_must_be_16
);
2469 sljit_emit_fast_enter(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
2470 /* Get type of the previous char, and put it to LOCALS1. */
2471 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
2472 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
2473 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, SLJIT_IMM
, 0);
2474 skipread
= CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP1
, 0);
2475 skip_char_back(common
);
2476 check_start_used_ptr(common
);
2479 /* Testing char type. */
2481 if (common
->use_ucp
)
2483 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 1);
2484 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_UNDERSCORE
);
2485 add_jump(compiler
, &common
->getunichartype_2
, JUMP(SLJIT_FAST_CALL
));
2486 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Ll
);
2487 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Lu
- ucp_Ll
);
2488 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2489 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Nd
- ucp_Ll
);
2490 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_No
- ucp_Nd
);
2491 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2493 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP2
, 0);
2498 #ifndef COMPILE_PCRE8
2499 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2500 #elif defined SUPPORT_UTF
2501 /* Here LOCALS1 has already been zeroed. */
2504 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2505 #endif /* COMPILE_PCRE8 */
2506 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), common
->ctypes
);
2507 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 4 /* ctype_word */);
2508 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2509 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP1
, 0);
2510 #ifndef COMPILE_PCRE8
2512 #elif defined SUPPORT_UTF
2515 #endif /* COMPILE_PCRE8 */
2519 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
2520 skipread
= check_str_end(common
);
2523 /* Testing char type. This is a code duplication. */
2525 if (common
->use_ucp
)
2527 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 1);
2528 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_UNDERSCORE
);
2529 add_jump(compiler
, &common
->getunichartype_2
, JUMP(SLJIT_FAST_CALL
));
2530 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Ll
);
2531 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Lu
- ucp_Ll
);
2532 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2533 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Nd
- ucp_Ll
);
2534 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_No
- ucp_Nd
);
2535 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2541 #ifndef COMPILE_PCRE8
2542 /* TMP2 may be destroyed by peek_char. */
2543 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
2544 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2545 #elif defined SUPPORT_UTF
2546 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
2549 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2551 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), common
->ctypes
);
2552 OP2(SLJIT_LSHR
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 4 /* ctype_word */);
2553 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 1);
2554 #ifndef COMPILE_PCRE8
2556 #elif defined SUPPORT_UTF
2559 #endif /* COMPILE_PCRE8 */
2563 OP2(SLJIT_XOR
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
2564 sljit_emit_fast_return(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
2567 static void check_anynewline(compiler_common
*common
)
2569 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2572 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2574 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x0a);
2575 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x0d - 0x0a);
2576 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2577 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x85 - 0x0a);
2578 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
2579 #ifdef COMPILE_PCRE8
2583 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2584 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x1);
2585 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x2029 - 0x0a);
2586 #ifdef COMPILE_PCRE8
2589 #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
2590 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
2591 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2594 static void check_hspace(compiler_common
*common
)
2596 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2599 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2601 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x09);
2602 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
2603 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x20);
2604 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2605 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xa0);
2606 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
2607 #ifdef COMPILE_PCRE8
2611 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2612 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x1680);
2613 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2614 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x180e);
2615 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2616 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x2000);
2617 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x200A - 0x2000);
2618 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2619 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x202f - 0x2000);
2620 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2621 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x205f - 0x2000);
2622 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2623 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x3000 - 0x2000);
2624 #ifdef COMPILE_PCRE8
2627 #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
2628 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
2630 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2633 static void check_vspace(compiler_common
*common
)
2635 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2638 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2640 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x0a);
2641 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x0d - 0x0a);
2642 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2643 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x85 - 0x0a);
2644 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
2645 #ifdef COMPILE_PCRE8
2649 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
2650 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x1);
2651 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x2029 - 0x0a);
2652 #ifdef COMPILE_PCRE8
2655 #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
2656 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
2658 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2661 #define CHAR1 STR_END
2662 #define CHAR2 STACK_TOP
2664 static void do_casefulcmp(compiler_common
*common
)
2667 struct sljit_jump
*jump
;
2668 struct sljit_label
*label
;
2670 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2671 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
2672 OP1(SLJIT_MOV
, TMP3
, 0, CHAR1
, 0);
2673 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, CHAR2
, 0);
2674 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(1));
2675 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2678 OP1(MOVU_UCHAR
, CHAR1
, 0, SLJIT_MEM1(TMP1
), IN_UCHARS(1));
2679 OP1(MOVU_UCHAR
, CHAR2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
2680 jump
= CMP(SLJIT_C_NOT_EQUAL
, CHAR1
, 0, CHAR2
, 0);
2681 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
2682 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
2685 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2686 OP1(SLJIT_MOV
, CHAR1
, 0, TMP3
, 0);
2687 OP1(SLJIT_MOV
, CHAR2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
2688 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2691 #define LCC_TABLE STACK_LIMIT
2693 static void do_caselesscmp(compiler_common
*common
)
2696 struct sljit_jump
*jump
;
2697 struct sljit_label
*label
;
2699 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2700 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
2702 OP1(SLJIT_MOV
, TMP3
, 0, LCC_TABLE
, 0);
2703 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, CHAR1
, 0);
2704 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, CHAR2
, 0);
2705 OP1(SLJIT_MOV
, LCC_TABLE
, 0, SLJIT_IMM
, common
->lcc
);
2706 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(1));
2707 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2710 OP1(MOVU_UCHAR
, CHAR1
, 0, SLJIT_MEM1(TMP1
), IN_UCHARS(1));
2711 OP1(MOVU_UCHAR
, CHAR2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
2712 #ifndef COMPILE_PCRE8
2713 jump
= CMP(SLJIT_C_GREATER
, CHAR1
, 0, SLJIT_IMM
, 255);
2715 OP1(SLJIT_MOV_UB
, CHAR1
, 0, SLJIT_MEM2(LCC_TABLE
, CHAR1
), 0);
2716 #ifndef COMPILE_PCRE8
2718 jump
= CMP(SLJIT_C_GREATER
, CHAR2
, 0, SLJIT_IMM
, 255);
2720 OP1(SLJIT_MOV_UB
, CHAR2
, 0, SLJIT_MEM2(LCC_TABLE
, CHAR2
), 0);
2721 #ifndef COMPILE_PCRE8
2724 jump
= CMP(SLJIT_C_NOT_EQUAL
, CHAR1
, 0, CHAR2
, 0);
2725 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
2726 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
2729 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2730 OP1(SLJIT_MOV
, LCC_TABLE
, 0, TMP3
, 0);
2731 OP1(SLJIT_MOV
, CHAR1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
2732 OP1(SLJIT_MOV
, CHAR2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
2733 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2740 #if defined SUPPORT_UTF && defined SUPPORT_UCP
2742 static const pcre_uchar
*SLJIT_CALL
do_utf_caselesscmp(pcre_uchar
*src1
, jit_arguments
*args
, pcre_uchar
*end1
)
2744 /* This function would be ineffective to do in JIT level. */
2746 const pcre_uchar
*src2
= args
->uchar_ptr
;
2747 const pcre_uchar
*end2
= args
->end
;
2752 return (pcre_uchar
*)1;
2753 GETCHARINC(c1
, src1
);
2754 GETCHARINC(c2
, src2
);
2755 if (c1
!= c2
&& c1
!= UCD_OTHERCASE(c2
)) return NULL
;
2760 #endif /* SUPPORT_UTF && SUPPORT_UCP */
2762 static pcre_uchar
*byte_sequence_compare(compiler_common
*common
, BOOL caseless
, pcre_uchar
*cc
,
2763 compare_context
* context
, jump_list
**backtracks
)
2766 unsigned int othercasebit
= 0;
2767 pcre_uchar
*othercasechar
= NULL
;
2772 if (caseless
&& char_has_othercase(common
, cc
))
2774 othercasebit
= char_get_othercase_bit(common
, cc
);
2775 SLJIT_ASSERT(othercasebit
);
2776 /* Extracting bit difference info. */
2777 #ifdef COMPILE_PCRE8
2778 othercasechar
= cc
+ (othercasebit
>> 8);
2779 othercasebit
&= 0xff;
2781 #ifdef COMPILE_PCRE16
2782 othercasechar
= cc
+ (othercasebit
>> 9);
2783 if ((othercasebit
& 0x100) != 0)
2784 othercasebit
= (othercasebit
& 0xff) << 8;
2786 othercasebit
&= 0xff;
2791 if (context
->sourcereg
== -1)
2793 #ifdef COMPILE_PCRE8
2794 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2795 if (context
->length
>= 4)
2796 OP1(SLJIT_MOV_SI
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2797 else if (context
->length
>= 2)
2798 OP1(SLJIT_MOV_UH
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2801 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2803 #ifdef COMPILE_PCRE16
2804 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2805 if (context
->length
>= 4)
2806 OP1(SLJIT_MOV_SI
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2809 OP1(SLJIT_MOV_UH
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2811 #endif /* COMPILE_PCRE8 */
2812 context
->sourcereg
= TMP2
;
2817 if (common
->utf
&& HAS_EXTRALEN(*cc
))
2818 utflength
+= GET_EXTRALEN(*cc
);
2824 context
->length
-= IN_UCHARS(1);
2825 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2827 /* Unaligned read is supported. */
2828 if (othercasebit
!= 0 && othercasechar
== cc
)
2830 context
->c
.asuchars
[context
->ucharptr
] = *cc
| othercasebit
;
2831 context
->oc
.asuchars
[context
->ucharptr
] = othercasebit
;
2835 context
->c
.asuchars
[context
->ucharptr
] = *cc
;
2836 context
->oc
.asuchars
[context
->ucharptr
] = 0;
2838 context
->ucharptr
++;
2840 #ifdef COMPILE_PCRE8
2841 if (context
->ucharptr
>= 4 || context
->length
== 0 || (context
->ucharptr
== 2 && context
->length
== 1))
2843 if (context
->ucharptr
>= 2 || context
->length
== 0)
2846 if (context
->length
>= 4)
2847 OP1(SLJIT_MOV_SI
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2848 #ifdef COMPILE_PCRE8
2849 else if (context
->length
>= 2)
2850 OP1(SLJIT_MOV_UH
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2851 else if (context
->length
>= 1)
2852 OP1(SLJIT_MOV_UB
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2854 else if (context
->length
>= 2)
2855 OP1(SLJIT_MOV_UH
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2857 context
->sourcereg
= context
->sourcereg
== TMP1
? TMP2
: TMP1
;
2859 switch(context
->ucharptr
)
2861 case 4 / sizeof(pcre_uchar
):
2862 if (context
->oc
.asint
!= 0)
2863 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, context
->oc
.asint
);
2864 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, context
->c
.asint
| context
->oc
.asint
));
2867 case 2 / sizeof(pcre_uchar
):
2868 if (context
->oc
.asushort
!= 0)
2869 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, context
->oc
.asushort
);
2870 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, context
->c
.asushort
| context
->oc
.asushort
));
2873 #ifdef COMPILE_PCRE8
2875 if (context
->oc
.asbyte
!= 0)
2876 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, context
->oc
.asbyte
);
2877 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, context
->c
.asbyte
| context
->oc
.asbyte
));
2882 SLJIT_ASSERT_STOP();
2885 context
->ucharptr
= 0;
2890 /* Unaligned read is unsupported. */
2891 #ifdef COMPILE_PCRE8
2892 if (context
->length
> 0)
2893 OP1(SLJIT_MOV_UB
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2895 if (context
->length
> 0)
2896 OP1(SLJIT_MOV_UH
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2898 context
->sourcereg
= context
->sourcereg
== TMP1
? TMP2
: TMP1
;
2900 if (othercasebit
!= 0 && othercasechar
== cc
)
2902 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, othercasebit
);
2903 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, *cc
| othercasebit
));
2906 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, *cc
));
2914 while (utflength
> 0);
2920 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
2922 #define SET_TYPE_OFFSET(value) \
2923 if ((value) != typeoffset) \
2925 if ((value) > typeoffset) \
2926 OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
2928 OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
2930 typeoffset = (value);
2932 #define SET_CHAR_OFFSET(value) \
2933 if ((value) != charoffset) \
2935 if ((value) > charoffset) \
2936 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \
2938 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \
2940 charoffset = (value);
2942 static void compile_xclass_trypath(compiler_common
*common
, pcre_uchar
*cc
, jump_list
**backtracks
)
2945 jump_list
*found
= NULL
;
2946 jump_list
**list
= (*cc
& XCL_NOT
) == 0 ? &found
: backtracks
;
2949 struct sljit_jump
*jump
= NULL
;
2950 pcre_uchar
*ccbegin
;
2952 BOOL needstype
= FALSE
, needsscript
= FALSE
, needschar
= FALSE
;
2953 BOOL charsaved
= FALSE
;
2954 int typereg
= TMP1
, scriptreg
= TMP1
;
2955 unsigned int typeoffset
;
2957 int invertcmp
, numberofcmps
;
2958 unsigned int charoffset
;
2960 /* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */
2961 detect_partial_match(common
, backtracks
);
2964 if ((*cc
++ & XCL_MAP
) != 0)
2966 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
2967 #ifndef COMPILE_PCRE8
2968 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2969 #elif defined SUPPORT_UTF
2971 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2974 OP2(SLJIT_AND
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x7);
2975 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3);
2976 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)cc
);
2977 OP2(SLJIT_SHL
, TMP2
, 0, SLJIT_IMM
, 1, TMP2
, 0);
2978 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, TMP2
, 0);
2979 add_jump(compiler
, list
, JUMP(SLJIT_C_NOT_ZERO
));
2981 #ifndef COMPILE_PCRE8
2983 #elif defined SUPPORT_UTF
2987 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
2991 cc
+= 32 / sizeof(pcre_uchar
);
2994 /* Scanning the necessary info. */
2997 while (*cc
!= XCL_END
)
3000 if (*cc
== XCL_SINGLE
)
3004 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
3010 else if (*cc
== XCL_RANGE
)
3014 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
3018 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
3027 SLJIT_ASSERT(*cc
== XCL_PROP
|| *cc
== XCL_NOTPROP
);
3053 SLJIT_ASSERT_STOP();
3062 /* Simple register allocation. TMP1 is preferred if possible. */
3063 if (needstype
|| needsscript
)
3065 if ((needschar
|| needsscript
) && !charsaved
)
3066 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
3068 /* Needed to save important temporary registers. */
3069 SLJIT_ASSERT(TMP1
== SLJIT_TEMPORARY_REG1
&&
3070 STACK_TOP
== SLJIT_TEMPORARY_REG2
&&
3071 TMP2
== SLJIT_TEMPORARY_REG3
);
3076 typereg
= RETURN_ADDR
;
3080 else if (needstype
&& needsscript
)
3082 /* In all other cases only one of them was specified, and that can goes to TMP1. */
3086 add_jump(compiler
, &common
->getunichartype
, JUMP(SLJIT_FAST_CALL
));
3087 if (typereg
!= TMP1
)
3088 OP1(SLJIT_MOV
, typereg
, 0, TMP1
, 0);
3093 /* Get the char again */
3095 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
3097 add_jump(compiler
, &common
->getunicharscript
, JUMP(SLJIT_FAST_CALL
));
3098 if (scriptreg
!= TMP1
)
3099 OP1(SLJIT_MOV
, scriptreg
, 0, TMP1
, 0);
3103 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
3107 /* Generating code. */
3115 while (*cc
!= XCL_END
)
3118 invertcmp
= (compares
== 0 && list
!= backtracks
);
3121 if (*cc
== XCL_SINGLE
)
3133 if (numberofcmps
< 3 && (*cc
== XCL_SINGLE
|| *cc
== XCL_RANGE
))
3135 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3136 COND_VALUE(numberofcmps
== 0 ? SLJIT_MOV
: SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
3139 else if (numberofcmps
> 0)
3141 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3142 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
3143 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3148 jump
= CMP(SLJIT_C_EQUAL
^ invertcmp
, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3152 else if (*cc
== XCL_RANGE
)
3172 if (numberofcmps
< 3 && (*cc
== XCL_SINGLE
|| *cc
== XCL_RANGE
))
3174 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3175 COND_VALUE(numberofcmps
== 0 ? SLJIT_MOV
: SLJIT_OR
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3178 else if (numberofcmps
> 0)
3180 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3181 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3182 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3187 jump
= CMP(SLJIT_C_LESS_EQUAL
^ invertcmp
, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3194 if (*cc
== XCL_NOTPROP
)
3200 if (list
!= backtracks
)
3202 if ((cc
[-1] == XCL_NOTPROP
&& compares
> 0) || (cc
[-1] == XCL_PROP
&& compares
== 0))
3205 else if (cc
[-1] == XCL_NOTPROP
)
3207 jump
= JUMP(SLJIT_JUMP
);
3211 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Lu
- typeoffset
);
3212 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
3213 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Ll
- typeoffset
);
3214 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
3215 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Lt
- typeoffset
);
3216 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
3217 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3221 c
= PRIV(ucp_typerange
)[(int)cc
[1] * 2];
3223 jump
= CMP(SLJIT_C_LESS_EQUAL
^ invertcmp
, typereg
, 0, SLJIT_IMM
, PRIV(ucp_typerange
)[(int)cc
[1] * 2 + 1] - c
);
3227 jump
= CMP(SLJIT_C_EQUAL
^ invertcmp
, typereg
, 0, SLJIT_IMM
, (int)cc
[1] - typeoffset
);
3231 jump
= CMP(SLJIT_C_EQUAL
^ invertcmp
, scriptreg
, 0, SLJIT_IMM
, (int)cc
[1]);
3236 if (*cc
== PT_SPACE
)
3238 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
3239 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 11 - charoffset
);
3242 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 13 - 9);
3243 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3244 if (*cc
== PT_SPACE
)
3247 SET_TYPE_OFFSET(ucp_Zl
);
3248 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Zs
- ucp_Zl
);
3249 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3250 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3254 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_UNDERSCORE
- charoffset
);
3255 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
3256 /* ... fall through */
3259 SET_TYPE_OFFSET(ucp_Ll
);
3260 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Lu
- ucp_Ll
);
3261 COND_VALUE((*cc
== PT_ALNUM
) ? SLJIT_MOV
: SLJIT_OR
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3262 SET_TYPE_OFFSET(ucp_Nd
);
3263 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_No
- ucp_Nd
);
3264 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3265 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3273 add_jump(compiler
, compares
> 0 ? list
: backtracks
, jump
);
3277 set_jumps(found
, LABEL());
3280 #undef SET_TYPE_OFFSET
3281 #undef SET_CHAR_OFFSET
3285 static pcre_uchar
*compile_char1_trypath(compiler_common
*common
, pcre_uchar type
, pcre_uchar
*cc
, jump_list
**backtracks
)
3289 unsigned int c
, oc
, bit
;
3290 compare_context context
;
3291 struct sljit_jump
*jump
[4];
3293 struct sljit_label
*label
;
3295 pcre_uchar propdata
[5];
3302 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
3303 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
3304 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, TMP1
, 0));
3308 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
3309 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
3310 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, TMP1
, 0));
3313 case OP_NOT_WORD_BOUNDARY
:
3314 case OP_WORD_BOUNDARY
:
3315 add_jump(compiler
, &common
->wordboundary
, JUMP(SLJIT_FAST_CALL
));
3316 add_jump(compiler
, backtracks
, JUMP(type
== OP_NOT_WORD_BOUNDARY
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
3321 detect_partial_match(common
, backtracks
);
3322 read_char8_type(common
);
3323 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ctype_digit
);
3324 add_jump(compiler
, backtracks
, JUMP(type
== OP_DIGIT
? SLJIT_C_ZERO
: SLJIT_C_NOT_ZERO
));
3327 case OP_NOT_WHITESPACE
:
3329 detect_partial_match(common
, backtracks
);
3330 read_char8_type(common
);
3331 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ctype_space
);
3332 add_jump(compiler
, backtracks
, JUMP(type
== OP_WHITESPACE
? SLJIT_C_ZERO
: SLJIT_C_NOT_ZERO
));
3335 case OP_NOT_WORDCHAR
:
3337 detect_partial_match(common
, backtracks
);
3338 read_char8_type(common
);
3339 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ctype_word
);
3340 add_jump(compiler
, backtracks
, JUMP(type
== OP_WORDCHAR
? SLJIT_C_ZERO
: SLJIT_C_NOT_ZERO
));
3344 detect_partial_match(common
, backtracks
);
3346 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
3348 jump
[0] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff);
3349 if (common
->mode
!= JIT_PARTIAL_HARD_COMPILE
)
3350 jump
[1] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
3352 jump
[1] = check_str_end(common
);
3354 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
3355 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, common
->newline
& 0xff));
3356 if (jump
[1] != NULL
)
3361 check_newlinechar(common
, common
->nltype
, backtracks
, TRUE
);
3365 detect_partial_match(common
, backtracks
);
3369 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
3370 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3371 #ifdef COMPILE_PCRE8
3372 jump
[0] = CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
3373 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
3374 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
3375 #else /* COMPILE_PCRE8 */
3376 #ifdef COMPILE_PCRE16
3377 jump
[0] = CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
3378 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
3379 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xd800);
3380 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
3381 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
3382 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
3383 #endif /* COMPILE_PCRE16 */
3384 #endif /* COMPILE_PCRE8 */
3389 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3393 detect_partial_match(common
, backtracks
);
3394 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3402 propdata
[1] = type
== OP_NOTPROP
? XCL_NOTPROP
: XCL_PROP
;
3403 propdata
[2] = cc
[0];
3404 propdata
[3] = cc
[1];
3405 propdata
[4] = XCL_END
;
3406 compile_xclass_trypath(common
, propdata
, backtracks
);
3412 detect_partial_match(common
, backtracks
);
3414 jump
[0] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
3415 /* We don't need to handle soft partial matching case. */
3416 if (common
->mode
!= JIT_PARTIAL_HARD_COMPILE
)
3417 jump
[1] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
3419 jump
[1] = check_str_end(common
);
3420 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
3421 jump
[2] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
3422 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3423 jump
[3] = JUMP(SLJIT_JUMP
);
3425 check_newlinechar(common
, common
->bsr_nltype
, backtracks
, FALSE
);
3433 detect_partial_match(common
, backtracks
);
3435 add_jump(compiler
, &common
->hspace
, JUMP(SLJIT_FAST_CALL
));
3436 add_jump(compiler
, backtracks
, JUMP(type
== OP_NOT_HSPACE
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
3441 detect_partial_match(common
, backtracks
);
3443 add_jump(compiler
, &common
->vspace
, JUMP(SLJIT_FAST_CALL
));
3444 add_jump(compiler
, backtracks
, JUMP(type
== OP_NOT_VSPACE
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
3449 detect_partial_match(common
, backtracks
);
3451 add_jump(compiler
, &common
->getunichartype
, JUMP(SLJIT_FAST_CALL
));
3452 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Mc
);
3453 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS_EQUAL
, TMP1
, 0, SLJIT_IMM
, ucp_Mn
- ucp_Mc
));
3456 jump
[0] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
3457 OP1(SLJIT_MOV
, TMP3
, 0, STR_PTR
, 0);
3459 add_jump(compiler
, &common
->getunichartype
, JUMP(SLJIT_FAST_CALL
));
3460 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Mc
);
3461 CMPTO(SLJIT_C_LESS_EQUAL
, TMP1
, 0, SLJIT_IMM
, ucp_Mn
- ucp_Mc
, label
);
3463 OP1(SLJIT_MOV
, STR_PTR
, 0, TMP3
, 0);
3465 if (common
->mode
== JIT_PARTIAL_HARD_COMPILE
)
3467 jump
[0] = CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
3468 /* Since we successfully read a char above, partial matching must occure. */
3469 check_partial(common
, TRUE
);
3476 /* Requires rather complex checks. */
3477 jump
[0] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
3478 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
3480 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
3481 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
3482 if (common
->mode
== JIT_COMPILE
)
3483 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_END
, 0));
3486 jump
[1] = CMP(SLJIT_C_EQUAL
, TMP2
, 0, STR_END
, 0);
3487 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP2
, 0, STR_END
, 0);
3488 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS
);
3489 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff);
3490 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_NOT_EQUAL
);
3491 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_NOT_EQUAL
));
3492 check_partial(common
, TRUE
);
3493 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
3496 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
3497 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
3498 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff));
3500 else if (common
->nltype
== NLTYPE_FIXED
)
3502 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3503 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
3504 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_END
, 0));
3505 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, common
->newline
));
3509 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
3510 jump
[1] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
3511 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
3512 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP2
, 0, STR_END
, 0);
3513 jump
[2] = JUMP(SLJIT_C_GREATER
);
3514 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_LESS
));
3516 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
3517 jump
[3] = CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
3518 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
3521 if (common
->nltype
== NLTYPE_ANYCRLF
)
3523 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3524 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, TMP2
, 0, STR_END
, 0));
3525 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_NL
));
3529 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, STR_PTR
, 0);
3531 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, STR_END
, 0));
3532 add_jump(compiler
, &common
->anynewline
, JUMP(SLJIT_FAST_CALL
));
3533 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_ZERO
));
3534 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
3540 check_partial(common
, FALSE
);
3544 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0));
3545 check_partial(common
, FALSE
);
3549 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
3550 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, begin
));
3551 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, STR_PTR
, 0, TMP1
, 0));
3552 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, notbol
));
3553 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
3557 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
3558 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, begin
));
3559 jump
[1] = CMP(SLJIT_C_GREATER
, STR_PTR
, 0, TMP1
, 0);
3560 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, notbol
));
3561 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
3562 jump
[0] = JUMP(SLJIT_JUMP
);
3565 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0));
3566 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
3568 OP2(SLJIT_SUB
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
3569 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, TMP2
, 0, TMP1
, 0));
3570 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-2));
3571 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-1));
3572 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
3573 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff));
3577 skip_char_back(common
);
3579 check_newlinechar(common
, common
->nltype
, backtracks
, FALSE
);
3585 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
3586 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, noteol
));
3587 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
3589 if (!common
->endonly
)
3590 compile_char1_trypath(common
, OP_EODN
, cc
, backtracks
);
3593 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0));
3594 check_partial(common
, FALSE
);
3599 jump
[1] = CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
3600 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
3601 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, noteol
));
3602 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
3603 check_partial(common
, FALSE
);
3604 jump
[0] = JUMP(SLJIT_JUMP
);
3607 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
3609 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
3610 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
3611 if (common
->mode
== JIT_COMPILE
)
3612 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, TMP2
, 0, STR_END
, 0));
3615 jump
[1] = CMP(SLJIT_C_LESS_EQUAL
, TMP2
, 0, STR_END
, 0);
3616 /* STR_PTR = STR_END - IN_UCHARS(1) */
3617 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
3618 check_partial(common
, TRUE
);
3619 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
3623 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
3624 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
3625 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff));
3630 check_newlinechar(common
, common
->nltype
, backtracks
, FALSE
);
3639 if (common
->utf
&& HAS_EXTRALEN(*cc
)) length
+= GET_EXTRALEN(*cc
);
3641 if (common
->mode
== JIT_COMPILE
&& (type
== OP_CHAR
|| !char_has_othercase(common
, cc
) || char_get_othercase_bit(common
, cc
) != 0))
3643 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(length
));
3644 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, STR_PTR
, 0, STR_END
, 0));
3646 context
.length
= IN_UCHARS(length
);
3647 context
.sourcereg
= -1;
3648 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3649 context
.ucharptr
= 0;
3651 return byte_sequence_compare(common
, type
== OP_CHARI
, cc
, &context
, backtracks
);
3653 detect_partial_match(common
, backtracks
);
3663 if (type
== OP_CHAR
|| !char_has_othercase(common
, cc
))
3665 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
3668 oc
= char_othercase(common
, c
);
3670 if (ispowerof2(bit
))
3672 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, bit
);
3673 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
| bit
));
3676 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
);
3677 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
3678 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, char_othercase(common
, c
));
3679 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
3680 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_ZERO
));
3685 detect_partial_match(common
, backtracks
);
3690 #ifdef COMPILE_PCRE8
3694 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
3695 if (type
== OP_NOT
|| !char_has_othercase(common
, cc
))
3696 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
3699 /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
3700 OP2(SLJIT_OR
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x20);
3701 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, c
| 0x20));
3703 /* Skip the variable-length character. */
3704 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3705 jump
[0] = CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
3706 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
3707 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
3712 #endif /* COMPILE_PCRE8 */
3714 GETCHARLEN(c
, cc
, length
);
3719 #endif /* SUPPORT_UTF */
3725 if (type
== OP_NOT
|| !char_has_othercase(common
, cc
))
3726 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
3729 oc
= char_othercase(common
, c
);
3731 if (ispowerof2(bit
))
3733 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, bit
);
3734 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
| bit
));
3738 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
3739 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, oc
));
3746 detect_partial_match(common
, backtracks
);
3748 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
3750 #ifdef COMPILE_PCRE8
3751 /* This check only affects 8 bit mode. In other modes, we
3752 always need to compare the value with 255. */
3754 #endif /* COMPILE_PCRE8 */
3756 jump
[0] = CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
3757 if (type
== OP_CLASS
)
3759 add_jump(compiler
, backtracks
, jump
[0]);
3763 #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
3764 OP2(SLJIT_AND
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x7);
3765 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3);
3766 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)cc
);
3767 OP2(SLJIT_SHL
, TMP2
, 0, SLJIT_IMM
, 1, TMP2
, 0);
3768 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, TMP2
, 0);
3769 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_ZERO
));
3770 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
3771 if (jump
[0] != NULL
)
3773 #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
3774 return cc
+ 32 / sizeof(pcre_uchar
);
3776 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
3778 compile_xclass_trypath(common
, cc
+ LINK_SIZE
, backtracks
);
3779 return cc
+ GET(cc
, 0) - 1;
3783 length
= GET(cc
, 0);
3785 return cc
+ LINK_SIZE
;
3786 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
3790 OP1(SLJIT_MOV
, TMP3
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
3791 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, length
);
3793 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP3
, 0));
3794 skip_char_back(common
);
3795 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 1);
3796 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
3801 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
3802 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(length
));
3803 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, STR_PTR
, 0, TMP1
, 0));
3805 check_start_used_ptr(common
);
3806 return cc
+ LINK_SIZE
;
3808 SLJIT_ASSERT_STOP();
3812 static SLJIT_INLINE pcre_uchar
*compile_charn_trypath(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
, jump_list
**backtracks
)
3814 /* This function consumes at least one input character. */
3815 /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
3817 pcre_uchar
*ccbegin
= cc
;
3818 compare_context context
;
3831 if (common
->utf
&& HAS_EXTRALEN(cc
[1]))
3832 size
+= GET_EXTRALEN(cc
[1]);
3835 else if (*cc
== OP_CHARI
)
3841 if (char_has_othercase(common
, cc
+ 1) && char_get_othercase_bit(common
, cc
+ 1) == 0)
3843 else if (HAS_EXTRALEN(cc
[1]))
3844 size
+= GET_EXTRALEN(cc
[1]);
3848 if (char_has_othercase(common
, cc
+ 1) && char_get_othercase_bit(common
, cc
+ 1) == 0)
3855 context
.length
+= IN_UCHARS(size
);
3857 while (size
> 0 && context
.length
<= 128);
3860 if (context
.length
> 0)
3862 /* We have a fixed-length byte sequence. */
3863 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, context
.length
);
3864 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, STR_PTR
, 0, STR_END
, 0));
3866 context
.sourcereg
= -1;
3867 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3868 context
.ucharptr
= 0;
3870 do cc
= byte_sequence_compare(common
, *cc
== OP_CHARI
, cc
+ 1, &context
, backtracks
); while (context
.length
> 0);
3874 /* A non-fixed length character will be checked if length == 0. */
3875 return compile_char1_trypath(common
, *cc
, cc
+ 1, backtracks
);
3878 static struct sljit_jump
*compile_ref_checks(compiler_common
*common
, pcre_uchar
*cc
, jump_list
**backtracks
)
3881 int offset
= GET2(cc
, 1) << 1;
3883 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
3884 if (!common
->jscript_compat
)
3886 if (backtracks
== NULL
)
3888 /* OVECTOR(1) contains the "string begin - 1" constant. */
3889 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1));
3890 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
3891 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
3892 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
3893 return JUMP(SLJIT_C_NOT_ZERO
);
3895 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1)));
3897 return CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
3900 /* Forward definitions. */
3901 static void compile_trypath(compiler_common
*, pcre_uchar
*, pcre_uchar
*, backtrack_common
*);
3902 static void compile_backtrackpath(compiler_common
*, struct backtrack_common
*);
3904 #define PUSH_BACKTRACK(size, ccstart, error) \
3907 backtrack = sljit_alloc_memory(compiler, (size)); \
3908 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3910 memset(backtrack, 0, size); \
3911 backtrack->prev = parent->top; \
3912 backtrack->cc = (ccstart); \
3913 parent->top = backtrack; \
3917 #define PUSH_BACKTRACK_NOVALUE(size, ccstart) \
3920 backtrack = sljit_alloc_memory(compiler, (size)); \
3921 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3923 memset(backtrack, 0, size); \
3924 backtrack->prev = parent->top; \
3925 backtrack->cc = (ccstart); \
3926 parent->top = backtrack; \
3930 #define BACKTRACK_AS(type) ((type *)backtrack)
3932 static pcre_uchar
*compile_ref_trypath(compiler_common
*common
, pcre_uchar
*cc
, jump_list
**backtracks
, BOOL withchecks
, BOOL emptyfail
)
3935 int offset
= GET2(cc
, 1) << 1;
3936 struct sljit_jump
*jump
= NULL
;
3937 struct sljit_jump
*partial
;
3938 struct sljit_jump
*nopartial
;
3940 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
3941 /* OVECTOR(1) contains the "string begin - 1" constant. */
3942 if (withchecks
&& !common
->jscript_compat
)
3943 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1)));
3945 #if defined SUPPORT_UTF && defined SUPPORT_UCP
3946 if (common
->utf
&& *cc
== OP_REFI
)
3948 SLJIT_ASSERT(TMP1
== SLJIT_TEMPORARY_REG1
&& STACK_TOP
== SLJIT_TEMPORARY_REG2
&& TMP2
== SLJIT_TEMPORARY_REG3
);
3949 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
3951 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, TMP2
, 0);
3953 /* Needed to save important temporary registers. */
3954 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, STACK_TOP
, 0);
3955 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG2
, 0, ARGUMENTS
, 0);
3956 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), SLJIT_OFFSETOF(jit_arguments
, uchar_ptr
), STR_PTR
, 0);
3957 sljit_emit_ijump(compiler
, SLJIT_CALL3
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(do_utf_caselesscmp
));
3958 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
3959 if (common
->mode
== JIT_COMPILE
)
3960 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 1));
3963 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 0));
3964 nopartial
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 1);
3965 check_partial(common
, FALSE
);
3966 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
3967 JUMPHERE(nopartial
);
3969 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_RETURN_REG
, 0);
3972 #endif /* SUPPORT_UTF && SUPPORT_UCP */
3974 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), TMP1
, 0);
3976 jump
= JUMP(SLJIT_C_ZERO
);
3978 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
3979 partial
= CMP(SLJIT_C_GREATER
, STR_PTR
, 0, STR_END
, 0);
3980 if (common
->mode
== JIT_COMPILE
)
3981 add_jump(compiler
, backtracks
, partial
);
3983 add_jump(compiler
, *cc
== OP_REF
? &common
->casefulcmp
: &common
->caselesscmp
, JUMP(SLJIT_FAST_CALL
));
3984 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
3986 if (common
->mode
!= JIT_COMPILE
)
3988 nopartial
= JUMP(SLJIT_JUMP
);
3990 /* TMP2 -= STR_END - STR_PTR */
3991 OP2(SLJIT_SUB
, TMP2
, 0, TMP2
, 0, STR_PTR
, 0);
3992 OP2(SLJIT_ADD
, TMP2
, 0, TMP2
, 0, STR_END
, 0);
3993 partial
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0);
3994 OP1(SLJIT_MOV
, STR_PTR
, 0, STR_END
, 0);
3995 add_jump(compiler
, *cc
== OP_REF
? &common
->casefulcmp
: &common
->caselesscmp
, JUMP(SLJIT_FAST_CALL
));
3996 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
3998 check_partial(common
, FALSE
);
3999 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
4000 JUMPHERE(nopartial
);
4007 add_jump(compiler
, backtracks
, jump
);
4011 return cc
+ 1 + IMM2_SIZE
;
4014 static SLJIT_INLINE pcre_uchar
*compile_ref_iterator_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
4017 backtrack_common
*backtrack
;
4019 struct sljit_label
*label
;
4020 struct sljit_jump
*zerolength
;
4021 struct sljit_jump
*jump
= NULL
;
4022 pcre_uchar
*ccbegin
= cc
;
4023 int min
= 0, max
= 0;
4026 PUSH_BACKTRACK(sizeof(iterator_backtrack
), cc
, NULL
);
4028 type
= cc
[1 + IMM2_SIZE
];
4029 minimize
= (type
& 0x1) != 0;
4036 cc
+= 1 + IMM2_SIZE
+ 1;
4042 cc
+= 1 + IMM2_SIZE
+ 1;
4048 cc
+= 1 + IMM2_SIZE
+ 1;
4052 min
= GET2(cc
, 1 + IMM2_SIZE
+ 1);
4053 max
= GET2(cc
, 1 + IMM2_SIZE
+ 1 + IMM2_SIZE
);
4054 cc
+= 1 + IMM2_SIZE
+ 1 + 2 * IMM2_SIZE
;
4057 SLJIT_ASSERT_STOP();
4065 allocate_stack(common
, 2);
4066 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4067 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 0);
4068 /* Temporary release of STR_PTR. */
4069 OP2(SLJIT_SUB
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4070 zerolength
= compile_ref_checks(common
, ccbegin
, NULL
);
4071 /* Restore if not zero length. */
4072 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4076 allocate_stack(common
, 1);
4077 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4078 zerolength
= compile_ref_checks(common
, ccbegin
, &backtrack
->topbacktracks
);
4081 if (min
> 1 || max
> 1)
4082 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 0);
4085 compile_ref_trypath(common
, ccbegin
, &backtrack
->topbacktracks
, FALSE
, FALSE
);
4087 if (min
> 1 || max
> 1)
4089 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
4090 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
4091 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, TMP1
, 0);
4093 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, min
, label
);
4096 jump
= CMP(SLJIT_C_GREATER_EQUAL
, TMP1
, 0, SLJIT_IMM
, max
);
4097 allocate_stack(common
, 1);
4098 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4099 JUMPTO(SLJIT_JUMP
, label
);
4106 /* Includes min > 1 case as well. */
4107 allocate_stack(common
, 1);
4108 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4109 JUMPTO(SLJIT_JUMP
, label
);
4112 JUMPHERE(zerolength
);
4113 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
4115 decrease_call_count(common
);
4119 allocate_stack(common
, 2);
4120 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4121 if (type
!= OP_CRMINSTAR
)
4122 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 0);
4126 zerolength
= compile_ref_checks(common
, ccbegin
, NULL
);
4127 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4128 jump
= JUMP(SLJIT_JUMP
);
4131 zerolength
= compile_ref_checks(common
, ccbegin
, &backtrack
->topbacktracks
);
4133 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
4135 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, max
));
4137 compile_ref_trypath(common
, ccbegin
, &backtrack
->topbacktracks
, TRUE
, TRUE
);
4138 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4142 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
4143 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
4144 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
4145 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, min
, BACKTRACK_AS(iterator_backtrack
)->trypath
);
4148 OP2(SLJIT_ADD
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 1);
4152 JUMPHERE(zerolength
);
4154 decrease_call_count(common
);
4158 static SLJIT_INLINE pcre_uchar
*compile_recurse_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
4161 backtrack_common
*backtrack
;
4162 recurse_entry
*entry
= common
->entries
;
4163 recurse_entry
*prev
= NULL
;
4164 int start
= GET(cc
, 1);
4166 PUSH_BACKTRACK(sizeof(recurse_backtrack
), cc
, NULL
);
4167 while (entry
!= NULL
)
4169 if (entry
->start
== start
)
4172 entry
= entry
->next
;
4177 entry
= sljit_alloc_memory(compiler
, sizeof(recurse_entry
));
4178 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
4181 entry
->entry
= NULL
;
4182 entry
->calls
= NULL
;
4183 entry
->start
= start
;
4188 common
->entries
= entry
;
4191 if (common
->has_set_som
&& common
->mark_ptr
!= 0)
4193 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
4194 allocate_stack(common
, 2);
4195 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
4196 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
4197 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
4199 else if (common
->has_set_som
|| common
->mark_ptr
!= 0)
4201 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->has_set_som
? (int)(OVECTOR(0)) : common
->mark_ptr
);
4202 allocate_stack(common
, 1);
4203 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
4206 if (entry
->entry
== NULL
)
4207 add_jump(compiler
, &entry
->calls
, JUMP(SLJIT_FAST_CALL
));
4209 JUMPTO(SLJIT_FAST_CALL
, entry
->entry
);
4210 /* Leave if the match is failed. */
4211 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0));
4212 return cc
+ 1 + LINK_SIZE
;
4215 static pcre_uchar
*compile_assert_trypath(compiler_common
*common
, pcre_uchar
*cc
, assert_backtrack
*backtrack
, BOOL conditional
)
4220 backtrack_common altbacktrack
;
4221 pcre_uchar
*ccbegin
;
4223 pcre_uchar bra
= OP_BRA
;
4224 jump_list
*tmp
= NULL
;
4225 jump_list
**target
= (conditional
) ? &backtrack
->condfailed
: &backtrack
->common
.topbacktracks
;
4227 /* Saving previous accept variables. */
4228 struct sljit_label
*save_leavelabel
= common
->leavelabel
;
4229 struct sljit_label
*save_acceptlabel
= common
->acceptlabel
;
4230 jump_list
*save_leave
= common
->leave
;
4231 jump_list
*save_accept
= common
->accept
;
4232 struct sljit_jump
*jump
;
4233 struct sljit_jump
*brajump
= NULL
;
4235 if (*cc
== OP_BRAZERO
|| *cc
== OP_BRAMINZERO
)
4237 SLJIT_ASSERT(!conditional
);
4241 localptr
= PRIV_DATA(cc
);
4242 SLJIT_ASSERT(localptr
!= 0);
4243 framesize
= get_framesize(common
, cc
, FALSE
);
4244 backtrack
->framesize
= framesize
;
4245 backtrack
->localptr
= localptr
;
4247 SLJIT_ASSERT(opcode
>= OP_ASSERT
&& opcode
<= OP_ASSERTBACK_NOT
);
4248 found
= (opcode
== OP_ASSERT
|| opcode
== OP_ASSERTBACK
) ? &tmp
: target
;
4252 if (bra
== OP_BRAMINZERO
)
4254 /* This is a braminzero backtrack path. */
4255 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4256 free_stack(common
, 1);
4257 brajump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
4262 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STACK_TOP
, 0);
4263 allocate_stack(common
, 1);
4264 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4268 allocate_stack(common
, framesize
+ 2);
4269 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4270 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(framesize
+ 1));
4271 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP2
, 0);
4272 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4273 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
4274 init_frame(common
, ccbegin
, framesize
+ 1, 2, FALSE
);
4277 memset(&altbacktrack
, 0, sizeof(backtrack_common
));
4278 common
->leavelabel
= NULL
;
4279 common
->leave
= NULL
;
4282 common
->acceptlabel
= NULL
;
4283 common
->accept
= NULL
;
4284 altbacktrack
.top
= NULL
;
4285 altbacktrack
.topbacktracks
= NULL
;
4287 if (*ccbegin
== OP_ALT
)
4288 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4290 altbacktrack
.cc
= ccbegin
;
4291 compile_trypath(common
, ccbegin
+ 1 + LINK_SIZE
, cc
, &altbacktrack
);
4292 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
4294 common
->leavelabel
= save_leavelabel
;
4295 common
->acceptlabel
= save_acceptlabel
;
4296 common
->leave
= save_leave
;
4297 common
->accept
= save_accept
;
4300 common
->acceptlabel
= LABEL();
4301 if (common
->accept
!= NULL
)
4302 set_jumps(common
->accept
, common
->acceptlabel
);
4306 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4308 if ((opcode
!= OP_ASSERT_NOT
&& opcode
!= OP_ASSERTBACK_NOT
) || conditional
)
4310 /* We don't need to keep the STR_PTR, only the previous localptr. */
4311 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, (framesize
+ 1) * sizeof(sljit_w
));
4315 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4316 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
4320 if (opcode
== OP_ASSERT_NOT
|| opcode
== OP_ASSERTBACK_NOT
)
4322 /* We know that STR_PTR was stored on the top of the stack. */
4324 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
4325 else if (bra
== OP_BRAZERO
)
4328 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
4331 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), framesize
* sizeof(sljit_w
));
4332 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), (framesize
+ 1) * sizeof(sljit_w
));
4333 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP1
, 0);
4335 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4336 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4338 else if (framesize
>= 0)
4340 /* For OP_BRA and OP_BRAMINZERO. */
4341 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), framesize
* sizeof(sljit_w
));
4344 add_jump(compiler
, found
, JUMP(SLJIT_JUMP
));
4346 compile_backtrackpath(common
, altbacktrack
.top
);
4347 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
4349 common
->leavelabel
= save_leavelabel
;
4350 common
->acceptlabel
= save_acceptlabel
;
4351 common
->leave
= save_leave
;
4352 common
->accept
= save_accept
;
4355 set_jumps(altbacktrack
.topbacktracks
, LABEL());
4363 /* None of them matched. */
4364 if (common
->leave
!= NULL
)
4365 set_jumps(common
->leave
, LABEL());
4367 if (opcode
== OP_ASSERT
|| opcode
== OP_ASSERTBACK
)
4369 /* Assert is failed. */
4370 if (conditional
|| bra
== OP_BRAZERO
)
4371 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4375 /* The topmost item should be 0. */
4376 if (bra
== OP_BRAZERO
)
4377 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4379 free_stack(common
, 1);
4383 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
4384 /* The topmost item should be 0. */
4385 if (bra
== OP_BRAZERO
)
4387 free_stack(common
, framesize
+ 1);
4388 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4391 free_stack(common
, framesize
+ 2);
4392 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP1
, 0);
4394 jump
= JUMP(SLJIT_JUMP
);
4395 if (bra
!= OP_BRAZERO
)
4396 add_jump(compiler
, target
, jump
);
4398 /* Assert is successful. */
4399 set_jumps(tmp
, LABEL());
4402 /* We know that STR_PTR was stored on the top of the stack. */
4403 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
4404 /* Keep the STR_PTR on the top of the stack. */
4405 if (bra
== OP_BRAZERO
)
4406 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4407 else if (bra
== OP_BRAMINZERO
)
4409 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4410 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4417 /* We don't need to keep the STR_PTR, only the previous localptr. */
4418 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, (framesize
+ 1) * sizeof(sljit_w
));
4419 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
4423 /* We don't need to keep the STR_PTR, only the previous localptr. */
4424 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, (framesize
+ 2) * sizeof(sljit_w
));
4425 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4426 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), bra
== OP_BRAZERO
? STR_PTR
: SLJIT_IMM
, 0);
4430 if (bra
== OP_BRAZERO
)
4432 backtrack
->trypath
= LABEL();
4433 sljit_set_label(jump
, backtrack
->trypath
);
4435 else if (bra
== OP_BRAMINZERO
)
4437 JUMPTO(SLJIT_JUMP
, backtrack
->trypath
);
4441 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4442 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
4443 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), framesize
* sizeof(sljit_w
));
4445 set_jumps(backtrack
->common
.topbacktracks
, LABEL());
4450 /* AssertNot is successful. */
4453 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4455 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4457 free_stack(common
, 1);
4461 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4462 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
4463 /* The topmost item should be 0. */
4466 free_stack(common
, framesize
+ 1);
4467 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4470 free_stack(common
, framesize
+ 2);
4471 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP1
, 0);
4474 if (bra
== OP_BRAZERO
)
4475 backtrack
->trypath
= LABEL();
4476 else if (bra
== OP_BRAMINZERO
)
4478 JUMPTO(SLJIT_JUMP
, backtrack
->trypath
);
4484 SLJIT_ASSERT(found
== &backtrack
->common
.topbacktracks
);
4485 set_jumps(backtrack
->common
.topbacktracks
, LABEL());
4486 backtrack
->common
.topbacktracks
= NULL
;
4490 common
->leavelabel
= save_leavelabel
;
4491 common
->acceptlabel
= save_acceptlabel
;
4492 common
->leave
= save_leave
;
4493 common
->accept
= save_accept
;
4494 return cc
+ 1 + LINK_SIZE
;
4497 static sljit_w SLJIT_CALL
do_searchovector(sljit_w refno
, sljit_w
* locals
, pcre_uchar
*name_table
)
4499 int condition
= FALSE
;
4500 pcre_uchar
*slotA
= name_table
;
4502 sljit_w name_count
= locals
[LOCALS0
/ sizeof(sljit_w
)];
4503 sljit_w name_entry_size
= locals
[LOCALS1
/ sizeof(sljit_w
)];
4507 locals
+= refno
& 0xff;
4509 no_capture
= locals
[1];
4511 for (i
= 0; i
< name_count
; i
++)
4513 if (GET2(slotA
, 0) == refno
) break;
4514 slotA
+= name_entry_size
;
4519 /* Found a name for the number - there can be only one; duplicate names
4520 for different numbers are allowed, but not vice versa. First scan down
4524 while (slotB
> name_table
)
4526 slotB
-= name_entry_size
;
4527 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
4529 condition
= locals
[GET2(slotB
, 0) << 1] != no_capture
;
4530 if (condition
) break;
4535 /* Scan up for duplicates */
4539 for (i
++; i
< name_count
; i
++)
4541 slotB
+= name_entry_size
;
4542 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
4544 condition
= locals
[GET2(slotB
, 0) << 1] != no_capture
;
4545 if (condition
) break;
4554 static sljit_w SLJIT_CALL
do_searchgroups(sljit_w recno
, sljit_w
* locals
, pcre_uchar
*name_table
)
4556 int condition
= FALSE
;
4557 pcre_uchar
*slotA
= name_table
;
4559 sljit_w name_count
= locals
[LOCALS0
/ sizeof(sljit_w
)];
4560 sljit_w name_entry_size
= locals
[LOCALS1
/ sizeof(sljit_w
)];
4561 sljit_w group_num
= locals
[POSSESSIVE0
/ sizeof(sljit_w
)];
4564 for (i
= 0; i
< name_count
; i
++)
4566 if (GET2(slotA
, 0) == recno
) break;
4567 slotA
+= name_entry_size
;
4572 /* Found a name for the number - there can be only one; duplicate
4573 names for different numbers are allowed, but not vice versa. First
4574 scan down for duplicates. */
4577 while (slotB
> name_table
)
4579 slotB
-= name_entry_size
;
4580 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
4582 condition
= GET2(slotB
, 0) == group_num
;
4583 if (condition
) break;
4588 /* Scan up for duplicates */
4592 for (i
++; i
< name_count
; i
++)
4594 slotB
+= name_entry_size
;
4595 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
4597 condition
= GET2(slotB
, 0) == group_num
;
4598 if (condition
) break;
4608 Handling bracketed expressions is probably the most complex part.
4610 Stack layout naming characters:
4611 S - Push the current STR_PTR
4613 A - Push the current STR_PTR. Needed for restoring the STR_PTR
4614 before the next alternative. Not pushed if there are no alternatives.
4615 M - Any values pushed by the current alternative. Can be empty, or anything.
4616 C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.
4617 L - Push the previous local (pointed by localptr) to the stack
4618 () - opional values stored on the stack
4619 ()* - optonal, can be stored multiple times
4621 The following list shows the regular expression templates, their PCRE byte codes
4622 and stack layout supported by pcre-sljit.
4624 (?:) OP_BRA | OP_KET A M
4625 () OP_CBRA | OP_KET C M
4626 (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*
4627 OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*
4628 (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*
4629 OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*
4630 ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*
4631 OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*
4632 ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*
4633 OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*
4634 (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )
4635 (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )
4636 ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )
4637 ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )
4638 (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*
4639 OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*
4640 (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*
4641 OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*
4642 ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*
4643 OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*
4644 ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*
4645 OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*
4648 Stack layout naming characters:
4649 A - Push the alternative index (starting from 0) on the stack.
4650 Not pushed if there is no alternatives.
4651 M - Any values pushed by the current alternative. Can be empty, or anything.
4653 The next list shows the possible content of a bracket:
4654 (|) OP_*BRA | OP_ALT ... M A
4655 (?()|) OP_*COND | OP_ALT M A
4656 (?>|) OP_ONCE | OP_ALT ... [stack trace] M A
4657 (?>|) OP_ONCE_NC | OP_ALT ... [stack trace] M A
4658 Or nothing, if trace is unnecessary
4661 static pcre_uchar
*compile_bracket_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
4664 backtrack_common
*backtrack
;
4669 pcre_uchar
*ccbegin
;
4670 pcre_uchar
*trypath
;
4671 pcre_uchar bra
= OP_BRA
;
4673 assert_backtrack
*assert;
4674 BOOL has_alternatives
;
4675 struct sljit_jump
*jump
;
4676 struct sljit_jump
*skip
;
4677 struct sljit_label
*rmaxlabel
= NULL
;
4678 struct sljit_jump
*braminzerojump
= NULL
;
4680 PUSH_BACKTRACK(sizeof(bracket_backtrack
), cc
, NULL
);
4682 if (*cc
== OP_BRAZERO
|| *cc
== OP_BRAMINZERO
)
4691 trypath
= ccbegin
+ 1 + LINK_SIZE
;
4693 if ((opcode
== OP_COND
|| opcode
== OP_SCOND
) && cc
[1 + LINK_SIZE
] == OP_DEF
)
4695 /* Drop this bracket_backtrack. */
4696 parent
->top
= backtrack
->prev
;
4697 return bracketend(cc
);
4700 ket
= *(bracketend(cc
) - 1 - LINK_SIZE
);
4701 SLJIT_ASSERT(ket
== OP_KET
|| ket
== OP_KETRMAX
|| ket
== OP_KETRMIN
);
4702 SLJIT_ASSERT(!((bra
== OP_BRAZERO
&& ket
== OP_KETRMIN
) || (bra
== OP_BRAMINZERO
&& ket
== OP_KETRMAX
)));
4705 has_alternatives
= *cc
== OP_ALT
;
4706 if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
4708 has_alternatives
= (*trypath
== OP_RREF
) ? FALSE
: TRUE
;
4709 if (*trypath
== OP_NRREF
)
4711 stacksize
= GET2(trypath
, 1);
4712 if (common
->currententry
== NULL
|| stacksize
== RREF_ANY
)
4713 has_alternatives
= FALSE
;
4714 else if (common
->currententry
->start
== 0)
4715 has_alternatives
= stacksize
!= 0;
4717 has_alternatives
= stacksize
!= GET2(common
->start
, common
->currententry
->start
+ 1 + LINK_SIZE
);
4721 if (SLJIT_UNLIKELY(opcode
== OP_COND
) && (*cc
== OP_KETRMAX
|| *cc
== OP_KETRMIN
))
4723 if (SLJIT_UNLIKELY(opcode
== OP_ONCE_NC
))
4726 if (opcode
== OP_CBRA
|| opcode
== OP_SCBRA
)
4728 /* Capturing brackets has a pre-allocated space. */
4729 offset
= GET2(ccbegin
, 1 + LINK_SIZE
);
4730 localptr
= OVECTOR_PRIV(offset
);
4732 BACKTRACK_AS(bracket_backtrack
)->localptr
= localptr
;
4733 trypath
+= IMM2_SIZE
;
4735 else if (opcode
== OP_ONCE
|| opcode
== OP_SBRA
|| opcode
== OP_SCOND
)
4737 /* Other brackets simply allocate the next entry. */
4738 localptr
= PRIV_DATA(ccbegin
);
4739 SLJIT_ASSERT(localptr
!= 0);
4740 BACKTRACK_AS(bracket_backtrack
)->localptr
= localptr
;
4741 if (opcode
== OP_ONCE
)
4742 BACKTRACK_AS(bracket_backtrack
)->u
.framesize
= get_framesize(common
, ccbegin
, FALSE
);
4745 /* Instructions before the first alternative. */
4747 if ((ket
== OP_KETRMAX
) || (ket
== OP_KETRMIN
&& bra
!= OP_BRAMINZERO
))
4749 if (bra
== OP_BRAZERO
)
4753 allocate_stack(common
, stacksize
);
4756 if ((ket
== OP_KETRMAX
) || (ket
== OP_KETRMIN
&& bra
!= OP_BRAMINZERO
))
4758 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
4762 if (bra
== OP_BRAZERO
)
4763 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), STR_PTR
, 0);
4765 if (bra
== OP_BRAMINZERO
)
4767 /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */
4768 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4769 if (ket
!= OP_KETRMIN
)
4771 free_stack(common
, 1);
4772 braminzerojump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
4776 if (opcode
== OP_ONCE
|| opcode
>= OP_SBRA
)
4778 jump
= CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
4779 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
4780 /* Nothing stored during the first run. */
4781 skip
= JUMP(SLJIT_JUMP
);
4783 /* Checking zero-length iteration. */
4784 if (opcode
!= OP_ONCE
|| BACKTRACK_AS(bracket_backtrack
)->u
.framesize
< 0)
4786 /* When we come from outside, localptr contains the previous STR_PTR. */
4787 braminzerojump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4791 /* Except when the whole stack frame must be saved. */
4792 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4793 braminzerojump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(TMP1
), (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1) * sizeof(sljit_w
));
4799 jump
= CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
4800 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
4806 if (ket
== OP_KETRMIN
)
4807 BACKTRACK_AS(bracket_backtrack
)->recursivetrypath
= LABEL();
4809 if (ket
== OP_KETRMAX
)
4811 rmaxlabel
= LABEL();
4812 if (has_alternatives
&& opcode
!= OP_ONCE
&& opcode
< OP_SBRA
)
4813 BACKTRACK_AS(bracket_backtrack
)->alttrypath
= rmaxlabel
;
4816 /* Handling capturing brackets and alternatives. */
4817 if (opcode
== OP_ONCE
)
4819 if (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
< 0)
4821 /* Neither capturing brackets nor recursions are not found in the block. */
4822 if (ket
== OP_KETRMIN
)
4824 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4825 allocate_stack(common
, 2);
4826 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4827 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP2
, 0);
4828 OP2(SLJIT_SUB
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4830 else if (ket
== OP_KETRMAX
|| has_alternatives
)
4832 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STACK_TOP
, 0);
4833 allocate_stack(common
, 1);
4834 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4837 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STACK_TOP
, 0);
4841 if (ket
== OP_KETRMIN
|| ket
== OP_KETRMAX
|| has_alternatives
)
4843 allocate_stack(common
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 2);
4844 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4845 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1));
4846 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4847 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP2
, 0);
4848 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
4849 init_frame(common
, ccbegin
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1, 2, FALSE
);
4853 allocate_stack(common
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1);
4854 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4855 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(BACKTRACK_AS(bracket_backtrack
)->u
.framesize
));
4856 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP2
, 0);
4857 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP1
, 0);
4858 init_frame(common
, ccbegin
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
, 1, FALSE
);
4862 else if (opcode
== OP_CBRA
|| opcode
== OP_SCBRA
)
4864 /* Saving the previous values. */
4865 allocate_stack(common
, 3);
4866 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
4867 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
4868 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP1
, 0);
4869 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP2
, 0);
4870 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4871 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STR_PTR
, 0);
4872 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(2), TMP1
, 0);
4874 else if (opcode
== OP_SBRA
|| opcode
== OP_SCOND
)
4876 /* Saving the previous value. */
4877 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4878 allocate_stack(common
, 1);
4879 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STR_PTR
, 0);
4880 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
4882 else if (has_alternatives
)
4884 /* Pushing the starting string pointer. */
4885 allocate_stack(common
, 1);
4886 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4889 /* Generating code for the first alternative. */
4890 if (opcode
== OP_COND
|| opcode
== OP_SCOND
)
4892 if (*trypath
== OP_CREF
)
4894 SLJIT_ASSERT(has_alternatives
);
4895 add_jump(compiler
, &(BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
),
4896 CMP(SLJIT_C_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(GET2(trypath
, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1)));
4897 trypath
+= 1 + IMM2_SIZE
;
4899 else if (*trypath
== OP_NCREF
)
4901 SLJIT_ASSERT(has_alternatives
);
4902 stacksize
= GET2(trypath
, 1);
4903 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(stacksize
<< 1), SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1));
4905 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STACK_TOP
, 0);
4906 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, SLJIT_IMM
, common
->name_count
);
4907 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, SLJIT_IMM
, common
->name_entry_size
);
4908 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_IMM
, (stacksize
<< 8) | (common
->ovector_start
/ sizeof(sljit_w
)));
4909 GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2
, 0, 0);
4910 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, common
->name_table
);
4911 sljit_emit_ijump(compiler
, SLJIT_CALL3
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(do_searchovector
));
4912 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
);
4913 add_jump(compiler
, &(BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
), CMP(SLJIT_C_EQUAL
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_IMM
, 0));
4916 trypath
+= 1 + IMM2_SIZE
;
4918 else if (*trypath
== OP_RREF
|| *trypath
== OP_NRREF
)
4920 /* Never has other case. */
4921 BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
= NULL
;
4923 stacksize
= GET2(trypath
, 1);
4924 if (common
->currententry
== NULL
)
4926 else if (stacksize
== RREF_ANY
)
4928 else if (common
->currententry
->start
== 0)
4929 stacksize
= stacksize
== 0;
4931 stacksize
= stacksize
== GET2(common
->start
, common
->currententry
->start
+ 1 + LINK_SIZE
);
4933 if (*trypath
== OP_RREF
|| stacksize
|| common
->currententry
== NULL
)
4935 SLJIT_ASSERT(!has_alternatives
);
4937 trypath
+= 1 + IMM2_SIZE
;
4942 trypath
= cc
+ 1 + LINK_SIZE
;
4951 SLJIT_ASSERT(has_alternatives
);
4953 stacksize
= GET2(trypath
, 1);
4954 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STACK_TOP
, 0);
4955 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, SLJIT_IMM
, common
->name_count
);
4956 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, SLJIT_IMM
, common
->name_entry_size
);
4957 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, GET2(common
->start
, common
->currententry
->start
+ 1 + LINK_SIZE
));
4958 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_IMM
, stacksize
);
4959 GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2
, 0, 0);
4960 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, common
->name_table
);
4961 sljit_emit_ijump(compiler
, SLJIT_CALL3
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(do_searchgroups
));
4962 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
);
4963 add_jump(compiler
, &(BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
), CMP(SLJIT_C_EQUAL
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_IMM
, 0));
4964 trypath
+= 1 + IMM2_SIZE
;
4969 SLJIT_ASSERT(has_alternatives
&& *trypath
>= OP_ASSERT
&& *trypath
<= OP_ASSERTBACK_NOT
);
4970 /* Similar code as PUSH_BACKTRACK macro. */
4971 assert = sljit_alloc_memory(compiler
, sizeof(assert_backtrack
));
4972 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
4974 memset(assert, 0, sizeof(assert_backtrack
));
4975 assert->common
.cc
= trypath
;
4976 BACKTRACK_AS(bracket_backtrack
)->u
.assert = assert;
4977 trypath
= compile_assert_trypath(common
, trypath
, assert, TRUE
);
4981 compile_trypath(common
, trypath
, cc
, backtrack
);
4982 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
4985 if (opcode
== OP_ONCE
)
4987 if (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
< 0)
4989 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4990 /* TMP2 which is set here used by OP_KETRMAX below. */
4991 if (ket
== OP_KETRMAX
)
4992 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), 0);
4993 else if (ket
== OP_KETRMIN
)
4995 /* Move the STR_PTR to the localptr. */
4996 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), 0);
5001 stacksize
= (ket
== OP_KETRMIN
|| ket
== OP_KETRMAX
|| has_alternatives
) ? 2 : 1;
5002 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ stacksize
) * sizeof(sljit_w
));
5003 if (ket
== OP_KETRMAX
)
5005 /* TMP2 which is set here used by OP_KETRMAX below. */
5006 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5012 if (ket
!= OP_KET
|| bra
!= OP_BRA
)
5014 if (has_alternatives
&& opcode
!= OP_ONCE
)
5018 allocate_stack(common
, stacksize
);
5023 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), STR_PTR
, 0);
5026 else if (bra
!= OP_BRA
)
5028 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
5032 if (has_alternatives
)
5034 if (opcode
!= OP_ONCE
)
5035 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
5036 if (ket
!= OP_KETRMAX
)
5037 BACKTRACK_AS(bracket_backtrack
)->alttrypath
= LABEL();
5040 /* Must be after the trypath label. */
5043 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5044 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
5045 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 0), TMP1
, 0);
5048 if (ket
== OP_KETRMAX
)
5050 if (opcode
== OP_ONCE
|| opcode
>= OP_SBRA
)
5052 if (has_alternatives
)
5053 BACKTRACK_AS(bracket_backtrack
)->alttrypath
= LABEL();
5054 /* Checking zero-length iteration. */
5055 if (opcode
!= OP_ONCE
)
5057 CMPTO(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STR_PTR
, 0, rmaxlabel
);
5058 /* Drop STR_PTR for greedy plus quantifier. */
5059 if (bra
!= OP_BRAZERO
)
5060 free_stack(common
, 1);
5063 /* TMP2 must contain the starting STR_PTR. */
5064 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0, rmaxlabel
);
5067 JUMPTO(SLJIT_JUMP
, rmaxlabel
);
5068 BACKTRACK_AS(bracket_backtrack
)->recursivetrypath
= LABEL();
5071 if (bra
== OP_BRAZERO
)
5072 BACKTRACK_AS(bracket_backtrack
)->zerotrypath
= LABEL();
5074 if (bra
== OP_BRAMINZERO
)
5076 /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */
5077 JUMPTO(SLJIT_JUMP
, ((braminzero_backtrack
*)parent
)->trypath
);
5078 if (braminzerojump
!= NULL
)
5080 JUMPHERE(braminzerojump
);
5081 /* We need to release the end pointer to perform the
5082 backtrack for the zero-length iteration. When
5083 framesize is < 0, OP_ONCE will do the release itself. */
5084 if (opcode
== OP_ONCE
&& BACKTRACK_AS(bracket_backtrack
)->u
.framesize
>= 0)
5086 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5087 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
5089 else if (ket
== OP_KETRMIN
&& opcode
!= OP_ONCE
)
5090 free_stack(common
, 1);
5092 /* Continue to the normal backtrack. */
5095 if ((ket
!= OP_KET
&& bra
!= OP_BRAMINZERO
) || bra
== OP_BRAZERO
)
5096 decrease_call_count(common
);
5098 /* Skip the other alternatives. */
5099 while (*cc
== OP_ALT
)
5101 cc
+= 1 + LINK_SIZE
;
5105 static pcre_uchar
*compile_bracketpos_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
5108 backtrack_common
*backtrack
;
5111 int cbraprivptr
= 0;
5116 pcre_uchar
*ccbegin
= NULL
;
5118 struct sljit_label
*loop
= NULL
;
5119 struct jump_list
*emptymatch
= NULL
;
5121 PUSH_BACKTRACK(sizeof(bracketpos_backtrack
), cc
, NULL
);
5122 if (*cc
== OP_BRAPOSZERO
)
5129 localptr
= PRIV_DATA(cc
);
5130 SLJIT_ASSERT(localptr
!= 0);
5131 BACKTRACK_AS(bracketpos_backtrack
)->localptr
= localptr
;
5136 ccbegin
= cc
+ 1 + LINK_SIZE
;
5141 offset
= GET2(cc
, 1 + LINK_SIZE
);
5142 cbraprivptr
= OVECTOR_PRIV(offset
);
5144 ccbegin
= cc
+ 1 + LINK_SIZE
+ IMM2_SIZE
;
5148 SLJIT_ASSERT_STOP();
5152 framesize
= get_framesize(common
, cc
, FALSE
);
5153 BACKTRACK_AS(bracketpos_backtrack
)->framesize
= framesize
;
5156 stacksize
= (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
) ? 2 : 1;
5159 BACKTRACK_AS(bracketpos_backtrack
)->stacksize
= stacksize
;
5160 allocate_stack(common
, stacksize
);
5161 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STACK_TOP
, 0);
5163 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5165 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
5166 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
5167 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP1
, 0);
5168 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP2
, 0);
5171 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5174 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 1);
5178 stacksize
= framesize
+ 1;
5181 if (opcode
== OP_BRAPOS
|| opcode
== OP_SBRAPOS
)
5183 BACKTRACK_AS(bracketpos_backtrack
)->stacksize
= stacksize
;
5184 allocate_stack(common
, stacksize
);
5186 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5187 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(stacksize
- 1));
5188 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP2
, 0);
5192 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 1);
5195 if (opcode
== OP_BRAPOS
|| opcode
== OP_SBRAPOS
)
5197 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stack
), STR_PTR
, 0);
5200 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stack
), TMP1
, 0);
5201 init_frame(common
, cc
, stacksize
- 1, stacksize
- framesize
, FALSE
);
5204 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5205 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
, STR_PTR
, 0);
5208 while (*cc
!= OP_KETRPOS
)
5210 backtrack
->top
= NULL
;
5211 backtrack
->topbacktracks
= NULL
;
5214 compile_trypath(common
, ccbegin
, cc
, backtrack
);
5215 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
5220 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5222 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5224 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
5225 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
5226 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
, STR_PTR
, 0);
5227 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
5231 if (opcode
== OP_SBRAPOS
)
5232 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5233 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5236 if (opcode
== OP_SBRAPOS
|| opcode
== OP_SCBRAPOS
)
5237 add_jump(compiler
, &emptymatch
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, STR_PTR
, 0));
5240 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 0);
5244 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5246 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, stacksize
* sizeof(sljit_w
));
5247 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
5248 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
5249 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
, STR_PTR
, 0);
5250 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
5254 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5255 OP2(SLJIT_ADD
, STACK_TOP
, 0, TMP2
, 0, SLJIT_IMM
, stacksize
* sizeof(sljit_w
));
5256 if (opcode
== OP_SBRAPOS
)
5257 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP2
), (framesize
+ 1) * sizeof(sljit_w
));
5258 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP2
), (framesize
+ 1) * sizeof(sljit_w
), STR_PTR
, 0);
5261 if (opcode
== OP_SBRAPOS
|| opcode
== OP_SCBRAPOS
)
5262 add_jump(compiler
, &emptymatch
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, STR_PTR
, 0));
5267 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 0);
5269 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5272 JUMPTO(SLJIT_JUMP
, loop
);
5273 flush_stubs(common
);
5275 compile_backtrackpath(common
, backtrack
->top
);
5276 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
5278 set_jumps(backtrack
->topbacktracks
, LABEL());
5282 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5283 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
5285 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5289 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5291 /* Last alternative. */
5292 if (*cc
== OP_KETRPOS
)
5293 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5294 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
5298 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5299 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(TMP2
), (framesize
+ 1) * sizeof(sljit_w
));
5303 if (*cc
== OP_KETRPOS
)
5305 ccbegin
= cc
+ 1 + LINK_SIZE
;
5308 backtrack
->topbacktracks
= NULL
;
5312 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 0));
5313 else /* TMP2 is set to [localptr] above. */
5314 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(TMP2
), (stacksize
- 1) * sizeof(sljit_w
), SLJIT_IMM
, 0));
5317 /* None of them matched. */
5318 set_jumps(emptymatch
, LABEL());
5319 decrease_call_count(common
);
5320 return cc
+ 1 + LINK_SIZE
;
5323 static SLJIT_INLINE pcre_uchar
*get_iterator_parameters(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*opcode
, pcre_uchar
*type
, int *arg1
, int *arg2
, pcre_uchar
**end
)
5328 if (*opcode
>= OP_STAR
&& *opcode
<= OP_POSUPTO
)
5333 else if (*opcode
>= OP_STARI
&& *opcode
<= OP_POSUPTOI
)
5337 *opcode
-= OP_STARI
- OP_STAR
;
5339 else if (*opcode
>= OP_NOTSTAR
&& *opcode
<= OP_NOTPOSUPTO
)
5343 *opcode
-= OP_NOTSTAR
- OP_STAR
;
5345 else if (*opcode
>= OP_NOTSTARI
&& *opcode
<= OP_NOTPOSUPTOI
)
5349 *opcode
-= OP_NOTSTARI
- OP_STAR
;
5351 else if (*opcode
>= OP_TYPESTAR
&& *opcode
<= OP_TYPEPOSUPTO
)
5354 *opcode
-= OP_TYPESTAR
- OP_STAR
;
5359 SLJIT_ASSERT(*opcode
>= OP_CLASS
|| *opcode
<= OP_XCLASS
);
5362 class_len
= (*type
< OP_XCLASS
) ? (int)(1 + (32 / sizeof(pcre_uchar
))) : GET(cc
, 0);
5363 *opcode
= cc
[class_len
- 1];
5364 if (*opcode
>= OP_CRSTAR
&& *opcode
<= OP_CRMINQUERY
)
5366 *opcode
-= OP_CRSTAR
- OP_STAR
;
5368 *end
= cc
+ class_len
;
5372 SLJIT_ASSERT(*opcode
== OP_CRRANGE
|| *opcode
== OP_CRMINRANGE
);
5373 *arg1
= GET2(cc
, (class_len
+ IMM2_SIZE
));
5374 *arg2
= GET2(cc
, class_len
);
5378 SLJIT_ASSERT(*arg1
!= 0);
5379 *opcode
= (*opcode
== OP_CRRANGE
) ? OP_UPTO
: OP_MINUPTO
;
5385 *end
= cc
+ class_len
+ 2 * IMM2_SIZE
;
5390 if (*opcode
== OP_UPTO
|| *opcode
== OP_MINUPTO
|| *opcode
== OP_EXACT
|| *opcode
== OP_POSUPTO
)
5392 *arg1
= GET2(cc
, 0);
5400 *end
= next_opcode(common
, cc
);
5409 if (common
->utf
&& HAS_EXTRALEN(*cc
)) *end
+= GET_EXTRALEN(*cc
);
5415 static pcre_uchar
*compile_iterator_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
5418 backtrack_common
*backtrack
;
5421 int arg1
= -1, arg2
= -1;
5423 jump_list
*nomatch
= NULL
;
5424 struct sljit_jump
*jump
= NULL
;
5425 struct sljit_label
*label
;
5427 PUSH_BACKTRACK(sizeof(iterator_backtrack
), cc
, NULL
);
5429 cc
= get_iterator_parameters(common
, cc
, &opcode
, &type
, &arg1
, &arg2
, &end
);
5437 if (type
== OP_ANYNL
|| type
== OP_EXTUNI
)
5439 if (opcode
== OP_STAR
|| opcode
== OP_UPTO
)
5441 allocate_stack(common
, 2);
5442 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5443 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 0);
5447 allocate_stack(common
, 1);
5448 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5450 if (opcode
== OP_UPTO
|| opcode
== OP_CRRANGE
)
5451 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 0);
5454 compile_char1_trypath(common
, type
, cc
, &backtrack
->topbacktracks
);
5455 if (opcode
== OP_UPTO
|| opcode
== OP_CRRANGE
)
5457 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
5458 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
5459 if (opcode
== OP_CRRANGE
&& arg2
> 0)
5460 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg2
, label
);
5461 if (opcode
== OP_UPTO
|| (opcode
== OP_CRRANGE
&& arg1
> 0))
5462 jump
= CMP(SLJIT_C_GREATER_EQUAL
, TMP1
, 0, SLJIT_IMM
, arg1
);
5463 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, TMP1
, 0);
5466 allocate_stack(common
, 1);
5467 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5468 JUMPTO(SLJIT_JUMP
, label
);
5474 if (opcode
== OP_PLUS
)
5475 compile_char1_trypath(common
, type
, cc
, &backtrack
->topbacktracks
);
5476 allocate_stack(common
, 2);
5477 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5478 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 1);
5480 compile_char1_trypath(common
, type
, cc
, &nomatch
);
5481 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5482 if (opcode
<= OP_PLUS
|| (opcode
== OP_CRRANGE
&& arg1
== 0))
5484 OP2(SLJIT_ADD
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 1);
5485 JUMPTO(SLJIT_JUMP
, label
);
5489 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
5490 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
5491 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
5492 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg1
+ 1, label
);
5494 set_jumps(nomatch
, LABEL());
5495 if (opcode
== OP_CRRANGE
)
5496 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_LESS
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, arg2
+ 1));
5497 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5499 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
5504 if (opcode
== OP_MINPLUS
)
5505 compile_char1_trypath(common
, type
, cc
, &backtrack
->topbacktracks
);
5506 allocate_stack(common
, 1);
5507 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5508 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
5513 allocate_stack(common
, 2);
5514 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5515 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 1);
5516 if (opcode
== OP_CRMINRANGE
)
5517 add_jump(compiler
, &backtrack
->topbacktracks
, JUMP(SLJIT_JUMP
));
5518 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
5523 allocate_stack(common
, 1);
5524 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5525 if (opcode
== OP_QUERY
)
5526 compile_char1_trypath(common
, type
, cc
, &backtrack
->topbacktracks
);
5527 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
5531 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 1);
5533 compile_char1_trypath(common
, type
, cc
, &backtrack
->topbacktracks
);
5534 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
5535 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
5536 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, TMP1
, 0);
5537 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg1
+ 1, label
);
5543 if (opcode
!= OP_POSSTAR
)
5544 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 1);
5545 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STR_PTR
, 0);
5547 compile_char1_trypath(common
, type
, cc
, &nomatch
);
5548 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STR_PTR
, 0);
5549 if (opcode
!= OP_POSUPTO
)
5551 if (opcode
== OP_POSPLUS
)
5552 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 2);
5553 JUMPTO(SLJIT_JUMP
, label
);
5557 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
5558 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
5559 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, TMP1
, 0);
5560 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg1
+ 1, label
);
5562 set_jumps(nomatch
, LABEL());
5563 if (opcode
== OP_POSPLUS
)
5564 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_LESS
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 2));
5565 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
);
5569 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STR_PTR
, 0);
5570 compile_char1_trypath(common
, type
, cc
, &nomatch
);
5571 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STR_PTR
, 0);
5572 set_jumps(nomatch
, LABEL());
5573 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
);
5577 SLJIT_ASSERT_STOP();
5581 decrease_call_count(common
);
5585 static SLJIT_INLINE pcre_uchar
*compile_fail_accept_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
5588 backtrack_common
*backtrack
;
5590 PUSH_BACKTRACK(sizeof(bracket_backtrack
), cc
, NULL
);
5594 add_jump(compiler
, &backtrack
->topbacktracks
, JUMP(SLJIT_JUMP
));
5598 if (*cc
== OP_ASSERT_ACCEPT
|| common
->currententry
!= NULL
)
5600 /* No need to check notempty conditions. */
5601 if (common
->acceptlabel
== NULL
)
5602 add_jump(compiler
, &common
->accept
, JUMP(SLJIT_JUMP
));
5604 JUMPTO(SLJIT_JUMP
, common
->acceptlabel
);
5608 if (common
->acceptlabel
== NULL
)
5609 add_jump(compiler
, &common
->accept
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0)));
5611 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), common
->acceptlabel
);
5612 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
5613 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty
));
5614 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
5615 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty_atstart
));
5616 if (common
->acceptlabel
== NULL
)
5617 add_jump(compiler
, &common
->accept
, CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
5619 CMPTO(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0, common
->acceptlabel
);
5620 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
5621 if (common
->acceptlabel
== NULL
)
5622 add_jump(compiler
, &common
->accept
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0));
5624 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0, common
->acceptlabel
);
5625 add_jump(compiler
, &backtrack
->topbacktracks
, JUMP(SLJIT_JUMP
));
5629 static SLJIT_INLINE pcre_uchar
*compile_close_trypath(compiler_common
*common
, pcre_uchar
*cc
)
5632 int offset
= GET2(cc
, 1);
5634 /* Data will be discarded anyway... */
5635 if (common
->currententry
!= NULL
)
5636 return cc
+ 1 + IMM2_SIZE
;
5638 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR_PRIV(offset
));
5640 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
5641 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
5642 return cc
+ 1 + IMM2_SIZE
;
5645 static void compile_trypath(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
, backtrack_common
*parent
)
5648 backtrack_common
*backtrack
;
5656 case OP_NOT_WORD_BOUNDARY
:
5657 case OP_WORD_BOUNDARY
:
5660 case OP_NOT_WHITESPACE
:
5662 case OP_NOT_WORDCHAR
:
5684 cc
= compile_char1_trypath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
5688 PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common
), cc
);
5689 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
5690 allocate_stack(common
, 1);
5691 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), STR_PTR
, 0);
5692 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
5698 if (common
->mode
== JIT_COMPILE
)
5699 cc
= compile_charn_trypath(common
, cc
, ccend
, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
5701 cc
= compile_char1_trypath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
5735 case OP_NOTMINQUERY
:
5741 case OP_NOTPOSQUERY
:
5744 case OP_NOTMINSTARI
:
5746 case OP_NOTMINPLUSI
:
5748 case OP_NOTMINQUERYI
:
5750 case OP_NOTMINUPTOI
:
5752 case OP_NOTPOSSTARI
:
5753 case OP_NOTPOSPLUSI
:
5754 case OP_NOTPOSQUERYI
:
5755 case OP_NOTPOSUPTOI
:
5757 case OP_TYPEMINSTAR
:
5759 case OP_TYPEMINPLUS
:
5761 case OP_TYPEMINQUERY
:
5763 case OP_TYPEMINUPTO
:
5765 case OP_TYPEPOSSTAR
:
5766 case OP_TYPEPOSPLUS
:
5767 case OP_TYPEPOSQUERY
:
5768 case OP_TYPEPOSUPTO
:
5769 cc
= compile_iterator_trypath(common
, cc
, parent
);
5774 if (cc
[1 + (32 / sizeof(pcre_uchar
))] >= OP_CRSTAR
&& cc
[1 + (32 / sizeof(pcre_uchar
))] <= OP_CRMINRANGE
)
5775 cc
= compile_iterator_trypath(common
, cc
, parent
);
5777 cc
= compile_char1_trypath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
5780 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
5782 if (*(cc
+ GET(cc
, 1)) >= OP_CRSTAR
&& *(cc
+ GET(cc
, 1)) <= OP_CRMINRANGE
)
5783 cc
= compile_iterator_trypath(common
, cc
, parent
);
5785 cc
= compile_char1_trypath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
5791 if (cc
[1 + IMM2_SIZE
] >= OP_CRSTAR
&& cc
[1 + IMM2_SIZE
] <= OP_CRMINRANGE
)
5792 cc
= compile_ref_iterator_trypath(common
, cc
, parent
);
5794 cc
= compile_ref_trypath(common
, cc
, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
, TRUE
, FALSE
);
5798 cc
= compile_recurse_trypath(common
, cc
, parent
);
5804 case OP_ASSERTBACK_NOT
:
5805 PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack
), cc
);
5806 cc
= compile_assert_trypath(common
, cc
, BACKTRACK_AS(assert_backtrack
), FALSE
);
5810 PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack
), cc
);
5811 cc
= bracketend(cc
+ 1);
5812 if (*(cc
- 1 - LINK_SIZE
) != OP_KETRMIN
)
5814 allocate_stack(common
, 1);
5815 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5819 allocate_stack(common
, 2);
5820 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5821 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), STR_PTR
, 0);
5823 BACKTRACK_AS(braminzero_backtrack
)->trypath
= LABEL();
5824 if (cc
[1] > OP_ASSERTBACK_NOT
)
5825 decrease_call_count(common
);
5836 cc
= compile_bracket_trypath(common
, cc
, parent
);
5840 if (cc
[1] > OP_ASSERTBACK_NOT
)
5841 cc
= compile_bracket_trypath(common
, cc
, parent
);
5844 PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack
), cc
);
5845 cc
= compile_assert_trypath(common
, cc
, BACKTRACK_AS(assert_backtrack
), FALSE
);
5854 cc
= compile_bracketpos_trypath(common
, cc
, parent
);
5858 PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common
), cc
);
5859 SLJIT_ASSERT(common
->mark_ptr
!= 0);
5860 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
5861 allocate_stack(common
, 1);
5862 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
5863 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
5864 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, (sljit_w
)(cc
+ 2));
5865 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP2
, 0);
5866 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, mark_ptr
), TMP2
, 0);
5867 cc
+= 1 + 2 + cc
[1];
5871 PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common
), cc
);
5877 case OP_ASSERT_ACCEPT
:
5878 cc
= compile_fail_accept_trypath(common
, cc
, parent
);
5882 cc
= compile_close_trypath(common
, cc
);
5886 cc
= bracketend(cc
+ 1);
5890 SLJIT_ASSERT_STOP();
5896 SLJIT_ASSERT(cc
== ccend
);
5899 #undef PUSH_BACKTRACK
5900 #undef PUSH_BACKTRACK_NOVALUE
5903 #define COMPILE_BACKTRACKPATH(current) \
5906 compile_backtrackpath(common, (current)); \
5907 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
5912 #define CURRENT_AS(type) ((type *)current)
5914 static void compile_iterator_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
5917 pcre_uchar
*cc
= current
->cc
;
5920 int arg1
= -1, arg2
= -1;
5921 struct sljit_label
*label
= NULL
;
5922 struct sljit_jump
*jump
= NULL
;
5923 jump_list
*jumplist
= NULL
;
5925 cc
= get_iterator_parameters(common
, cc
, &opcode
, &type
, &arg1
, &arg2
, NULL
);
5933 if (type
== OP_ANYNL
|| type
== OP_EXTUNI
)
5935 set_jumps(current
->topbacktracks
, LABEL());
5936 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5937 free_stack(common
, 1);
5938 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->trypath
);
5942 if (opcode
<= OP_PLUS
|| opcode
== OP_UPTO
)
5944 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
5945 jump
= CMP(SLJIT_C_LESS_EQUAL
, TMP1
, 0, SLJIT_IMM
, arg2
+ 1);
5946 OP2(SLJIT_SUB
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0, SLJIT_IMM
, 1);
5947 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5948 skip_char_back(common
);
5949 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5950 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->trypath
);
5951 if (opcode
== OP_CRRANGE
)
5952 set_jumps(current
->topbacktracks
, LABEL());
5954 free_stack(common
, 2);
5955 if (opcode
== OP_PLUS
)
5956 set_jumps(current
->topbacktracks
, LABEL());
5962 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5963 compile_char1_trypath(common
, type
, cc
, &jumplist
);
5964 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5965 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->trypath
);
5966 set_jumps(jumplist
, LABEL());
5967 free_stack(common
, 1);
5968 if (opcode
== OP_MINPLUS
)
5969 set_jumps(current
->topbacktracks
, LABEL());
5974 if (opcode
== OP_CRMINRANGE
)
5977 set_jumps(current
->topbacktracks
, label
);
5979 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5980 compile_char1_trypath(common
, type
, cc
, &jumplist
);
5982 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
5983 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5984 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
5985 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
5987 if (opcode
== OP_CRMINRANGE
)
5988 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg2
+ 1, label
);
5990 if (opcode
== OP_CRMINRANGE
&& arg1
== 0)
5991 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->trypath
);
5993 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg1
+ 2, CURRENT_AS(iterator_backtrack
)->trypath
);
5995 set_jumps(jumplist
, LABEL());
5996 free_stack(common
, 2);
6000 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6001 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6002 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->trypath
);
6003 jump
= JUMP(SLJIT_JUMP
);
6004 set_jumps(current
->topbacktracks
, LABEL());
6005 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6006 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6007 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->trypath
);
6009 free_stack(common
, 1);
6013 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6014 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6015 jump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
6016 compile_char1_trypath(common
, type
, cc
, &jumplist
);
6017 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->trypath
);
6018 set_jumps(jumplist
, LABEL());
6020 free_stack(common
, 1);
6025 set_jumps(current
->topbacktracks
, LABEL());
6034 SLJIT_ASSERT_STOP();
6039 static void compile_ref_iterator_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6042 pcre_uchar
*cc
= current
->cc
;
6045 type
= cc
[1 + IMM2_SIZE
];
6046 if ((type
& 0x1) == 0)
6048 set_jumps(current
->topbacktracks
, LABEL());
6049 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6050 free_stack(common
, 1);
6051 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->trypath
);
6055 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6056 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->trypath
);
6057 set_jumps(current
->topbacktracks
, LABEL());
6058 free_stack(common
, 2);
6061 static void compile_recurse_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6065 set_jumps(current
->topbacktracks
, LABEL());
6067 if (common
->has_set_som
&& common
->mark_ptr
!= 0)
6069 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6070 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
6071 free_stack(common
, 2);
6072 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), TMP2
, 0);
6073 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP1
, 0);
6075 else if (common
->has_set_som
|| common
->mark_ptr
!= 0)
6077 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6078 free_stack(common
, 1);
6079 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->has_set_som
? (int)(OVECTOR(0)) : common
->mark_ptr
, TMP2
, 0);
6083 static void compile_assert_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6086 pcre_uchar
*cc
= current
->cc
;
6087 pcre_uchar bra
= OP_BRA
;
6088 struct sljit_jump
*brajump
= NULL
;
6090 SLJIT_ASSERT(*cc
!= OP_BRAMINZERO
);
6091 if (*cc
== OP_BRAZERO
)
6097 if (bra
== OP_BRAZERO
)
6099 SLJIT_ASSERT(current
->topbacktracks
== NULL
);
6100 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6103 if (CURRENT_AS(assert_backtrack
)->framesize
< 0)
6105 set_jumps(current
->topbacktracks
, LABEL());
6107 if (bra
== OP_BRAZERO
)
6109 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6110 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(assert_backtrack
)->trypath
);
6111 free_stack(common
, 1);
6116 if (bra
== OP_BRAZERO
)
6118 if (*cc
== OP_ASSERT_NOT
|| *cc
== OP_ASSERTBACK_NOT
)
6120 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6121 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(assert_backtrack
)->trypath
);
6122 free_stack(common
, 1);
6125 free_stack(common
, 1);
6126 brajump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
6129 if (*cc
== OP_ASSERT
|| *cc
== OP_ASSERTBACK
)
6131 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), CURRENT_AS(assert_backtrack
)->localptr
);
6132 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6133 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), CURRENT_AS(assert_backtrack
)->localptr
, SLJIT_MEM1(STACK_TOP
), CURRENT_AS(assert_backtrack
)->framesize
* sizeof(sljit_w
));
6135 set_jumps(current
->topbacktracks
, LABEL());
6138 set_jumps(current
->topbacktracks
, LABEL());
6140 if (bra
== OP_BRAZERO
)
6142 /* We know there is enough place on the stack. */
6143 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
6144 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6145 JUMPTO(SLJIT_JUMP
, CURRENT_AS(assert_backtrack
)->trypath
);
6150 static void compile_bracket_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6155 int localptr
= CURRENT_AS(bracket_backtrack
)->localptr
;
6158 pcre_uchar
*cc
= current
->cc
;
6159 pcre_uchar
*ccbegin
;
6161 jump_list
*jumplist
= NULL
;
6162 jump_list
*jumplistitem
= NULL
;
6163 pcre_uchar bra
= OP_BRA
;
6165 assert_backtrack
*assert;
6166 BOOL has_alternatives
;
6167 struct sljit_jump
*brazero
= NULL
;
6168 struct sljit_jump
*once
= NULL
;
6169 struct sljit_jump
*cond
= NULL
;
6170 struct sljit_label
*rminlabel
= NULL
;
6172 if (*cc
== OP_BRAZERO
|| *cc
== OP_BRAMINZERO
)
6180 ket
= *(bracketend(ccbegin
) - 1 - LINK_SIZE
);
6182 has_alternatives
= *cc
== OP_ALT
;
6183 if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
6184 has_alternatives
= (ccbegin
[1 + LINK_SIZE
] >= OP_ASSERT
&& ccbegin
[1 + LINK_SIZE
] <= OP_ASSERTBACK_NOT
) || CURRENT_AS(bracket_backtrack
)->u
.condfailed
!= NULL
;
6185 if (opcode
== OP_CBRA
|| opcode
== OP_SCBRA
)
6186 offset
= (GET2(ccbegin
, 1 + LINK_SIZE
)) << 1;
6187 if (SLJIT_UNLIKELY(opcode
== OP_COND
) && (*cc
== OP_KETRMAX
|| *cc
== OP_KETRMIN
))
6189 if (SLJIT_UNLIKELY(opcode
== OP_ONCE_NC
))
6192 if (ket
== OP_KETRMAX
)
6194 if (bra
== OP_BRAZERO
)
6196 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6197 free_stack(common
, 1);
6198 brazero
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0);
6201 else if (ket
== OP_KETRMIN
)
6203 if (bra
!= OP_BRAMINZERO
)
6205 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6206 if (opcode
>= OP_SBRA
|| opcode
== OP_ONCE
)
6208 /* Checking zero-length iteration. */
6209 if (opcode
!= OP_ONCE
|| CURRENT_AS(bracket_backtrack
)->u
.framesize
< 0)
6210 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, CURRENT_AS(bracket_backtrack
)->recursivetrypath
);
6213 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
6214 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(TMP1
), (CURRENT_AS(bracket_backtrack
)->u
.framesize
+ 1) * sizeof(sljit_w
), CURRENT_AS(bracket_backtrack
)->recursivetrypath
);
6216 if (opcode
!= OP_ONCE
)
6217 free_stack(common
, 1);
6220 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->recursivetrypath
);
6222 rminlabel
= LABEL();
6224 else if (bra
== OP_BRAZERO
)
6226 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6227 free_stack(common
, 1);
6228 brazero
= CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0);
6231 if (SLJIT_UNLIKELY(opcode
== OP_ONCE
))
6233 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
6235 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
6236 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6238 once
= JUMP(SLJIT_JUMP
);
6240 else if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
6242 if (has_alternatives
)
6244 /* Always exactly one alternative. */
6245 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6246 free_stack(common
, 1);
6248 jumplistitem
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
6249 if (SLJIT_UNLIKELY(!jumplistitem
))
6251 jumplist
= jumplistitem
;
6252 jumplistitem
->next
= NULL
;
6253 jumplistitem
->jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 1);
6256 else if (*cc
== OP_ALT
)
6258 /* Build a jump list. Get the last successfully matched branch index. */
6259 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6260 free_stack(common
, 1);
6264 /* Append as the last item. */
6265 if (jumplist
!= NULL
)
6267 jumplistitem
->next
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
6268 jumplistitem
= jumplistitem
->next
;
6272 jumplistitem
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
6273 jumplist
= jumplistitem
;
6276 if (SLJIT_UNLIKELY(!jumplistitem
))
6279 jumplistitem
->next
= NULL
;
6280 jumplistitem
->jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, count
++);
6283 while (*cc
== OP_ALT
);
6285 cc
= ccbegin
+ GET(ccbegin
, 1);
6288 COMPILE_BACKTRACKPATH(current
->top
);
6289 if (current
->topbacktracks
)
6290 set_jumps(current
->topbacktracks
, LABEL());
6292 if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
6294 /* Conditional block always has at most one alternative. */
6295 if (ccbegin
[1 + LINK_SIZE
] >= OP_ASSERT
&& ccbegin
[1 + LINK_SIZE
] <= OP_ASSERTBACK_NOT
)
6297 SLJIT_ASSERT(has_alternatives
);
6298 assert = CURRENT_AS(bracket_backtrack
)->u
.assert;
6299 if (assert->framesize
>= 0 && (ccbegin
[1 + LINK_SIZE
] == OP_ASSERT
|| ccbegin
[1 + LINK_SIZE
] == OP_ASSERTBACK
))
6301 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->localptr
);
6302 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6303 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->localptr
, SLJIT_MEM1(STACK_TOP
), assert->framesize
* sizeof(sljit_w
));
6305 cond
= JUMP(SLJIT_JUMP
);
6306 set_jumps(CURRENT_AS(bracket_backtrack
)->u
.assert->condfailed
, LABEL());
6308 else if (CURRENT_AS(bracket_backtrack
)->u
.condfailed
!= NULL
)
6310 SLJIT_ASSERT(has_alternatives
);
6311 cond
= JUMP(SLJIT_JUMP
);
6312 set_jumps(CURRENT_AS(bracket_backtrack
)->u
.condfailed
, LABEL());
6315 SLJIT_ASSERT(!has_alternatives
);
6318 if (has_alternatives
)
6323 current
->top
= NULL
;
6324 current
->topbacktracks
= NULL
;
6325 current
->nextbacktracks
= NULL
;
6328 ccprev
= cc
+ 1 + LINK_SIZE
;
6330 if (opcode
!= OP_COND
&& opcode
!= OP_SCOND
)
6332 if (localptr
!= 0 && opcode
!= OP_ONCE
)
6333 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
6335 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6337 compile_trypath(common
, ccprev
, cc
, current
);
6338 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
6342 /* Instructions after the current alternative is succesfully matched. */
6343 /* There is a similar code in compile_bracket_trypath. */
6344 if (opcode
== OP_ONCE
)
6346 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
< 0)
6348 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
6349 /* TMP2 which is set here used by OP_KETRMAX below. */
6350 if (ket
== OP_KETRMAX
)
6351 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), 0);
6352 else if (ket
== OP_KETRMIN
)
6354 /* Move the STR_PTR to the localptr. */
6355 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), 0);
6360 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, (CURRENT_AS(bracket_backtrack
)->u
.framesize
+ 2) * sizeof(sljit_w
));
6361 if (ket
== OP_KETRMAX
)
6363 /* TMP2 which is set here used by OP_KETRMAX below. */
6364 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6370 if (opcode
!= OP_ONCE
)
6372 if (ket
!= OP_KET
|| bra
!= OP_BRA
)
6375 if (stacksize
> 0) {
6376 if (opcode
!= OP_ONCE
|| CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
6377 allocate_stack(common
, stacksize
);
6380 /* We know we have place at least for one item on the top of the stack. */
6381 SLJIT_ASSERT(stacksize
== 1);
6382 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
6387 if (ket
!= OP_KET
|| bra
!= OP_BRA
)
6390 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), STR_PTR
, 0);
6392 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
6396 if (opcode
!= OP_ONCE
)
6397 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, count
++);
6401 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
6402 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
6403 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 0), TMP1
, 0);
6406 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->alttrypath
);
6408 if (opcode
!= OP_ONCE
)
6410 SLJIT_ASSERT(jumplist
);
6411 JUMPHERE(jumplist
->jump
);
6412 jumplist
= jumplist
->next
;
6415 COMPILE_BACKTRACKPATH(current
->top
);
6416 if (current
->topbacktracks
)
6417 set_jumps(current
->topbacktracks
, LABEL());
6418 SLJIT_ASSERT(!current
->nextbacktracks
);
6420 while (*cc
== OP_ALT
);
6421 SLJIT_ASSERT(!jumplist
);
6425 SLJIT_ASSERT(opcode
== OP_COND
|| opcode
== OP_SCOND
);
6426 assert = CURRENT_AS(bracket_backtrack
)->u
.assert;
6427 if ((ccbegin
[1 + LINK_SIZE
] == OP_ASSERT_NOT
|| ccbegin
[1 + LINK_SIZE
] == OP_ASSERTBACK_NOT
) && assert->framesize
>= 0)
6430 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->localptr
);
6431 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6432 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->localptr
, SLJIT_MEM1(STACK_TOP
), assert->framesize
* sizeof(sljit_w
));
6437 /* Free the STR_PTR. */
6439 free_stack(common
, 1);
6444 /* Using both tmp register is better for instruction scheduling. */
6445 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6446 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
6447 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
6448 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), TMP2
, 0);
6449 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), STACK(2));
6450 free_stack(common
, 3);
6452 else if (opcode
== OP_SBRA
|| opcode
== OP_SCOND
)
6454 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), STACK(0));
6455 free_stack(common
, 1);
6457 else if (opcode
== OP_ONCE
)
6459 cc
= ccbegin
+ GET(ccbegin
, 1);
6460 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
6462 /* Reset head and drop saved frame. */
6463 stacksize
= (ket
== OP_KETRMAX
|| ket
== OP_KETRMIN
|| *cc
== OP_ALT
) ? 2 : 1;
6464 free_stack(common
, CURRENT_AS(bracket_backtrack
)->u
.framesize
+ stacksize
);
6466 else if (ket
== OP_KETRMAX
|| (*cc
== OP_ALT
&& ket
!= OP_KETRMIN
))
6468 /* The STR_PTR must be released. */
6469 free_stack(common
, 1);
6473 /* Restore previous localptr */
6474 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
6475 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), CURRENT_AS(bracket_backtrack
)->u
.framesize
* sizeof(sljit_w
));
6476 else if (ket
== OP_KETRMIN
)
6478 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
6479 /* See the comment below. */
6480 free_stack(common
, 2);
6481 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP1
, 0);
6485 if (ket
== OP_KETRMAX
)
6487 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6488 if (bra
!= OP_BRAZERO
)
6489 free_stack(common
, 1);
6490 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(bracket_backtrack
)->recursivetrypath
);
6491 if (bra
== OP_BRAZERO
)
6493 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
6494 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->zerotrypath
);
6496 free_stack(common
, 1);
6499 else if (ket
== OP_KETRMIN
)
6501 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6503 /* OP_ONCE removes everything in case of a backtrack, so we don't
6504 need to explicitly release the STR_PTR. The extra release would
6505 affect badly the free_stack(2) above. */
6506 if (opcode
!= OP_ONCE
)
6507 free_stack(common
, 1);
6508 CMPTO(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0, rminlabel
);
6509 if (opcode
== OP_ONCE
)
6510 free_stack(common
, bra
== OP_BRAMINZERO
? 2 : 1);
6511 else if (bra
== OP_BRAMINZERO
)
6512 free_stack(common
, 1);
6514 else if (bra
== OP_BRAZERO
)
6516 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6517 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->zerotrypath
);
6522 static void compile_bracketpos_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6526 struct sljit_jump
*jump
;
6528 if (CURRENT_AS(bracketpos_backtrack
)->framesize
< 0)
6530 if (*current
->cc
== OP_CBRAPOS
|| *current
->cc
== OP_SCBRAPOS
)
6532 offset
= (GET2(current
->cc
, 1 + LINK_SIZE
)) << 1;
6533 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6534 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
6535 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
6536 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), TMP2
, 0);
6538 set_jumps(current
->topbacktracks
, LABEL());
6539 free_stack(common
, CURRENT_AS(bracketpos_backtrack
)->stacksize
);
6543 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), CURRENT_AS(bracketpos_backtrack
)->localptr
);
6544 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6546 if (current
->topbacktracks
)
6548 jump
= JUMP(SLJIT_JUMP
);
6549 set_jumps(current
->topbacktracks
, LABEL());
6550 /* Drop the stack frame. */
6551 free_stack(common
, CURRENT_AS(bracketpos_backtrack
)->stacksize
);
6554 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), CURRENT_AS(bracketpos_backtrack
)->localptr
, SLJIT_MEM1(STACK_TOP
), CURRENT_AS(bracketpos_backtrack
)->framesize
* sizeof(sljit_w
));
6557 static void compile_braminzero_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6559 assert_backtrack backtrack
;
6561 current
->top
= NULL
;
6562 current
->topbacktracks
= NULL
;
6563 current
->nextbacktracks
= NULL
;
6564 if (current
->cc
[1] > OP_ASSERTBACK_NOT
)
6566 /* Manual call of compile_bracket_trypath and compile_bracket_backtrackpath. */
6567 compile_bracket_trypath(common
, current
->cc
, current
);
6568 compile_bracket_backtrackpath(common
, current
->top
);
6572 memset(&backtrack
, 0, sizeof(backtrack
));
6573 backtrack
.common
.cc
= current
->cc
;
6574 backtrack
.trypath
= CURRENT_AS(braminzero_backtrack
)->trypath
;
6575 /* Manual call of compile_assert_trypath. */
6576 compile_assert_trypath(common
, current
->cc
, &backtrack
, FALSE
);
6578 SLJIT_ASSERT(!current
->nextbacktracks
&& !current
->topbacktracks
);
6581 static void compile_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6587 if (current
->nextbacktracks
!= NULL
)
6588 set_jumps(current
->nextbacktracks
, LABEL());
6589 switch(*current
->cc
)
6592 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6593 free_stack(common
, 1);
6594 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), TMP1
, 0);
6628 case OP_NOTMINQUERY
:
6634 case OP_NOTPOSQUERY
:
6637 case OP_NOTMINSTARI
:
6639 case OP_NOTMINPLUSI
:
6641 case OP_NOTMINQUERYI
:
6643 case OP_NOTMINUPTOI
:
6645 case OP_NOTPOSSTARI
:
6646 case OP_NOTPOSPLUSI
:
6647 case OP_NOTPOSQUERYI
:
6648 case OP_NOTPOSUPTOI
:
6650 case OP_TYPEMINSTAR
:
6652 case OP_TYPEMINPLUS
:
6654 case OP_TYPEMINQUERY
:
6656 case OP_TYPEMINUPTO
:
6658 case OP_TYPEPOSSTAR
:
6659 case OP_TYPEPOSPLUS
:
6660 case OP_TYPEPOSQUERY
:
6661 case OP_TYPEPOSUPTO
:
6664 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
6667 compile_iterator_backtrackpath(common
, current
);
6672 compile_ref_iterator_backtrackpath(common
, current
);
6676 compile_recurse_backtrackpath(common
, current
);
6682 case OP_ASSERTBACK_NOT
:
6683 compile_assert_backtrackpath(common
, current
);
6694 compile_bracket_backtrackpath(common
, current
);
6698 if (current
->cc
[1] > OP_ASSERTBACK_NOT
)
6699 compile_bracket_backtrackpath(common
, current
);
6701 compile_assert_backtrackpath(common
, current
);
6709 compile_bracketpos_backtrackpath(common
, current
);
6713 compile_braminzero_backtrackpath(common
, current
);
6717 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6718 free_stack(common
, 1);
6719 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP1
, 0);
6723 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_NOMATCH
);
6724 if (common
->leavelabel
== NULL
)
6725 add_jump(compiler
, &common
->leave
, JUMP(SLJIT_JUMP
));
6727 JUMPTO(SLJIT_JUMP
, common
->leavelabel
);
6732 case OP_ASSERT_ACCEPT
:
6733 set_jumps(current
->topbacktracks
, LABEL());
6737 SLJIT_ASSERT_STOP();
6740 current
= current
->prev
;
6744 static SLJIT_INLINE
void compile_recurse(compiler_common
*common
)
6747 pcre_uchar
*cc
= common
->start
+ common
->currententry
->start
;
6748 pcre_uchar
*ccbegin
= cc
+ 1 + LINK_SIZE
+ (*cc
== OP_BRA
? 0 : IMM2_SIZE
);
6749 pcre_uchar
*ccend
= bracketend(cc
);
6750 int localsize
= get_localsize(common
, ccbegin
, ccend
);
6751 int framesize
= get_framesize(common
, cc
, TRUE
);
6752 int alternativesize
;
6754 backtrack_common altbacktrack
;
6755 struct sljit_label
*save_leavelabel
= common
->leavelabel
;
6756 jump_list
*save_leave
= common
->leave
;
6757 struct sljit_jump
*jump
;
6759 SLJIT_ASSERT(*cc
== OP_BRA
|| *cc
== OP_CBRA
|| *cc
== OP_CBRAPOS
|| *cc
== OP_SCBRA
|| *cc
== OP_SCBRAPOS
);
6760 needsframe
= framesize
>= 0;
6763 alternativesize
= *(cc
+ GET(cc
, 1)) == OP_ALT
? 1 : 0;
6765 SLJIT_ASSERT(common
->currententry
->entry
== NULL
&& common
->recursive_head
!= 0);
6766 common
->currententry
->entry
= LABEL();
6767 set_jumps(common
->currententry
->calls
, common
->currententry
->entry
);
6769 sljit_emit_fast_enter(compiler
, TMP2
, 0);
6770 allocate_stack(common
, localsize
+ framesize
+ alternativesize
);
6771 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(localsize
+ framesize
+ alternativesize
- 1), TMP2
, 0);
6772 copy_locals(common
, ccbegin
, ccend
, TRUE
, localsize
+ framesize
+ alternativesize
, framesize
+ alternativesize
);
6773 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->recursive_head
, STACK_TOP
, 0);
6775 init_frame(common
, cc
, framesize
+ alternativesize
- 1, alternativesize
, TRUE
);
6777 if (alternativesize
> 0)
6778 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
6780 memset(&altbacktrack
, 0, sizeof(backtrack_common
));
6781 common
->leavelabel
= NULL
;
6782 common
->acceptlabel
= NULL
;
6783 common
->leave
= NULL
;
6784 common
->accept
= NULL
;
6785 altbacktrack
.cc
= ccbegin
;
6789 altbacktrack
.top
= NULL
;
6790 altbacktrack
.topbacktracks
= NULL
;
6792 if (altbacktrack
.cc
!= ccbegin
)
6793 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6795 compile_trypath(common
, altbacktrack
.cc
, cc
, &altbacktrack
);
6796 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
6798 common
->leavelabel
= save_leavelabel
;
6799 common
->leave
= save_leave
;
6803 add_jump(compiler
, &common
->accept
, JUMP(SLJIT_JUMP
));
6805 compile_backtrackpath(common
, altbacktrack
.top
);
6806 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
6808 common
->leavelabel
= save_leavelabel
;
6809 common
->leave
= save_leave
;
6812 set_jumps(altbacktrack
.topbacktracks
, LABEL());
6817 altbacktrack
.cc
= cc
+ 1 + LINK_SIZE
;
6820 /* None of them matched. */
6821 if (common
->leave
!= NULL
)
6822 set_jumps(common
->leave
, LABEL());
6824 OP1(SLJIT_MOV
, TMP3
, 0, SLJIT_IMM
, 0);
6825 jump
= JUMP(SLJIT_JUMP
);
6827 set_jumps(common
->accept
, LABEL());
6828 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->recursive_head
);
6831 OP2(SLJIT_SUB
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, (framesize
+ alternativesize
) * sizeof(sljit_w
));
6832 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6833 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, (framesize
+ alternativesize
) * sizeof(sljit_w
));
6835 OP1(SLJIT_MOV
, TMP3
, 0, SLJIT_IMM
, 1);
6838 copy_locals(common
, ccbegin
, ccend
, FALSE
, localsize
+ framesize
+ alternativesize
, framesize
+ alternativesize
);
6839 free_stack(common
, localsize
+ framesize
+ alternativesize
);
6840 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), sizeof(sljit_w
));
6841 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
6842 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->recursive_head
, TMP2
, 0);
6843 sljit_emit_fast_return(compiler
, SLJIT_MEM1(STACK_TOP
), 0);
6845 common
->leavelabel
= save_leavelabel
;
6846 common
->leave
= save_leave
;
6849 #undef COMPILE_BACKTRACKPATH
6853 PRIV(jit_compile
)(const REAL_PCRE
*re
, PUBL(extra
) *extra
, int mode
)
6855 struct sljit_compiler
*compiler
;
6856 backtrack_common rootbacktrack
;
6857 compiler_common common_data
;
6858 compiler_common
*common
= &common_data
;
6859 const pcre_uint8
*tables
= re
->tables
;
6860 pcre_study_data
*study
;
6863 executable_functions
*functions
;
6864 void *executable_func
;
6865 sljit_uw executable_size
;
6866 struct sljit_label
*mainloop
= NULL
;
6867 struct sljit_label
*empty_match_found
;
6868 struct sljit_label
*empty_match_backtrack
;
6869 struct sljit_jump
*jump
;
6870 struct sljit_jump
*reqbyte_notfound
= NULL
;
6871 struct sljit_jump
*empty_match
;
6873 SLJIT_ASSERT((extra
->flags
& PCRE_EXTRA_STUDY_DATA
) != 0);
6874 study
= extra
->study_data
;
6877 tables
= PRIV(default_tables
);
6879 memset(&rootbacktrack
, 0, sizeof(backtrack_common
));
6880 memset(common
, 0, sizeof(compiler_common
));
6881 rootbacktrack
.cc
= (pcre_uchar
*)re
+ re
->name_table_offset
+ re
->name_count
* re
->name_entry_size
;
6883 common
->start
= rootbacktrack
.cc
;
6884 common
->fcc
= tables
+ fcc_offset
;
6885 common
->lcc
= (sljit_w
)(tables
+ lcc_offset
);
6886 common
->mode
= mode
;
6887 common
->nltype
= NLTYPE_FIXED
;
6888 switch(re
->options
& PCRE_NEWLINE_BITS
)
6891 /* Compile-time default */
6894 case -1: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANY
; break;
6895 case -2: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANYCRLF
; break;
6896 default: common
->newline
= NEWLINE
; break;
6899 case PCRE_NEWLINE_CR
: common
->newline
= CHAR_CR
; break;
6900 case PCRE_NEWLINE_LF
: common
->newline
= CHAR_NL
; break;
6901 case PCRE_NEWLINE_CR
+
6902 PCRE_NEWLINE_LF
: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; break;
6903 case PCRE_NEWLINE_ANY
: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANY
; break;
6904 case PCRE_NEWLINE_ANYCRLF
: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANYCRLF
; break;
6907 if ((re
->options
& PCRE_BSR_ANYCRLF
) != 0)
6908 common
->bsr_nltype
= NLTYPE_ANYCRLF
;
6909 else if ((re
->options
& PCRE_BSR_UNICODE
) != 0)
6910 common
->bsr_nltype
= NLTYPE_ANY
;
6914 common
->bsr_nltype
= NLTYPE_ANYCRLF
;
6916 common
->bsr_nltype
= NLTYPE_ANY
;
6919 common
->endonly
= (re
->options
& PCRE_DOLLAR_ENDONLY
) != 0;
6920 common
->ctypes
= (sljit_w
)(tables
+ ctypes_offset
);
6921 common
->name_table
= (sljit_w
)((pcre_uchar
*)re
+ re
->name_table_offset
);
6922 common
->name_count
= re
->name_count
;
6923 common
->name_entry_size
= re
->name_entry_size
;
6924 common
->jscript_compat
= (re
->options
& PCRE_JAVASCRIPT_COMPAT
) != 0;
6926 /* PCRE_UTF16 has the same value as PCRE_UTF8. */
6927 common
->utf
= (re
->options
& PCRE_UTF8
) != 0;
6929 common
->use_ucp
= (re
->options
& PCRE_UCP
) != 0;
6931 #endif /* SUPPORT_UTF */
6932 ccend
= bracketend(rootbacktrack
.cc
);
6934 /* Calculate the local space size on the stack. */
6935 common
->ovector_start
= CALL_LIMIT
+ sizeof(sljit_w
);
6937 SLJIT_ASSERT(*rootbacktrack
.cc
== OP_BRA
&& ccend
[-(1 + LINK_SIZE
)] == OP_KET
);
6938 localsize
= get_localspace(common
, rootbacktrack
.cc
, ccend
);
6942 /* Checking flags and updating ovector_start. */
6943 if (mode
== JIT_COMPILE
&& (re
->flags
& PCRE_REQCHSET
) != 0 && (re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
6945 common
->req_char_ptr
= common
->ovector_start
;
6946 common
->ovector_start
+= sizeof(sljit_w
);
6948 if (mode
!= JIT_COMPILE
)
6950 common
->start_used_ptr
= common
->ovector_start
;
6951 common
->ovector_start
+= sizeof(sljit_w
);
6952 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
6954 common
->hit_start
= common
->ovector_start
;
6955 common
->ovector_start
+= sizeof(sljit_w
);
6958 if ((re
->options
& PCRE_FIRSTLINE
) != 0)
6960 common
->first_line_end
= common
->ovector_start
;
6961 common
->ovector_start
+= sizeof(sljit_w
);
6964 /* Aligning ovector to even number of sljit words. */
6965 if ((common
->ovector_start
& sizeof(sljit_w
)) != 0)
6966 common
->ovector_start
+= sizeof(sljit_w
);
6968 SLJIT_ASSERT(!(common
->req_char_ptr
!= 0 && common
->start_used_ptr
!= 0));
6969 common
->cbraptr
= OVECTOR_START
+ (re
->top_bracket
+ 1) * 2 * sizeof(sljit_w
);
6970 localsize
+= common
->cbraptr
+ (re
->top_bracket
+ 1) * sizeof(sljit_w
);
6971 if (localsize
> SLJIT_MAX_LOCAL_SIZE
)
6973 common
->localptrs
= (int *)SLJIT_MALLOC((ccend
- rootbacktrack
.cc
) * sizeof(int));
6974 if (!common
->localptrs
)
6976 memset(common
->localptrs
, 0, (ccend
- rootbacktrack
.cc
) * sizeof(int));
6977 set_localptrs(common
, common
->cbraptr
+ (re
->top_bracket
+ 1) * sizeof(sljit_w
), ccend
);
6979 compiler
= sljit_create_compiler();
6982 SLJIT_FREE(common
->localptrs
);
6985 common
->compiler
= compiler
;
6987 /* Main pcre_jit_exec entry. */
6988 sljit_emit_enter(compiler
, 1, 5, 5, localsize
);
6990 /* Register init. */
6991 reset_ovector(common
, (re
->top_bracket
+ 1) * 2);
6992 if (common
->req_char_ptr
!= 0)
6993 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->req_char_ptr
, SLJIT_TEMPORARY_REG1
, 0);
6995 OP1(SLJIT_MOV
, ARGUMENTS
, 0, SLJIT_SAVED_REG1
, 0);
6996 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_SAVED_REG1
, 0);
6997 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
6998 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, end
));
6999 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, stack
));
7000 OP1(SLJIT_MOV_SI
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, calllimit
));
7001 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(struct sljit_stack
, base
));
7002 OP1(SLJIT_MOV
, STACK_LIMIT
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(struct sljit_stack
, limit
));
7003 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), CALL_LIMIT
, TMP1
, 0);
7005 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
7006 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, 0);
7008 /* Main part of the matching */
7009 if ((re
->options
& PCRE_ANCHORED
) == 0)
7011 mainloop
= mainloop_entry(common
, (re
->flags
& PCRE_HASCRORLF
) != 0, (re
->options
& PCRE_FIRSTLINE
) != 0);
7012 /* Forward search if possible. */
7013 if ((re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
7015 if ((re
->flags
& PCRE_FIRSTSET
) != 0)
7016 fast_forward_first_char(common
, (pcre_uchar
)re
->first_char
, (re
->flags
& PCRE_FCH_CASELESS
) != 0, (re
->options
& PCRE_FIRSTLINE
) != 0);
7017 else if ((re
->flags
& PCRE_STARTLINE
) != 0)
7018 fast_forward_newline(common
, (re
->options
& PCRE_FIRSTLINE
) != 0);
7019 else if ((re
->flags
& PCRE_STARTLINE
) == 0 && study
!= NULL
&& (study
->flags
& PCRE_STUDY_MAPPED
) != 0)
7020 fast_forward_start_bits(common
, (sljit_uw
)study
->start_bits
, (re
->options
& PCRE_FIRSTLINE
) != 0);
7023 if (common
->req_char_ptr
!= 0)
7024 reqbyte_notfound
= search_requested_char(common
, (pcre_uchar
)re
->req_char
, (re
->flags
& PCRE_RCH_CASELESS
) != 0, (re
->flags
& PCRE_FIRSTSET
) != 0);
7026 /* Store the current STR_PTR in OVECTOR(0). */
7027 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), STR_PTR
, 0);
7028 /* Copy the limit of allowed recursions. */
7029 OP1(SLJIT_MOV
, CALL_COUNT
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), CALL_LIMIT
);
7030 if (common
->mark_ptr
!= 0)
7031 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, SLJIT_IMM
, 0);
7032 /* Copy the beginning of the string. */
7033 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
7035 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, 0);
7036 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
7039 else if (mode
== JIT_PARTIAL_HARD_COMPILE
)
7040 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
7042 compile_trypath(common
, rootbacktrack
.cc
, ccend
, &rootbacktrack
);
7043 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
7045 sljit_free_compiler(compiler
);
7046 SLJIT_FREE(common
->localptrs
);
7050 empty_match
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
7051 empty_match_found
= LABEL();
7053 common
->acceptlabel
= LABEL();
7054 if (common
->accept
!= NULL
)
7055 set_jumps(common
->accept
, common
->acceptlabel
);
7057 /* This means we have a match. Update the ovector. */
7058 copy_ovector(common
, re
->top_bracket
+ 1);
7059 common
->leavelabel
= LABEL();
7060 if (common
->leave
!= NULL
)
7061 set_jumps(common
->leave
, common
->leavelabel
);
7062 sljit_emit_return(compiler
, SLJIT_MOV
, SLJIT_RETURN_REG
, 0);
7064 if (mode
!= JIT_COMPILE
)
7066 common
->partialmatchlabel
= LABEL();
7067 set_jumps(common
->partialmatch
, common
->partialmatchlabel
);
7068 return_with_partial_match(common
, common
->leavelabel
);
7071 empty_match_backtrack
= LABEL();
7072 compile_backtrackpath(common
, rootbacktrack
.top
);
7073 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
7075 sljit_free_compiler(compiler
);
7076 SLJIT_FREE(common
->localptrs
);
7080 SLJIT_ASSERT(rootbacktrack
.prev
== NULL
);
7082 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
7084 /* Update hit_start only in the first time. */
7085 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
7086 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
);
7087 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, SLJIT_IMM
, -1);
7088 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, TMP1
, 0);
7092 /* Check we have remaining characters. */
7093 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
7095 if ((re
->options
& PCRE_ANCHORED
) == 0)
7097 if ((re
->options
& PCRE_FIRSTLINE
) == 0)
7099 if (mode
== JIT_COMPILE
&& study
!= NULL
&& study
->minlength
> 1 && (re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
7101 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(study
->minlength
+ 1));
7102 CMPTO(SLJIT_C_LESS_EQUAL
, TMP1
, 0, STR_END
, 0, mainloop
);
7105 CMPTO(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0, mainloop
);
7109 SLJIT_ASSERT(common
->first_line_end
!= 0);
7110 if (mode
== JIT_COMPILE
&& study
!= NULL
&& study
->minlength
> 1 && (re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
7112 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(study
->minlength
+ 1));
7113 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, STR_END
, 0);
7114 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_GREATER
);
7115 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
7116 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_GREATER_EQUAL
);
7117 JUMPTO(SLJIT_C_ZERO
, mainloop
);
7120 CMPTO(SLJIT_C_LESS
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, mainloop
);
7124 /* No more remaining characters. */
7125 if (reqbyte_notfound
!= NULL
)
7126 JUMPHERE(reqbyte_notfound
);
7128 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
7129 CMPTO(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, 0, common
->partialmatchlabel
);
7131 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_NOMATCH
);
7132 JUMPTO(SLJIT_JUMP
, common
->leavelabel
);
7134 flush_stubs(common
);
7136 JUMPHERE(empty_match
);
7137 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
7138 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty
));
7139 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0, empty_match_backtrack
);
7140 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty_atstart
));
7141 CMPTO(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0, empty_match_found
);
7142 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
7143 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0, empty_match_found
);
7144 JUMPTO(SLJIT_JUMP
, empty_match_backtrack
);
7146 common
->currententry
= common
->entries
;
7147 while (common
->currententry
!= NULL
)
7149 /* Might add new entries. */
7150 compile_recurse(common
);
7151 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
7153 sljit_free_compiler(compiler
);
7154 SLJIT_FREE(common
->localptrs
);
7157 flush_stubs(common
);
7158 common
->currententry
= common
->currententry
->next
;
7161 /* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */
7162 /* This is a (really) rare case. */
7163 set_jumps(common
->stackalloc
, LABEL());
7164 /* RETURN_ADDR is not a saved register. */
7165 sljit_emit_fast_enter(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
7166 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP2
, 0);
7167 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
7168 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, stack
));
7169 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, top
), STACK_TOP
, 0);
7170 OP2(SLJIT_ADD
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, limit
), SLJIT_IMM
, STACK_GROWTH_RATE
);
7172 sljit_emit_ijump(compiler
, SLJIT_CALL2
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(sljit_stack_resize
));
7173 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 0);
7174 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
7175 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, stack
));
7176 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, top
));
7177 OP1(SLJIT_MOV
, STACK_LIMIT
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, limit
));
7178 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
7179 sljit_emit_fast_return(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
7181 /* Allocation failed. */
7183 /* We break the return address cache here, but this is a really rare case. */
7184 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_JIT_STACKLIMIT
);
7185 JUMPTO(SLJIT_JUMP
, common
->leavelabel
);
7187 /* Call limit reached. */
7188 set_jumps(common
->calllimit
, LABEL());
7189 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_MATCHLIMIT
);
7190 JUMPTO(SLJIT_JUMP
, common
->leavelabel
);
7192 if (common
->revertframes
!= NULL
)
7194 set_jumps(common
->revertframes
, LABEL());
7195 do_revertframes(common
);
7197 if (common
->wordboundary
!= NULL
)
7199 set_jumps(common
->wordboundary
, LABEL());
7200 check_wordboundary(common
);
7202 if (common
->anynewline
!= NULL
)
7204 set_jumps(common
->anynewline
, LABEL());
7205 check_anynewline(common
);
7207 if (common
->hspace
!= NULL
)
7209 set_jumps(common
->hspace
, LABEL());
7210 check_hspace(common
);
7212 if (common
->vspace
!= NULL
)
7214 set_jumps(common
->vspace
, LABEL());
7215 check_vspace(common
);
7217 if (common
->casefulcmp
!= NULL
)
7219 set_jumps(common
->casefulcmp
, LABEL());
7220 do_casefulcmp(common
);
7222 if (common
->caselesscmp
!= NULL
)
7224 set_jumps(common
->caselesscmp
, LABEL());
7225 do_caselesscmp(common
);
7228 if (common
->utfreadchar
!= NULL
)
7230 set_jumps(common
->utfreadchar
, LABEL());
7231 do_utfreadchar(common
);
7233 #ifdef COMPILE_PCRE8
7234 if (common
->utfreadtype8
!= NULL
)
7236 set_jumps(common
->utfreadtype8
, LABEL());
7237 do_utfreadtype8(common
);
7240 #endif /* COMPILE_PCRE8 */
7242 if (common
->getunichartype
!= NULL
)
7244 set_jumps(common
->getunichartype
, LABEL());
7245 do_getunichartype(common
);
7247 if (common
->getunichartype_2
!= NULL
)
7249 set_jumps(common
->getunichartype_2
, LABEL());
7250 do_getunichartype_2(common
);
7252 if (common
->getunicharscript
!= NULL
)
7254 set_jumps(common
->getunicharscript
, LABEL());
7255 do_getunicharscript(common
);
7259 SLJIT_FREE(common
->localptrs
);
7260 executable_func
= sljit_generate_code(compiler
);
7261 executable_size
= sljit_get_generated_code_size(compiler
);
7262 sljit_free_compiler(compiler
);
7263 if (executable_func
== NULL
)
7266 /* Reuse the function descriptor if possible. */
7267 if ((extra
->flags
& PCRE_EXTRA_EXECUTABLE_JIT
) != 0 && extra
->executable_jit
!= NULL
)
7268 functions
= (executable_functions
*)extra
->executable_jit
;
7271 functions
= SLJIT_MALLOC(sizeof(executable_functions
));
7272 if (functions
== NULL
)
7274 /* This case is highly unlikely since we just recently
7275 freed a lot of memory. Although not impossible. */
7276 sljit_free_code(executable_func
);
7279 memset(functions
, 0, sizeof(executable_functions
));
7280 extra
->executable_jit
= functions
;
7281 extra
->flags
|= PCRE_EXTRA_EXECUTABLE_JIT
;
7284 functions
->executable_funcs
[mode
] = executable_func
;
7285 functions
->executable_sizes
[mode
] = executable_size
;
7288 static int jit_machine_stack_exec(jit_arguments
*arguments
, void* executable_func
)
7291 void* executable_func
;
7292 jit_function call_executable_func
;
7293 } convert_executable_func
;
7294 pcre_uint8 local_area
[LOCAL_SPACE_SIZE
];
7295 struct sljit_stack local_stack
;
7297 local_stack
.top
= (sljit_w
)&local_area
;
7298 local_stack
.base
= local_stack
.top
;
7299 local_stack
.limit
= local_stack
.base
+ LOCAL_SPACE_SIZE
;
7300 local_stack
.max_limit
= local_stack
.limit
;
7301 arguments
->stack
= &local_stack
;
7302 convert_executable_func
.executable_func
= executable_func
;
7303 return convert_executable_func
.call_executable_func(arguments
);
7307 PRIV(jit_exec
)(const REAL_PCRE
*re
, const PUBL(extra
) *extra_data
, const pcre_uchar
*subject
,
7308 int length
, int start_offset
, int options
, int *offsets
, int offsetcount
)
7310 executable_functions
*functions
= (executable_functions
*)extra_data
->executable_jit
;
7312 void* executable_func
;
7313 jit_function call_executable_func
;
7314 } convert_executable_func
;
7315 jit_arguments arguments
;
7318 int mode
= JIT_COMPILE
;
7320 if ((options
& PCRE_PARTIAL_HARD
) != 0)
7321 mode
= JIT_PARTIAL_HARD_COMPILE
;
7322 else if ((options
& PCRE_PARTIAL_SOFT
) != 0)
7323 mode
= JIT_PARTIAL_SOFT_COMPILE
;
7325 if (functions
->executable_funcs
[mode
] == NULL
)
7326 return PCRE_ERROR_NULL
;
7328 /* Sanity checks should be handled by pcre_exec. */
7329 arguments
.stack
= NULL
;
7330 arguments
.str
= subject
+ start_offset
;
7331 arguments
.begin
= subject
;
7332 arguments
.end
= subject
+ length
;
7333 arguments
.mark_ptr
= NULL
;
7334 /* JIT decreases this value less frequently than the interpreter. */
7335 arguments
.calllimit
= ((extra_data
->flags
& PCRE_EXTRA_MATCH_LIMIT
) == 0) ? MATCH_LIMIT
: extra_data
->match_limit
;
7336 arguments
.notbol
= (options
& PCRE_NOTBOL
) != 0;
7337 arguments
.noteol
= (options
& PCRE_NOTEOL
) != 0;
7338 arguments
.notempty
= (options
& PCRE_NOTEMPTY
) != 0;
7339 arguments
.notempty_atstart
= (options
& PCRE_NOTEMPTY_ATSTART
) != 0;
7340 arguments
.offsets
= offsets
;
7342 /* pcre_exec() rounds offsetcount to a multiple of 3, and then uses only 2/3 of
7343 the output vector for storing captured strings, with the remainder used as
7344 workspace. We don't need the workspace here. For compatibility, we limit the
7345 number of captured strings in the same way as pcre_exec(), so that the user
7346 gets the same result with and without JIT. */
7348 if (offsetcount
!= 2)
7349 offsetcount
= ((offsetcount
- (offsetcount
% 3)) * 2) / 3;
7350 maxoffsetcount
= (re
->top_bracket
+ 1) * 2;
7351 if (offsetcount
> maxoffsetcount
)
7352 offsetcount
= maxoffsetcount
;
7353 arguments
.offsetcount
= offsetcount
;
7355 if (functions
->callback
)
7356 arguments
.stack
= (struct sljit_stack
*)functions
->callback(functions
->userdata
);
7358 arguments
.stack
= (struct sljit_stack
*)functions
->userdata
;
7360 if (arguments
.stack
== NULL
)
7361 retval
= jit_machine_stack_exec(&arguments
, functions
->executable_funcs
[mode
]);
7364 convert_executable_func
.executable_func
= functions
->executable_funcs
[mode
];
7365 retval
= convert_executable_func
.call_executable_func(&arguments
);
7368 if (retval
* 2 > offsetcount
)
7370 if ((extra_data
->flags
& PCRE_EXTRA_MARK
) != 0)
7371 *(extra_data
->mark
) = arguments
.mark_ptr
;
7377 PRIV(jit_free
)(void *executable_funcs
)
7380 executable_functions
*functions
= (executable_functions
*)executable_funcs
;
7381 for (i
= 0; i
< JIT_NUMBER_OF_COMPILE_MODES
; i
++)
7383 if (functions
->executable_funcs
[i
] != NULL
)
7384 sljit_free_code(functions
->executable_funcs
[i
]);
7386 SLJIT_FREE(functions
);
7390 PRIV(jit_get_size
)(void *executable_funcs
)
7394 sljit_uw
*executable_sizes
= ((executable_functions
*)executable_funcs
)->executable_sizes
;
7395 for (i
= 0; i
< JIT_NUMBER_OF_COMPILE_MODES
; i
++)
7396 size
+= executable_sizes
[i
];
7401 PRIV(jit_get_target
)(void)
7403 return sljit_get_platform_name();
7406 #ifdef COMPILE_PCRE8
7407 PCRE_EXP_DECL pcre_jit_stack
*
7408 pcre_jit_stack_alloc(int startsize
, int maxsize
)
7410 PCRE_EXP_DECL pcre16_jit_stack
*
7411 pcre16_jit_stack_alloc(int startsize
, int maxsize
)
7414 if (startsize
< 1 || maxsize
< 1)
7416 if (startsize
> maxsize
)
7417 startsize
= maxsize
;
7418 startsize
= (startsize
+ STACK_GROWTH_RATE
- 1) & ~(STACK_GROWTH_RATE
- 1);
7419 maxsize
= (maxsize
+ STACK_GROWTH_RATE
- 1) & ~(STACK_GROWTH_RATE
- 1);
7420 return (PUBL(jit_stack
)*)sljit_allocate_stack(startsize
, maxsize
);
7423 #ifdef COMPILE_PCRE8
7425 pcre_jit_stack_free(pcre_jit_stack
*stack
)
7428 pcre16_jit_stack_free(pcre16_jit_stack
*stack
)
7431 sljit_free_stack((struct sljit_stack
*)stack
);
7434 #ifdef COMPILE_PCRE8
7436 pcre_assign_jit_stack(pcre_extra
*extra
, pcre_jit_callback callback
, void *userdata
)
7439 pcre16_assign_jit_stack(pcre16_extra
*extra
, pcre16_jit_callback callback
, void *userdata
)
7442 executable_functions
*functions
;
7443 if (extra
!= NULL
&&
7444 (extra
->flags
& PCRE_EXTRA_EXECUTABLE_JIT
) != 0 &&
7445 extra
->executable_jit
!= NULL
)
7447 functions
= (executable_functions
*)extra
->executable_jit
;
7448 functions
->callback
= callback
;
7449 functions
->userdata
= userdata
;
7453 #else /* SUPPORT_JIT */
7455 /* These are dummy functions to avoid linking errors when JIT support is not
7458 #ifdef COMPILE_PCRE8
7459 PCRE_EXP_DECL pcre_jit_stack
*
7460 pcre_jit_stack_alloc(int startsize
, int maxsize
)
7462 PCRE_EXP_DECL pcre16_jit_stack
*
7463 pcre16_jit_stack_alloc(int startsize
, int maxsize
)
7471 #ifdef COMPILE_PCRE8
7473 pcre_jit_stack_free(pcre_jit_stack
*stack
)
7476 pcre16_jit_stack_free(pcre16_jit_stack
*stack
)
7482 #ifdef COMPILE_PCRE8
7484 pcre_assign_jit_stack(pcre_extra
*extra
, pcre_jit_callback callback
, void *userdata
)
7487 pcre16_assign_jit_stack(pcre16_extra
*extra
, pcre16_jit_callback callback
, void *userdata
)
7497 /* End of pcre_jit_compile.c */