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 -----------------------------------------------------------------------------
47 #include "pcre_internal.h"
51 /* All-in-one: Since we use the JIT compiler only from here,
52 we just include it. This way we don't need to touch the build
55 #define SLJIT_MALLOC(size) (PUBL(malloc))(size)
56 #define SLJIT_FREE(ptr) (PUBL(free))(ptr)
57 #define SLJIT_CONFIG_AUTO 1
58 #define SLJIT_CONFIG_STATIC 1
59 #define SLJIT_VERBOSE 0
62 #include "sljit/sljitLir.c"
64 #if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
65 #error Unsupported architecture
68 /* Allocate memory on the stack. Fast, but limited size. */
69 #define LOCAL_SPACE_SIZE 32768
71 #define STACK_GROWTH_RATE 8192
73 /* Enable to check that the allocation could destroy temporaries. */
74 #if defined SLJIT_DEBUG && SLJIT_DEBUG
75 #define DESTROY_REGISTERS 1
79 Short summary about the backtracking mechanism empolyed by the jit code generator:
81 The code generator follows the recursive nature of the PERL compatible regular
82 expressions. The basic blocks of regular expressions are condition checkers
83 whose execute different commands depending on the result of the condition check.
84 The relationship between the operators can be horizontal (concatenation) and
85 vertical (sub-expression) (See struct backtrack_common for more details).
87 'ab' - 'a' and 'b' regexps are concatenated
88 'a+' - 'a' is the sub-expression of the '+' operator
90 The condition checkers are boolean (true/false) checkers. Machine code is generated
91 for the checker itself and for the actions depending on the result of the checker.
92 The 'true' case is called as the try path (expected path), and the other is called as
93 the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken
94 branches on the try path.
96 Greedy star operator (*) :
97 Try path: match happens.
98 Backtrack path: match failed.
99 Non-greedy star operator (*?) :
100 Try path: no need to perform a match.
101 Backtrack path: match is required.
103 The following example shows how the code generated for a capturing bracket
104 with two alternatives. Let A, B, C, D are arbirary regular expressions, and
105 we have the following regular expression:
109 The generated code will be the following:
112 '(' try path (pushing arguments to the stack)
114 ')' try path (pushing arguments to the stack)
116 return with successful match
119 ')' backtrack path (If we arrived from "C" jump to the backtrack of "C")
126 Notice, that the order of backtrack code paths are the opposite of the fast
127 code paths. In this way the topmost value on the stack is always belong
128 to the current backtrack code path. The backtrack path must check
129 whether there is a next alternative. If so, it needs to jump back to
130 the try path eventually. Otherwise it needs to clear out its own stack
131 frame and continue the execution on the backtrack code paths.
137 Atomic blocks and asserts require reloading the values of local variables
138 when the backtrack mechanism performed. Because of OP_RECURSE, the locals
139 are not necessarly known in compile time, thus we need a dynamic restore
142 The stack frames are stored in a chain list, and have the following format:
143 ([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]
145 Thus we can restore the locals to a particular point in the stack.
148 typedef struct jit_arguments
{
149 /* Pointers first. */
150 struct sljit_stack
*stack
;
151 const pcre_uchar
*str
;
152 const pcre_uchar
*begin
;
153 const pcre_uchar
*end
;
155 pcre_uchar
*uchar_ptr
;
156 pcre_uchar
*mark_ptr
;
157 /* Everything else after. */
163 pcre_uint8 notempty_atstart
;
166 typedef struct executable_functions
{
167 void *executable_funcs
[JIT_NUMBER_OF_COMPILE_MODES
];
168 PUBL(jit_callback
) callback
;
170 sljit_uw executable_sizes
[JIT_NUMBER_OF_COMPILE_MODES
];
171 } executable_functions
;
173 typedef struct jump_list
{
174 struct sljit_jump
*jump
;
175 struct jump_list
*next
;
178 enum stub_types
{ stack_alloc
};
180 typedef struct stub_list
{
181 enum stub_types type
;
183 struct sljit_jump
*start
;
184 struct sljit_label
*leave
;
185 struct stub_list
*next
;
188 typedef int (SLJIT_CALL
*jit_function
)(jit_arguments
*args
);
190 /* The following structure is the key data type for the recursive
191 code generator. It is allocated by compile_trypath, and contains
192 the aguments for compile_backtrackpath. Must be the first member
193 of its descendants. */
194 typedef struct backtrack_common
{
195 /* Concatenation stack. */
196 struct backtrack_common
*prev
;
197 jump_list
*nextbacktracks
;
198 /* Internal stack (for component operators). */
199 struct backtrack_common
*top
;
200 jump_list
*topbacktracks
;
201 /* Opcode pointer. */
205 typedef struct assert_backtrack
{
206 backtrack_common common
;
207 jump_list
*condfailed
;
208 /* Less than 0 (-1) if a frame is not needed. */
210 /* Points to our private memory word on the stack. */
213 struct sljit_label
*trypath
;
216 typedef struct bracket_backtrack
{
217 backtrack_common common
;
218 /* Where to coninue if an alternative is successfully matched. */
219 struct sljit_label
*alttrypath
;
220 /* For rmin and rmax iterators. */
221 struct sljit_label
*recursivetrypath
;
222 /* For greedy ? operator. */
223 struct sljit_label
*zerotrypath
;
224 /* Contains the branches of a failed condition. */
226 /* Both for OP_COND, OP_SCOND. */
227 jump_list
*condfailed
;
228 assert_backtrack
*assert;
229 /* For OP_ONCE. -1 if not needed. */
232 /* Points to our private memory word on the stack. */
236 typedef struct bracketpos_backtrack
{
237 backtrack_common common
;
238 /* Points to our private memory word on the stack. */
240 /* Reverting stack is needed. */
242 /* Allocated stack size. */
244 } bracketpos_backtrack
;
246 typedef struct braminzero_backtrack
{
247 backtrack_common common
;
248 struct sljit_label
*trypath
;
249 } braminzero_backtrack
;
251 typedef struct iterator_backtrack
{
252 backtrack_common common
;
253 /* Next iteration. */
254 struct sljit_label
*trypath
;
255 } iterator_backtrack
;
257 typedef struct recurse_entry
{
258 struct recurse_entry
*next
;
259 /* Contains the function entry. */
260 struct sljit_label
*entry
;
261 /* Collects the calls until the function is not created. */
263 /* Points to the starting opcode. */
267 typedef struct recurse_backtrack
{
268 backtrack_common common
;
271 typedef struct compiler_common
{
272 struct sljit_compiler
*compiler
;
275 /* Opcode local area direct map. */
278 /* OVector starting point. Must be divisible by 2. */
280 /* Last known position of the requested byte. */
282 /* Head of the last recursion. */
284 /* First inspected character for partial matching. */
286 /* Starting pointer for partial soft matches. */
288 /* End pointer of the first line. */
290 /* Points to the marked string. */
294 const pcre_uint8
*fcc
;
305 sljit_w name_entry_size
;
307 /* Labels and jump lists. */
308 struct sljit_label
*partialmatchlabel
;
309 struct sljit_label
*leavelabel
;
310 struct sljit_label
*acceptlabel
;
312 recurse_entry
*entries
;
313 recurse_entry
*currententry
;
314 jump_list
*partialmatch
;
317 jump_list
*calllimit
;
318 jump_list
*stackalloc
;
319 jump_list
*revertframes
;
320 jump_list
*wordboundary
;
321 jump_list
*anynewline
;
324 jump_list
*casefulcmp
;
325 jump_list
*caselesscmp
;
332 jump_list
*utfreadchar
;
334 jump_list
*utfreadtype8
;
336 #endif /* SUPPORT_UTF */
338 jump_list
*getunichartype
;
339 jump_list
*getunichartype_2
;
340 jump_list
*getunicharscript
;
344 /* For byte_sequence_compare. */
346 typedef struct compare_context
{
349 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
356 sljit_ub asuchars
[4];
358 #ifdef COMPILE_PCRE16
359 sljit_uh asuchars
[2];
368 sljit_ub asuchars
[4];
370 #ifdef COMPILE_PCRE16
371 sljit_uh asuchars
[2];
380 frame_setstrbegin
= -1,
384 /* Undefine sljit macros. */
387 /* Used for accessing the elements of the stack. */
388 #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w))
390 #define TMP1 SLJIT_TEMPORARY_REG1
391 #define TMP2 SLJIT_TEMPORARY_REG3
392 #define TMP3 SLJIT_TEMPORARY_EREG2
393 #define STR_PTR SLJIT_SAVED_REG1
394 #define STR_END SLJIT_SAVED_REG2
395 #define STACK_TOP SLJIT_TEMPORARY_REG2
396 #define STACK_LIMIT SLJIT_SAVED_REG3
397 #define ARGUMENTS SLJIT_SAVED_EREG1
398 #define CALL_COUNT SLJIT_SAVED_EREG2
399 #define RETURN_ADDR SLJIT_TEMPORARY_EREG1
402 /* These two locals can be used by the current opcode. */
403 #define LOCALS0 (0 * sizeof(sljit_w))
404 #define LOCALS1 (1 * sizeof(sljit_w))
405 /* Two local variables for possessive quantifiers (char1 cannot use them). */
406 #define POSSESSIVE0 (2 * sizeof(sljit_w))
407 #define POSSESSIVE1 (3 * sizeof(sljit_w))
408 /* Max limit of recursions. */
409 #define CALL_LIMIT (4 * sizeof(sljit_w))
410 /* The output vector is stored on the stack, and contains pointers
411 to characters. The vector data is divided into two groups: the first
412 group contains the start / end character pointers, and the second is
413 the start pointers when the end of the capturing group has not yet reached. */
414 #define OVECTOR_START (common->ovector_start)
415 #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w))
416 #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w))
417 #define PRIV_DATA(cc) (common->localptrs[(cc) - common->start])
420 #define MOV_UCHAR SLJIT_MOV_UB
421 #define MOVU_UCHAR SLJIT_MOVU_UB
423 #ifdef COMPILE_PCRE16
424 #define MOV_UCHAR SLJIT_MOV_UH
425 #define MOVU_UCHAR SLJIT_MOVU_UH
427 #error Unsupported compiling mode
432 #define DEFINE_COMPILER \
433 struct sljit_compiler *compiler = common->compiler
434 #define OP1(op, dst, dstw, src, srcw) \
435 sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
436 #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
437 sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
439 sljit_emit_label(compiler)
441 sljit_emit_jump(compiler, (type))
442 #define JUMPTO(type, label) \
443 sljit_set_label(sljit_emit_jump(compiler, (type)), (label))
444 #define JUMPHERE(jump) \
445 sljit_set_label((jump), sljit_emit_label(compiler))
446 #define CMP(type, src1, src1w, src2, src2w) \
447 sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
448 #define CMPTO(type, src1, src1w, src2, src2w, label) \
449 sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
450 #define COND_VALUE(op, dst, dstw, type) \
451 sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type))
452 #define GET_LOCAL_BASE(dst, dstw, offset) \
453 sljit_get_local_base(compiler, (dst), (dstw), (offset))
455 static pcre_uchar
* bracketend(pcre_uchar
* cc
)
457 SLJIT_ASSERT((*cc
>= OP_ASSERT
&& *cc
<= OP_ASSERTBACK_NOT
) || (*cc
>= OP_ONCE
&& *cc
<= OP_SCOND
));
458 do cc
+= GET(cc
, 1); while (*cc
== OP_ALT
);
459 SLJIT_ASSERT(*cc
>= OP_KET
&& *cc
<= OP_KETRPOS
);
464 /* Functions whose might need modification for all new supported opcodes:
473 compile_backtrackpath
476 static pcre_uchar
*next_opcode(compiler_common
*common
, pcre_uchar
*cc
)
478 SLJIT_UNUSED_ARG(common
);
484 case OP_NOT_WORD_BOUNDARY
:
485 case OP_WORD_BOUNDARY
:
488 case OP_NOT_WHITESPACE
:
490 case OP_NOT_WORDCHAR
:
511 case OP_TYPEMINQUERY
:
514 case OP_TYPEPOSQUERY
:
528 case OP_ASSERT_ACCEPT
:
534 if (common
->utf
) return NULL
;
574 case OP_NOTMINQUERYI
:
577 case OP_NOTPOSQUERYI
:
580 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
602 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
626 return cc
+ 1 + 2 * IMM2_SIZE
;
630 return cc
+ 1 + 32 / sizeof(pcre_uchar
);
632 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
634 return cc
+ GET(cc
, 1);
641 case OP_ASSERTBACK_NOT
:
656 return cc
+ 1 + LINK_SIZE
;
662 return cc
+ 1 + LINK_SIZE
+ IMM2_SIZE
;
665 return cc
+ 1 + 2 + cc
[1];
672 static int get_localspace(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
)
675 pcre_uchar
*alternative
;
676 /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
682 common
->has_set_som
= TRUE
;
689 case OP_ASSERTBACK_NOT
:
696 localspace
+= sizeof(sljit_w
);
702 localspace
+= sizeof(sljit_w
);
703 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
707 /* Might be a hidden SCOND. */
708 alternative
= cc
+ GET(cc
, 1);
709 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
710 localspace
+= sizeof(sljit_w
);
715 /* Set its value only once. */
716 if (common
->recursive_head
== 0)
718 common
->recursive_head
= common
->ovector_start
;
719 common
->ovector_start
+= sizeof(sljit_w
);
725 if (common
->mark_ptr
== 0)
727 common
->mark_ptr
= common
->ovector_start
;
728 common
->ovector_start
+= sizeof(sljit_w
);
734 cc
= next_opcode(common
, cc
);
743 static void set_localptrs(compiler_common
*common
, int localptr
, pcre_uchar
*ccend
)
745 pcre_uchar
*cc
= common
->start
;
746 pcre_uchar
*alternative
;
754 case OP_ASSERTBACK_NOT
:
761 common
->localptrs
[cc
- common
->start
] = localptr
;
762 localptr
+= sizeof(sljit_w
);
768 common
->localptrs
[cc
- common
->start
] = localptr
;
769 localptr
+= sizeof(sljit_w
);
770 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
774 /* Might be a hidden SCOND. */
775 alternative
= cc
+ GET(cc
, 1);
776 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
778 common
->localptrs
[cc
- common
->start
] = localptr
;
779 localptr
+= sizeof(sljit_w
);
785 cc
= next_opcode(common
, cc
);
786 SLJIT_ASSERT(cc
!= NULL
);
792 /* Returns with -1 if no need for frame. */
793 static int get_framesize(compiler_common
*common
, pcre_uchar
*cc
, BOOL recursive
)
795 pcre_uchar
*ccend
= bracketend(cc
);
797 BOOL possessive
= FALSE
;
798 BOOL setsom_found
= recursive
;
799 BOOL setmark_found
= recursive
;
801 if (!recursive
&& (*cc
== OP_CBRAPOS
|| *cc
== OP_SCBRAPOS
))
807 cc
= next_opcode(common
, cc
);
808 SLJIT_ASSERT(cc
!= NULL
);
813 SLJIT_ASSERT(common
->has_set_som
);
823 SLJIT_ASSERT(common
->mark_ptr
!= 0);
827 setmark_found
= TRUE
;
833 if (common
->has_set_som
&& !setsom_found
)
838 if (common
->mark_ptr
!= 0 && !setmark_found
)
841 setmark_found
= TRUE
;
851 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
855 cc
= next_opcode(common
, cc
);
856 SLJIT_ASSERT(cc
!= NULL
);
860 /* Possessive quantifiers can use a special case. */
861 if (SLJIT_UNLIKELY(possessive
) && length
== 3)
869 static void init_frame(compiler_common
*common
, pcre_uchar
*cc
, int stackpos
, int stacktop
, BOOL recursive
)
872 pcre_uchar
*ccend
= bracketend(cc
);
873 BOOL setsom_found
= recursive
;
874 BOOL setmark_found
= recursive
;
877 /* >= 1 + shortest item size (2) */
878 SLJIT_UNUSED_ARG(stacktop
);
879 SLJIT_ASSERT(stackpos
>= stacktop
+ 2);
881 stackpos
= STACK(stackpos
);
882 if (recursive
|| (*cc
!= OP_CBRAPOS
&& *cc
!= OP_SCBRAPOS
))
883 cc
= next_opcode(common
, cc
);
884 SLJIT_ASSERT(cc
!= NULL
);
889 SLJIT_ASSERT(common
->has_set_som
);
892 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
893 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setstrbegin
);
894 stackpos
+= (int)sizeof(sljit_w
);
895 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
896 stackpos
+= (int)sizeof(sljit_w
);
903 SLJIT_ASSERT(common
->mark_ptr
!= 0);
906 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
907 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setmark
);
908 stackpos
+= (int)sizeof(sljit_w
);
909 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
910 stackpos
+= (int)sizeof(sljit_w
);
911 setmark_found
= TRUE
;
917 if (common
->has_set_som
&& !setsom_found
)
919 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
920 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setstrbegin
);
921 stackpos
+= (int)sizeof(sljit_w
);
922 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
923 stackpos
+= (int)sizeof(sljit_w
);
926 if (common
->mark_ptr
!= 0 && !setmark_found
)
928 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
929 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setmark
);
930 stackpos
+= (int)sizeof(sljit_w
);
931 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
932 stackpos
+= (int)sizeof(sljit_w
);
933 setmark_found
= TRUE
;
942 offset
= (GET2(cc
, 1 + LINK_SIZE
)) << 1;
943 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, OVECTOR(offset
));
944 stackpos
+= (int)sizeof(sljit_w
);
945 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
946 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
947 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
948 stackpos
+= (int)sizeof(sljit_w
);
949 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP2
, 0);
950 stackpos
+= (int)sizeof(sljit_w
);
952 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
956 cc
= next_opcode(common
, cc
);
957 SLJIT_ASSERT(cc
!= NULL
);
961 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_end
);
962 SLJIT_ASSERT(stackpos
== STACK(stacktop
));
965 static SLJIT_INLINE
int get_localsize(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
)
968 pcre_uchar
*alternative
;
969 /* Calculate the sum of the local variables. */
977 case OP_ASSERTBACK_NOT
:
991 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
997 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
1001 /* Might be a hidden SCOND. */
1002 alternative
= cc
+ GET(cc
, 1);
1003 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
1005 cc
+= 1 + LINK_SIZE
;
1009 cc
= next_opcode(common
, cc
);
1010 SLJIT_ASSERT(cc
!= NULL
);
1014 SLJIT_ASSERT(cc
== ccend
);
1018 static void copy_locals(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
,
1019 BOOL save
, int stackptr
, int stacktop
)
1024 BOOL tmp1next
= TRUE
;
1025 BOOL tmp1empty
= TRUE
;
1026 BOOL tmp2empty
= TRUE
;
1027 pcre_uchar
*alternative
;
1034 status
= save
? start
: loop
;
1035 stackptr
= STACK(stackptr
- 2);
1036 stacktop
= STACK(stacktop
- 1);
1040 stackptr
+= sizeof(sljit_w
);
1041 if (stackptr
< stacktop
)
1043 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1044 stackptr
+= sizeof(sljit_w
);
1047 if (stackptr
< stacktop
)
1049 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1050 stackptr
+= sizeof(sljit_w
);
1053 /* The tmp1next must be TRUE in either way. */
1056 while (status
!= end
)
1062 SLJIT_ASSERT(save
&& common
->recursive_head
!= 0);
1064 srcw
[0] = common
->recursive_head
;
1080 case OP_ASSERTBACK_NOT
:
1088 srcw
[0] = PRIV_DATA(cc
);
1089 SLJIT_ASSERT(srcw
[0] != 0);
1090 cc
+= 1 + LINK_SIZE
;
1096 srcw
[0] = OVECTOR_PRIV(GET2(cc
, 1 + LINK_SIZE
));
1097 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
1103 srcw
[1] = OVECTOR_PRIV(GET2(cc
, 1 + LINK_SIZE
));
1104 srcw
[0] = PRIV_DATA(cc
);
1105 SLJIT_ASSERT(srcw
[0] != 0);
1106 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
1110 /* Might be a hidden SCOND. */
1111 alternative
= cc
+ GET(cc
, 1);
1112 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
1115 srcw
[0] = PRIV_DATA(cc
);
1116 SLJIT_ASSERT(srcw
[0] != 0);
1118 cc
+= 1 + LINK_SIZE
;
1122 cc
= next_opcode(common
, cc
);
1123 SLJIT_ASSERT(cc
!= NULL
);
1129 SLJIT_ASSERT_STOP();
1142 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP1
, 0);
1143 stackptr
+= sizeof(sljit_w
);
1145 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
]);
1153 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP2
, 0);
1154 stackptr
+= sizeof(sljit_w
);
1156 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
]);
1165 SLJIT_ASSERT(!tmp1empty
);
1166 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
], TMP1
, 0);
1167 tmp1empty
= stackptr
>= stacktop
;
1170 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1171 stackptr
+= sizeof(sljit_w
);
1177 SLJIT_ASSERT(!tmp2empty
);
1178 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
], TMP2
, 0);
1179 tmp2empty
= stackptr
>= stacktop
;
1182 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1183 stackptr
+= sizeof(sljit_w
);
1197 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP1
, 0);
1198 stackptr
+= sizeof(sljit_w
);
1202 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP2
, 0);
1203 stackptr
+= sizeof(sljit_w
);
1210 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP2
, 0);
1211 stackptr
+= sizeof(sljit_w
);
1215 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP1
, 0);
1216 stackptr
+= sizeof(sljit_w
);
1220 SLJIT_ASSERT(cc
== ccend
&& stackptr
== stacktop
&& (save
|| (tmp1empty
&& tmp2empty
)));
1223 static SLJIT_INLINE BOOL
ispowerof2(unsigned int value
)
1225 return (value
& (value
- 1)) == 0;
1228 static SLJIT_INLINE
void set_jumps(jump_list
*list
, struct sljit_label
*label
)
1232 /* sljit_set_label is clever enough to do nothing
1233 if either the jump or the label is NULL */
1234 sljit_set_label(list
->jump
, label
);
1239 static SLJIT_INLINE
void add_jump(struct sljit_compiler
*compiler
, jump_list
**list
, struct sljit_jump
* jump
)
1241 jump_list
*list_item
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
1244 list_item
->next
= *list
;
1245 list_item
->jump
= jump
;
1250 static void add_stub(compiler_common
*common
, enum stub_types type
, int data
, struct sljit_jump
*start
)
1253 stub_list
* list_item
= sljit_alloc_memory(compiler
, sizeof(stub_list
));
1257 list_item
->type
= type
;
1258 list_item
->data
= data
;
1259 list_item
->start
= start
;
1260 list_item
->leave
= LABEL();
1261 list_item
->next
= common
->stubs
;
1262 common
->stubs
= list_item
;
1266 static void flush_stubs(compiler_common
*common
)
1269 stub_list
* list_item
= common
->stubs
;
1273 JUMPHERE(list_item
->start
);
1274 switch(list_item
->type
)
1277 add_jump(compiler
, &common
->stackalloc
, JUMP(SLJIT_FAST_CALL
));
1280 JUMPTO(SLJIT_JUMP
, list_item
->leave
);
1281 list_item
= list_item
->next
;
1283 common
->stubs
= NULL
;
1286 static SLJIT_INLINE
void decrease_call_count(compiler_common
*common
)
1290 OP2(SLJIT_SUB
| SLJIT_SET_E
, CALL_COUNT
, 0, CALL_COUNT
, 0, SLJIT_IMM
, 1);
1291 add_jump(compiler
, &common
->calllimit
, JUMP(SLJIT_C_ZERO
));
1294 static SLJIT_INLINE
void allocate_stack(compiler_common
*common
, int size
)
1296 /* May destroy all locals and registers except TMP2. */
1299 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, size
* sizeof(sljit_w
));
1300 #ifdef DESTROY_REGISTERS
1301 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 12345);
1302 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
1303 OP1(SLJIT_MOV
, RETURN_ADDR
, 0, TMP1
, 0);
1304 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, TMP1
, 0);
1305 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP1
, 0);
1307 add_stub(common
, stack_alloc
, 0, CMP(SLJIT_C_GREATER
, STACK_TOP
, 0, STACK_LIMIT
, 0));
1310 static SLJIT_INLINE
void free_stack(compiler_common
*common
, int size
)
1313 OP2(SLJIT_SUB
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, size
* sizeof(sljit_w
));
1316 static SLJIT_INLINE
void reset_ovector(compiler_common
*common
, int length
)
1319 struct sljit_label
*loop
;
1321 /* At this point we can freely use all temporary registers. */
1322 /* TMP1 returns with begin - 1. */
1323 OP2(SLJIT_SUB
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_MEM1(SLJIT_SAVED_REG1
), SLJIT_OFFSETOF(jit_arguments
, begin
), SLJIT_IMM
, IN_UCHARS(1));
1326 for (i
= 0; i
< length
; i
++)
1327 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(i
), SLJIT_TEMPORARY_REG1
, 0);
1331 GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2
, 0, OVECTOR_START
- sizeof(sljit_w
));
1332 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, length
);
1334 OP1(SLJIT_MOVU
, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), sizeof(sljit_w
), SLJIT_TEMPORARY_REG1
, 0);
1335 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, 1);
1336 JUMPTO(SLJIT_C_NOT_ZERO
, loop
);
1340 static SLJIT_INLINE
void copy_ovector(compiler_common
*common
, int topbracket
)
1343 struct sljit_label
*loop
;
1344 struct sljit_jump
*earlyexit
;
1346 /* At this point we can freely use all registers. */
1347 OP1(SLJIT_MOV
, SLJIT_SAVED_REG3
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1));
1348 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1), STR_PTR
, 0);
1350 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG1
, 0, ARGUMENTS
, 0);
1351 if (common
->mark_ptr
!= 0)
1352 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
1353 OP1(SLJIT_MOV_SI
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1
), SLJIT_OFFSETOF(jit_arguments
, offsetcount
));
1354 if (common
->mark_ptr
!= 0)
1355 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_TEMPORARY_REG1
), SLJIT_OFFSETOF(jit_arguments
, mark_ptr
), SLJIT_TEMPORARY_REG3
, 0);
1356 OP2(SLJIT_SUB
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1
), SLJIT_OFFSETOF(jit_arguments
, offsets
), SLJIT_IMM
, sizeof(int));
1357 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
1358 GET_LOCAL_BASE(SLJIT_SAVED_REG1
, 0, OVECTOR_START
);
1359 /* Unlikely, but possible */
1360 earlyexit
= CMP(SLJIT_C_EQUAL
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_IMM
, 0);
1362 OP2(SLJIT_SUB
, SLJIT_SAVED_REG2
, 0, SLJIT_MEM1(SLJIT_SAVED_REG1
), 0, SLJIT_TEMPORARY_REG1
, 0);
1363 OP2(SLJIT_ADD
, SLJIT_SAVED_REG1
, 0, SLJIT_SAVED_REG1
, 0, SLJIT_IMM
, sizeof(sljit_w
));
1364 /* Copy the integer value to the output buffer */
1365 #ifdef COMPILE_PCRE16
1366 OP2(SLJIT_ASHR
, SLJIT_SAVED_REG2
, 0, SLJIT_SAVED_REG2
, 0, SLJIT_IMM
, 1);
1368 OP1(SLJIT_MOVU_SI
, SLJIT_MEM1(SLJIT_TEMPORARY_REG3
), sizeof(int), SLJIT_SAVED_REG2
, 0);
1369 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_TEMPORARY_REG2
, 0, SLJIT_IMM
, 1);
1370 JUMPTO(SLJIT_C_NOT_ZERO
, loop
);
1371 JUMPHERE(earlyexit
);
1373 /* Calculate the return value, which is the maximum ovector value. */
1376 GET_LOCAL_BASE(SLJIT_TEMPORARY_REG1
, 0, OVECTOR_START
+ topbracket
* 2 * sizeof(sljit_w
));
1377 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_IMM
, topbracket
+ 1);
1379 /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */
1381 OP1(SLJIT_MOVU
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1
), -(2 * (sljit_w
)sizeof(sljit_w
)));
1382 OP2(SLJIT_SUB
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_TEMPORARY_REG2
, 0, SLJIT_IMM
, 1);
1383 CMPTO(SLJIT_C_EQUAL
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_SAVED_REG3
, 0, loop
);
1384 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_TEMPORARY_REG2
, 0);
1387 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 1);
1390 static SLJIT_INLINE
void return_with_partial_match(compiler_common
*common
, struct sljit_label
*leave
)
1394 SLJIT_COMPILE_ASSERT(STR_END
== SLJIT_SAVED_REG2
, str_end_must_be_saved_reg2
);
1395 SLJIT_ASSERT(common
->start_used_ptr
!= 0 && (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
? common
->hit_start
!= 0 : common
->hit_start
== 0));
1397 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG2
, 0, ARGUMENTS
, 0);
1398 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_PARTIAL
);
1399 OP1(SLJIT_MOV_SI
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), SLJIT_OFFSETOF(jit_arguments
, offsetcount
));
1400 CMPTO(SLJIT_C_LESS
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, 2, leave
);
1402 /* Store match begin and end. */
1403 OP1(SLJIT_MOV
, SLJIT_SAVED_REG1
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), SLJIT_OFFSETOF(jit_arguments
, begin
));
1404 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG2
, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), SLJIT_OFFSETOF(jit_arguments
, offsets
));
1405 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
);
1406 OP2(SLJIT_SUB
, SLJIT_SAVED_REG2
, 0, STR_END
, 0, SLJIT_SAVED_REG1
, 0);
1407 #ifdef COMPILE_PCRE16
1408 OP2(SLJIT_ASHR
, SLJIT_SAVED_REG2
, 0, SLJIT_SAVED_REG2
, 0, SLJIT_IMM
, 1);
1410 OP1(SLJIT_MOV_SI
, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), sizeof(int), SLJIT_SAVED_REG2
, 0);
1412 OP2(SLJIT_SUB
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_TEMPORARY_REG3
, 0, SLJIT_SAVED_REG1
, 0);
1413 #ifdef COMPILE_PCRE16
1414 OP2(SLJIT_ASHR
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, 1);
1416 OP1(SLJIT_MOV_SI
, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), 0, SLJIT_TEMPORARY_REG3
, 0);
1418 JUMPTO(SLJIT_JUMP
, leave
);
1421 static SLJIT_INLINE
void check_start_used_ptr(compiler_common
*common
)
1423 /* May destroy TMP1. */
1425 struct sljit_jump
*jump
;
1427 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
1429 /* The value of -1 must be kept for start_used_ptr! */
1430 OP2(SLJIT_ADD
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, SLJIT_IMM
, 1);
1431 /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting
1432 is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */
1433 jump
= CMP(SLJIT_C_LESS_EQUAL
, TMP1
, 0, STR_PTR
, 0);
1434 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1437 else if (common
->mode
== JIT_PARTIAL_HARD_COMPILE
)
1439 jump
= CMP(SLJIT_C_LESS_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1440 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1445 static SLJIT_INLINE BOOL
char_has_othercase(compiler_common
*common
, pcre_uchar
* cc
)
1447 /* Detects if the character has an othercase. */
1457 return c
!= UCD_OTHERCASE(c
);
1462 #ifndef COMPILE_PCRE8
1463 return common
->fcc
[c
] != c
;
1469 return MAX_255(c
) ? common
->fcc
[c
] != c
: FALSE
;
1472 static SLJIT_INLINE
unsigned int char_othercase(compiler_common
*common
, unsigned int c
)
1474 /* Returns with the othercase. */
1476 if (common
->utf
&& c
> 127)
1479 return UCD_OTHERCASE(c
);
1485 return TABLE_GET(c
, common
->fcc
, c
);
1488 static unsigned int char_get_othercase_bit(compiler_common
*common
, pcre_uchar
* cc
)
1490 /* Detects if the character and its othercase has only 1 bit difference. */
1491 unsigned int c
, oc
, bit
;
1492 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1501 oc
= common
->fcc
[c
];
1505 oc
= UCD_OTHERCASE(c
);
1514 oc
= TABLE_GET(c
, common
->fcc
, c
);
1518 oc
= TABLE_GET(c
, common
->fcc
, c
);
1521 SLJIT_ASSERT(c
!= oc
);
1524 /* Optimized for English alphabet. */
1525 if (c
<= 127 && bit
== 0x20)
1526 return (0 << 8) | 0x20;
1528 /* Since c != oc, they must have at least 1 bit difference. */
1529 if (!ispowerof2(bit
))
1532 #ifdef COMPILE_PCRE8
1535 if (common
->utf
&& c
> 127)
1537 n
= GET_EXTRALEN(*cc
);
1538 while ((bit
& 0x3f) == 0)
1543 return (n
<< 8) | bit
;
1545 #endif /* SUPPORT_UTF */
1546 return (0 << 8) | bit
;
1548 #else /* COMPILE_PCRE8 */
1550 #ifdef COMPILE_PCRE16
1552 if (common
->utf
&& c
> 65535)
1554 if (bit
>= (1 << 10))
1557 return (bit
< 256) ? ((2 << 8) | bit
) : ((3 << 8) | (bit
>> 8));
1559 #endif /* SUPPORT_UTF */
1560 return (bit
< 256) ? ((0 << 8) | bit
) : ((1 << 8) | (bit
>> 8));
1561 #endif /* COMPILE_PCRE16 */
1563 #endif /* COMPILE_PCRE8 */
1566 static void check_partial(compiler_common
*common
, BOOL force
)
1568 /* Checks whether a partial matching is occured. Does not modify registers. */
1570 struct sljit_jump
*jump
= NULL
;
1572 SLJIT_ASSERT(!force
|| common
->mode
!= JIT_COMPILE
);
1574 if (common
->mode
== JIT_COMPILE
)
1578 jump
= CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1579 else if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
1580 jump
= CMP(SLJIT_C_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, SLJIT_IMM
, -1);
1582 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
1583 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
1586 if (common
->partialmatchlabel
!= NULL
)
1587 JUMPTO(SLJIT_JUMP
, common
->partialmatchlabel
);
1589 add_jump(compiler
, &common
->partialmatch
, JUMP(SLJIT_JUMP
));
1596 static struct sljit_jump
*check_str_end(compiler_common
*common
)
1598 /* Does not affect registers. Usually used in a tight spot. */
1600 struct sljit_jump
*jump
;
1601 struct sljit_jump
*nohit
;
1602 struct sljit_jump
*return_value
;
1604 if (common
->mode
== JIT_COMPILE
)
1605 return CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
1607 jump
= CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
1608 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
1610 nohit
= CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1611 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
1613 return_value
= JUMP(SLJIT_JUMP
);
1617 return_value
= CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1618 if (common
->partialmatchlabel
!= NULL
)
1619 JUMPTO(SLJIT_JUMP
, common
->partialmatchlabel
);
1621 add_jump(compiler
, &common
->partialmatch
, JUMP(SLJIT_JUMP
));
1624 return return_value
;
1627 static void detect_partial_match(compiler_common
*common
, jump_list
**backtracks
)
1630 struct sljit_jump
*jump
;
1632 if (common
->mode
== JIT_COMPILE
)
1634 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0));
1638 /* Partial matching mode. */
1639 jump
= CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
1640 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0));
1641 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
1643 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
1644 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
1648 if (common
->partialmatchlabel
!= NULL
)
1649 JUMPTO(SLJIT_JUMP
, common
->partialmatchlabel
);
1651 add_jump(compiler
, &common
->partialmatch
, JUMP(SLJIT_JUMP
));
1656 static void read_char(compiler_common
*common
)
1658 /* Reads the character into TMP1, updates STR_PTR.
1659 Does not check STR_END. TMP2 Destroyed. */
1662 struct sljit_jump
*jump
;
1665 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
1669 #ifdef COMPILE_PCRE8
1670 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
1672 #ifdef COMPILE_PCRE16
1673 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
1675 #endif /* COMPILE_PCRE8 */
1676 add_jump(compiler
, &common
->utfreadchar
, JUMP(SLJIT_FAST_CALL
));
1680 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1683 static void peek_char(compiler_common
*common
)
1685 /* Reads the character into TMP1, keeps STR_PTR.
1686 Does not check STR_END. TMP2 Destroyed. */
1689 struct sljit_jump
*jump
;
1692 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
1696 #ifdef COMPILE_PCRE8
1697 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
1699 #ifdef COMPILE_PCRE16
1700 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
1702 #endif /* COMPILE_PCRE8 */
1703 add_jump(compiler
, &common
->utfreadchar
, JUMP(SLJIT_FAST_CALL
));
1704 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
1710 static void read_char8_type(compiler_common
*common
)
1712 /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
1714 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
1715 struct sljit_jump
*jump
;
1721 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), 0);
1722 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1723 #ifdef COMPILE_PCRE8
1724 /* This can be an extra read in some situations, but hopefully
1725 it is needed in most cases. */
1726 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
1727 jump
= CMP(SLJIT_C_LESS
, TMP2
, 0, SLJIT_IMM
, 0xc0);
1728 add_jump(compiler
, &common
->utfreadtype8
, JUMP(SLJIT_FAST_CALL
));
1731 #ifdef COMPILE_PCRE16
1732 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
1733 jump
= CMP(SLJIT_C_GREATER
, TMP2
, 0, SLJIT_IMM
, 255);
1734 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
1736 /* Skip low surrogate if necessary. */
1737 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0xfc00);
1738 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP2
, 0, SLJIT_IMM
, 0xd800);
1739 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
1740 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 1);
1741 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
1743 #endif /* COMPILE_PCRE8 */
1747 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), 0);
1748 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1749 #ifdef COMPILE_PCRE16
1750 /* The ctypes array contains only 256 values. */
1751 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
1752 jump
= CMP(SLJIT_C_GREATER
, TMP2
, 0, SLJIT_IMM
, 255);
1754 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
1755 #ifdef COMPILE_PCRE16
1760 static void skip_char_back(compiler_common
*common
)
1762 /* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */
1764 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1765 struct sljit_label
*label
;
1770 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -IN_UCHARS(1));
1771 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1772 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xc0);
1773 CMPTO(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0x80, label
);
1777 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
1780 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -IN_UCHARS(1));
1781 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1782 /* Skip low surrogate if necessary. */
1783 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
1784 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xdc00);
1785 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
1786 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
1787 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
1791 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1794 static void check_newlinechar(compiler_common
*common
, int nltype
, jump_list
**backtracks
, BOOL jumpiftrue
)
1796 /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
1799 if (nltype
== NLTYPE_ANY
)
1801 add_jump(compiler
, &common
->anynewline
, JUMP(SLJIT_FAST_CALL
));
1802 add_jump(compiler
, backtracks
, JUMP(jumpiftrue
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
1804 else if (nltype
== NLTYPE_ANYCRLF
)
1806 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
1807 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
1808 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
1809 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
1810 add_jump(compiler
, backtracks
, JUMP(jumpiftrue
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
1814 SLJIT_ASSERT(nltype
== NLTYPE_FIXED
&& common
->newline
< 256);
1815 add_jump(compiler
, backtracks
, CMP(jumpiftrue
? SLJIT_C_EQUAL
: SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, common
->newline
));
1821 #ifdef COMPILE_PCRE8
1822 static void do_utfreadchar(compiler_common
*common
)
1824 /* Fast decoding a UTF-8 character. TMP1 contains the first byte
1825 of the character (>= 0xc0). Return char value in TMP1, length - 1 in TMP2. */
1827 struct sljit_jump
*jump
;
1829 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1830 /* Searching for the first zero. */
1831 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x20);
1832 jump
= JUMP(SLJIT_C_NOT_ZERO
);
1833 /* Two byte sequence. */
1834 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
1835 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1836 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x1f);
1837 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 6);
1838 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1839 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1840 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
1841 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1844 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x10);
1845 jump
= JUMP(SLJIT_C_NOT_ZERO
);
1846 /* Three byte sequence. */
1847 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
1848 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x0f);
1849 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 12);
1850 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1851 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 6);
1852 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1853 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(2));
1854 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
1855 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1856 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1857 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(2));
1858 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1861 /* Four byte sequence. */
1862 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
1863 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x07);
1864 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 18);
1865 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1866 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 12);
1867 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1868 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(2));
1869 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1870 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 6);
1871 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1872 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(3));
1873 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(3));
1874 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
1875 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1876 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(3));
1877 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1880 static void do_utfreadtype8(compiler_common
*common
)
1882 /* Fast decoding a UTF-8 character type. TMP2 contains the first byte
1883 of the character (>= 0xc0). Return value in TMP1. */
1885 struct sljit_jump
*jump
;
1886 struct sljit_jump
*compare
;
1888 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1890 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP2
, 0, SLJIT_IMM
, 0x20);
1891 jump
= JUMP(SLJIT_C_NOT_ZERO
);
1892 /* Two byte sequence. */
1893 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
1894 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1895 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x1f);
1896 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 6);
1897 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x3f);
1898 OP2(SLJIT_OR
, TMP2
, 0, TMP2
, 0, TMP1
, 0);
1899 compare
= CMP(SLJIT_C_GREATER
, TMP2
, 0, SLJIT_IMM
, 255);
1900 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
1901 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1904 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
1905 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1908 /* We only have types for characters less than 256. */
1909 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
1910 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
1911 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
1912 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1915 #else /* COMPILE_PCRE8 */
1917 #ifdef COMPILE_PCRE16
1918 static void do_utfreadchar(compiler_common
*common
)
1920 /* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char
1921 of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */
1923 struct sljit_jump
*jump
;
1925 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1926 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xdc00);
1927 /* Do nothing, only return. */
1928 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1931 /* Combine two 16 bit characters. */
1932 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
1933 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
1934 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x3ff);
1935 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 10);
1936 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3ff);
1937 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
1938 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
1939 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x10000);
1940 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1942 #endif /* COMPILE_PCRE16 */
1944 #endif /* COMPILE_PCRE8 */
1946 #endif /* SUPPORT_UTF */
1950 static sljit_w SLJIT_CALL
getunichartype(sljit_w c
)
1952 return (sljit_w
)(unsigned int)UCD_CHARTYPE((unsigned int)c
);
1955 static sljit_w SLJIT_CALL
getunicharscript(sljit_w c
)
1957 return (sljit_w
)(unsigned int)UCD_SCRIPT((unsigned int)c
);
1960 static void do_getunichartype(compiler_common
*common
)
1962 /* Character comes in TMP1. Returns chartype in TMP1 */
1965 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1966 /* Save registers */
1967 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, STACK_TOP
, 0);
1968 sljit_emit_ijump(compiler
, SLJIT_CALL1
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(getunichartype
));
1969 /* Restore registers */
1970 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
1971 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1974 static void do_getunichartype_2(compiler_common
*common
)
1976 /* Character comes in TMP1. Returns chartype in TMP1 */
1979 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1980 /* Save registers */
1981 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, STACK_TOP
, 0);
1982 sljit_emit_ijump(compiler
, SLJIT_CALL1
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(getunichartype
));
1983 /* Restore registers */
1984 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
1985 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
1988 static void do_getunicharscript(compiler_common
*common
)
1990 /* Character comes in TMP1. Returns chartype in TMP1 */
1993 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
1994 /* Save registers */
1995 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, STACK_TOP
, 0);
1996 sljit_emit_ijump(compiler
, SLJIT_CALL1
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(getunicharscript
));
1997 /* Restore registers */
1998 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
1999 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2003 static SLJIT_INLINE
struct sljit_label
*mainloop_entry(compiler_common
*common
, BOOL hascrorlf
, BOOL firstline
)
2006 struct sljit_label
*mainloop
;
2007 struct sljit_label
*newlinelabel
= NULL
;
2008 struct sljit_jump
*start
;
2009 struct sljit_jump
*end
= NULL
;
2010 struct sljit_jump
*nl
= NULL
;
2012 struct sljit_jump
*singlechar
;
2014 jump_list
*newline
= NULL
;
2015 BOOL newlinecheck
= FALSE
;
2016 BOOL readuchar
= FALSE
;
2018 if (!(hascrorlf
|| firstline
) && (common
->nltype
== NLTYPE_ANY
||
2019 common
->nltype
== NLTYPE_ANYCRLF
|| common
->newline
> 255))
2020 newlinecheck
= TRUE
;
2024 /* Search for the end of the first line. */
2025 SLJIT_ASSERT(common
->first_line_end
!= 0);
2026 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, STR_PTR
, 0);
2027 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, STR_END
, 0);
2029 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
2032 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2033 end
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2034 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-1));
2035 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
2036 CMPTO(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff, mainloop
);
2037 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff, mainloop
);
2038 OP2(SLJIT_SUB
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2042 end
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2044 /* Continual stores does not cause data dependency. */
2045 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, STR_PTR
, 0);
2047 check_newlinechar(common
, common
->nltype
, &newline
, TRUE
);
2048 CMPTO(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0, mainloop
);
2049 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, STR_PTR
, 0);
2050 set_jumps(newline
, LABEL());
2054 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
2057 start
= JUMP(SLJIT_JUMP
);
2061 newlinelabel
= LABEL();
2062 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2063 end
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2064 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2065 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, common
->newline
& 0xff);
2066 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
2067 #ifdef COMPILE_PCRE16
2068 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2070 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2071 nl
= JUMP(SLJIT_JUMP
);
2076 /* Increasing the STR_PTR here requires one less jump in the most common case. */
2078 if (common
->utf
) readuchar
= TRUE
;
2080 if (newlinecheck
) readuchar
= TRUE
;
2083 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2086 CMPTO(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff, newlinelabel
);
2088 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2089 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
2092 singlechar
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
2093 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
2094 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2095 JUMPHERE(singlechar
);
2098 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
2101 singlechar
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
2102 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
2103 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xd800);
2104 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
2105 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2106 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2107 JUMPHERE(singlechar
);
2121 static SLJIT_INLINE
void fast_forward_first_char(compiler_common
*common
, pcre_uchar first_char
, BOOL caseless
, BOOL firstline
)
2124 struct sljit_label
*start
;
2125 struct sljit_jump
*leave
;
2126 struct sljit_jump
*found
;
2131 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, STR_END
, 0);
2132 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
2136 leave
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2137 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2142 oc
= TABLE_GET(first_char
, common
->fcc
, first_char
);
2143 #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
2144 if (first_char
> 127 && common
->utf
)
2145 oc
= UCD_OTHERCASE(first_char
);
2148 if (first_char
== oc
)
2149 found
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, first_char
);
2152 bit
= first_char
^ oc
;
2153 if (ispowerof2(bit
))
2155 OP2(SLJIT_OR
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, bit
);
2156 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, first_char
| bit
);
2160 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, first_char
);
2161 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
2162 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, oc
);
2163 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
2164 found
= JUMP(SLJIT_C_NOT_ZERO
);
2168 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2169 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
2172 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0, start
);
2173 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
2174 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2177 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
2180 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800, start
);
2181 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
2182 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xd800);
2183 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
2184 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2185 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2188 JUMPTO(SLJIT_JUMP
, start
);
2193 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
2196 static SLJIT_INLINE
void fast_forward_newline(compiler_common
*common
, BOOL firstline
)
2199 struct sljit_label
*loop
;
2200 struct sljit_jump
*lastchar
;
2201 struct sljit_jump
*firstchar
;
2202 struct sljit_jump
*leave
;
2203 struct sljit_jump
*foundcr
= NULL
;
2204 struct sljit_jump
*notfoundnl
;
2205 jump_list
*newline
= NULL
;
2209 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, STR_END
, 0);
2210 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
2213 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
2215 lastchar
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2216 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
2217 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
2218 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
2219 firstchar
= CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP2
, 0);
2221 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(2));
2222 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, STR_PTR
, 0, TMP1
, 0);
2223 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_GREATER_EQUAL
);
2224 #ifdef COMPILE_PCRE16
2225 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 1);
2227 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
2230 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2231 leave
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2232 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-2));
2233 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-1));
2234 CMPTO(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff, loop
);
2235 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff, loop
);
2238 JUMPHERE(firstchar
);
2242 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
2246 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
2247 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
2248 firstchar
= CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP2
, 0);
2249 skip_char_back(common
);
2253 lastchar
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2254 if (common
->nltype
== NLTYPE_ANY
|| common
->nltype
== NLTYPE_ANYCRLF
)
2255 foundcr
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
2256 check_newlinechar(common
, common
->nltype
, &newline
, FALSE
);
2257 set_jumps(newline
, loop
);
2259 if (common
->nltype
== NLTYPE_ANY
|| common
->nltype
== NLTYPE_ANYCRLF
)
2261 leave
= JUMP(SLJIT_JUMP
);
2263 notfoundnl
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2264 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2265 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
2266 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
2267 #ifdef COMPILE_PCRE16
2268 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2270 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2271 JUMPHERE(notfoundnl
);
2275 JUMPHERE(firstchar
);
2278 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
2281 static SLJIT_INLINE
void fast_forward_start_bits(compiler_common
*common
, sljit_uw start_bits
, BOOL firstline
)
2284 struct sljit_label
*start
;
2285 struct sljit_jump
*leave
;
2286 struct sljit_jump
*found
;
2287 #ifndef COMPILE_PCRE8
2288 struct sljit_jump
*jump
;
2293 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, STR_END
, 0);
2294 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
2298 leave
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2299 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2302 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
2304 #ifndef COMPILE_PCRE8
2305 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 255);
2306 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 255);
2309 OP2(SLJIT_AND
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x7);
2310 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3);
2311 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), start_bits
);
2312 OP2(SLJIT_SHL
, TMP2
, 0, SLJIT_IMM
, 1, TMP2
, 0);
2313 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, TMP2
, 0);
2314 found
= JUMP(SLJIT_C_NOT_ZERO
);
2318 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
2320 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2321 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
2324 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0, start
);
2325 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
2326 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2329 #if defined SUPPORT_UTF && defined COMPILE_PCRE16
2332 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800, start
);
2333 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
2334 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xd800);
2335 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
2336 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2337 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2340 JUMPTO(SLJIT_JUMP
, start
);
2345 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
2348 static SLJIT_INLINE
struct sljit_jump
*search_requested_char(compiler_common
*common
, pcre_uchar req_char
, BOOL caseless
, BOOL has_firstchar
)
2351 struct sljit_label
*loop
;
2352 struct sljit_jump
*toolong
;
2353 struct sljit_jump
*alreadyfound
;
2354 struct sljit_jump
*found
;
2355 struct sljit_jump
*foundoc
= NULL
;
2356 struct sljit_jump
*notfound
;
2359 SLJIT_ASSERT(common
->req_char_ptr
!= 0);
2360 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->req_char_ptr
);
2361 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, REQ_BYTE_MAX
);
2362 toolong
= CMP(SLJIT_C_LESS
, TMP1
, 0, STR_END
, 0);
2363 alreadyfound
= CMP(SLJIT_C_LESS
, STR_PTR
, 0, TMP2
, 0);
2366 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2368 OP1(SLJIT_MOV
, TMP1
, 0, STR_PTR
, 0);
2371 notfound
= CMP(SLJIT_C_GREATER_EQUAL
, TMP1
, 0, STR_END
, 0);
2373 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(TMP1
), 0);
2377 oc
= TABLE_GET(req_char
, common
->fcc
, req_char
);
2378 #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
2379 if (req_char
> 127 && common
->utf
)
2380 oc
= UCD_OTHERCASE(req_char
);
2384 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, req_char
);
2387 bit
= req_char
^ oc
;
2388 if (ispowerof2(bit
))
2390 OP2(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, bit
);
2391 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, req_char
| bit
);
2395 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, req_char
);
2396 foundoc
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, oc
);
2399 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(1));
2400 JUMPTO(SLJIT_JUMP
, loop
);
2405 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->req_char_ptr
, TMP1
, 0);
2406 JUMPHERE(alreadyfound
);
2411 static void do_revertframes(compiler_common
*common
)
2414 struct sljit_jump
*jump
;
2415 struct sljit_label
*mainloop
;
2417 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2418 OP1(SLJIT_MOV
, TMP1
, 0, STACK_TOP
, 0);
2419 GET_LOCAL_BASE(TMP3
, 0, 0);
2421 /* Drop frames until we reach STACK_TOP. */
2423 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), 0);
2424 jump
= CMP(SLJIT_C_SIG_LESS_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_end
);
2425 OP2(SLJIT_ADD
, TMP2
, 0, TMP2
, 0, TMP3
, 0);
2426 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP2
), 0, SLJIT_MEM1(TMP1
), sizeof(sljit_w
));
2427 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP2
), sizeof(sljit_w
), SLJIT_MEM1(TMP1
), 2 * sizeof(sljit_w
));
2428 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3 * sizeof(sljit_w
));
2429 JUMPTO(SLJIT_JUMP
, mainloop
);
2432 jump
= CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_end
);
2433 /* End of dropping frames. */
2434 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2437 jump
= CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_setstrbegin
);
2438 /* Set string begin. */
2439 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), sizeof(sljit_w
));
2440 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 2 * sizeof(sljit_w
));
2441 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), TMP2
, 0);
2442 JUMPTO(SLJIT_JUMP
, mainloop
);
2445 if (common
->mark_ptr
!= 0)
2447 jump
= CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_setmark
);
2448 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), sizeof(sljit_w
));
2449 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 2 * sizeof(sljit_w
));
2450 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP2
, 0);
2451 JUMPTO(SLJIT_JUMP
, mainloop
);
2456 /* Unknown command. */
2457 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 2 * sizeof(sljit_w
));
2458 JUMPTO(SLJIT_JUMP
, mainloop
);
2461 static void check_wordboundary(compiler_common
*common
)
2464 struct sljit_jump
*skipread
;
2465 #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF
2466 struct sljit_jump
*jump
;
2469 SLJIT_COMPILE_ASSERT(ctype_word
== 0x10, ctype_word_must_be_16
);
2471 sljit_emit_fast_enter(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
2472 /* Get type of the previous char, and put it to LOCALS1. */
2473 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
2474 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
2475 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, SLJIT_IMM
, 0);
2476 skipread
= CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP1
, 0);
2477 skip_char_back(common
);
2478 check_start_used_ptr(common
);
2481 /* Testing char type. */
2483 if (common
->use_ucp
)
2485 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 1);
2486 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_UNDERSCORE
);
2487 add_jump(compiler
, &common
->getunichartype_2
, JUMP(SLJIT_FAST_CALL
));
2488 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Ll
);
2489 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Lu
- ucp_Ll
);
2490 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2491 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Nd
- ucp_Ll
);
2492 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_No
- ucp_Nd
);
2493 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2495 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP2
, 0);
2500 #ifndef COMPILE_PCRE8
2501 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2502 #elif defined SUPPORT_UTF
2503 /* Here LOCALS1 has already been zeroed. */
2506 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2507 #endif /* COMPILE_PCRE8 */
2508 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), common
->ctypes
);
2509 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 4 /* ctype_word */);
2510 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2511 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP1
, 0);
2512 #ifndef COMPILE_PCRE8
2514 #elif defined SUPPORT_UTF
2517 #endif /* COMPILE_PCRE8 */
2521 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
2522 skipread
= check_str_end(common
);
2525 /* Testing char type. This is a code duplication. */
2527 if (common
->use_ucp
)
2529 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 1);
2530 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_UNDERSCORE
);
2531 add_jump(compiler
, &common
->getunichartype_2
, JUMP(SLJIT_FAST_CALL
));
2532 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Ll
);
2533 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Lu
- ucp_Ll
);
2534 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2535 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Nd
- ucp_Ll
);
2536 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_No
- ucp_Nd
);
2537 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2543 #ifndef COMPILE_PCRE8
2544 /* TMP2 may be destroyed by peek_char. */
2545 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
2546 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2547 #elif defined SUPPORT_UTF
2548 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
2551 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2553 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), common
->ctypes
);
2554 OP2(SLJIT_LSHR
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 4 /* ctype_word */);
2555 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 1);
2556 #ifndef COMPILE_PCRE8
2558 #elif defined SUPPORT_UTF
2561 #endif /* COMPILE_PCRE8 */
2565 OP2(SLJIT_XOR
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
2566 sljit_emit_fast_return(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
2569 static void check_anynewline(compiler_common
*common
)
2571 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2574 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2576 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x0a);
2577 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x0d - 0x0a);
2578 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2579 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x85 - 0x0a);
2580 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
2581 #ifdef COMPILE_PCRE8
2585 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2586 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x1);
2587 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x2029 - 0x0a);
2588 #ifdef COMPILE_PCRE8
2591 #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
2592 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
2593 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2596 static void check_hspace(compiler_common
*common
)
2598 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2601 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2603 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x09);
2604 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
2605 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x20);
2606 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2607 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xa0);
2608 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
2609 #ifdef COMPILE_PCRE8
2613 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2614 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x1680);
2615 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2616 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x180e);
2617 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2618 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x2000);
2619 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x200A - 0x2000);
2620 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2621 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x202f - 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
, 0x205f - 0x2000);
2624 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
2625 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x3000 - 0x2000);
2626 #ifdef COMPILE_PCRE8
2629 #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
2630 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
2632 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2635 static void check_vspace(compiler_common
*common
)
2637 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
2640 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2642 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x0a);
2643 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x0d - 0x0a);
2644 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
2645 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x85 - 0x0a);
2646 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
2647 #ifdef COMPILE_PCRE8
2651 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
2652 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x1);
2653 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x2029 - 0x0a);
2654 #ifdef COMPILE_PCRE8
2657 #endif /* SUPPORT_UTF || COMPILE_PCRE16 */
2658 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
2660 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2663 #define CHAR1 STR_END
2664 #define CHAR2 STACK_TOP
2666 static void do_casefulcmp(compiler_common
*common
)
2669 struct sljit_jump
*jump
;
2670 struct sljit_label
*label
;
2672 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2673 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
2674 OP1(SLJIT_MOV
, TMP3
, 0, CHAR1
, 0);
2675 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, CHAR2
, 0);
2676 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(1));
2677 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2680 OP1(MOVU_UCHAR
, CHAR1
, 0, SLJIT_MEM1(TMP1
), IN_UCHARS(1));
2681 OP1(MOVU_UCHAR
, CHAR2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
2682 jump
= CMP(SLJIT_C_NOT_EQUAL
, CHAR1
, 0, CHAR2
, 0);
2683 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
2684 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
2687 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2688 OP1(SLJIT_MOV
, CHAR1
, 0, TMP3
, 0);
2689 OP1(SLJIT_MOV
, CHAR2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
2690 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2693 #define LCC_TABLE STACK_LIMIT
2695 static void do_caselesscmp(compiler_common
*common
)
2698 struct sljit_jump
*jump
;
2699 struct sljit_label
*label
;
2701 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2702 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
2704 OP1(SLJIT_MOV
, TMP3
, 0, LCC_TABLE
, 0);
2705 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, CHAR1
, 0);
2706 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, CHAR2
, 0);
2707 OP1(SLJIT_MOV
, LCC_TABLE
, 0, SLJIT_IMM
, common
->lcc
);
2708 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(1));
2709 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2712 OP1(MOVU_UCHAR
, CHAR1
, 0, SLJIT_MEM1(TMP1
), IN_UCHARS(1));
2713 OP1(MOVU_UCHAR
, CHAR2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
2714 #ifndef COMPILE_PCRE8
2715 jump
= CMP(SLJIT_C_GREATER
, CHAR1
, 0, SLJIT_IMM
, 255);
2717 OP1(SLJIT_MOV_UB
, CHAR1
, 0, SLJIT_MEM2(LCC_TABLE
, CHAR1
), 0);
2718 #ifndef COMPILE_PCRE8
2720 jump
= CMP(SLJIT_C_GREATER
, CHAR2
, 0, SLJIT_IMM
, 255);
2722 OP1(SLJIT_MOV_UB
, CHAR2
, 0, SLJIT_MEM2(LCC_TABLE
, CHAR2
), 0);
2723 #ifndef COMPILE_PCRE8
2726 jump
= CMP(SLJIT_C_NOT_EQUAL
, CHAR1
, 0, CHAR2
, 0);
2727 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
2728 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
2731 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2732 OP1(SLJIT_MOV
, LCC_TABLE
, 0, TMP3
, 0);
2733 OP1(SLJIT_MOV
, CHAR1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
2734 OP1(SLJIT_MOV
, CHAR2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
2735 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2742 #if defined SUPPORT_UTF && defined SUPPORT_UCP
2744 static const pcre_uchar
*SLJIT_CALL
do_utf_caselesscmp(pcre_uchar
*src1
, jit_arguments
*args
, pcre_uchar
*end1
)
2746 /* This function would be ineffective to do in JIT level. */
2748 const pcre_uchar
*src2
= args
->uchar_ptr
;
2749 const pcre_uchar
*end2
= args
->end
;
2754 return (pcre_uchar
*)1;
2755 GETCHARINC(c1
, src1
);
2756 GETCHARINC(c2
, src2
);
2757 if (c1
!= c2
&& c1
!= UCD_OTHERCASE(c2
)) return NULL
;
2762 #endif /* SUPPORT_UTF && SUPPORT_UCP */
2764 static pcre_uchar
*byte_sequence_compare(compiler_common
*common
, BOOL caseless
, pcre_uchar
*cc
,
2765 compare_context
* context
, jump_list
**backtracks
)
2768 unsigned int othercasebit
= 0;
2769 pcre_uchar
*othercasechar
= NULL
;
2774 if (caseless
&& char_has_othercase(common
, cc
))
2776 othercasebit
= char_get_othercase_bit(common
, cc
);
2777 SLJIT_ASSERT(othercasebit
);
2778 /* Extracting bit difference info. */
2779 #ifdef COMPILE_PCRE8
2780 othercasechar
= cc
+ (othercasebit
>> 8);
2781 othercasebit
&= 0xff;
2783 #ifdef COMPILE_PCRE16
2784 othercasechar
= cc
+ (othercasebit
>> 9);
2785 if ((othercasebit
& 0x100) != 0)
2786 othercasebit
= (othercasebit
& 0xff) << 8;
2788 othercasebit
&= 0xff;
2793 if (context
->sourcereg
== -1)
2795 #ifdef COMPILE_PCRE8
2796 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2797 if (context
->length
>= 4)
2798 OP1(SLJIT_MOV_SI
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2799 else if (context
->length
>= 2)
2800 OP1(SLJIT_MOV_UH
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2803 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2805 #ifdef COMPILE_PCRE16
2806 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2807 if (context
->length
>= 4)
2808 OP1(SLJIT_MOV_SI
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2811 OP1(SLJIT_MOV_UH
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2813 #endif /* COMPILE_PCRE8 */
2814 context
->sourcereg
= TMP2
;
2819 if (common
->utf
&& HAS_EXTRALEN(*cc
))
2820 utflength
+= GET_EXTRALEN(*cc
);
2826 context
->length
-= IN_UCHARS(1);
2827 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
2829 /* Unaligned read is supported. */
2830 if (othercasebit
!= 0 && othercasechar
== cc
)
2832 context
->c
.asuchars
[context
->ucharptr
] = *cc
| othercasebit
;
2833 context
->oc
.asuchars
[context
->ucharptr
] = othercasebit
;
2837 context
->c
.asuchars
[context
->ucharptr
] = *cc
;
2838 context
->oc
.asuchars
[context
->ucharptr
] = 0;
2840 context
->ucharptr
++;
2842 #ifdef COMPILE_PCRE8
2843 if (context
->ucharptr
>= 4 || context
->length
== 0 || (context
->ucharptr
== 2 && context
->length
== 1))
2845 if (context
->ucharptr
>= 2 || context
->length
== 0)
2848 if (context
->length
>= 4)
2849 OP1(SLJIT_MOV_SI
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2850 #ifdef COMPILE_PCRE8
2851 else if (context
->length
>= 2)
2852 OP1(SLJIT_MOV_UH
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2853 else if (context
->length
>= 1)
2854 OP1(SLJIT_MOV_UB
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2856 else if (context
->length
>= 2)
2857 OP1(SLJIT_MOV_UH
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2859 context
->sourcereg
= context
->sourcereg
== TMP1
? TMP2
: TMP1
;
2861 switch(context
->ucharptr
)
2863 case 4 / sizeof(pcre_uchar
):
2864 if (context
->oc
.asint
!= 0)
2865 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, context
->oc
.asint
);
2866 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, context
->c
.asint
| context
->oc
.asint
));
2869 case 2 / sizeof(pcre_uchar
):
2870 if (context
->oc
.asushort
!= 0)
2871 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, context
->oc
.asushort
);
2872 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, context
->c
.asushort
| context
->oc
.asushort
));
2875 #ifdef COMPILE_PCRE8
2877 if (context
->oc
.asbyte
!= 0)
2878 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, context
->oc
.asbyte
);
2879 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, context
->c
.asbyte
| context
->oc
.asbyte
));
2884 SLJIT_ASSERT_STOP();
2887 context
->ucharptr
= 0;
2892 /* Unaligned read is unsupported. */
2893 #ifdef COMPILE_PCRE8
2894 if (context
->length
> 0)
2895 OP1(SLJIT_MOV_UB
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2897 if (context
->length
> 0)
2898 OP1(SLJIT_MOV_UH
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
2900 context
->sourcereg
= context
->sourcereg
== TMP1
? TMP2
: TMP1
;
2902 if (othercasebit
!= 0 && othercasechar
== cc
)
2904 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, othercasebit
);
2905 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, *cc
| othercasebit
));
2908 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, *cc
));
2916 while (utflength
> 0);
2922 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
2924 #define SET_TYPE_OFFSET(value) \
2925 if ((value) != typeoffset) \
2927 if ((value) > typeoffset) \
2928 OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
2930 OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
2932 typeoffset = (value);
2934 #define SET_CHAR_OFFSET(value) \
2935 if ((value) != charoffset) \
2937 if ((value) > charoffset) \
2938 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \
2940 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \
2942 charoffset = (value);
2944 static void compile_xclass_trypath(compiler_common
*common
, pcre_uchar
*cc
, jump_list
**backtracks
)
2947 jump_list
*found
= NULL
;
2948 jump_list
**list
= (*cc
& XCL_NOT
) == 0 ? &found
: backtracks
;
2951 struct sljit_jump
*jump
= NULL
;
2952 pcre_uchar
*ccbegin
;
2954 BOOL needstype
= FALSE
, needsscript
= FALSE
, needschar
= FALSE
;
2955 BOOL charsaved
= FALSE
;
2956 int typereg
= TMP1
, scriptreg
= TMP1
;
2957 unsigned int typeoffset
;
2959 int invertcmp
, numberofcmps
;
2960 unsigned int charoffset
;
2962 /* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */
2963 detect_partial_match(common
, backtracks
);
2966 if ((*cc
++ & XCL_MAP
) != 0)
2968 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
2969 #ifndef COMPILE_PCRE8
2970 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2971 #elif defined SUPPORT_UTF
2973 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
2976 OP2(SLJIT_AND
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x7);
2977 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3);
2978 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)cc
);
2979 OP2(SLJIT_SHL
, TMP2
, 0, SLJIT_IMM
, 1, TMP2
, 0);
2980 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, TMP2
, 0);
2981 add_jump(compiler
, list
, JUMP(SLJIT_C_NOT_ZERO
));
2983 #ifndef COMPILE_PCRE8
2985 #elif defined SUPPORT_UTF
2989 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
2993 cc
+= 32 / sizeof(pcre_uchar
);
2996 /* Scanning the necessary info. */
2999 while (*cc
!= XCL_END
)
3002 if (*cc
== XCL_SINGLE
)
3006 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
3012 else if (*cc
== XCL_RANGE
)
3016 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
3020 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
3029 SLJIT_ASSERT(*cc
== XCL_PROP
|| *cc
== XCL_NOTPROP
);
3055 SLJIT_ASSERT_STOP();
3064 /* Simple register allocation. TMP1 is preferred if possible. */
3065 if (needstype
|| needsscript
)
3067 if ((needschar
|| needsscript
) && !charsaved
)
3068 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
3070 /* Needed to save important temporary registers. */
3071 SLJIT_ASSERT(TMP1
== SLJIT_TEMPORARY_REG1
&&
3072 STACK_TOP
== SLJIT_TEMPORARY_REG2
&&
3073 TMP2
== SLJIT_TEMPORARY_REG3
);
3078 typereg
= RETURN_ADDR
;
3082 else if (needstype
&& needsscript
)
3084 /* In all other cases only one of them was specified, and that can goes to TMP1. */
3088 add_jump(compiler
, &common
->getunichartype
, JUMP(SLJIT_FAST_CALL
));
3089 if (typereg
!= TMP1
)
3090 OP1(SLJIT_MOV
, typereg
, 0, TMP1
, 0);
3095 /* Get the char again */
3097 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
3099 add_jump(compiler
, &common
->getunicharscript
, JUMP(SLJIT_FAST_CALL
));
3100 if (scriptreg
!= TMP1
)
3101 OP1(SLJIT_MOV
, scriptreg
, 0, TMP1
, 0);
3105 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
3109 /* Generating code. */
3117 while (*cc
!= XCL_END
)
3120 invertcmp
= (compares
== 0 && list
!= backtracks
);
3123 if (*cc
== XCL_SINGLE
)
3135 if (numberofcmps
< 3 && (*cc
== XCL_SINGLE
|| *cc
== XCL_RANGE
))
3137 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3138 COND_VALUE(numberofcmps
== 0 ? SLJIT_MOV
: SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
3141 else if (numberofcmps
> 0)
3143 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3144 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
3145 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3150 jump
= CMP(SLJIT_C_EQUAL
^ invertcmp
, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3154 else if (*cc
== XCL_RANGE
)
3174 if (numberofcmps
< 3 && (*cc
== XCL_SINGLE
|| *cc
== XCL_RANGE
))
3176 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3177 COND_VALUE(numberofcmps
== 0 ? SLJIT_MOV
: SLJIT_OR
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3180 else if (numberofcmps
> 0)
3182 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3183 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3184 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3189 jump
= CMP(SLJIT_C_LESS_EQUAL
^ invertcmp
, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3196 if (*cc
== XCL_NOTPROP
)
3202 if (list
!= backtracks
)
3204 if ((cc
[-1] == XCL_NOTPROP
&& compares
> 0) || (cc
[-1] == XCL_PROP
&& compares
== 0))
3207 else if (cc
[-1] == XCL_NOTPROP
)
3209 jump
= JUMP(SLJIT_JUMP
);
3213 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Lu
- typeoffset
);
3214 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
3215 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Ll
- typeoffset
);
3216 COND_VALUE(SLJIT_OR
, TMP2
, 0, SLJIT_C_EQUAL
);
3217 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Lt
- typeoffset
);
3218 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
3219 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3223 c
= PRIV(ucp_typerange
)[(int)cc
[1] * 2];
3225 jump
= CMP(SLJIT_C_LESS_EQUAL
^ invertcmp
, typereg
, 0, SLJIT_IMM
, PRIV(ucp_typerange
)[(int)cc
[1] * 2 + 1] - c
);
3229 jump
= CMP(SLJIT_C_EQUAL
^ invertcmp
, typereg
, 0, SLJIT_IMM
, (int)cc
[1] - typeoffset
);
3233 jump
= CMP(SLJIT_C_EQUAL
^ invertcmp
, scriptreg
, 0, SLJIT_IMM
, (int)cc
[1]);
3238 if (*cc
== PT_SPACE
)
3240 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
3241 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 11 - charoffset
);
3244 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 13 - 9);
3245 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3246 if (*cc
== PT_SPACE
)
3249 SET_TYPE_OFFSET(ucp_Zl
);
3250 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Zs
- ucp_Zl
);
3251 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3252 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3256 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_UNDERSCORE
- charoffset
);
3257 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
3258 /* ... fall through */
3261 SET_TYPE_OFFSET(ucp_Ll
);
3262 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Lu
- ucp_Ll
);
3263 COND_VALUE((*cc
== PT_ALNUM
) ? SLJIT_MOV
: SLJIT_OR
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3264 SET_TYPE_OFFSET(ucp_Nd
);
3265 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_No
- ucp_Nd
);
3266 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3267 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3275 add_jump(compiler
, compares
> 0 ? list
: backtracks
, jump
);
3279 set_jumps(found
, LABEL());
3282 #undef SET_TYPE_OFFSET
3283 #undef SET_CHAR_OFFSET
3287 static pcre_uchar
*compile_char1_trypath(compiler_common
*common
, pcre_uchar type
, pcre_uchar
*cc
, jump_list
**backtracks
)
3291 unsigned int c
, oc
, bit
;
3292 compare_context context
;
3293 struct sljit_jump
*jump
[4];
3295 struct sljit_label
*label
;
3297 pcre_uchar propdata
[5];
3304 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
3305 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
3306 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, TMP1
, 0));
3310 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
3311 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
3312 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, TMP1
, 0));
3315 case OP_NOT_WORD_BOUNDARY
:
3316 case OP_WORD_BOUNDARY
:
3317 add_jump(compiler
, &common
->wordboundary
, JUMP(SLJIT_FAST_CALL
));
3318 add_jump(compiler
, backtracks
, JUMP(type
== OP_NOT_WORD_BOUNDARY
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
3323 detect_partial_match(common
, backtracks
);
3324 read_char8_type(common
);
3325 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ctype_digit
);
3326 add_jump(compiler
, backtracks
, JUMP(type
== OP_DIGIT
? SLJIT_C_ZERO
: SLJIT_C_NOT_ZERO
));
3329 case OP_NOT_WHITESPACE
:
3331 detect_partial_match(common
, backtracks
);
3332 read_char8_type(common
);
3333 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ctype_space
);
3334 add_jump(compiler
, backtracks
, JUMP(type
== OP_WHITESPACE
? SLJIT_C_ZERO
: SLJIT_C_NOT_ZERO
));
3337 case OP_NOT_WORDCHAR
:
3339 detect_partial_match(common
, backtracks
);
3340 read_char8_type(common
);
3341 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ctype_word
);
3342 add_jump(compiler
, backtracks
, JUMP(type
== OP_WORDCHAR
? SLJIT_C_ZERO
: SLJIT_C_NOT_ZERO
));
3346 detect_partial_match(common
, backtracks
);
3348 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
3350 jump
[0] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff);
3351 if (common
->mode
!= JIT_PARTIAL_HARD_COMPILE
)
3352 jump
[1] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
3354 jump
[1] = check_str_end(common
);
3356 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
3357 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, common
->newline
& 0xff));
3358 if (jump
[1] != NULL
)
3363 check_newlinechar(common
, common
->nltype
, backtracks
, TRUE
);
3367 detect_partial_match(common
, backtracks
);
3371 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
3372 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3373 #ifdef COMPILE_PCRE8
3374 jump
[0] = CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
3375 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
3376 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
3377 #else /* COMPILE_PCRE8 */
3378 #ifdef COMPILE_PCRE16
3379 jump
[0] = CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
3380 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
3381 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xd800);
3382 COND_VALUE(SLJIT_MOV
, TMP1
, 0, SLJIT_C_EQUAL
);
3383 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
3384 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
3385 #endif /* COMPILE_PCRE16 */
3386 #endif /* COMPILE_PCRE8 */
3391 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3395 detect_partial_match(common
, backtracks
);
3396 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3404 propdata
[1] = type
== OP_NOTPROP
? XCL_NOTPROP
: XCL_PROP
;
3405 propdata
[2] = cc
[0];
3406 propdata
[3] = cc
[1];
3407 propdata
[4] = XCL_END
;
3408 compile_xclass_trypath(common
, propdata
, backtracks
);
3414 detect_partial_match(common
, backtracks
);
3416 jump
[0] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
3417 /* We don't need to handle soft partial matching case. */
3418 if (common
->mode
!= JIT_PARTIAL_HARD_COMPILE
)
3419 jump
[1] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
3421 jump
[1] = check_str_end(common
);
3422 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
3423 jump
[2] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
3424 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3425 jump
[3] = JUMP(SLJIT_JUMP
);
3427 check_newlinechar(common
, common
->bsr_nltype
, backtracks
, FALSE
);
3435 detect_partial_match(common
, backtracks
);
3437 add_jump(compiler
, &common
->hspace
, JUMP(SLJIT_FAST_CALL
));
3438 add_jump(compiler
, backtracks
, JUMP(type
== OP_NOT_HSPACE
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
3443 detect_partial_match(common
, backtracks
);
3445 add_jump(compiler
, &common
->vspace
, JUMP(SLJIT_FAST_CALL
));
3446 add_jump(compiler
, backtracks
, JUMP(type
== OP_NOT_VSPACE
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
3451 detect_partial_match(common
, backtracks
);
3453 add_jump(compiler
, &common
->getunichartype
, JUMP(SLJIT_FAST_CALL
));
3454 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Mc
);
3455 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS_EQUAL
, TMP1
, 0, SLJIT_IMM
, ucp_Mn
- ucp_Mc
));
3458 jump
[0] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
3459 OP1(SLJIT_MOV
, TMP3
, 0, STR_PTR
, 0);
3461 add_jump(compiler
, &common
->getunichartype
, JUMP(SLJIT_FAST_CALL
));
3462 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Mc
);
3463 CMPTO(SLJIT_C_LESS_EQUAL
, TMP1
, 0, SLJIT_IMM
, ucp_Mn
- ucp_Mc
, label
);
3465 OP1(SLJIT_MOV
, STR_PTR
, 0, TMP3
, 0);
3467 if (common
->mode
== JIT_PARTIAL_HARD_COMPILE
)
3469 jump
[0] = CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
3470 /* Since we successfully read a char above, partial matching must occure. */
3471 check_partial(common
, TRUE
);
3478 /* Requires rather complex checks. */
3479 jump
[0] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
3480 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
3482 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
3483 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
3484 if (common
->mode
== JIT_COMPILE
)
3485 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_END
, 0));
3488 jump
[1] = CMP(SLJIT_C_EQUAL
, TMP2
, 0, STR_END
, 0);
3489 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP2
, 0, STR_END
, 0);
3490 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_LESS
);
3491 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff);
3492 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_NOT_EQUAL
);
3493 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_NOT_EQUAL
));
3494 check_partial(common
, TRUE
);
3495 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
3498 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
3499 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
3500 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff));
3502 else if (common
->nltype
== NLTYPE_FIXED
)
3504 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3505 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
3506 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_END
, 0));
3507 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, common
->newline
));
3511 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
3512 jump
[1] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
3513 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
3514 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP2
, 0, STR_END
, 0);
3515 jump
[2] = JUMP(SLJIT_C_GREATER
);
3516 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_LESS
));
3518 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
3519 jump
[3] = CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
3520 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
3523 if (common
->nltype
== NLTYPE_ANYCRLF
)
3525 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3526 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, TMP2
, 0, STR_END
, 0));
3527 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_NL
));
3531 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, STR_PTR
, 0);
3533 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, STR_END
, 0));
3534 add_jump(compiler
, &common
->anynewline
, JUMP(SLJIT_FAST_CALL
));
3535 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_ZERO
));
3536 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
3542 check_partial(common
, FALSE
);
3546 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0));
3547 check_partial(common
, FALSE
);
3551 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
3552 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, begin
));
3553 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, STR_PTR
, 0, TMP1
, 0));
3554 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, notbol
));
3555 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
3559 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
3560 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, begin
));
3561 jump
[1] = CMP(SLJIT_C_GREATER
, STR_PTR
, 0, TMP1
, 0);
3562 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, notbol
));
3563 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
3564 jump
[0] = JUMP(SLJIT_JUMP
);
3567 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0));
3568 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
3570 OP2(SLJIT_SUB
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
3571 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, TMP2
, 0, TMP1
, 0));
3572 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-2));
3573 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-1));
3574 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
3575 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff));
3579 skip_char_back(common
);
3581 check_newlinechar(common
, common
->nltype
, backtracks
, FALSE
);
3587 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
3588 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, noteol
));
3589 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
3591 if (!common
->endonly
)
3592 compile_char1_trypath(common
, OP_EODN
, cc
, backtracks
);
3595 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0));
3596 check_partial(common
, FALSE
);
3601 jump
[1] = CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
3602 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
3603 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, noteol
));
3604 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
3605 check_partial(common
, FALSE
);
3606 jump
[0] = JUMP(SLJIT_JUMP
);
3609 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
3611 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
3612 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
3613 if (common
->mode
== JIT_COMPILE
)
3614 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, TMP2
, 0, STR_END
, 0));
3617 jump
[1] = CMP(SLJIT_C_LESS_EQUAL
, TMP2
, 0, STR_END
, 0);
3618 /* STR_PTR = STR_END - IN_UCHARS(1) */
3619 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
3620 check_partial(common
, TRUE
);
3621 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
3625 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
3626 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
3627 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff));
3632 check_newlinechar(common
, common
->nltype
, backtracks
, FALSE
);
3641 if (common
->utf
&& HAS_EXTRALEN(*cc
)) length
+= GET_EXTRALEN(*cc
);
3643 if (common
->mode
== JIT_COMPILE
&& (type
== OP_CHAR
|| !char_has_othercase(common
, cc
) || char_get_othercase_bit(common
, cc
) != 0))
3645 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(length
));
3646 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, STR_PTR
, 0, STR_END
, 0));
3648 context
.length
= IN_UCHARS(length
);
3649 context
.sourcereg
= -1;
3650 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3651 context
.ucharptr
= 0;
3653 return byte_sequence_compare(common
, type
== OP_CHARI
, cc
, &context
, backtracks
);
3655 detect_partial_match(common
, backtracks
);
3665 if (type
== OP_CHAR
|| !char_has_othercase(common
, cc
))
3667 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
3670 oc
= char_othercase(common
, c
);
3672 if (ispowerof2(bit
))
3674 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, bit
);
3675 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
| bit
));
3678 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
);
3679 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
3680 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, char_othercase(common
, c
));
3681 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
3682 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_ZERO
));
3687 detect_partial_match(common
, backtracks
);
3692 #ifdef COMPILE_PCRE8
3696 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
3697 if (type
== OP_NOT
|| !char_has_othercase(common
, cc
))
3698 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
3701 /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
3702 OP2(SLJIT_OR
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x20);
3703 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, c
| 0x20));
3705 /* Skip the variable-length character. */
3706 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3707 jump
[0] = CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
3708 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)PRIV(utf8_table4
) - 0xc0);
3709 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
3714 #endif /* COMPILE_PCRE8 */
3716 GETCHARLEN(c
, cc
, length
);
3721 #endif /* SUPPORT_UTF */
3727 if (type
== OP_NOT
|| !char_has_othercase(common
, cc
))
3728 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
3731 oc
= char_othercase(common
, c
);
3733 if (ispowerof2(bit
))
3735 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, bit
);
3736 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
| bit
));
3740 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
3741 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, oc
));
3748 detect_partial_match(common
, backtracks
);
3750 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
3752 #ifdef COMPILE_PCRE8
3753 /* This check only affects 8 bit mode. In other modes, we
3754 always need to compare the value with 255. */
3756 #endif /* COMPILE_PCRE8 */
3758 jump
[0] = CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
3759 if (type
== OP_CLASS
)
3761 add_jump(compiler
, backtracks
, jump
[0]);
3765 #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
3766 OP2(SLJIT_AND
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x7);
3767 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3);
3768 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_w
)cc
);
3769 OP2(SLJIT_SHL
, TMP2
, 0, SLJIT_IMM
, 1, TMP2
, 0);
3770 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, TMP2
, 0);
3771 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_ZERO
));
3772 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
3773 if (jump
[0] != NULL
)
3775 #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
3776 return cc
+ 32 / sizeof(pcre_uchar
);
3778 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
3780 compile_xclass_trypath(common
, cc
+ LINK_SIZE
, backtracks
);
3781 return cc
+ GET(cc
, 0) - 1;
3785 length
= GET(cc
, 0);
3787 return cc
+ LINK_SIZE
;
3788 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
3792 OP1(SLJIT_MOV
, TMP3
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
3793 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, length
);
3795 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP3
, 0));
3796 skip_char_back(common
);
3797 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 1);
3798 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
3803 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
3804 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(length
));
3805 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, STR_PTR
, 0, TMP1
, 0));
3807 check_start_used_ptr(common
);
3808 return cc
+ LINK_SIZE
;
3810 SLJIT_ASSERT_STOP();
3814 static SLJIT_INLINE pcre_uchar
*compile_charn_trypath(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
, jump_list
**backtracks
)
3816 /* This function consumes at least one input character. */
3817 /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
3819 pcre_uchar
*ccbegin
= cc
;
3820 compare_context context
;
3833 if (common
->utf
&& HAS_EXTRALEN(cc
[1]))
3834 size
+= GET_EXTRALEN(cc
[1]);
3837 else if (*cc
== OP_CHARI
)
3843 if (char_has_othercase(common
, cc
+ 1) && char_get_othercase_bit(common
, cc
+ 1) == 0)
3845 else if (HAS_EXTRALEN(cc
[1]))
3846 size
+= GET_EXTRALEN(cc
[1]);
3850 if (char_has_othercase(common
, cc
+ 1) && char_get_othercase_bit(common
, cc
+ 1) == 0)
3857 context
.length
+= IN_UCHARS(size
);
3859 while (size
> 0 && context
.length
<= 128);
3862 if (context
.length
> 0)
3864 /* We have a fixed-length byte sequence. */
3865 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, context
.length
);
3866 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, STR_PTR
, 0, STR_END
, 0));
3868 context
.sourcereg
= -1;
3869 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3870 context
.ucharptr
= 0;
3872 do cc
= byte_sequence_compare(common
, *cc
== OP_CHARI
, cc
+ 1, &context
, backtracks
); while (context
.length
> 0);
3876 /* A non-fixed length character will be checked if length == 0. */
3877 return compile_char1_trypath(common
, *cc
, cc
+ 1, backtracks
);
3880 static struct sljit_jump
*compile_ref_checks(compiler_common
*common
, pcre_uchar
*cc
, jump_list
**backtracks
)
3883 int offset
= GET2(cc
, 1) << 1;
3885 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
3886 if (!common
->jscript_compat
)
3888 if (backtracks
== NULL
)
3890 /* OVECTOR(1) contains the "string begin - 1" constant. */
3891 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1));
3892 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_EQUAL
);
3893 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
3894 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_EQUAL
);
3895 return JUMP(SLJIT_C_NOT_ZERO
);
3897 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1)));
3899 return CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
3902 /* Forward definitions. */
3903 static void compile_trypath(compiler_common
*, pcre_uchar
*, pcre_uchar
*, backtrack_common
*);
3904 static void compile_backtrackpath(compiler_common
*, struct backtrack_common
*);
3906 #define PUSH_BACKTRACK(size, ccstart, error) \
3909 backtrack = sljit_alloc_memory(compiler, (size)); \
3910 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3912 memset(backtrack, 0, size); \
3913 backtrack->prev = parent->top; \
3914 backtrack->cc = (ccstart); \
3915 parent->top = backtrack; \
3919 #define PUSH_BACKTRACK_NOVALUE(size, ccstart) \
3922 backtrack = sljit_alloc_memory(compiler, (size)); \
3923 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
3925 memset(backtrack, 0, size); \
3926 backtrack->prev = parent->top; \
3927 backtrack->cc = (ccstart); \
3928 parent->top = backtrack; \
3932 #define BACKTRACK_AS(type) ((type *)backtrack)
3934 static pcre_uchar
*compile_ref_trypath(compiler_common
*common
, pcre_uchar
*cc
, jump_list
**backtracks
, BOOL withchecks
, BOOL emptyfail
)
3937 int offset
= GET2(cc
, 1) << 1;
3938 struct sljit_jump
*jump
= NULL
;
3939 struct sljit_jump
*partial
;
3940 struct sljit_jump
*nopartial
;
3942 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
3943 /* OVECTOR(1) contains the "string begin - 1" constant. */
3944 if (withchecks
&& !common
->jscript_compat
)
3945 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1)));
3947 #if defined SUPPORT_UTF && defined SUPPORT_UCP
3948 if (common
->utf
&& *cc
== OP_REFI
)
3950 SLJIT_ASSERT(TMP1
== SLJIT_TEMPORARY_REG1
&& STACK_TOP
== SLJIT_TEMPORARY_REG2
&& TMP2
== SLJIT_TEMPORARY_REG3
);
3951 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
3953 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, TMP2
, 0);
3955 /* Needed to save important temporary registers. */
3956 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, STACK_TOP
, 0);
3957 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG2
, 0, ARGUMENTS
, 0);
3958 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_TEMPORARY_REG2
), SLJIT_OFFSETOF(jit_arguments
, uchar_ptr
), STR_PTR
, 0);
3959 sljit_emit_ijump(compiler
, SLJIT_CALL3
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(do_utf_caselesscmp
));
3960 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
3961 if (common
->mode
== JIT_COMPILE
)
3962 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 1));
3965 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 0));
3966 nopartial
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 1);
3967 check_partial(common
, FALSE
);
3968 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
3969 JUMPHERE(nopartial
);
3971 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_RETURN_REG
, 0);
3974 #endif /* SUPPORT_UTF && SUPPORT_UCP */
3976 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), TMP1
, 0);
3978 jump
= JUMP(SLJIT_C_ZERO
);
3980 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
3981 partial
= CMP(SLJIT_C_GREATER
, STR_PTR
, 0, STR_END
, 0);
3982 if (common
->mode
== JIT_COMPILE
)
3983 add_jump(compiler
, backtracks
, partial
);
3985 add_jump(compiler
, *cc
== OP_REF
? &common
->casefulcmp
: &common
->caselesscmp
, JUMP(SLJIT_FAST_CALL
));
3986 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
3988 if (common
->mode
!= JIT_COMPILE
)
3990 nopartial
= JUMP(SLJIT_JUMP
);
3992 /* TMP2 -= STR_END - STR_PTR */
3993 OP2(SLJIT_SUB
, TMP2
, 0, TMP2
, 0, STR_PTR
, 0);
3994 OP2(SLJIT_ADD
, TMP2
, 0, TMP2
, 0, STR_END
, 0);
3995 partial
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0);
3996 OP1(SLJIT_MOV
, STR_PTR
, 0, STR_END
, 0);
3997 add_jump(compiler
, *cc
== OP_REF
? &common
->casefulcmp
: &common
->caselesscmp
, JUMP(SLJIT_FAST_CALL
));
3998 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
4000 check_partial(common
, FALSE
);
4001 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
4002 JUMPHERE(nopartial
);
4009 add_jump(compiler
, backtracks
, jump
);
4013 return cc
+ 1 + IMM2_SIZE
;
4016 static SLJIT_INLINE pcre_uchar
*compile_ref_iterator_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
4019 backtrack_common
*backtrack
;
4021 struct sljit_label
*label
;
4022 struct sljit_jump
*zerolength
;
4023 struct sljit_jump
*jump
= NULL
;
4024 pcre_uchar
*ccbegin
= cc
;
4025 int min
= 0, max
= 0;
4028 PUSH_BACKTRACK(sizeof(iterator_backtrack
), cc
, NULL
);
4030 type
= cc
[1 + IMM2_SIZE
];
4031 minimize
= (type
& 0x1) != 0;
4038 cc
+= 1 + IMM2_SIZE
+ 1;
4044 cc
+= 1 + IMM2_SIZE
+ 1;
4050 cc
+= 1 + IMM2_SIZE
+ 1;
4054 min
= GET2(cc
, 1 + IMM2_SIZE
+ 1);
4055 max
= GET2(cc
, 1 + IMM2_SIZE
+ 1 + IMM2_SIZE
);
4056 cc
+= 1 + IMM2_SIZE
+ 1 + 2 * IMM2_SIZE
;
4059 SLJIT_ASSERT_STOP();
4067 allocate_stack(common
, 2);
4068 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4069 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 0);
4070 /* Temporary release of STR_PTR. */
4071 OP2(SLJIT_SUB
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4072 zerolength
= compile_ref_checks(common
, ccbegin
, NULL
);
4073 /* Restore if not zero length. */
4074 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4078 allocate_stack(common
, 1);
4079 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4080 zerolength
= compile_ref_checks(common
, ccbegin
, &backtrack
->topbacktracks
);
4083 if (min
> 1 || max
> 1)
4084 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 0);
4087 compile_ref_trypath(common
, ccbegin
, &backtrack
->topbacktracks
, FALSE
, FALSE
);
4089 if (min
> 1 || max
> 1)
4091 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
4092 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
4093 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, TMP1
, 0);
4095 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, min
, label
);
4098 jump
= CMP(SLJIT_C_GREATER_EQUAL
, TMP1
, 0, SLJIT_IMM
, max
);
4099 allocate_stack(common
, 1);
4100 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4101 JUMPTO(SLJIT_JUMP
, label
);
4108 /* Includes min > 1 case as well. */
4109 allocate_stack(common
, 1);
4110 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4111 JUMPTO(SLJIT_JUMP
, label
);
4114 JUMPHERE(zerolength
);
4115 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
4117 decrease_call_count(common
);
4121 allocate_stack(common
, 2);
4122 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4123 if (type
!= OP_CRMINSTAR
)
4124 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 0);
4128 zerolength
= compile_ref_checks(common
, ccbegin
, NULL
);
4129 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4130 jump
= JUMP(SLJIT_JUMP
);
4133 zerolength
= compile_ref_checks(common
, ccbegin
, &backtrack
->topbacktracks
);
4135 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
4137 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, max
));
4139 compile_ref_trypath(common
, ccbegin
, &backtrack
->topbacktracks
, TRUE
, TRUE
);
4140 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4144 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
4145 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
4146 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
4147 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, min
, BACKTRACK_AS(iterator_backtrack
)->trypath
);
4150 OP2(SLJIT_ADD
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 1);
4154 JUMPHERE(zerolength
);
4156 decrease_call_count(common
);
4160 static SLJIT_INLINE pcre_uchar
*compile_recurse_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
4163 backtrack_common
*backtrack
;
4164 recurse_entry
*entry
= common
->entries
;
4165 recurse_entry
*prev
= NULL
;
4166 int start
= GET(cc
, 1);
4168 PUSH_BACKTRACK(sizeof(recurse_backtrack
), cc
, NULL
);
4169 while (entry
!= NULL
)
4171 if (entry
->start
== start
)
4174 entry
= entry
->next
;
4179 entry
= sljit_alloc_memory(compiler
, sizeof(recurse_entry
));
4180 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
4183 entry
->entry
= NULL
;
4184 entry
->calls
= NULL
;
4185 entry
->start
= start
;
4190 common
->entries
= entry
;
4193 if (common
->has_set_som
&& common
->mark_ptr
!= 0)
4195 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
4196 allocate_stack(common
, 2);
4197 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
4198 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
4199 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
4201 else if (common
->has_set_som
|| common
->mark_ptr
!= 0)
4203 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->has_set_som
? (int)(OVECTOR(0)) : common
->mark_ptr
);
4204 allocate_stack(common
, 1);
4205 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
4208 if (entry
->entry
== NULL
)
4209 add_jump(compiler
, &entry
->calls
, JUMP(SLJIT_FAST_CALL
));
4211 JUMPTO(SLJIT_FAST_CALL
, entry
->entry
);
4212 /* Leave if the match is failed. */
4213 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0));
4214 return cc
+ 1 + LINK_SIZE
;
4217 static pcre_uchar
*compile_assert_trypath(compiler_common
*common
, pcre_uchar
*cc
, assert_backtrack
*backtrack
, BOOL conditional
)
4222 backtrack_common altbacktrack
;
4223 pcre_uchar
*ccbegin
;
4225 pcre_uchar bra
= OP_BRA
;
4226 jump_list
*tmp
= NULL
;
4227 jump_list
**target
= (conditional
) ? &backtrack
->condfailed
: &backtrack
->common
.topbacktracks
;
4229 /* Saving previous accept variables. */
4230 struct sljit_label
*save_leavelabel
= common
->leavelabel
;
4231 struct sljit_label
*save_acceptlabel
= common
->acceptlabel
;
4232 jump_list
*save_leave
= common
->leave
;
4233 jump_list
*save_accept
= common
->accept
;
4234 struct sljit_jump
*jump
;
4235 struct sljit_jump
*brajump
= NULL
;
4237 if (*cc
== OP_BRAZERO
|| *cc
== OP_BRAMINZERO
)
4239 SLJIT_ASSERT(!conditional
);
4243 localptr
= PRIV_DATA(cc
);
4244 SLJIT_ASSERT(localptr
!= 0);
4245 framesize
= get_framesize(common
, cc
, FALSE
);
4246 backtrack
->framesize
= framesize
;
4247 backtrack
->localptr
= localptr
;
4249 SLJIT_ASSERT(opcode
>= OP_ASSERT
&& opcode
<= OP_ASSERTBACK_NOT
);
4250 found
= (opcode
== OP_ASSERT
|| opcode
== OP_ASSERTBACK
) ? &tmp
: target
;
4254 if (bra
== OP_BRAMINZERO
)
4256 /* This is a braminzero backtrack path. */
4257 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4258 free_stack(common
, 1);
4259 brajump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
4264 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STACK_TOP
, 0);
4265 allocate_stack(common
, 1);
4266 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4270 allocate_stack(common
, framesize
+ 2);
4271 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4272 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(framesize
+ 1));
4273 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP2
, 0);
4274 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4275 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
4276 init_frame(common
, ccbegin
, framesize
+ 1, 2, FALSE
);
4279 memset(&altbacktrack
, 0, sizeof(backtrack_common
));
4280 common
->leavelabel
= NULL
;
4281 common
->leave
= NULL
;
4284 common
->acceptlabel
= NULL
;
4285 common
->accept
= NULL
;
4286 altbacktrack
.top
= NULL
;
4287 altbacktrack
.topbacktracks
= NULL
;
4289 if (*ccbegin
== OP_ALT
)
4290 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4292 altbacktrack
.cc
= ccbegin
;
4293 compile_trypath(common
, ccbegin
+ 1 + LINK_SIZE
, cc
, &altbacktrack
);
4294 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
4296 common
->leavelabel
= save_leavelabel
;
4297 common
->acceptlabel
= save_acceptlabel
;
4298 common
->leave
= save_leave
;
4299 common
->accept
= save_accept
;
4302 common
->acceptlabel
= LABEL();
4303 if (common
->accept
!= NULL
)
4304 set_jumps(common
->accept
, common
->acceptlabel
);
4308 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4310 if ((opcode
!= OP_ASSERT_NOT
&& opcode
!= OP_ASSERTBACK_NOT
) || conditional
)
4312 /* We don't need to keep the STR_PTR, only the previous localptr. */
4313 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, (framesize
+ 1) * sizeof(sljit_w
));
4317 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4318 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
4322 if (opcode
== OP_ASSERT_NOT
|| opcode
== OP_ASSERTBACK_NOT
)
4324 /* We know that STR_PTR was stored on the top of the stack. */
4326 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
4327 else if (bra
== OP_BRAZERO
)
4330 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
4333 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), framesize
* sizeof(sljit_w
));
4334 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), (framesize
+ 1) * sizeof(sljit_w
));
4335 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP1
, 0);
4337 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4338 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4340 else if (framesize
>= 0)
4342 /* For OP_BRA and OP_BRAMINZERO. */
4343 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), framesize
* sizeof(sljit_w
));
4346 add_jump(compiler
, found
, JUMP(SLJIT_JUMP
));
4348 compile_backtrackpath(common
, altbacktrack
.top
);
4349 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
4351 common
->leavelabel
= save_leavelabel
;
4352 common
->acceptlabel
= save_acceptlabel
;
4353 common
->leave
= save_leave
;
4354 common
->accept
= save_accept
;
4357 set_jumps(altbacktrack
.topbacktracks
, LABEL());
4365 /* None of them matched. */
4366 if (common
->leave
!= NULL
)
4367 set_jumps(common
->leave
, LABEL());
4369 if (opcode
== OP_ASSERT
|| opcode
== OP_ASSERTBACK
)
4371 /* Assert is failed. */
4372 if (conditional
|| bra
== OP_BRAZERO
)
4373 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4377 /* The topmost item should be 0. */
4378 if (bra
== OP_BRAZERO
)
4379 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4381 free_stack(common
, 1);
4385 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
4386 /* The topmost item should be 0. */
4387 if (bra
== OP_BRAZERO
)
4389 free_stack(common
, framesize
+ 1);
4390 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4393 free_stack(common
, framesize
+ 2);
4394 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP1
, 0);
4396 jump
= JUMP(SLJIT_JUMP
);
4397 if (bra
!= OP_BRAZERO
)
4398 add_jump(compiler
, target
, jump
);
4400 /* Assert is successful. */
4401 set_jumps(tmp
, LABEL());
4404 /* We know that STR_PTR was stored on the top of the stack. */
4405 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
4406 /* Keep the STR_PTR on the top of the stack. */
4407 if (bra
== OP_BRAZERO
)
4408 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4409 else if (bra
== OP_BRAMINZERO
)
4411 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4412 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4419 /* We don't need to keep the STR_PTR, only the previous localptr. */
4420 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, (framesize
+ 1) * sizeof(sljit_w
));
4421 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
4425 /* We don't need to keep the STR_PTR, only the previous localptr. */
4426 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, (framesize
+ 2) * sizeof(sljit_w
));
4427 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4428 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), bra
== OP_BRAZERO
? STR_PTR
: SLJIT_IMM
, 0);
4432 if (bra
== OP_BRAZERO
)
4434 backtrack
->trypath
= LABEL();
4435 sljit_set_label(jump
, backtrack
->trypath
);
4437 else if (bra
== OP_BRAMINZERO
)
4439 JUMPTO(SLJIT_JUMP
, backtrack
->trypath
);
4443 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4444 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
4445 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), framesize
* sizeof(sljit_w
));
4447 set_jumps(backtrack
->common
.topbacktracks
, LABEL());
4452 /* AssertNot is successful. */
4455 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4457 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4459 free_stack(common
, 1);
4463 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4464 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
4465 /* The topmost item should be 0. */
4468 free_stack(common
, framesize
+ 1);
4469 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4472 free_stack(common
, framesize
+ 2);
4473 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP1
, 0);
4476 if (bra
== OP_BRAZERO
)
4477 backtrack
->trypath
= LABEL();
4478 else if (bra
== OP_BRAMINZERO
)
4480 JUMPTO(SLJIT_JUMP
, backtrack
->trypath
);
4486 SLJIT_ASSERT(found
== &backtrack
->common
.topbacktracks
);
4487 set_jumps(backtrack
->common
.topbacktracks
, LABEL());
4488 backtrack
->common
.topbacktracks
= NULL
;
4492 common
->leavelabel
= save_leavelabel
;
4493 common
->acceptlabel
= save_acceptlabel
;
4494 common
->leave
= save_leave
;
4495 common
->accept
= save_accept
;
4496 return cc
+ 1 + LINK_SIZE
;
4499 static sljit_w SLJIT_CALL
do_searchovector(sljit_w refno
, sljit_w
* locals
, pcre_uchar
*name_table
)
4501 int condition
= FALSE
;
4502 pcre_uchar
*slotA
= name_table
;
4504 sljit_w name_count
= locals
[LOCALS0
/ sizeof(sljit_w
)];
4505 sljit_w name_entry_size
= locals
[LOCALS1
/ sizeof(sljit_w
)];
4509 locals
+= refno
& 0xff;
4511 no_capture
= locals
[1];
4513 for (i
= 0; i
< name_count
; i
++)
4515 if (GET2(slotA
, 0) == refno
) break;
4516 slotA
+= name_entry_size
;
4521 /* Found a name for the number - there can be only one; duplicate names
4522 for different numbers are allowed, but not vice versa. First scan down
4526 while (slotB
> name_table
)
4528 slotB
-= name_entry_size
;
4529 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
4531 condition
= locals
[GET2(slotB
, 0) << 1] != no_capture
;
4532 if (condition
) break;
4537 /* Scan up for duplicates */
4541 for (i
++; i
< name_count
; i
++)
4543 slotB
+= name_entry_size
;
4544 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
4546 condition
= locals
[GET2(slotB
, 0) << 1] != no_capture
;
4547 if (condition
) break;
4556 static sljit_w SLJIT_CALL
do_searchgroups(sljit_w recno
, sljit_w
* locals
, pcre_uchar
*name_table
)
4558 int condition
= FALSE
;
4559 pcre_uchar
*slotA
= name_table
;
4561 sljit_w name_count
= locals
[LOCALS0
/ sizeof(sljit_w
)];
4562 sljit_w name_entry_size
= locals
[LOCALS1
/ sizeof(sljit_w
)];
4563 sljit_w group_num
= locals
[POSSESSIVE0
/ sizeof(sljit_w
)];
4566 for (i
= 0; i
< name_count
; i
++)
4568 if (GET2(slotA
, 0) == recno
) break;
4569 slotA
+= name_entry_size
;
4574 /* Found a name for the number - there can be only one; duplicate
4575 names for different numbers are allowed, but not vice versa. First
4576 scan down for duplicates. */
4579 while (slotB
> name_table
)
4581 slotB
-= name_entry_size
;
4582 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
4584 condition
= GET2(slotB
, 0) == group_num
;
4585 if (condition
) break;
4590 /* Scan up for duplicates */
4594 for (i
++; i
< name_count
; i
++)
4596 slotB
+= name_entry_size
;
4597 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
4599 condition
= GET2(slotB
, 0) == group_num
;
4600 if (condition
) break;
4610 Handling bracketed expressions is probably the most complex part.
4612 Stack layout naming characters:
4613 S - Push the current STR_PTR
4615 A - Push the current STR_PTR. Needed for restoring the STR_PTR
4616 before the next alternative. Not pushed if there are no alternatives.
4617 M - Any values pushed by the current alternative. Can be empty, or anything.
4618 C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.
4619 L - Push the previous local (pointed by localptr) to the stack
4620 () - opional values stored on the stack
4621 ()* - optonal, can be stored multiple times
4623 The following list shows the regular expression templates, their PCRE byte codes
4624 and stack layout supported by pcre-sljit.
4626 (?:) OP_BRA | OP_KET A M
4627 () OP_CBRA | OP_KET C M
4628 (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*
4629 OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*
4630 (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*
4631 OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*
4632 ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*
4633 OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*
4634 ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*
4635 OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*
4636 (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )
4637 (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )
4638 ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )
4639 ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )
4640 (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*
4641 OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*
4642 (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*
4643 OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*
4644 ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*
4645 OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*
4646 ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*
4647 OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*
4650 Stack layout naming characters:
4651 A - Push the alternative index (starting from 0) on the stack.
4652 Not pushed if there is no alternatives.
4653 M - Any values pushed by the current alternative. Can be empty, or anything.
4655 The next list shows the possible content of a bracket:
4656 (|) OP_*BRA | OP_ALT ... M A
4657 (?()|) OP_*COND | OP_ALT M A
4658 (?>|) OP_ONCE | OP_ALT ... [stack trace] M A
4659 (?>|) OP_ONCE_NC | OP_ALT ... [stack trace] M A
4660 Or nothing, if trace is unnecessary
4663 static pcre_uchar
*compile_bracket_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
4666 backtrack_common
*backtrack
;
4671 pcre_uchar
*ccbegin
;
4672 pcre_uchar
*trypath
;
4673 pcre_uchar bra
= OP_BRA
;
4675 assert_backtrack
*assert;
4676 BOOL has_alternatives
;
4677 struct sljit_jump
*jump
;
4678 struct sljit_jump
*skip
;
4679 struct sljit_label
*rmaxlabel
= NULL
;
4680 struct sljit_jump
*braminzerojump
= NULL
;
4682 PUSH_BACKTRACK(sizeof(bracket_backtrack
), cc
, NULL
);
4684 if (*cc
== OP_BRAZERO
|| *cc
== OP_BRAMINZERO
)
4693 trypath
= ccbegin
+ 1 + LINK_SIZE
;
4695 if ((opcode
== OP_COND
|| opcode
== OP_SCOND
) && cc
[1 + LINK_SIZE
] == OP_DEF
)
4697 /* Drop this bracket_backtrack. */
4698 parent
->top
= backtrack
->prev
;
4699 return bracketend(cc
);
4702 ket
= *(bracketend(cc
) - 1 - LINK_SIZE
);
4703 SLJIT_ASSERT(ket
== OP_KET
|| ket
== OP_KETRMAX
|| ket
== OP_KETRMIN
);
4704 SLJIT_ASSERT(!((bra
== OP_BRAZERO
&& ket
== OP_KETRMIN
) || (bra
== OP_BRAMINZERO
&& ket
== OP_KETRMAX
)));
4707 has_alternatives
= *cc
== OP_ALT
;
4708 if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
4710 has_alternatives
= (*trypath
== OP_RREF
) ? FALSE
: TRUE
;
4711 if (*trypath
== OP_NRREF
)
4713 stacksize
= GET2(trypath
, 1);
4714 if (common
->currententry
== NULL
|| stacksize
== RREF_ANY
)
4715 has_alternatives
= FALSE
;
4716 else if (common
->currententry
->start
== 0)
4717 has_alternatives
= stacksize
!= 0;
4719 has_alternatives
= stacksize
!= GET2(common
->start
, common
->currententry
->start
+ 1 + LINK_SIZE
);
4723 if (SLJIT_UNLIKELY(opcode
== OP_COND
) && (*cc
== OP_KETRMAX
|| *cc
== OP_KETRMIN
))
4725 if (SLJIT_UNLIKELY(opcode
== OP_ONCE_NC
))
4728 if (opcode
== OP_CBRA
|| opcode
== OP_SCBRA
)
4730 /* Capturing brackets has a pre-allocated space. */
4731 offset
= GET2(ccbegin
, 1 + LINK_SIZE
);
4732 localptr
= OVECTOR_PRIV(offset
);
4734 BACKTRACK_AS(bracket_backtrack
)->localptr
= localptr
;
4735 trypath
+= IMM2_SIZE
;
4737 else if (opcode
== OP_ONCE
|| opcode
== OP_SBRA
|| opcode
== OP_SCOND
)
4739 /* Other brackets simply allocate the next entry. */
4740 localptr
= PRIV_DATA(ccbegin
);
4741 SLJIT_ASSERT(localptr
!= 0);
4742 BACKTRACK_AS(bracket_backtrack
)->localptr
= localptr
;
4743 if (opcode
== OP_ONCE
)
4744 BACKTRACK_AS(bracket_backtrack
)->u
.framesize
= get_framesize(common
, ccbegin
, FALSE
);
4747 /* Instructions before the first alternative. */
4749 if ((ket
== OP_KETRMAX
) || (ket
== OP_KETRMIN
&& bra
!= OP_BRAMINZERO
))
4751 if (bra
== OP_BRAZERO
)
4755 allocate_stack(common
, stacksize
);
4758 if ((ket
== OP_KETRMAX
) || (ket
== OP_KETRMIN
&& bra
!= OP_BRAMINZERO
))
4760 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
4764 if (bra
== OP_BRAZERO
)
4765 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), STR_PTR
, 0);
4767 if (bra
== OP_BRAMINZERO
)
4769 /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */
4770 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
4771 if (ket
!= OP_KETRMIN
)
4773 free_stack(common
, 1);
4774 braminzerojump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
4778 if (opcode
== OP_ONCE
|| opcode
>= OP_SBRA
)
4780 jump
= CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
4781 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
4782 /* Nothing stored during the first run. */
4783 skip
= JUMP(SLJIT_JUMP
);
4785 /* Checking zero-length iteration. */
4786 if (opcode
!= OP_ONCE
|| BACKTRACK_AS(bracket_backtrack
)->u
.framesize
< 0)
4788 /* When we come from outside, localptr contains the previous STR_PTR. */
4789 braminzerojump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4793 /* Except when the whole stack frame must be saved. */
4794 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4795 braminzerojump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(TMP1
), (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1) * sizeof(sljit_w
));
4801 jump
= CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
4802 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
4808 if (ket
== OP_KETRMIN
)
4809 BACKTRACK_AS(bracket_backtrack
)->recursivetrypath
= LABEL();
4811 if (ket
== OP_KETRMAX
)
4813 rmaxlabel
= LABEL();
4814 if (has_alternatives
&& opcode
!= OP_ONCE
&& opcode
< OP_SBRA
)
4815 BACKTRACK_AS(bracket_backtrack
)->alttrypath
= rmaxlabel
;
4818 /* Handling capturing brackets and alternatives. */
4819 if (opcode
== OP_ONCE
)
4821 if (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
< 0)
4823 /* Neither capturing brackets nor recursions are not found in the block. */
4824 if (ket
== OP_KETRMIN
)
4826 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4827 allocate_stack(common
, 2);
4828 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4829 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP2
, 0);
4830 OP2(SLJIT_SUB
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
4832 else if (ket
== OP_KETRMAX
|| has_alternatives
)
4834 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STACK_TOP
, 0);
4835 allocate_stack(common
, 1);
4836 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4839 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STACK_TOP
, 0);
4843 if (ket
== OP_KETRMIN
|| ket
== OP_KETRMAX
|| has_alternatives
)
4845 allocate_stack(common
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 2);
4846 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4847 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1));
4848 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4849 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP2
, 0);
4850 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
4851 init_frame(common
, ccbegin
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1, 2, FALSE
);
4855 allocate_stack(common
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1);
4856 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4857 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(BACKTRACK_AS(bracket_backtrack
)->u
.framesize
));
4858 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP2
, 0);
4859 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP1
, 0);
4860 init_frame(common
, ccbegin
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
, 1, FALSE
);
4864 else if (opcode
== OP_CBRA
|| opcode
== OP_SCBRA
)
4866 /* Saving the previous values. */
4867 allocate_stack(common
, 3);
4868 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
4869 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
4870 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP1
, 0);
4871 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP2
, 0);
4872 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4873 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STR_PTR
, 0);
4874 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(2), TMP1
, 0);
4876 else if (opcode
== OP_SBRA
|| opcode
== OP_SCOND
)
4878 /* Saving the previous value. */
4879 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4880 allocate_stack(common
, 1);
4881 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STR_PTR
, 0);
4882 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
4884 else if (has_alternatives
)
4886 /* Pushing the starting string pointer. */
4887 allocate_stack(common
, 1);
4888 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4891 /* Generating code for the first alternative. */
4892 if (opcode
== OP_COND
|| opcode
== OP_SCOND
)
4894 if (*trypath
== OP_CREF
)
4896 SLJIT_ASSERT(has_alternatives
);
4897 add_jump(compiler
, &(BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
),
4898 CMP(SLJIT_C_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(GET2(trypath
, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1)));
4899 trypath
+= 1 + IMM2_SIZE
;
4901 else if (*trypath
== OP_NCREF
)
4903 SLJIT_ASSERT(has_alternatives
);
4904 stacksize
= GET2(trypath
, 1);
4905 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(stacksize
<< 1), SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1));
4907 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STACK_TOP
, 0);
4908 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, SLJIT_IMM
, common
->name_count
);
4909 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, SLJIT_IMM
, common
->name_entry_size
);
4910 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_IMM
, (stacksize
<< 8) | (common
->ovector_start
/ sizeof(sljit_w
)));
4911 GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2
, 0, 0);
4912 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, common
->name_table
);
4913 sljit_emit_ijump(compiler
, SLJIT_CALL3
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(do_searchovector
));
4914 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
);
4915 add_jump(compiler
, &(BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
), CMP(SLJIT_C_EQUAL
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_IMM
, 0));
4918 trypath
+= 1 + IMM2_SIZE
;
4920 else if (*trypath
== OP_RREF
|| *trypath
== OP_NRREF
)
4922 /* Never has other case. */
4923 BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
= NULL
;
4925 stacksize
= GET2(trypath
, 1);
4926 if (common
->currententry
== NULL
)
4928 else if (stacksize
== RREF_ANY
)
4930 else if (common
->currententry
->start
== 0)
4931 stacksize
= stacksize
== 0;
4933 stacksize
= stacksize
== GET2(common
->start
, common
->currententry
->start
+ 1 + LINK_SIZE
);
4935 if (*trypath
== OP_RREF
|| stacksize
|| common
->currententry
== NULL
)
4937 SLJIT_ASSERT(!has_alternatives
);
4939 trypath
+= 1 + IMM2_SIZE
;
4944 trypath
= cc
+ 1 + LINK_SIZE
;
4953 SLJIT_ASSERT(has_alternatives
);
4955 stacksize
= GET2(trypath
, 1);
4956 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STACK_TOP
, 0);
4957 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, SLJIT_IMM
, common
->name_count
);
4958 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, SLJIT_IMM
, common
->name_entry_size
);
4959 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, GET2(common
->start
, common
->currententry
->start
+ 1 + LINK_SIZE
));
4960 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_IMM
, stacksize
);
4961 GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2
, 0, 0);
4962 OP1(SLJIT_MOV
, SLJIT_TEMPORARY_REG3
, 0, SLJIT_IMM
, common
->name_table
);
4963 sljit_emit_ijump(compiler
, SLJIT_CALL3
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(do_searchgroups
));
4964 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
);
4965 add_jump(compiler
, &(BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
), CMP(SLJIT_C_EQUAL
, SLJIT_TEMPORARY_REG1
, 0, SLJIT_IMM
, 0));
4966 trypath
+= 1 + IMM2_SIZE
;
4971 SLJIT_ASSERT(has_alternatives
&& *trypath
>= OP_ASSERT
&& *trypath
<= OP_ASSERTBACK_NOT
);
4972 /* Similar code as PUSH_BACKTRACK macro. */
4973 assert = sljit_alloc_memory(compiler
, sizeof(assert_backtrack
));
4974 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
4976 memset(assert, 0, sizeof(assert_backtrack
));
4977 assert->common
.cc
= trypath
;
4978 BACKTRACK_AS(bracket_backtrack
)->u
.assert = assert;
4979 trypath
= compile_assert_trypath(common
, trypath
, assert, TRUE
);
4983 compile_trypath(common
, trypath
, cc
, backtrack
);
4984 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
4987 if (opcode
== OP_ONCE
)
4989 if (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
< 0)
4991 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
4992 /* TMP2 which is set here used by OP_KETRMAX below. */
4993 if (ket
== OP_KETRMAX
)
4994 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), 0);
4995 else if (ket
== OP_KETRMIN
)
4997 /* Move the STR_PTR to the localptr. */
4998 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), 0);
5003 stacksize
= (ket
== OP_KETRMIN
|| ket
== OP_KETRMAX
|| has_alternatives
) ? 2 : 1;
5004 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ stacksize
) * sizeof(sljit_w
));
5005 if (ket
== OP_KETRMAX
)
5007 /* TMP2 which is set here used by OP_KETRMAX below. */
5008 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5014 if (ket
!= OP_KET
|| bra
!= OP_BRA
)
5016 if (has_alternatives
&& opcode
!= OP_ONCE
)
5020 allocate_stack(common
, stacksize
);
5025 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), STR_PTR
, 0);
5028 else if (bra
!= OP_BRA
)
5030 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
5034 if (has_alternatives
)
5036 if (opcode
!= OP_ONCE
)
5037 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
5038 if (ket
!= OP_KETRMAX
)
5039 BACKTRACK_AS(bracket_backtrack
)->alttrypath
= LABEL();
5042 /* Must be after the trypath label. */
5045 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5046 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
5047 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 0), TMP1
, 0);
5050 if (ket
== OP_KETRMAX
)
5052 if (opcode
== OP_ONCE
|| opcode
>= OP_SBRA
)
5054 if (has_alternatives
)
5055 BACKTRACK_AS(bracket_backtrack
)->alttrypath
= LABEL();
5056 /* Checking zero-length iteration. */
5057 if (opcode
!= OP_ONCE
)
5059 CMPTO(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STR_PTR
, 0, rmaxlabel
);
5060 /* Drop STR_PTR for greedy plus quantifier. */
5061 if (bra
!= OP_BRAZERO
)
5062 free_stack(common
, 1);
5065 /* TMP2 must contain the starting STR_PTR. */
5066 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0, rmaxlabel
);
5069 JUMPTO(SLJIT_JUMP
, rmaxlabel
);
5070 BACKTRACK_AS(bracket_backtrack
)->recursivetrypath
= LABEL();
5073 if (bra
== OP_BRAZERO
)
5074 BACKTRACK_AS(bracket_backtrack
)->zerotrypath
= LABEL();
5076 if (bra
== OP_BRAMINZERO
)
5078 /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */
5079 JUMPTO(SLJIT_JUMP
, ((braminzero_backtrack
*)parent
)->trypath
);
5080 if (braminzerojump
!= NULL
)
5082 JUMPHERE(braminzerojump
);
5083 /* We need to release the end pointer to perform the
5084 backtrack for the zero-length iteration. When
5085 framesize is < 0, OP_ONCE will do the release itself. */
5086 if (opcode
== OP_ONCE
&& BACKTRACK_AS(bracket_backtrack
)->u
.framesize
>= 0)
5088 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5089 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
5091 else if (ket
== OP_KETRMIN
&& opcode
!= OP_ONCE
)
5092 free_stack(common
, 1);
5094 /* Continue to the normal backtrack. */
5097 if ((ket
!= OP_KET
&& bra
!= OP_BRAMINZERO
) || bra
== OP_BRAZERO
)
5098 decrease_call_count(common
);
5100 /* Skip the other alternatives. */
5101 while (*cc
== OP_ALT
)
5103 cc
+= 1 + LINK_SIZE
;
5107 static pcre_uchar
*compile_bracketpos_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
5110 backtrack_common
*backtrack
;
5113 int cbraprivptr
= 0;
5118 pcre_uchar
*ccbegin
= NULL
;
5120 struct sljit_label
*loop
= NULL
;
5121 struct jump_list
*emptymatch
= NULL
;
5123 PUSH_BACKTRACK(sizeof(bracketpos_backtrack
), cc
, NULL
);
5124 if (*cc
== OP_BRAPOSZERO
)
5131 localptr
= PRIV_DATA(cc
);
5132 SLJIT_ASSERT(localptr
!= 0);
5133 BACKTRACK_AS(bracketpos_backtrack
)->localptr
= localptr
;
5138 ccbegin
= cc
+ 1 + LINK_SIZE
;
5143 offset
= GET2(cc
, 1 + LINK_SIZE
);
5144 cbraprivptr
= OVECTOR_PRIV(offset
);
5146 ccbegin
= cc
+ 1 + LINK_SIZE
+ IMM2_SIZE
;
5150 SLJIT_ASSERT_STOP();
5154 framesize
= get_framesize(common
, cc
, FALSE
);
5155 BACKTRACK_AS(bracketpos_backtrack
)->framesize
= framesize
;
5158 stacksize
= (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
) ? 2 : 1;
5161 BACKTRACK_AS(bracketpos_backtrack
)->stacksize
= stacksize
;
5162 allocate_stack(common
, stacksize
);
5163 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, STACK_TOP
, 0);
5165 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5167 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
5168 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
5169 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP1
, 0);
5170 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP2
, 0);
5173 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5176 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 1);
5180 stacksize
= framesize
+ 1;
5183 if (opcode
== OP_BRAPOS
|| opcode
== OP_SBRAPOS
)
5185 BACKTRACK_AS(bracketpos_backtrack
)->stacksize
= stacksize
;
5186 allocate_stack(common
, stacksize
);
5188 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5189 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(stacksize
- 1));
5190 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP2
, 0);
5194 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 1);
5197 if (opcode
== OP_BRAPOS
|| opcode
== OP_SBRAPOS
)
5199 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stack
), STR_PTR
, 0);
5202 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stack
), TMP1
, 0);
5203 init_frame(common
, cc
, stacksize
- 1, stacksize
- framesize
, FALSE
);
5206 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5207 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
, STR_PTR
, 0);
5210 while (*cc
!= OP_KETRPOS
)
5212 backtrack
->top
= NULL
;
5213 backtrack
->topbacktracks
= NULL
;
5216 compile_trypath(common
, ccbegin
, cc
, backtrack
);
5217 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
5222 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5224 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5226 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
5227 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
5228 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
, STR_PTR
, 0);
5229 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
5233 if (opcode
== OP_SBRAPOS
)
5234 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5235 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5238 if (opcode
== OP_SBRAPOS
|| opcode
== OP_SCBRAPOS
)
5239 add_jump(compiler
, &emptymatch
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, STR_PTR
, 0));
5242 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 0);
5246 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5248 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, stacksize
* sizeof(sljit_w
));
5249 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
5250 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
5251 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
, STR_PTR
, 0);
5252 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
5256 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5257 OP2(SLJIT_ADD
, STACK_TOP
, 0, TMP2
, 0, SLJIT_IMM
, stacksize
* sizeof(sljit_w
));
5258 if (opcode
== OP_SBRAPOS
)
5259 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP2
), (framesize
+ 1) * sizeof(sljit_w
));
5260 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP2
), (framesize
+ 1) * sizeof(sljit_w
), STR_PTR
, 0);
5263 if (opcode
== OP_SBRAPOS
|| opcode
== OP_SCBRAPOS
)
5264 add_jump(compiler
, &emptymatch
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, STR_PTR
, 0));
5269 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 0);
5271 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5274 JUMPTO(SLJIT_JUMP
, loop
);
5275 flush_stubs(common
);
5277 compile_backtrackpath(common
, backtrack
->top
);
5278 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
5280 set_jumps(backtrack
->topbacktracks
, LABEL());
5284 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5285 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
5287 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5291 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
5293 /* Last alternative. */
5294 if (*cc
== OP_KETRPOS
)
5295 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5296 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
5300 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
5301 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(TMP2
), (framesize
+ 1) * sizeof(sljit_w
));
5305 if (*cc
== OP_KETRPOS
)
5307 ccbegin
= cc
+ 1 + LINK_SIZE
;
5310 backtrack
->topbacktracks
= NULL
;
5314 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 0));
5315 else /* TMP2 is set to [localptr] above. */
5316 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(TMP2
), (stacksize
- 1) * sizeof(sljit_w
), SLJIT_IMM
, 0));
5319 /* None of them matched. */
5320 set_jumps(emptymatch
, LABEL());
5321 decrease_call_count(common
);
5322 return cc
+ 1 + LINK_SIZE
;
5325 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
)
5330 if (*opcode
>= OP_STAR
&& *opcode
<= OP_POSUPTO
)
5335 else if (*opcode
>= OP_STARI
&& *opcode
<= OP_POSUPTOI
)
5339 *opcode
-= OP_STARI
- OP_STAR
;
5341 else if (*opcode
>= OP_NOTSTAR
&& *opcode
<= OP_NOTPOSUPTO
)
5345 *opcode
-= OP_NOTSTAR
- OP_STAR
;
5347 else if (*opcode
>= OP_NOTSTARI
&& *opcode
<= OP_NOTPOSUPTOI
)
5351 *opcode
-= OP_NOTSTARI
- OP_STAR
;
5353 else if (*opcode
>= OP_TYPESTAR
&& *opcode
<= OP_TYPEPOSUPTO
)
5356 *opcode
-= OP_TYPESTAR
- OP_STAR
;
5361 SLJIT_ASSERT(*opcode
>= OP_CLASS
|| *opcode
<= OP_XCLASS
);
5364 class_len
= (*type
< OP_XCLASS
) ? (int)(1 + (32 / sizeof(pcre_uchar
))) : GET(cc
, 0);
5365 *opcode
= cc
[class_len
- 1];
5366 if (*opcode
>= OP_CRSTAR
&& *opcode
<= OP_CRMINQUERY
)
5368 *opcode
-= OP_CRSTAR
- OP_STAR
;
5370 *end
= cc
+ class_len
;
5374 SLJIT_ASSERT(*opcode
== OP_CRRANGE
|| *opcode
== OP_CRMINRANGE
);
5375 *arg1
= GET2(cc
, (class_len
+ IMM2_SIZE
));
5376 *arg2
= GET2(cc
, class_len
);
5380 SLJIT_ASSERT(*arg1
!= 0);
5381 *opcode
= (*opcode
== OP_CRRANGE
) ? OP_UPTO
: OP_MINUPTO
;
5387 *end
= cc
+ class_len
+ 2 * IMM2_SIZE
;
5392 if (*opcode
== OP_UPTO
|| *opcode
== OP_MINUPTO
|| *opcode
== OP_EXACT
|| *opcode
== OP_POSUPTO
)
5394 *arg1
= GET2(cc
, 0);
5402 *end
= next_opcode(common
, cc
);
5411 if (common
->utf
&& HAS_EXTRALEN(*cc
)) *end
+= GET_EXTRALEN(*cc
);
5417 static pcre_uchar
*compile_iterator_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
5420 backtrack_common
*backtrack
;
5423 int arg1
= -1, arg2
= -1;
5425 jump_list
*nomatch
= NULL
;
5426 struct sljit_jump
*jump
= NULL
;
5427 struct sljit_label
*label
;
5429 PUSH_BACKTRACK(sizeof(iterator_backtrack
), cc
, NULL
);
5431 cc
= get_iterator_parameters(common
, cc
, &opcode
, &type
, &arg1
, &arg2
, &end
);
5439 if (type
== OP_ANYNL
|| type
== OP_EXTUNI
)
5441 if (opcode
== OP_STAR
|| opcode
== OP_UPTO
)
5443 allocate_stack(common
, 2);
5444 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5445 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 0);
5449 allocate_stack(common
, 1);
5450 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5452 if (opcode
== OP_UPTO
|| opcode
== OP_CRRANGE
)
5453 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 0);
5456 compile_char1_trypath(common
, type
, cc
, &backtrack
->topbacktracks
);
5457 if (opcode
== OP_UPTO
|| opcode
== OP_CRRANGE
)
5459 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
5460 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
5461 if (opcode
== OP_CRRANGE
&& arg2
> 0)
5462 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg2
, label
);
5463 if (opcode
== OP_UPTO
|| (opcode
== OP_CRRANGE
&& arg1
> 0))
5464 jump
= CMP(SLJIT_C_GREATER_EQUAL
, TMP1
, 0, SLJIT_IMM
, arg1
);
5465 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, TMP1
, 0);
5468 allocate_stack(common
, 1);
5469 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5470 JUMPTO(SLJIT_JUMP
, label
);
5476 if (opcode
== OP_PLUS
)
5477 compile_char1_trypath(common
, type
, cc
, &backtrack
->topbacktracks
);
5478 allocate_stack(common
, 2);
5479 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5480 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 1);
5482 compile_char1_trypath(common
, type
, cc
, &nomatch
);
5483 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5484 if (opcode
<= OP_PLUS
|| (opcode
== OP_CRRANGE
&& arg1
== 0))
5486 OP2(SLJIT_ADD
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 1);
5487 JUMPTO(SLJIT_JUMP
, label
);
5491 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
5492 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
5493 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
5494 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg1
+ 1, label
);
5496 set_jumps(nomatch
, LABEL());
5497 if (opcode
== OP_CRRANGE
)
5498 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_LESS
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, arg2
+ 1));
5499 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5501 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
5506 if (opcode
== OP_MINPLUS
)
5507 compile_char1_trypath(common
, type
, cc
, &backtrack
->topbacktracks
);
5508 allocate_stack(common
, 1);
5509 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5510 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
5515 allocate_stack(common
, 2);
5516 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5517 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 1);
5518 if (opcode
== OP_CRMINRANGE
)
5519 add_jump(compiler
, &backtrack
->topbacktracks
, JUMP(SLJIT_JUMP
));
5520 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
5525 allocate_stack(common
, 1);
5526 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5527 if (opcode
== OP_QUERY
)
5528 compile_char1_trypath(common
, type
, cc
, &backtrack
->topbacktracks
);
5529 BACKTRACK_AS(iterator_backtrack
)->trypath
= LABEL();
5533 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 1);
5535 compile_char1_trypath(common
, type
, cc
, &backtrack
->topbacktracks
);
5536 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
5537 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
5538 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, TMP1
, 0);
5539 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg1
+ 1, label
);
5545 if (opcode
!= OP_POSSTAR
)
5546 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 1);
5547 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STR_PTR
, 0);
5549 compile_char1_trypath(common
, type
, cc
, &nomatch
);
5550 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STR_PTR
, 0);
5551 if (opcode
!= OP_POSUPTO
)
5553 if (opcode
== OP_POSPLUS
)
5554 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 2);
5555 JUMPTO(SLJIT_JUMP
, label
);
5559 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
5560 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
5561 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, TMP1
, 0);
5562 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg1
+ 1, label
);
5564 set_jumps(nomatch
, LABEL());
5565 if (opcode
== OP_POSPLUS
)
5566 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_LESS
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 2));
5567 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
);
5571 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STR_PTR
, 0);
5572 compile_char1_trypath(common
, type
, cc
, &nomatch
);
5573 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STR_PTR
, 0);
5574 set_jumps(nomatch
, LABEL());
5575 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
);
5579 SLJIT_ASSERT_STOP();
5583 decrease_call_count(common
);
5587 static SLJIT_INLINE pcre_uchar
*compile_fail_accept_trypath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
5590 backtrack_common
*backtrack
;
5592 PUSH_BACKTRACK(sizeof(bracket_backtrack
), cc
, NULL
);
5596 add_jump(compiler
, &backtrack
->topbacktracks
, JUMP(SLJIT_JUMP
));
5600 if (*cc
== OP_ASSERT_ACCEPT
|| common
->currententry
!= NULL
)
5602 /* No need to check notempty conditions. */
5603 if (common
->acceptlabel
== NULL
)
5604 add_jump(compiler
, &common
->accept
, JUMP(SLJIT_JUMP
));
5606 JUMPTO(SLJIT_JUMP
, common
->acceptlabel
);
5610 if (common
->acceptlabel
== NULL
)
5611 add_jump(compiler
, &common
->accept
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0)));
5613 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), common
->acceptlabel
);
5614 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
5615 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty
));
5616 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
5617 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty_atstart
));
5618 if (common
->acceptlabel
== NULL
)
5619 add_jump(compiler
, &common
->accept
, CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
5621 CMPTO(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0, common
->acceptlabel
);
5622 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
5623 if (common
->acceptlabel
== NULL
)
5624 add_jump(compiler
, &common
->accept
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0));
5626 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0, common
->acceptlabel
);
5627 add_jump(compiler
, &backtrack
->topbacktracks
, JUMP(SLJIT_JUMP
));
5631 static SLJIT_INLINE pcre_uchar
*compile_close_trypath(compiler_common
*common
, pcre_uchar
*cc
)
5634 int offset
= GET2(cc
, 1);
5636 /* Data will be discarded anyway... */
5637 if (common
->currententry
!= NULL
)
5638 return cc
+ 1 + IMM2_SIZE
;
5640 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR_PRIV(offset
));
5642 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
5643 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
5644 return cc
+ 1 + IMM2_SIZE
;
5647 static void compile_trypath(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
, backtrack_common
*parent
)
5650 backtrack_common
*backtrack
;
5658 case OP_NOT_WORD_BOUNDARY
:
5659 case OP_WORD_BOUNDARY
:
5662 case OP_NOT_WHITESPACE
:
5664 case OP_NOT_WORDCHAR
:
5686 cc
= compile_char1_trypath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
5690 PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common
), cc
);
5691 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
5692 allocate_stack(common
, 1);
5693 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), STR_PTR
, 0);
5694 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
5700 if (common
->mode
== JIT_COMPILE
)
5701 cc
= compile_charn_trypath(common
, cc
, ccend
, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
5703 cc
= compile_char1_trypath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
5737 case OP_NOTMINQUERY
:
5743 case OP_NOTPOSQUERY
:
5746 case OP_NOTMINSTARI
:
5748 case OP_NOTMINPLUSI
:
5750 case OP_NOTMINQUERYI
:
5752 case OP_NOTMINUPTOI
:
5754 case OP_NOTPOSSTARI
:
5755 case OP_NOTPOSPLUSI
:
5756 case OP_NOTPOSQUERYI
:
5757 case OP_NOTPOSUPTOI
:
5759 case OP_TYPEMINSTAR
:
5761 case OP_TYPEMINPLUS
:
5763 case OP_TYPEMINQUERY
:
5765 case OP_TYPEMINUPTO
:
5767 case OP_TYPEPOSSTAR
:
5768 case OP_TYPEPOSPLUS
:
5769 case OP_TYPEPOSQUERY
:
5770 case OP_TYPEPOSUPTO
:
5771 cc
= compile_iterator_trypath(common
, cc
, parent
);
5776 if (cc
[1 + (32 / sizeof(pcre_uchar
))] >= OP_CRSTAR
&& cc
[1 + (32 / sizeof(pcre_uchar
))] <= OP_CRMINRANGE
)
5777 cc
= compile_iterator_trypath(common
, cc
, parent
);
5779 cc
= compile_char1_trypath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
5782 #if defined SUPPORT_UTF || defined COMPILE_PCRE16
5784 if (*(cc
+ GET(cc
, 1)) >= OP_CRSTAR
&& *(cc
+ GET(cc
, 1)) <= OP_CRMINRANGE
)
5785 cc
= compile_iterator_trypath(common
, cc
, parent
);
5787 cc
= compile_char1_trypath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
5793 if (cc
[1 + IMM2_SIZE
] >= OP_CRSTAR
&& cc
[1 + IMM2_SIZE
] <= OP_CRMINRANGE
)
5794 cc
= compile_ref_iterator_trypath(common
, cc
, parent
);
5796 cc
= compile_ref_trypath(common
, cc
, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
, TRUE
, FALSE
);
5800 cc
= compile_recurse_trypath(common
, cc
, parent
);
5806 case OP_ASSERTBACK_NOT
:
5807 PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack
), cc
);
5808 cc
= compile_assert_trypath(common
, cc
, BACKTRACK_AS(assert_backtrack
), FALSE
);
5812 PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack
), cc
);
5813 cc
= bracketend(cc
+ 1);
5814 if (*(cc
- 1 - LINK_SIZE
) != OP_KETRMIN
)
5816 allocate_stack(common
, 1);
5817 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5821 allocate_stack(common
, 2);
5822 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5823 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), STR_PTR
, 0);
5825 BACKTRACK_AS(braminzero_backtrack
)->trypath
= LABEL();
5826 if (cc
[1] > OP_ASSERTBACK_NOT
)
5827 decrease_call_count(common
);
5838 cc
= compile_bracket_trypath(common
, cc
, parent
);
5842 if (cc
[1] > OP_ASSERTBACK_NOT
)
5843 cc
= compile_bracket_trypath(common
, cc
, parent
);
5846 PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack
), cc
);
5847 cc
= compile_assert_trypath(common
, cc
, BACKTRACK_AS(assert_backtrack
), FALSE
);
5856 cc
= compile_bracketpos_trypath(common
, cc
, parent
);
5860 PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common
), cc
);
5861 SLJIT_ASSERT(common
->mark_ptr
!= 0);
5862 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
5863 allocate_stack(common
, 1);
5864 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
5865 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
5866 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, (sljit_w
)(cc
+ 2));
5867 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP2
, 0);
5868 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, mark_ptr
), TMP2
, 0);
5869 cc
+= 1 + 2 + cc
[1];
5873 PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common
), cc
);
5879 case OP_ASSERT_ACCEPT
:
5880 cc
= compile_fail_accept_trypath(common
, cc
, parent
);
5884 cc
= compile_close_trypath(common
, cc
);
5888 cc
= bracketend(cc
+ 1);
5892 SLJIT_ASSERT_STOP();
5898 SLJIT_ASSERT(cc
== ccend
);
5901 #undef PUSH_BACKTRACK
5902 #undef PUSH_BACKTRACK_NOVALUE
5905 #define COMPILE_BACKTRACKPATH(current) \
5908 compile_backtrackpath(common, (current)); \
5909 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
5914 #define CURRENT_AS(type) ((type *)current)
5916 static void compile_iterator_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
5919 pcre_uchar
*cc
= current
->cc
;
5922 int arg1
= -1, arg2
= -1;
5923 struct sljit_label
*label
= NULL
;
5924 struct sljit_jump
*jump
= NULL
;
5925 jump_list
*jumplist
= NULL
;
5927 cc
= get_iterator_parameters(common
, cc
, &opcode
, &type
, &arg1
, &arg2
, NULL
);
5935 if (type
== OP_ANYNL
|| type
== OP_EXTUNI
)
5937 set_jumps(current
->topbacktracks
, LABEL());
5938 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5939 free_stack(common
, 1);
5940 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->trypath
);
5944 if (opcode
<= OP_PLUS
|| opcode
== OP_UPTO
)
5946 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
5947 jump
= CMP(SLJIT_C_LESS_EQUAL
, TMP1
, 0, SLJIT_IMM
, arg2
+ 1);
5948 OP2(SLJIT_SUB
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0, SLJIT_IMM
, 1);
5949 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5950 skip_char_back(common
);
5951 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5952 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->trypath
);
5953 if (opcode
== OP_CRRANGE
)
5954 set_jumps(current
->topbacktracks
, LABEL());
5956 free_stack(common
, 2);
5957 if (opcode
== OP_PLUS
)
5958 set_jumps(current
->topbacktracks
, LABEL());
5964 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5965 compile_char1_trypath(common
, type
, cc
, &jumplist
);
5966 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5967 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->trypath
);
5968 set_jumps(jumplist
, LABEL());
5969 free_stack(common
, 1);
5970 if (opcode
== OP_MINPLUS
)
5971 set_jumps(current
->topbacktracks
, LABEL());
5976 if (opcode
== OP_CRMINRANGE
)
5979 set_jumps(current
->topbacktracks
, label
);
5981 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5982 compile_char1_trypath(common
, type
, cc
, &jumplist
);
5984 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
5985 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5986 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
5987 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
5989 if (opcode
== OP_CRMINRANGE
)
5990 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg2
+ 1, label
);
5992 if (opcode
== OP_CRMINRANGE
&& arg1
== 0)
5993 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->trypath
);
5995 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg1
+ 2, CURRENT_AS(iterator_backtrack
)->trypath
);
5997 set_jumps(jumplist
, LABEL());
5998 free_stack(common
, 2);
6002 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6003 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6004 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->trypath
);
6005 jump
= JUMP(SLJIT_JUMP
);
6006 set_jumps(current
->topbacktracks
, LABEL());
6007 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6008 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6009 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->trypath
);
6011 free_stack(common
, 1);
6015 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6016 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6017 jump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
6018 compile_char1_trypath(common
, type
, cc
, &jumplist
);
6019 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->trypath
);
6020 set_jumps(jumplist
, LABEL());
6022 free_stack(common
, 1);
6027 set_jumps(current
->topbacktracks
, LABEL());
6036 SLJIT_ASSERT_STOP();
6041 static void compile_ref_iterator_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6044 pcre_uchar
*cc
= current
->cc
;
6047 type
= cc
[1 + IMM2_SIZE
];
6048 if ((type
& 0x1) == 0)
6050 set_jumps(current
->topbacktracks
, LABEL());
6051 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6052 free_stack(common
, 1);
6053 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->trypath
);
6057 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6058 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->trypath
);
6059 set_jumps(current
->topbacktracks
, LABEL());
6060 free_stack(common
, 2);
6063 static void compile_recurse_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6067 set_jumps(current
->topbacktracks
, LABEL());
6069 if (common
->has_set_som
&& common
->mark_ptr
!= 0)
6071 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6072 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
6073 free_stack(common
, 2);
6074 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), TMP2
, 0);
6075 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP1
, 0);
6077 else if (common
->has_set_som
|| common
->mark_ptr
!= 0)
6079 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6080 free_stack(common
, 1);
6081 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->has_set_som
? (int)(OVECTOR(0)) : common
->mark_ptr
, TMP2
, 0);
6085 static void compile_assert_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6088 pcre_uchar
*cc
= current
->cc
;
6089 pcre_uchar bra
= OP_BRA
;
6090 struct sljit_jump
*brajump
= NULL
;
6092 SLJIT_ASSERT(*cc
!= OP_BRAMINZERO
);
6093 if (*cc
== OP_BRAZERO
)
6099 if (bra
== OP_BRAZERO
)
6101 SLJIT_ASSERT(current
->topbacktracks
== NULL
);
6102 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6105 if (CURRENT_AS(assert_backtrack
)->framesize
< 0)
6107 set_jumps(current
->topbacktracks
, LABEL());
6109 if (bra
== OP_BRAZERO
)
6111 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6112 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(assert_backtrack
)->trypath
);
6113 free_stack(common
, 1);
6118 if (bra
== OP_BRAZERO
)
6120 if (*cc
== OP_ASSERT_NOT
|| *cc
== OP_ASSERTBACK_NOT
)
6122 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6123 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(assert_backtrack
)->trypath
);
6124 free_stack(common
, 1);
6127 free_stack(common
, 1);
6128 brajump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
6131 if (*cc
== OP_ASSERT
|| *cc
== OP_ASSERTBACK
)
6133 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), CURRENT_AS(assert_backtrack
)->localptr
);
6134 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6135 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
));
6137 set_jumps(current
->topbacktracks
, LABEL());
6140 set_jumps(current
->topbacktracks
, LABEL());
6142 if (bra
== OP_BRAZERO
)
6144 /* We know there is enough place on the stack. */
6145 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
6146 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6147 JUMPTO(SLJIT_JUMP
, CURRENT_AS(assert_backtrack
)->trypath
);
6152 static void compile_bracket_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6157 int localptr
= CURRENT_AS(bracket_backtrack
)->localptr
;
6160 pcre_uchar
*cc
= current
->cc
;
6161 pcre_uchar
*ccbegin
;
6163 jump_list
*jumplist
= NULL
;
6164 jump_list
*jumplistitem
= NULL
;
6165 pcre_uchar bra
= OP_BRA
;
6167 assert_backtrack
*assert;
6168 BOOL has_alternatives
;
6169 struct sljit_jump
*brazero
= NULL
;
6170 struct sljit_jump
*once
= NULL
;
6171 struct sljit_jump
*cond
= NULL
;
6172 struct sljit_label
*rminlabel
= NULL
;
6174 if (*cc
== OP_BRAZERO
|| *cc
== OP_BRAMINZERO
)
6182 ket
= *(bracketend(ccbegin
) - 1 - LINK_SIZE
);
6184 has_alternatives
= *cc
== OP_ALT
;
6185 if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
6186 has_alternatives
= (ccbegin
[1 + LINK_SIZE
] >= OP_ASSERT
&& ccbegin
[1 + LINK_SIZE
] <= OP_ASSERTBACK_NOT
) || CURRENT_AS(bracket_backtrack
)->u
.condfailed
!= NULL
;
6187 if (opcode
== OP_CBRA
|| opcode
== OP_SCBRA
)
6188 offset
= (GET2(ccbegin
, 1 + LINK_SIZE
)) << 1;
6189 if (SLJIT_UNLIKELY(opcode
== OP_COND
) && (*cc
== OP_KETRMAX
|| *cc
== OP_KETRMIN
))
6191 if (SLJIT_UNLIKELY(opcode
== OP_ONCE_NC
))
6194 if (ket
== OP_KETRMAX
)
6196 if (bra
== OP_BRAZERO
)
6198 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6199 free_stack(common
, 1);
6200 brazero
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0);
6203 else if (ket
== OP_KETRMIN
)
6205 if (bra
!= OP_BRAMINZERO
)
6207 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6208 if (opcode
>= OP_SBRA
|| opcode
== OP_ONCE
)
6210 /* Checking zero-length iteration. */
6211 if (opcode
!= OP_ONCE
|| CURRENT_AS(bracket_backtrack
)->u
.framesize
< 0)
6212 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, CURRENT_AS(bracket_backtrack
)->recursivetrypath
);
6215 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
6216 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
);
6218 if (opcode
!= OP_ONCE
)
6219 free_stack(common
, 1);
6222 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->recursivetrypath
);
6224 rminlabel
= LABEL();
6226 else if (bra
== OP_BRAZERO
)
6228 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6229 free_stack(common
, 1);
6230 brazero
= CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0);
6233 if (SLJIT_UNLIKELY(opcode
== OP_ONCE
))
6235 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
6237 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
6238 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6240 once
= JUMP(SLJIT_JUMP
);
6242 else if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
6244 if (has_alternatives
)
6246 /* Always exactly one alternative. */
6247 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6248 free_stack(common
, 1);
6250 jumplistitem
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
6251 if (SLJIT_UNLIKELY(!jumplistitem
))
6253 jumplist
= jumplistitem
;
6254 jumplistitem
->next
= NULL
;
6255 jumplistitem
->jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 1);
6258 else if (*cc
== OP_ALT
)
6260 /* Build a jump list. Get the last successfully matched branch index. */
6261 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6262 free_stack(common
, 1);
6266 /* Append as the last item. */
6267 if (jumplist
!= NULL
)
6269 jumplistitem
->next
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
6270 jumplistitem
= jumplistitem
->next
;
6274 jumplistitem
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
6275 jumplist
= jumplistitem
;
6278 if (SLJIT_UNLIKELY(!jumplistitem
))
6281 jumplistitem
->next
= NULL
;
6282 jumplistitem
->jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, count
++);
6285 while (*cc
== OP_ALT
);
6287 cc
= ccbegin
+ GET(ccbegin
, 1);
6290 COMPILE_BACKTRACKPATH(current
->top
);
6291 if (current
->topbacktracks
)
6292 set_jumps(current
->topbacktracks
, LABEL());
6294 if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
6296 /* Conditional block always has at most one alternative. */
6297 if (ccbegin
[1 + LINK_SIZE
] >= OP_ASSERT
&& ccbegin
[1 + LINK_SIZE
] <= OP_ASSERTBACK_NOT
)
6299 SLJIT_ASSERT(has_alternatives
);
6300 assert = CURRENT_AS(bracket_backtrack
)->u
.assert;
6301 if (assert->framesize
>= 0 && (ccbegin
[1 + LINK_SIZE
] == OP_ASSERT
|| ccbegin
[1 + LINK_SIZE
] == OP_ASSERTBACK
))
6303 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->localptr
);
6304 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6305 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->localptr
, SLJIT_MEM1(STACK_TOP
), assert->framesize
* sizeof(sljit_w
));
6307 cond
= JUMP(SLJIT_JUMP
);
6308 set_jumps(CURRENT_AS(bracket_backtrack
)->u
.assert->condfailed
, LABEL());
6310 else if (CURRENT_AS(bracket_backtrack
)->u
.condfailed
!= NULL
)
6312 SLJIT_ASSERT(has_alternatives
);
6313 cond
= JUMP(SLJIT_JUMP
);
6314 set_jumps(CURRENT_AS(bracket_backtrack
)->u
.condfailed
, LABEL());
6317 SLJIT_ASSERT(!has_alternatives
);
6320 if (has_alternatives
)
6325 current
->top
= NULL
;
6326 current
->topbacktracks
= NULL
;
6327 current
->nextbacktracks
= NULL
;
6330 ccprev
= cc
+ 1 + LINK_SIZE
;
6332 if (opcode
!= OP_COND
&& opcode
!= OP_SCOND
)
6334 if (localptr
!= 0 && opcode
!= OP_ONCE
)
6335 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
6337 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6339 compile_trypath(common
, ccprev
, cc
, current
);
6340 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
6344 /* Instructions after the current alternative is succesfully matched. */
6345 /* There is a similar code in compile_bracket_trypath. */
6346 if (opcode
== OP_ONCE
)
6348 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
< 0)
6350 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
6351 /* TMP2 which is set here used by OP_KETRMAX below. */
6352 if (ket
== OP_KETRMAX
)
6353 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), 0);
6354 else if (ket
== OP_KETRMIN
)
6356 /* Move the STR_PTR to the localptr. */
6357 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), 0);
6362 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_IMM
, (CURRENT_AS(bracket_backtrack
)->u
.framesize
+ 2) * sizeof(sljit_w
));
6363 if (ket
== OP_KETRMAX
)
6365 /* TMP2 which is set here used by OP_KETRMAX below. */
6366 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6372 if (opcode
!= OP_ONCE
)
6374 if (ket
!= OP_KET
|| bra
!= OP_BRA
)
6377 if (stacksize
> 0) {
6378 if (opcode
!= OP_ONCE
|| CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
6379 allocate_stack(common
, stacksize
);
6382 /* We know we have place at least for one item on the top of the stack. */
6383 SLJIT_ASSERT(stacksize
== 1);
6384 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_w
));
6389 if (ket
!= OP_KET
|| bra
!= OP_BRA
)
6392 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), STR_PTR
, 0);
6394 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
6398 if (opcode
!= OP_ONCE
)
6399 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, count
++);
6403 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
);
6404 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
6405 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 0), TMP1
, 0);
6408 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->alttrypath
);
6410 if (opcode
!= OP_ONCE
)
6412 SLJIT_ASSERT(jumplist
);
6413 JUMPHERE(jumplist
->jump
);
6414 jumplist
= jumplist
->next
;
6417 COMPILE_BACKTRACKPATH(current
->top
);
6418 if (current
->topbacktracks
)
6419 set_jumps(current
->topbacktracks
, LABEL());
6420 SLJIT_ASSERT(!current
->nextbacktracks
);
6422 while (*cc
== OP_ALT
);
6423 SLJIT_ASSERT(!jumplist
);
6427 SLJIT_ASSERT(opcode
== OP_COND
|| opcode
== OP_SCOND
);
6428 assert = CURRENT_AS(bracket_backtrack
)->u
.assert;
6429 if ((ccbegin
[1 + LINK_SIZE
] == OP_ASSERT_NOT
|| ccbegin
[1 + LINK_SIZE
] == OP_ASSERTBACK_NOT
) && assert->framesize
>= 0)
6432 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->localptr
);
6433 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6434 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->localptr
, SLJIT_MEM1(STACK_TOP
), assert->framesize
* sizeof(sljit_w
));
6439 /* Free the STR_PTR. */
6441 free_stack(common
, 1);
6446 /* Using both tmp register is better for instruction scheduling. */
6447 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6448 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
6449 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
6450 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), TMP2
, 0);
6451 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), STACK(2));
6452 free_stack(common
, 3);
6454 else if (opcode
== OP_SBRA
|| opcode
== OP_SCOND
)
6456 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), STACK(0));
6457 free_stack(common
, 1);
6459 else if (opcode
== OP_ONCE
)
6461 cc
= ccbegin
+ GET(ccbegin
, 1);
6462 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
6464 /* Reset head and drop saved frame. */
6465 stacksize
= (ket
== OP_KETRMAX
|| ket
== OP_KETRMIN
|| *cc
== OP_ALT
) ? 2 : 1;
6466 free_stack(common
, CURRENT_AS(bracket_backtrack
)->u
.framesize
+ stacksize
);
6468 else if (ket
== OP_KETRMAX
|| (*cc
== OP_ALT
&& ket
!= OP_KETRMIN
))
6470 /* The STR_PTR must be released. */
6471 free_stack(common
, 1);
6475 /* Restore previous localptr */
6476 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
6477 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, SLJIT_MEM1(STACK_TOP
), CURRENT_AS(bracket_backtrack
)->u
.framesize
* sizeof(sljit_w
));
6478 else if (ket
== OP_KETRMIN
)
6480 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
6481 /* See the comment below. */
6482 free_stack(common
, 2);
6483 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), localptr
, TMP1
, 0);
6487 if (ket
== OP_KETRMAX
)
6489 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6490 if (bra
!= OP_BRAZERO
)
6491 free_stack(common
, 1);
6492 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(bracket_backtrack
)->recursivetrypath
);
6493 if (bra
== OP_BRAZERO
)
6495 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
6496 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->zerotrypath
);
6498 free_stack(common
, 1);
6501 else if (ket
== OP_KETRMIN
)
6503 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6505 /* OP_ONCE removes everything in case of a backtrack, so we don't
6506 need to explicitly release the STR_PTR. The extra release would
6507 affect badly the free_stack(2) above. */
6508 if (opcode
!= OP_ONCE
)
6509 free_stack(common
, 1);
6510 CMPTO(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0, rminlabel
);
6511 if (opcode
== OP_ONCE
)
6512 free_stack(common
, bra
== OP_BRAMINZERO
? 2 : 1);
6513 else if (bra
== OP_BRAMINZERO
)
6514 free_stack(common
, 1);
6516 else if (bra
== OP_BRAZERO
)
6518 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6519 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->zerotrypath
);
6524 static void compile_bracketpos_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6528 struct sljit_jump
*jump
;
6530 if (CURRENT_AS(bracketpos_backtrack
)->framesize
< 0)
6532 if (*current
->cc
== OP_CBRAPOS
|| *current
->cc
== OP_SCBRAPOS
)
6534 offset
= (GET2(current
->cc
, 1 + LINK_SIZE
)) << 1;
6535 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6536 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
6537 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
6538 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), TMP2
, 0);
6540 set_jumps(current
->topbacktracks
, LABEL());
6541 free_stack(common
, CURRENT_AS(bracketpos_backtrack
)->stacksize
);
6545 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), CURRENT_AS(bracketpos_backtrack
)->localptr
);
6546 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6548 if (current
->topbacktracks
)
6550 jump
= JUMP(SLJIT_JUMP
);
6551 set_jumps(current
->topbacktracks
, LABEL());
6552 /* Drop the stack frame. */
6553 free_stack(common
, CURRENT_AS(bracketpos_backtrack
)->stacksize
);
6556 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
));
6559 static void compile_braminzero_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6561 assert_backtrack backtrack
;
6563 current
->top
= NULL
;
6564 current
->topbacktracks
= NULL
;
6565 current
->nextbacktracks
= NULL
;
6566 if (current
->cc
[1] > OP_ASSERTBACK_NOT
)
6568 /* Manual call of compile_bracket_trypath and compile_bracket_backtrackpath. */
6569 compile_bracket_trypath(common
, current
->cc
, current
);
6570 compile_bracket_backtrackpath(common
, current
->top
);
6574 memset(&backtrack
, 0, sizeof(backtrack
));
6575 backtrack
.common
.cc
= current
->cc
;
6576 backtrack
.trypath
= CURRENT_AS(braminzero_backtrack
)->trypath
;
6577 /* Manual call of compile_assert_trypath. */
6578 compile_assert_trypath(common
, current
->cc
, &backtrack
, FALSE
);
6580 SLJIT_ASSERT(!current
->nextbacktracks
&& !current
->topbacktracks
);
6583 static void compile_backtrackpath(compiler_common
*common
, struct backtrack_common
*current
)
6589 if (current
->nextbacktracks
!= NULL
)
6590 set_jumps(current
->nextbacktracks
, LABEL());
6591 switch(*current
->cc
)
6594 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6595 free_stack(common
, 1);
6596 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), TMP1
, 0);
6630 case OP_NOTMINQUERY
:
6636 case OP_NOTPOSQUERY
:
6639 case OP_NOTMINSTARI
:
6641 case OP_NOTMINPLUSI
:
6643 case OP_NOTMINQUERYI
:
6645 case OP_NOTMINUPTOI
:
6647 case OP_NOTPOSSTARI
:
6648 case OP_NOTPOSPLUSI
:
6649 case OP_NOTPOSQUERYI
:
6650 case OP_NOTPOSUPTOI
:
6652 case OP_TYPEMINSTAR
:
6654 case OP_TYPEMINPLUS
:
6656 case OP_TYPEMINQUERY
:
6658 case OP_TYPEMINUPTO
:
6660 case OP_TYPEPOSSTAR
:
6661 case OP_TYPEPOSPLUS
:
6662 case OP_TYPEPOSQUERY
:
6663 case OP_TYPEPOSUPTO
:
6666 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
6669 compile_iterator_backtrackpath(common
, current
);
6674 compile_ref_iterator_backtrackpath(common
, current
);
6678 compile_recurse_backtrackpath(common
, current
);
6684 case OP_ASSERTBACK_NOT
:
6685 compile_assert_backtrackpath(common
, current
);
6696 compile_bracket_backtrackpath(common
, current
);
6700 if (current
->cc
[1] > OP_ASSERTBACK_NOT
)
6701 compile_bracket_backtrackpath(common
, current
);
6703 compile_assert_backtrackpath(common
, current
);
6711 compile_bracketpos_backtrackpath(common
, current
);
6715 compile_braminzero_backtrackpath(common
, current
);
6719 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6720 free_stack(common
, 1);
6721 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP1
, 0);
6725 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_NOMATCH
);
6726 if (common
->leavelabel
== NULL
)
6727 add_jump(compiler
, &common
->leave
, JUMP(SLJIT_JUMP
));
6729 JUMPTO(SLJIT_JUMP
, common
->leavelabel
);
6734 case OP_ASSERT_ACCEPT
:
6735 set_jumps(current
->topbacktracks
, LABEL());
6739 SLJIT_ASSERT_STOP();
6742 current
= current
->prev
;
6746 static SLJIT_INLINE
void compile_recurse(compiler_common
*common
)
6749 pcre_uchar
*cc
= common
->start
+ common
->currententry
->start
;
6750 pcre_uchar
*ccbegin
= cc
+ 1 + LINK_SIZE
+ (*cc
== OP_BRA
? 0 : IMM2_SIZE
);
6751 pcre_uchar
*ccend
= bracketend(cc
);
6752 int localsize
= get_localsize(common
, ccbegin
, ccend
);
6753 int framesize
= get_framesize(common
, cc
, TRUE
);
6754 int alternativesize
;
6756 backtrack_common altbacktrack
;
6757 struct sljit_label
*save_leavelabel
= common
->leavelabel
;
6758 jump_list
*save_leave
= common
->leave
;
6759 struct sljit_jump
*jump
;
6761 SLJIT_ASSERT(*cc
== OP_BRA
|| *cc
== OP_CBRA
|| *cc
== OP_CBRAPOS
|| *cc
== OP_SCBRA
|| *cc
== OP_SCBRAPOS
);
6762 needsframe
= framesize
>= 0;
6765 alternativesize
= *(cc
+ GET(cc
, 1)) == OP_ALT
? 1 : 0;
6767 SLJIT_ASSERT(common
->currententry
->entry
== NULL
&& common
->recursive_head
!= 0);
6768 common
->currententry
->entry
= LABEL();
6769 set_jumps(common
->currententry
->calls
, common
->currententry
->entry
);
6771 sljit_emit_fast_enter(compiler
, TMP2
, 0);
6772 allocate_stack(common
, localsize
+ framesize
+ alternativesize
);
6773 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(localsize
+ framesize
+ alternativesize
- 1), TMP2
, 0);
6774 copy_locals(common
, ccbegin
, ccend
, TRUE
, localsize
+ framesize
+ alternativesize
, framesize
+ alternativesize
);
6775 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->recursive_head
, STACK_TOP
, 0);
6777 init_frame(common
, cc
, framesize
+ alternativesize
- 1, alternativesize
, TRUE
);
6779 if (alternativesize
> 0)
6780 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
6782 memset(&altbacktrack
, 0, sizeof(backtrack_common
));
6783 common
->leavelabel
= NULL
;
6784 common
->acceptlabel
= NULL
;
6785 common
->leave
= NULL
;
6786 common
->accept
= NULL
;
6787 altbacktrack
.cc
= ccbegin
;
6791 altbacktrack
.top
= NULL
;
6792 altbacktrack
.topbacktracks
= NULL
;
6794 if (altbacktrack
.cc
!= ccbegin
)
6795 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6797 compile_trypath(common
, altbacktrack
.cc
, cc
, &altbacktrack
);
6798 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
6800 common
->leavelabel
= save_leavelabel
;
6801 common
->leave
= save_leave
;
6805 add_jump(compiler
, &common
->accept
, JUMP(SLJIT_JUMP
));
6807 compile_backtrackpath(common
, altbacktrack
.top
);
6808 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
6810 common
->leavelabel
= save_leavelabel
;
6811 common
->leave
= save_leave
;
6814 set_jumps(altbacktrack
.topbacktracks
, LABEL());
6819 altbacktrack
.cc
= cc
+ 1 + LINK_SIZE
;
6822 /* None of them matched. */
6823 if (common
->leave
!= NULL
)
6824 set_jumps(common
->leave
, LABEL());
6826 OP1(SLJIT_MOV
, TMP3
, 0, SLJIT_IMM
, 0);
6827 jump
= JUMP(SLJIT_JUMP
);
6829 set_jumps(common
->accept
, LABEL());
6830 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->recursive_head
);
6833 OP2(SLJIT_SUB
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, (framesize
+ alternativesize
) * sizeof(sljit_w
));
6834 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
6835 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, (framesize
+ alternativesize
) * sizeof(sljit_w
));
6837 OP1(SLJIT_MOV
, TMP3
, 0, SLJIT_IMM
, 1);
6840 copy_locals(common
, ccbegin
, ccend
, FALSE
, localsize
+ framesize
+ alternativesize
, framesize
+ alternativesize
);
6841 free_stack(common
, localsize
+ framesize
+ alternativesize
);
6842 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), sizeof(sljit_w
));
6843 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
6844 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->recursive_head
, TMP2
, 0);
6845 sljit_emit_fast_return(compiler
, SLJIT_MEM1(STACK_TOP
), 0);
6847 common
->leavelabel
= save_leavelabel
;
6848 common
->leave
= save_leave
;
6851 #undef COMPILE_BACKTRACKPATH
6855 PRIV(jit_compile
)(const REAL_PCRE
*re
, PUBL(extra
) *extra
, int mode
)
6857 struct sljit_compiler
*compiler
;
6858 backtrack_common rootbacktrack
;
6859 compiler_common common_data
;
6860 compiler_common
*common
= &common_data
;
6861 const pcre_uint8
*tables
= re
->tables
;
6862 pcre_study_data
*study
;
6865 executable_functions
*functions
;
6866 void *executable_func
;
6867 sljit_uw executable_size
;
6868 struct sljit_label
*mainloop
= NULL
;
6869 struct sljit_label
*empty_match_found
;
6870 struct sljit_label
*empty_match_backtrack
;
6871 struct sljit_jump
*jump
;
6872 struct sljit_jump
*reqbyte_notfound
= NULL
;
6873 struct sljit_jump
*empty_match
;
6875 SLJIT_ASSERT((extra
->flags
& PCRE_EXTRA_STUDY_DATA
) != 0);
6876 study
= extra
->study_data
;
6879 tables
= PRIV(default_tables
);
6881 memset(&rootbacktrack
, 0, sizeof(backtrack_common
));
6882 memset(common
, 0, sizeof(compiler_common
));
6883 rootbacktrack
.cc
= (pcre_uchar
*)re
+ re
->name_table_offset
+ re
->name_count
* re
->name_entry_size
;
6885 common
->start
= rootbacktrack
.cc
;
6886 common
->fcc
= tables
+ fcc_offset
;
6887 common
->lcc
= (sljit_w
)(tables
+ lcc_offset
);
6888 common
->mode
= mode
;
6889 common
->nltype
= NLTYPE_FIXED
;
6890 switch(re
->options
& PCRE_NEWLINE_BITS
)
6893 /* Compile-time default */
6896 case -1: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANY
; break;
6897 case -2: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANYCRLF
; break;
6898 default: common
->newline
= NEWLINE
; break;
6901 case PCRE_NEWLINE_CR
: common
->newline
= CHAR_CR
; break;
6902 case PCRE_NEWLINE_LF
: common
->newline
= CHAR_NL
; break;
6903 case PCRE_NEWLINE_CR
+
6904 PCRE_NEWLINE_LF
: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; break;
6905 case PCRE_NEWLINE_ANY
: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANY
; break;
6906 case PCRE_NEWLINE_ANYCRLF
: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANYCRLF
; break;
6909 if ((re
->options
& PCRE_BSR_ANYCRLF
) != 0)
6910 common
->bsr_nltype
= NLTYPE_ANYCRLF
;
6911 else if ((re
->options
& PCRE_BSR_UNICODE
) != 0)
6912 common
->bsr_nltype
= NLTYPE_ANY
;
6916 common
->bsr_nltype
= NLTYPE_ANYCRLF
;
6918 common
->bsr_nltype
= NLTYPE_ANY
;
6921 common
->endonly
= (re
->options
& PCRE_DOLLAR_ENDONLY
) != 0;
6922 common
->ctypes
= (sljit_w
)(tables
+ ctypes_offset
);
6923 common
->name_table
= (sljit_w
)((pcre_uchar
*)re
+ re
->name_table_offset
);
6924 common
->name_count
= re
->name_count
;
6925 common
->name_entry_size
= re
->name_entry_size
;
6926 common
->jscript_compat
= (re
->options
& PCRE_JAVASCRIPT_COMPAT
) != 0;
6928 /* PCRE_UTF16 has the same value as PCRE_UTF8. */
6929 common
->utf
= (re
->options
& PCRE_UTF8
) != 0;
6931 common
->use_ucp
= (re
->options
& PCRE_UCP
) != 0;
6933 #endif /* SUPPORT_UTF */
6934 ccend
= bracketend(rootbacktrack
.cc
);
6936 /* Calculate the local space size on the stack. */
6937 common
->ovector_start
= CALL_LIMIT
+ sizeof(sljit_w
);
6939 SLJIT_ASSERT(*rootbacktrack
.cc
== OP_BRA
&& ccend
[-(1 + LINK_SIZE
)] == OP_KET
);
6940 localsize
= get_localspace(common
, rootbacktrack
.cc
, ccend
);
6944 /* Checking flags and updating ovector_start. */
6945 if (mode
== JIT_COMPILE
&& (re
->flags
& PCRE_REQCHSET
) != 0 && (re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
6947 common
->req_char_ptr
= common
->ovector_start
;
6948 common
->ovector_start
+= sizeof(sljit_w
);
6950 if (mode
!= JIT_COMPILE
)
6952 common
->start_used_ptr
= common
->ovector_start
;
6953 common
->ovector_start
+= sizeof(sljit_w
);
6954 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
6956 common
->hit_start
= common
->ovector_start
;
6957 common
->ovector_start
+= sizeof(sljit_w
);
6960 if ((re
->options
& PCRE_FIRSTLINE
) != 0)
6962 common
->first_line_end
= common
->ovector_start
;
6963 common
->ovector_start
+= sizeof(sljit_w
);
6966 /* Aligning ovector to even number of sljit words. */
6967 if ((common
->ovector_start
& sizeof(sljit_w
)) != 0)
6968 common
->ovector_start
+= sizeof(sljit_w
);
6970 SLJIT_ASSERT(!(common
->req_char_ptr
!= 0 && common
->start_used_ptr
!= 0));
6971 common
->cbraptr
= OVECTOR_START
+ (re
->top_bracket
+ 1) * 2 * sizeof(sljit_w
);
6972 localsize
+= common
->cbraptr
+ (re
->top_bracket
+ 1) * sizeof(sljit_w
);
6973 if (localsize
> SLJIT_MAX_LOCAL_SIZE
)
6975 common
->localptrs
= (int *)SLJIT_MALLOC((ccend
- rootbacktrack
.cc
) * sizeof(int));
6976 if (!common
->localptrs
)
6978 memset(common
->localptrs
, 0, (ccend
- rootbacktrack
.cc
) * sizeof(int));
6979 set_localptrs(common
, common
->cbraptr
+ (re
->top_bracket
+ 1) * sizeof(sljit_w
), ccend
);
6981 compiler
= sljit_create_compiler();
6984 SLJIT_FREE(common
->localptrs
);
6987 common
->compiler
= compiler
;
6989 /* Main pcre_jit_exec entry. */
6990 sljit_emit_enter(compiler
, 1, 5, 5, localsize
);
6992 /* Register init. */
6993 reset_ovector(common
, (re
->top_bracket
+ 1) * 2);
6994 if (common
->req_char_ptr
!= 0)
6995 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->req_char_ptr
, SLJIT_TEMPORARY_REG1
, 0);
6997 OP1(SLJIT_MOV
, ARGUMENTS
, 0, SLJIT_SAVED_REG1
, 0);
6998 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_SAVED_REG1
, 0);
6999 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
7000 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, end
));
7001 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, stack
));
7002 OP1(SLJIT_MOV_SI
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, calllimit
));
7003 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(struct sljit_stack
, base
));
7004 OP1(SLJIT_MOV
, STACK_LIMIT
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(struct sljit_stack
, limit
));
7005 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), CALL_LIMIT
, TMP1
, 0);
7007 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
7008 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, 0);
7010 /* Main part of the matching */
7011 if ((re
->options
& PCRE_ANCHORED
) == 0)
7013 mainloop
= mainloop_entry(common
, (re
->flags
& PCRE_HASCRORLF
) != 0, (re
->options
& PCRE_FIRSTLINE
) != 0);
7014 /* Forward search if possible. */
7015 if ((re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
7017 if ((re
->flags
& PCRE_FIRSTSET
) != 0)
7018 fast_forward_first_char(common
, (pcre_uchar
)re
->first_char
, (re
->flags
& PCRE_FCH_CASELESS
) != 0, (re
->options
& PCRE_FIRSTLINE
) != 0);
7019 else if ((re
->flags
& PCRE_STARTLINE
) != 0)
7020 fast_forward_newline(common
, (re
->options
& PCRE_FIRSTLINE
) != 0);
7021 else if ((re
->flags
& PCRE_STARTLINE
) == 0 && study
!= NULL
&& (study
->flags
& PCRE_STUDY_MAPPED
) != 0)
7022 fast_forward_start_bits(common
, (sljit_uw
)study
->start_bits
, (re
->options
& PCRE_FIRSTLINE
) != 0);
7025 if (common
->req_char_ptr
!= 0)
7026 reqbyte_notfound
= search_requested_char(common
, (pcre_uchar
)re
->req_char
, (re
->flags
& PCRE_RCH_CASELESS
) != 0, (re
->flags
& PCRE_FIRSTSET
) != 0);
7028 /* Store the current STR_PTR in OVECTOR(0). */
7029 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), STR_PTR
, 0);
7030 /* Copy the limit of allowed recursions. */
7031 OP1(SLJIT_MOV
, CALL_COUNT
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), CALL_LIMIT
);
7032 if (common
->mark_ptr
!= 0)
7033 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, SLJIT_IMM
, 0);
7034 /* Copy the beginning of the string. */
7035 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
7037 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, 0);
7038 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
7041 else if (mode
== JIT_PARTIAL_HARD_COMPILE
)
7042 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
7044 compile_trypath(common
, rootbacktrack
.cc
, ccend
, &rootbacktrack
);
7045 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
7047 sljit_free_compiler(compiler
);
7048 SLJIT_FREE(common
->localptrs
);
7052 empty_match
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
7053 empty_match_found
= LABEL();
7055 common
->acceptlabel
= LABEL();
7056 if (common
->accept
!= NULL
)
7057 set_jumps(common
->accept
, common
->acceptlabel
);
7059 /* This means we have a match. Update the ovector. */
7060 copy_ovector(common
, re
->top_bracket
+ 1);
7061 common
->leavelabel
= LABEL();
7062 if (common
->leave
!= NULL
)
7063 set_jumps(common
->leave
, common
->leavelabel
);
7064 sljit_emit_return(compiler
, SLJIT_MOV
, SLJIT_RETURN_REG
, 0);
7066 if (mode
!= JIT_COMPILE
)
7068 common
->partialmatchlabel
= LABEL();
7069 set_jumps(common
->partialmatch
, common
->partialmatchlabel
);
7070 return_with_partial_match(common
, common
->leavelabel
);
7073 empty_match_backtrack
= LABEL();
7074 compile_backtrackpath(common
, rootbacktrack
.top
);
7075 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
7077 sljit_free_compiler(compiler
);
7078 SLJIT_FREE(common
->localptrs
);
7082 SLJIT_ASSERT(rootbacktrack
.prev
== NULL
);
7084 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
7086 /* Update hit_start only in the first time. */
7087 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
7088 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
);
7089 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, SLJIT_IMM
, -1);
7090 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, TMP1
, 0);
7094 /* Check we have remaining characters. */
7095 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
7097 if ((re
->options
& PCRE_ANCHORED
) == 0)
7099 if ((re
->options
& PCRE_FIRSTLINE
) == 0)
7101 if (mode
== JIT_COMPILE
&& study
!= NULL
&& study
->minlength
> 1 && (re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
7103 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(study
->minlength
+ 1));
7104 CMPTO(SLJIT_C_LESS_EQUAL
, TMP1
, 0, STR_END
, 0, mainloop
);
7107 CMPTO(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0, mainloop
);
7111 SLJIT_ASSERT(common
->first_line_end
!= 0);
7112 if (mode
== JIT_COMPILE
&& study
!= NULL
&& study
->minlength
> 1 && (re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
7114 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(study
->minlength
+ 1));
7115 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, STR_END
, 0);
7116 COND_VALUE(SLJIT_MOV
, TMP2
, 0, SLJIT_C_GREATER
);
7117 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
7118 COND_VALUE(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, SLJIT_C_GREATER_EQUAL
);
7119 JUMPTO(SLJIT_C_ZERO
, mainloop
);
7122 CMPTO(SLJIT_C_LESS
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, mainloop
);
7126 /* No more remaining characters. */
7127 if (reqbyte_notfound
!= NULL
)
7128 JUMPHERE(reqbyte_notfound
);
7130 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
7131 CMPTO(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, 0, common
->partialmatchlabel
);
7133 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_NOMATCH
);
7134 JUMPTO(SLJIT_JUMP
, common
->leavelabel
);
7136 flush_stubs(common
);
7138 JUMPHERE(empty_match
);
7139 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
7140 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty
));
7141 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0, empty_match_backtrack
);
7142 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty_atstart
));
7143 CMPTO(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0, empty_match_found
);
7144 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
7145 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0, empty_match_found
);
7146 JUMPTO(SLJIT_JUMP
, empty_match_backtrack
);
7148 common
->currententry
= common
->entries
;
7149 while (common
->currententry
!= NULL
)
7151 /* Might add new entries. */
7152 compile_recurse(common
);
7153 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
7155 sljit_free_compiler(compiler
);
7156 SLJIT_FREE(common
->localptrs
);
7159 flush_stubs(common
);
7160 common
->currententry
= common
->currententry
->next
;
7163 /* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */
7164 /* This is a (really) rare case. */
7165 set_jumps(common
->stackalloc
, LABEL());
7166 /* RETURN_ADDR is not a saved register. */
7167 sljit_emit_fast_enter(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
7168 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP2
, 0);
7169 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
7170 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, stack
));
7171 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, top
), STACK_TOP
, 0);
7172 OP2(SLJIT_ADD
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, limit
), SLJIT_IMM
, STACK_GROWTH_RATE
);
7174 sljit_emit_ijump(compiler
, SLJIT_CALL2
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(sljit_stack_resize
));
7175 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 0);
7176 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
7177 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, stack
));
7178 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, top
));
7179 OP1(SLJIT_MOV
, STACK_LIMIT
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, limit
));
7180 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
7181 sljit_emit_fast_return(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
7183 /* Allocation failed. */
7185 /* We break the return address cache here, but this is a really rare case. */
7186 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_JIT_STACKLIMIT
);
7187 JUMPTO(SLJIT_JUMP
, common
->leavelabel
);
7189 /* Call limit reached. */
7190 set_jumps(common
->calllimit
, LABEL());
7191 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_MATCHLIMIT
);
7192 JUMPTO(SLJIT_JUMP
, common
->leavelabel
);
7194 if (common
->revertframes
!= NULL
)
7196 set_jumps(common
->revertframes
, LABEL());
7197 do_revertframes(common
);
7199 if (common
->wordboundary
!= NULL
)
7201 set_jumps(common
->wordboundary
, LABEL());
7202 check_wordboundary(common
);
7204 if (common
->anynewline
!= NULL
)
7206 set_jumps(common
->anynewline
, LABEL());
7207 check_anynewline(common
);
7209 if (common
->hspace
!= NULL
)
7211 set_jumps(common
->hspace
, LABEL());
7212 check_hspace(common
);
7214 if (common
->vspace
!= NULL
)
7216 set_jumps(common
->vspace
, LABEL());
7217 check_vspace(common
);
7219 if (common
->casefulcmp
!= NULL
)
7221 set_jumps(common
->casefulcmp
, LABEL());
7222 do_casefulcmp(common
);
7224 if (common
->caselesscmp
!= NULL
)
7226 set_jumps(common
->caselesscmp
, LABEL());
7227 do_caselesscmp(common
);
7230 if (common
->utfreadchar
!= NULL
)
7232 set_jumps(common
->utfreadchar
, LABEL());
7233 do_utfreadchar(common
);
7235 #ifdef COMPILE_PCRE8
7236 if (common
->utfreadtype8
!= NULL
)
7238 set_jumps(common
->utfreadtype8
, LABEL());
7239 do_utfreadtype8(common
);
7242 #endif /* COMPILE_PCRE8 */
7244 if (common
->getunichartype
!= NULL
)
7246 set_jumps(common
->getunichartype
, LABEL());
7247 do_getunichartype(common
);
7249 if (common
->getunichartype_2
!= NULL
)
7251 set_jumps(common
->getunichartype_2
, LABEL());
7252 do_getunichartype_2(common
);
7254 if (common
->getunicharscript
!= NULL
)
7256 set_jumps(common
->getunicharscript
, LABEL());
7257 do_getunicharscript(common
);
7261 SLJIT_FREE(common
->localptrs
);
7262 executable_func
= sljit_generate_code(compiler
);
7263 executable_size
= sljit_get_generated_code_size(compiler
);
7264 sljit_free_compiler(compiler
);
7265 if (executable_func
== NULL
)
7268 /* Reuse the function descriptor if possible. */
7269 if ((extra
->flags
& PCRE_EXTRA_EXECUTABLE_JIT
) != 0 && extra
->executable_jit
!= NULL
)
7270 functions
= (executable_functions
*)extra
->executable_jit
;
7273 functions
= SLJIT_MALLOC(sizeof(executable_functions
));
7274 if (functions
== NULL
)
7276 /* This case is highly unlikely since we just recently
7277 freed a lot of memory. Although not impossible. */
7278 sljit_free_code(executable_func
);
7281 memset(functions
, 0, sizeof(executable_functions
));
7282 extra
->executable_jit
= functions
;
7283 extra
->flags
|= PCRE_EXTRA_EXECUTABLE_JIT
;
7286 functions
->executable_funcs
[mode
] = executable_func
;
7287 functions
->executable_sizes
[mode
] = executable_size
;
7290 static int jit_machine_stack_exec(jit_arguments
*arguments
, void* executable_func
)
7293 void* executable_func
;
7294 jit_function call_executable_func
;
7295 } convert_executable_func
;
7296 pcre_uint8 local_area
[LOCAL_SPACE_SIZE
];
7297 struct sljit_stack local_stack
;
7299 local_stack
.top
= (sljit_w
)&local_area
;
7300 local_stack
.base
= local_stack
.top
;
7301 local_stack
.limit
= local_stack
.base
+ LOCAL_SPACE_SIZE
;
7302 local_stack
.max_limit
= local_stack
.limit
;
7303 arguments
->stack
= &local_stack
;
7304 convert_executable_func
.executable_func
= executable_func
;
7305 return convert_executable_func
.call_executable_func(arguments
);
7309 PRIV(jit_exec
)(const REAL_PCRE
*re
, const PUBL(extra
) *extra_data
, const pcre_uchar
*subject
,
7310 int length
, int start_offset
, int options
, int *offsets
, int offsetcount
)
7312 executable_functions
*functions
= (executable_functions
*)extra_data
->executable_jit
;
7314 void* executable_func
;
7315 jit_function call_executable_func
;
7316 } convert_executable_func
;
7317 jit_arguments arguments
;
7320 int mode
= JIT_COMPILE
;
7322 if ((options
& PCRE_PARTIAL_HARD
) != 0)
7323 mode
= JIT_PARTIAL_HARD_COMPILE
;
7324 else if ((options
& PCRE_PARTIAL_SOFT
) != 0)
7325 mode
= JIT_PARTIAL_SOFT_COMPILE
;
7327 if (functions
->executable_funcs
[mode
] == NULL
)
7328 return PCRE_ERROR_NULL
;
7330 /* Sanity checks should be handled by pcre_exec. */
7331 arguments
.stack
= NULL
;
7332 arguments
.str
= subject
+ start_offset
;
7333 arguments
.begin
= subject
;
7334 arguments
.end
= subject
+ length
;
7335 arguments
.mark_ptr
= NULL
;
7336 /* JIT decreases this value less frequently than the interpreter. */
7337 arguments
.calllimit
= ((extra_data
->flags
& PCRE_EXTRA_MATCH_LIMIT
) == 0) ? MATCH_LIMIT
: extra_data
->match_limit
;
7338 arguments
.notbol
= (options
& PCRE_NOTBOL
) != 0;
7339 arguments
.noteol
= (options
& PCRE_NOTEOL
) != 0;
7340 arguments
.notempty
= (options
& PCRE_NOTEMPTY
) != 0;
7341 arguments
.notempty_atstart
= (options
& PCRE_NOTEMPTY_ATSTART
) != 0;
7342 arguments
.offsets
= offsets
;
7344 /* pcre_exec() rounds offsetcount to a multiple of 3, and then uses only 2/3 of
7345 the output vector for storing captured strings, with the remainder used as
7346 workspace. We don't need the workspace here. For compatibility, we limit the
7347 number of captured strings in the same way as pcre_exec(), so that the user
7348 gets the same result with and without JIT. */
7350 if (offsetcount
!= 2)
7351 offsetcount
= ((offsetcount
- (offsetcount
% 3)) * 2) / 3;
7352 maxoffsetcount
= (re
->top_bracket
+ 1) * 2;
7353 if (offsetcount
> maxoffsetcount
)
7354 offsetcount
= maxoffsetcount
;
7355 arguments
.offsetcount
= offsetcount
;
7357 if (functions
->callback
)
7358 arguments
.stack
= (struct sljit_stack
*)functions
->callback(functions
->userdata
);
7360 arguments
.stack
= (struct sljit_stack
*)functions
->userdata
;
7362 if (arguments
.stack
== NULL
)
7363 retval
= jit_machine_stack_exec(&arguments
, functions
->executable_funcs
[mode
]);
7366 convert_executable_func
.executable_func
= functions
->executable_funcs
[mode
];
7367 retval
= convert_executable_func
.call_executable_func(&arguments
);
7370 if (retval
* 2 > offsetcount
)
7372 if ((extra_data
->flags
& PCRE_EXTRA_MARK
) != 0)
7373 *(extra_data
->mark
) = arguments
.mark_ptr
;
7379 PRIV(jit_free
)(void *executable_funcs
)
7382 executable_functions
*functions
= (executable_functions
*)executable_funcs
;
7383 for (i
= 0; i
< JIT_NUMBER_OF_COMPILE_MODES
; i
++)
7385 if (functions
->executable_funcs
[i
] != NULL
)
7386 sljit_free_code(functions
->executable_funcs
[i
]);
7388 SLJIT_FREE(functions
);
7392 PRIV(jit_get_size
)(void *executable_funcs
)
7396 sljit_uw
*executable_sizes
= ((executable_functions
*)executable_funcs
)->executable_sizes
;
7397 for (i
= 0; i
< JIT_NUMBER_OF_COMPILE_MODES
; i
++)
7398 size
+= executable_sizes
[i
];
7403 PRIV(jit_get_target
)(void)
7405 return sljit_get_platform_name();
7408 #ifdef COMPILE_PCRE8
7409 PCRE_EXP_DECL pcre_jit_stack
*
7410 pcre_jit_stack_alloc(int startsize
, int maxsize
)
7412 PCRE_EXP_DECL pcre16_jit_stack
*
7413 pcre16_jit_stack_alloc(int startsize
, int maxsize
)
7416 if (startsize
< 1 || maxsize
< 1)
7418 if (startsize
> maxsize
)
7419 startsize
= maxsize
;
7420 startsize
= (startsize
+ STACK_GROWTH_RATE
- 1) & ~(STACK_GROWTH_RATE
- 1);
7421 maxsize
= (maxsize
+ STACK_GROWTH_RATE
- 1) & ~(STACK_GROWTH_RATE
- 1);
7422 return (PUBL(jit_stack
)*)sljit_allocate_stack(startsize
, maxsize
);
7425 #ifdef COMPILE_PCRE8
7427 pcre_jit_stack_free(pcre_jit_stack
*stack
)
7430 pcre16_jit_stack_free(pcre16_jit_stack
*stack
)
7433 sljit_free_stack((struct sljit_stack
*)stack
);
7436 #ifdef COMPILE_PCRE8
7438 pcre_assign_jit_stack(pcre_extra
*extra
, pcre_jit_callback callback
, void *userdata
)
7441 pcre16_assign_jit_stack(pcre16_extra
*extra
, pcre16_jit_callback callback
, void *userdata
)
7444 executable_functions
*functions
;
7445 if (extra
!= NULL
&&
7446 (extra
->flags
& PCRE_EXTRA_EXECUTABLE_JIT
) != 0 &&
7447 extra
->executable_jit
!= NULL
)
7449 functions
= (executable_functions
*)extra
->executable_jit
;
7450 functions
->callback
= callback
;
7451 functions
->userdata
= userdata
;
7455 #else /* SUPPORT_JIT */
7457 /* These are dummy functions to avoid linking errors when JIT support is not
7460 #ifdef COMPILE_PCRE8
7461 PCRE_EXP_DECL pcre_jit_stack
*
7462 pcre_jit_stack_alloc(int startsize
, int maxsize
)
7464 PCRE_EXP_DECL pcre16_jit_stack
*
7465 pcre16_jit_stack_alloc(int startsize
, int maxsize
)
7473 #ifdef COMPILE_PCRE8
7475 pcre_jit_stack_free(pcre_jit_stack
*stack
)
7478 pcre16_jit_stack_free(pcre16_jit_stack
*stack
)
7484 #ifdef COMPILE_PCRE8
7486 pcre_assign_jit_stack(pcre_extra
*extra
, pcre_jit_callback callback
, void *userdata
)
7489 pcre16_assign_jit_stack(pcre16_extra
*extra
, pcre16_jit_callback callback
, void *userdata
)
7499 /* End of pcre_jit_compile.c */