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"
49 #if defined SUPPORT_JIT
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 for the regex stack on the real machine stack.
69 Fast, but limited size. */
70 #define MACHINE_STACK_SIZE 32768
72 /* Growth rate for stack allocated by the OS. Should be the multiply
74 #define STACK_GROWTH_RATE 8192
76 /* Enable to check that the allocation could destroy temporaries. */
77 #if defined SLJIT_DEBUG && SLJIT_DEBUG
78 #define DESTROY_REGISTERS 1
82 Short summary about the backtracking mechanism empolyed by the jit code generator:
84 The code generator follows the recursive nature of the PERL compatible regular
85 expressions. The basic blocks of regular expressions are condition checkers
86 whose execute different commands depending on the result of the condition check.
87 The relationship between the operators can be horizontal (concatenation) and
88 vertical (sub-expression) (See struct backtrack_common for more details).
90 'ab' - 'a' and 'b' regexps are concatenated
91 'a+' - 'a' is the sub-expression of the '+' operator
93 The condition checkers are boolean (true/false) checkers. Machine code is generated
94 for the checker itself and for the actions depending on the result of the checker.
95 The 'true' case is called as the matching path (expected path), and the other is called as
96 the 'backtrack' path. Branch instructions are expesive for all CPUs, so we avoid taken
97 branches on the matching path.
99 Greedy star operator (*) :
100 Matching path: match happens.
101 Backtrack path: match failed.
102 Non-greedy star operator (*?) :
103 Matching path: no need to perform a match.
104 Backtrack path: match is required.
106 The following example shows how the code generated for a capturing bracket
107 with two alternatives. Let A, B, C, D are arbirary regular expressions, and
108 we have the following regular expression:
112 The generated code will be the following:
115 '(' matching path (pushing arguments to the stack)
117 ')' matching path (pushing arguments to the stack)
119 return with successful match
122 ')' backtrack path (If we arrived from "C" jump to the backtrack of "C")
125 jump to D matching path
129 Notice, that the order of backtrack code paths are the opposite of the fast
130 code paths. In this way the topmost value on the stack is always belong
131 to the current backtrack code path. The backtrack path must check
132 whether there is a next alternative. If so, it needs to jump back to
133 the matching path eventually. Otherwise it needs to clear out its own stack
134 frame and continue the execution on the backtrack code paths.
140 Atomic blocks and asserts require reloading the values of private data
141 when the backtrack mechanism performed. Because of OP_RECURSE, the data
142 are not necessarly known in compile time, thus we need a dynamic restore
145 The stack frames are stored in a chain list, and have the following format:
146 ([ capturing bracket offset ][ start value ][ end value ])+ ... [ 0 ] [ previous head ]
148 Thus we can restore the private data to a particular point in the stack.
151 typedef struct jit_arguments
{
152 /* Pointers first. */
153 struct sljit_stack
*stack
;
154 const pcre_uchar
*str
;
155 const pcre_uchar
*begin
;
156 const pcre_uchar
*end
;
158 pcre_uchar
*uchar_ptr
;
159 pcre_uchar
*mark_ptr
;
160 /* Everything else after. */
166 pcre_uint8 notempty_atstart
;
169 typedef struct executable_functions
{
170 void *executable_funcs
[JIT_NUMBER_OF_COMPILE_MODES
];
171 PUBL(jit_callback
) callback
;
173 pcre_uint32 top_bracket
;
174 sljit_uw executable_sizes
[JIT_NUMBER_OF_COMPILE_MODES
];
175 } executable_functions
;
177 typedef struct jump_list
{
178 struct sljit_jump
*jump
;
179 struct jump_list
*next
;
182 enum stub_types
{ stack_alloc
};
184 typedef struct stub_list
{
185 enum stub_types type
;
187 struct sljit_jump
*start
;
188 struct sljit_label
*quit
;
189 struct stub_list
*next
;
192 typedef int (SLJIT_CALL
*jit_function
)(jit_arguments
*args
);
194 /* The following structure is the key data type for the recursive
195 code generator. It is allocated by compile_matchingpath, and contains
196 the aguments for compile_backtrackingpath. Must be the first member
197 of its descendants. */
198 typedef struct backtrack_common
{
199 /* Concatenation stack. */
200 struct backtrack_common
*prev
;
201 jump_list
*nextbacktracks
;
202 /* Internal stack (for component operators). */
203 struct backtrack_common
*top
;
204 jump_list
*topbacktracks
;
205 /* Opcode pointer. */
209 typedef struct assert_backtrack
{
210 backtrack_common common
;
211 jump_list
*condfailed
;
212 /* Less than 0 (-1) if a frame is not needed. */
214 /* Points to our private memory word on the stack. */
215 int private_data_ptr
;
217 struct sljit_label
*matchingpath
;
220 typedef struct bracket_backtrack
{
221 backtrack_common common
;
222 /* Where to coninue if an alternative is successfully matched. */
223 struct sljit_label
*alternative_matchingpath
;
224 /* For rmin and rmax iterators. */
225 struct sljit_label
*recursive_matchingpath
;
226 /* For greedy ? operator. */
227 struct sljit_label
*zero_matchingpath
;
228 /* Contains the branches of a failed condition. */
230 /* Both for OP_COND, OP_SCOND. */
231 jump_list
*condfailed
;
232 assert_backtrack
*assert;
233 /* For OP_ONCE. -1 if not needed. */
236 /* Points to our private memory word on the stack. */
237 int private_data_ptr
;
240 typedef struct bracketpos_backtrack
{
241 backtrack_common common
;
242 /* Points to our private memory word on the stack. */
243 int private_data_ptr
;
244 /* Reverting stack is needed. */
246 /* Allocated stack size. */
248 } bracketpos_backtrack
;
250 typedef struct braminzero_backtrack
{
251 backtrack_common common
;
252 struct sljit_label
*matchingpath
;
253 } braminzero_backtrack
;
255 typedef struct iterator_backtrack
{
256 backtrack_common common
;
257 /* Next iteration. */
258 struct sljit_label
*matchingpath
;
259 } iterator_backtrack
;
261 typedef struct recurse_entry
{
262 struct recurse_entry
*next
;
263 /* Contains the function entry. */
264 struct sljit_label
*entry
;
265 /* Collects the calls until the function is not created. */
267 /* Points to the starting opcode. */
271 typedef struct recurse_backtrack
{
272 backtrack_common common
;
275 #define MAX_RANGE_SIZE 6
277 typedef struct compiler_common
{
278 struct sljit_compiler
*compiler
;
281 /* Maps private data offset to each opcode. */
282 int *private_data_ptrs
;
283 /* Tells whether the capturing bracket is optimized. */
284 pcre_uint8
*optimized_cbracket
;
285 /* Starting offset of private data for capturing brackets. */
287 /* OVector starting point. Must be divisible by 2. */
289 /* Last known position of the requested byte. */
291 /* Head of the last recursion. */
293 /* First inspected character for partial matching. */
295 /* Starting pointer for partial soft matches. */
297 /* End pointer of the first line. */
299 /* Points to the marked string. */
302 /* Flipped and lower case tables. */
303 const pcre_uint8
*fcc
;
305 /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */
307 /* Newline control. */
311 /* Dollar endonly. */
316 int digits
[2 + MAX_RANGE_SIZE
];
317 /* Named capturing brackets. */
320 sljit_sw name_entry_size
;
322 /* Labels and jump lists. */
323 struct sljit_label
*partialmatchlabel
;
324 struct sljit_label
*quitlabel
;
325 struct sljit_label
*acceptlabel
;
327 recurse_entry
*entries
;
328 recurse_entry
*currententry
;
329 jump_list
*partialmatch
;
332 jump_list
*calllimit
;
333 jump_list
*stackalloc
;
334 jump_list
*revertframes
;
335 jump_list
*wordboundary
;
336 jump_list
*anynewline
;
339 jump_list
*casefulcmp
;
340 jump_list
*caselesscmp
;
347 #ifndef COMPILE_PCRE32
348 jump_list
*utfreadchar
;
351 jump_list
*utfreadtype8
;
353 #endif /* SUPPORT_UTF */
359 /* For byte_sequence_compare. */
361 typedef struct compare_context
{
364 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
369 #if defined COMPILE_PCRE8
371 sljit_ub asuchars
[4];
372 #elif defined COMPILE_PCRE16
373 sljit_uh asuchars
[2];
374 #elif defined COMPILE_PCRE32
375 sljit_ui asuchars
[1];
381 #if defined COMPILE_PCRE8
383 sljit_ub asuchars
[4];
384 #elif defined COMPILE_PCRE16
385 sljit_uh asuchars
[2];
386 #elif defined COMPILE_PCRE32
387 sljit_ui asuchars
[1];
395 frame_setstrbegin
= -1,
399 /* Undefine sljit macros. */
402 /* Used for accessing the elements of the stack. */
403 #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_sw))
405 #define TMP1 SLJIT_SCRATCH_REG1
406 #define TMP2 SLJIT_SCRATCH_REG3
407 #define TMP3 SLJIT_TEMPORARY_EREG2
408 #define STR_PTR SLJIT_SAVED_REG1
409 #define STR_END SLJIT_SAVED_REG2
410 #define STACK_TOP SLJIT_SCRATCH_REG2
411 #define STACK_LIMIT SLJIT_SAVED_REG3
412 #define ARGUMENTS SLJIT_SAVED_EREG1
413 #define CALL_COUNT SLJIT_SAVED_EREG2
414 #define RETURN_ADDR SLJIT_TEMPORARY_EREG1
416 /* Local space layout. */
417 /* These two locals can be used by the current opcode. */
418 #define LOCALS0 (0 * sizeof(sljit_sw))
419 #define LOCALS1 (1 * sizeof(sljit_sw))
420 /* Two local variables for possessive quantifiers (char1 cannot use them). */
421 #define POSSESSIVE0 (2 * sizeof(sljit_sw))
422 #define POSSESSIVE1 (3 * sizeof(sljit_sw))
423 /* Max limit of recursions. */
424 #define CALL_LIMIT (4 * sizeof(sljit_sw))
425 /* The output vector is stored on the stack, and contains pointers
426 to characters. The vector data is divided into two groups: the first
427 group contains the start / end character pointers, and the second is
428 the start pointers when the end of the capturing group has not yet reached. */
429 #define OVECTOR_START (common->ovector_start)
430 #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_sw))
431 #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_sw))
432 #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start])
434 #if defined COMPILE_PCRE8
435 #define MOV_UCHAR SLJIT_MOV_UB
436 #define MOVU_UCHAR SLJIT_MOVU_UB
437 #elif defined COMPILE_PCRE16
438 #define MOV_UCHAR SLJIT_MOV_UH
439 #define MOVU_UCHAR SLJIT_MOVU_UH
440 #elif defined COMPILE_PCRE32
441 #define MOV_UCHAR SLJIT_MOV_UI
442 #define MOVU_UCHAR SLJIT_MOVU_UI
444 #error Unsupported compiling mode
448 #define DEFINE_COMPILER \
449 struct sljit_compiler *compiler = common->compiler
450 #define OP1(op, dst, dstw, src, srcw) \
451 sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
452 #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
453 sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
455 sljit_emit_label(compiler)
457 sljit_emit_jump(compiler, (type))
458 #define JUMPTO(type, label) \
459 sljit_set_label(sljit_emit_jump(compiler, (type)), (label))
460 #define JUMPHERE(jump) \
461 sljit_set_label((jump), sljit_emit_label(compiler))
462 #define CMP(type, src1, src1w, src2, src2w) \
463 sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w))
464 #define CMPTO(type, src1, src1w, src2, src2w, label) \
465 sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label))
466 #define OP_FLAGS(op, dst, dstw, src, srcw, type) \
467 sljit_emit_op_flags(compiler, (op), (dst), (dstw), (src), (srcw), (type))
468 #define GET_LOCAL_BASE(dst, dstw, offset) \
469 sljit_get_local_base(compiler, (dst), (dstw), (offset))
471 static pcre_uchar
* bracketend(pcre_uchar
* cc
)
473 SLJIT_ASSERT((*cc
>= OP_ASSERT
&& *cc
<= OP_ASSERTBACK_NOT
) || (*cc
>= OP_ONCE
&& *cc
<= OP_SCOND
));
474 do cc
+= GET(cc
, 1); while (*cc
== OP_ALT
);
475 SLJIT_ASSERT(*cc
>= OP_KET
&& *cc
<= OP_KETRPOS
);
480 /* Functions whose might need modification for all new supported opcodes:
482 get_private_data_length
483 set_private_data_ptrs
486 get_private_data_length_for_copy
489 compile_backtrackingpath
492 static pcre_uchar
*next_opcode(compiler_common
*common
, pcre_uchar
*cc
)
494 SLJIT_UNUSED_ARG(common
);
500 case OP_NOT_WORD_BOUNDARY
:
501 case OP_WORD_BOUNDARY
:
504 case OP_NOT_WHITESPACE
:
506 case OP_NOT_WORDCHAR
:
527 case OP_TYPEMINQUERY
:
530 case OP_TYPEPOSQUERY
:
544 case OP_ASSERT_ACCEPT
:
550 if (common
->utf
) return NULL
;
590 case OP_NOTMINQUERYI
:
593 case OP_NOTPOSQUERYI
:
596 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
618 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
642 return cc
+ 1 + 2 * IMM2_SIZE
;
646 return cc
+ 1 + 32 / sizeof(pcre_uchar
);
648 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
650 return cc
+ GET(cc
, 1);
657 case OP_ASSERTBACK_NOT
:
672 return cc
+ 1 + LINK_SIZE
;
678 return cc
+ 1 + LINK_SIZE
+ IMM2_SIZE
;
681 return cc
+ 1 + 2 + cc
[1];
688 #define CASE_ITERATOR_PRIVATE_DATA_1 \
697 case OP_NOTMINSTAR: \
698 case OP_NOTMINPLUS: \
700 case OP_NOTMINQUERY: \
701 case OP_NOTMINSTARI: \
702 case OP_NOTMINPLUSI: \
704 case OP_NOTMINQUERYI:
706 #define CASE_ITERATOR_PRIVATE_DATA_2A \
716 #define CASE_ITERATOR_PRIVATE_DATA_2B \
722 case OP_NOTMINUPTO: \
726 #define CASE_ITERATOR_TYPE_PRIVATE_DATA_1 \
727 case OP_TYPEMINSTAR: \
728 case OP_TYPEMINPLUS: \
730 case OP_TYPEMINQUERY:
732 #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2A \
736 #define CASE_ITERATOR_TYPE_PRIVATE_DATA_2B \
740 static int get_class_iterator_size(pcre_uchar
*cc
)
756 if (GET2(cc
, 1) == GET2(cc
, 1 + IMM2_SIZE
))
765 static int get_private_data_length(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
)
767 int private_data_length
= 0;
768 pcre_uchar
*alternative
;
770 pcre_uchar
*end
= NULL
;
772 pcre_uint32 bracketlen
;
774 /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */
783 common
->has_set_som
= TRUE
;
789 common
->optimized_cbracket
[GET2(cc
, 1)] = 0;
796 case OP_ASSERTBACK_NOT
:
802 private_data_length
+= sizeof(sljit_sw
);
803 bracketlen
= 1 + LINK_SIZE
;
808 private_data_length
+= sizeof(sljit_sw
);
809 common
->optimized_cbracket
[GET2(cc
, 1 + LINK_SIZE
)] = 0;
810 bracketlen
= 1 + LINK_SIZE
+ IMM2_SIZE
;
815 bracketlen
= cc
[1 + LINK_SIZE
];
816 if (bracketlen
== OP_CREF
)
818 bracketlen
= GET2(cc
, 1 + LINK_SIZE
+ 1);
819 common
->optimized_cbracket
[bracketlen
] = 0;
821 else if (bracketlen
== OP_NCREF
)
823 bracketlen
= GET2(cc
, 1 + LINK_SIZE
+ 1);
824 name
= (pcre_uchar
*)common
->name_table
;
826 for (i
= 0; i
< common
->name_count
; i
++)
828 if (GET2(name
, 0) == bracketlen
) break;
829 name
+= common
->name_entry_size
;
831 SLJIT_ASSERT(i
!= common
->name_count
);
833 for (i
= 0; i
< common
->name_count
; i
++)
835 if (STRCMP_UC_UC(alternative
+ IMM2_SIZE
, name
+ IMM2_SIZE
) == 0)
836 common
->optimized_cbracket
[GET2(alternative
, 0)] = 0;
837 alternative
+= common
->name_entry_size
;
843 /* Might be a hidden SCOND. */
844 alternative
= cc
+ GET(cc
, 1);
845 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
846 private_data_length
+= sizeof(sljit_sw
);
849 private_data_length
+= sizeof(sljit_sw
);
850 bracketlen
= 1 + LINK_SIZE
;
854 bracketlen
= 1 + LINK_SIZE
;
859 bracketlen
= 1 + LINK_SIZE
+ IMM2_SIZE
;
862 CASE_ITERATOR_PRIVATE_DATA_1
867 CASE_ITERATOR_PRIVATE_DATA_2A
872 CASE_ITERATOR_PRIVATE_DATA_2B
874 size
= -(2 + IMM2_SIZE
);
877 CASE_ITERATOR_TYPE_PRIVATE_DATA_1
882 CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
883 if (cc
[1] != OP_ANYNL
&& cc
[1] != OP_EXTUNI
)
888 CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
889 if (cc
[1 + IMM2_SIZE
] != OP_ANYNL
&& cc
[1 + IMM2_SIZE
] != OP_EXTUNI
)
891 size
= 1 + IMM2_SIZE
;
896 size
+= 1 + 32 / sizeof(pcre_uchar
);
897 space
= get_class_iterator_size(cc
+ size
);
900 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
903 space
= get_class_iterator_size(cc
+ size
);
908 /* Set its value only once. */
909 if (common
->recursive_head
== 0)
911 common
->recursive_head
= common
->ovector_start
;
912 common
->ovector_start
+= sizeof(sljit_sw
);
918 if (common
->mark_ptr
== 0)
920 common
->mark_ptr
= common
->ovector_start
;
921 common
->ovector_start
+= sizeof(sljit_sw
);
927 cc
= next_opcode(common
, cc
);
933 if (space
> 0 && cc
>= end
)
934 private_data_length
+= sizeof(sljit_sw
) * space
;
942 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
953 end
= bracketend(cc
);
954 if (end
[-1 - LINK_SIZE
] == OP_KET
)
960 return private_data_length
;
963 static void set_private_data_ptrs(compiler_common
*common
, int private_data_ptr
, pcre_uchar
*ccend
)
965 pcre_uchar
*cc
= common
->start
;
966 pcre_uchar
*alternative
;
967 pcre_uchar
*end
= NULL
;
968 int space
, size
, bracketlen
;
980 case OP_ASSERTBACK_NOT
:
987 common
->private_data_ptrs
[cc
- common
->start
] = private_data_ptr
;
988 private_data_ptr
+= sizeof(sljit_sw
);
989 bracketlen
= 1 + LINK_SIZE
;
994 common
->private_data_ptrs
[cc
- common
->start
] = private_data_ptr
;
995 private_data_ptr
+= sizeof(sljit_sw
);
996 bracketlen
= 1 + LINK_SIZE
+ IMM2_SIZE
;
1000 /* Might be a hidden SCOND. */
1001 alternative
= cc
+ GET(cc
, 1);
1002 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
1004 common
->private_data_ptrs
[cc
- common
->start
] = private_data_ptr
;
1005 private_data_ptr
+= sizeof(sljit_sw
);
1007 bracketlen
= 1 + LINK_SIZE
;
1011 bracketlen
= 1 + LINK_SIZE
;
1016 bracketlen
= 1 + LINK_SIZE
+ IMM2_SIZE
;
1019 CASE_ITERATOR_PRIVATE_DATA_1
1024 CASE_ITERATOR_PRIVATE_DATA_2A
1029 CASE_ITERATOR_PRIVATE_DATA_2B
1031 size
= -(2 + IMM2_SIZE
);
1034 CASE_ITERATOR_TYPE_PRIVATE_DATA_1
1039 CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
1040 if (cc
[1] != OP_ANYNL
&& cc
[1] != OP_EXTUNI
)
1045 CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
1046 if (cc
[1 + IMM2_SIZE
] != OP_ANYNL
&& cc
[1 + IMM2_SIZE
] != OP_EXTUNI
)
1048 size
= 1 + IMM2_SIZE
;
1053 size
+= 1 + 32 / sizeof(pcre_uchar
);
1054 space
= get_class_iterator_size(cc
+ size
);
1057 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1060 space
= get_class_iterator_size(cc
+ size
);
1065 cc
= next_opcode(common
, cc
);
1066 SLJIT_ASSERT(cc
!= NULL
);
1070 if (space
> 0 && cc
>= end
)
1072 common
->private_data_ptrs
[cc
- common
->start
] = private_data_ptr
;
1073 private_data_ptr
+= sizeof(sljit_sw
) * space
;
1082 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
1093 end
= bracketend(cc
);
1094 if (end
[-1 - LINK_SIZE
] == OP_KET
)
1102 /* Returns with -1 if no need for frame. */
1103 static int get_framesize(compiler_common
*common
, pcre_uchar
*cc
, BOOL recursive
)
1105 pcre_uchar
*ccend
= bracketend(cc
);
1107 BOOL possessive
= FALSE
;
1108 BOOL setsom_found
= recursive
;
1109 BOOL setmark_found
= recursive
;
1111 if (!recursive
&& (*cc
== OP_CBRAPOS
|| *cc
== OP_SCBRAPOS
))
1117 cc
= next_opcode(common
, cc
);
1118 SLJIT_ASSERT(cc
!= NULL
);
1123 SLJIT_ASSERT(common
->has_set_som
);
1127 setsom_found
= TRUE
;
1133 SLJIT_ASSERT(common
->mark_ptr
!= 0);
1137 setmark_found
= TRUE
;
1139 cc
+= 1 + 2 + cc
[1];
1143 if (common
->has_set_som
&& !setsom_found
)
1146 setsom_found
= TRUE
;
1148 if (common
->mark_ptr
!= 0 && !setmark_found
)
1151 setmark_found
= TRUE
;
1153 cc
+= 1 + LINK_SIZE
;
1161 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
1165 cc
= next_opcode(common
, cc
);
1166 SLJIT_ASSERT(cc
!= NULL
);
1170 /* Possessive quantifiers can use a special case. */
1171 if (SLJIT_UNLIKELY(possessive
) && length
== 3)
1179 static void init_frame(compiler_common
*common
, pcre_uchar
*cc
, int stackpos
, int stacktop
, BOOL recursive
)
1182 pcre_uchar
*ccend
= bracketend(cc
);
1183 BOOL setsom_found
= recursive
;
1184 BOOL setmark_found
= recursive
;
1187 /* >= 1 + shortest item size (2) */
1188 SLJIT_UNUSED_ARG(stacktop
);
1189 SLJIT_ASSERT(stackpos
>= stacktop
+ 2);
1191 stackpos
= STACK(stackpos
);
1192 if (recursive
|| (*cc
!= OP_CBRAPOS
&& *cc
!= OP_SCBRAPOS
))
1193 cc
= next_opcode(common
, cc
);
1194 SLJIT_ASSERT(cc
!= NULL
);
1199 SLJIT_ASSERT(common
->has_set_som
);
1202 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
1203 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setstrbegin
);
1204 stackpos
+= (int)sizeof(sljit_sw
);
1205 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
1206 stackpos
+= (int)sizeof(sljit_sw
);
1207 setsom_found
= TRUE
;
1213 SLJIT_ASSERT(common
->mark_ptr
!= 0);
1216 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
1217 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setmark
);
1218 stackpos
+= (int)sizeof(sljit_sw
);
1219 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
1220 stackpos
+= (int)sizeof(sljit_sw
);
1221 setmark_found
= TRUE
;
1223 cc
+= 1 + 2 + cc
[1];
1227 if (common
->has_set_som
&& !setsom_found
)
1229 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
1230 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setstrbegin
);
1231 stackpos
+= (int)sizeof(sljit_sw
);
1232 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
1233 stackpos
+= (int)sizeof(sljit_sw
);
1234 setsom_found
= TRUE
;
1236 if (common
->mark_ptr
!= 0 && !setmark_found
)
1238 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
1239 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_setmark
);
1240 stackpos
+= (int)sizeof(sljit_sw
);
1241 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
1242 stackpos
+= (int)sizeof(sljit_sw
);
1243 setmark_found
= TRUE
;
1245 cc
+= 1 + LINK_SIZE
;
1252 offset
= (GET2(cc
, 1 + LINK_SIZE
)) << 1;
1253 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, OVECTOR(offset
));
1254 stackpos
+= (int)sizeof(sljit_sw
);
1255 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
1256 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
1257 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP1
, 0);
1258 stackpos
+= (int)sizeof(sljit_sw
);
1259 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, TMP2
, 0);
1260 stackpos
+= (int)sizeof(sljit_sw
);
1262 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
1266 cc
= next_opcode(common
, cc
);
1267 SLJIT_ASSERT(cc
!= NULL
);
1271 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackpos
, SLJIT_IMM
, frame_end
);
1272 SLJIT_ASSERT(stackpos
== STACK(stacktop
));
1275 static SLJIT_INLINE
int get_private_data_length_for_copy(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
)
1277 int private_data_length
= 2;
1279 pcre_uchar
*alternative
;
1280 /* Calculate the sum of the private machine words. */
1289 case OP_ASSERTBACK_NOT
:
1296 private_data_length
++;
1297 cc
+= 1 + LINK_SIZE
;
1302 if (common
->optimized_cbracket
[GET2(cc
, 1 + LINK_SIZE
)] == 0)
1303 private_data_length
++;
1304 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
1309 private_data_length
+= 2;
1310 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
1314 /* Might be a hidden SCOND. */
1315 alternative
= cc
+ GET(cc
, 1);
1316 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
1317 private_data_length
++;
1318 cc
+= 1 + LINK_SIZE
;
1321 CASE_ITERATOR_PRIVATE_DATA_1
1322 if (PRIVATE_DATA(cc
))
1323 private_data_length
++;
1326 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
1330 CASE_ITERATOR_PRIVATE_DATA_2A
1331 if (PRIVATE_DATA(cc
))
1332 private_data_length
+= 2;
1335 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
1339 CASE_ITERATOR_PRIVATE_DATA_2B
1340 if (PRIVATE_DATA(cc
))
1341 private_data_length
+= 2;
1342 cc
+= 2 + IMM2_SIZE
;
1344 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
1348 CASE_ITERATOR_TYPE_PRIVATE_DATA_1
1349 if (PRIVATE_DATA(cc
))
1350 private_data_length
++;
1354 CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
1355 if (PRIVATE_DATA(cc
))
1356 private_data_length
+= 2;
1360 CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
1361 if (PRIVATE_DATA(cc
))
1362 private_data_length
+= 2;
1363 cc
+= 1 + IMM2_SIZE
;
1368 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1370 size
= (*cc
== OP_XCLASS
) ? GET(cc
, 1) : 1 + 32 / (int)sizeof(pcre_uchar
);
1372 size
= 1 + 32 / (int)sizeof(pcre_uchar
);
1374 if (PRIVATE_DATA(cc
))
1375 private_data_length
+= get_class_iterator_size(cc
+ size
);
1380 cc
= next_opcode(common
, cc
);
1381 SLJIT_ASSERT(cc
!= NULL
);
1385 SLJIT_ASSERT(cc
== ccend
);
1386 return private_data_length
;
1389 static void copy_private_data(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
,
1390 BOOL save
, int stackptr
, int stacktop
)
1395 BOOL tmp1next
= TRUE
;
1396 BOOL tmp1empty
= TRUE
;
1397 BOOL tmp2empty
= TRUE
;
1398 pcre_uchar
*alternative
;
1405 status
= save
? start
: loop
;
1406 stackptr
= STACK(stackptr
- 2);
1407 stacktop
= STACK(stacktop
- 1);
1411 stackptr
+= sizeof(sljit_sw
);
1412 if (stackptr
< stacktop
)
1414 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1415 stackptr
+= sizeof(sljit_sw
);
1418 if (stackptr
< stacktop
)
1420 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1421 stackptr
+= sizeof(sljit_sw
);
1424 /* The tmp1next must be TRUE in either way. */
1427 while (status
!= end
)
1433 SLJIT_ASSERT(save
&& common
->recursive_head
!= 0);
1435 srcw
[0] = common
->recursive_head
;
1451 case OP_ASSERTBACK_NOT
:
1459 srcw
[0] = PRIVATE_DATA(cc
);
1460 SLJIT_ASSERT(srcw
[0] != 0);
1461 cc
+= 1 + LINK_SIZE
;
1466 if (common
->optimized_cbracket
[GET2(cc
, 1 + LINK_SIZE
)] == 0)
1469 srcw
[0] = OVECTOR_PRIV(GET2(cc
, 1 + LINK_SIZE
));
1471 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
1477 srcw
[0] = PRIVATE_DATA(cc
);
1478 srcw
[1] = OVECTOR_PRIV(GET2(cc
, 1 + LINK_SIZE
));
1479 SLJIT_ASSERT(srcw
[0] != 0 && srcw
[1] != 0);
1480 cc
+= 1 + LINK_SIZE
+ IMM2_SIZE
;
1484 /* Might be a hidden SCOND. */
1485 alternative
= cc
+ GET(cc
, 1);
1486 if (*alternative
== OP_KETRMAX
|| *alternative
== OP_KETRMIN
)
1489 srcw
[0] = PRIVATE_DATA(cc
);
1490 SLJIT_ASSERT(srcw
[0] != 0);
1492 cc
+= 1 + LINK_SIZE
;
1495 CASE_ITERATOR_PRIVATE_DATA_1
1496 if (PRIVATE_DATA(cc
))
1499 srcw
[0] = PRIVATE_DATA(cc
);
1503 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
1507 CASE_ITERATOR_PRIVATE_DATA_2A
1508 if (PRIVATE_DATA(cc
))
1511 srcw
[0] = PRIVATE_DATA(cc
);
1512 srcw
[1] = PRIVATE_DATA(cc
) + sizeof(sljit_sw
);
1516 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
1520 CASE_ITERATOR_PRIVATE_DATA_2B
1521 if (PRIVATE_DATA(cc
))
1524 srcw
[0] = PRIVATE_DATA(cc
);
1525 srcw
[1] = PRIVATE_DATA(cc
) + sizeof(sljit_sw
);
1527 cc
+= 2 + IMM2_SIZE
;
1529 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
1533 CASE_ITERATOR_TYPE_PRIVATE_DATA_1
1534 if (PRIVATE_DATA(cc
))
1537 srcw
[0] = PRIVATE_DATA(cc
);
1542 CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
1543 if (PRIVATE_DATA(cc
))
1546 srcw
[0] = PRIVATE_DATA(cc
);
1547 srcw
[1] = srcw
[0] + sizeof(sljit_sw
);
1552 CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
1553 if (PRIVATE_DATA(cc
))
1556 srcw
[0] = PRIVATE_DATA(cc
);
1557 srcw
[1] = srcw
[0] + sizeof(sljit_sw
);
1559 cc
+= 1 + IMM2_SIZE
;
1564 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
1566 size
= (*cc
== OP_XCLASS
) ? GET(cc
, 1) : 1 + 32 / (int)sizeof(pcre_uchar
);
1568 size
= 1 + 32 / (int)sizeof(pcre_uchar
);
1570 if (PRIVATE_DATA(cc
))
1571 switch(get_class_iterator_size(cc
+ size
))
1575 srcw
[0] = PRIVATE_DATA(cc
);
1580 srcw
[0] = PRIVATE_DATA(cc
);
1581 srcw
[1] = srcw
[0] + sizeof(sljit_sw
);
1585 SLJIT_ASSERT_STOP();
1592 cc
= next_opcode(common
, cc
);
1593 SLJIT_ASSERT(cc
!= NULL
);
1599 SLJIT_ASSERT_STOP();
1612 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP1
, 0);
1613 stackptr
+= sizeof(sljit_sw
);
1615 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
]);
1623 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP2
, 0);
1624 stackptr
+= sizeof(sljit_sw
);
1626 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
]);
1635 SLJIT_ASSERT(!tmp1empty
);
1636 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
], TMP1
, 0);
1637 tmp1empty
= stackptr
>= stacktop
;
1640 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1641 stackptr
+= sizeof(sljit_sw
);
1647 SLJIT_ASSERT(!tmp2empty
);
1648 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), srcw
[count
], TMP2
, 0);
1649 tmp2empty
= stackptr
>= stacktop
;
1652 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), stackptr
);
1653 stackptr
+= sizeof(sljit_sw
);
1667 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP1
, 0);
1668 stackptr
+= sizeof(sljit_sw
);
1672 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP2
, 0);
1673 stackptr
+= sizeof(sljit_sw
);
1680 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP2
, 0);
1681 stackptr
+= sizeof(sljit_sw
);
1685 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), stackptr
, TMP1
, 0);
1686 stackptr
+= sizeof(sljit_sw
);
1690 SLJIT_ASSERT(cc
== ccend
&& stackptr
== stacktop
&& (save
|| (tmp1empty
&& tmp2empty
)));
1693 #undef CASE_ITERATOR_PRIVATE_DATA_1
1694 #undef CASE_ITERATOR_PRIVATE_DATA_2A
1695 #undef CASE_ITERATOR_PRIVATE_DATA_2B
1696 #undef CASE_ITERATOR_TYPE_PRIVATE_DATA_1
1697 #undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
1698 #undef CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
1700 static SLJIT_INLINE BOOL
is_powerof2(unsigned int value
)
1702 return (value
& (value
- 1)) == 0;
1705 static SLJIT_INLINE
void set_jumps(jump_list
*list
, struct sljit_label
*label
)
1709 /* sljit_set_label is clever enough to do nothing
1710 if either the jump or the label is NULL. */
1711 sljit_set_label(list
->jump
, label
);
1716 static SLJIT_INLINE
void add_jump(struct sljit_compiler
*compiler
, jump_list
**list
, struct sljit_jump
* jump
)
1718 jump_list
*list_item
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
1721 list_item
->next
= *list
;
1722 list_item
->jump
= jump
;
1727 static void add_stub(compiler_common
*common
, enum stub_types type
, int data
, struct sljit_jump
*start
)
1730 stub_list
* list_item
= sljit_alloc_memory(compiler
, sizeof(stub_list
));
1734 list_item
->type
= type
;
1735 list_item
->data
= data
;
1736 list_item
->start
= start
;
1737 list_item
->quit
= LABEL();
1738 list_item
->next
= common
->stubs
;
1739 common
->stubs
= list_item
;
1743 static void flush_stubs(compiler_common
*common
)
1746 stub_list
* list_item
= common
->stubs
;
1750 JUMPHERE(list_item
->start
);
1751 switch(list_item
->type
)
1754 add_jump(compiler
, &common
->stackalloc
, JUMP(SLJIT_FAST_CALL
));
1757 JUMPTO(SLJIT_JUMP
, list_item
->quit
);
1758 list_item
= list_item
->next
;
1760 common
->stubs
= NULL
;
1763 static SLJIT_INLINE
void decrease_call_count(compiler_common
*common
)
1767 OP2(SLJIT_SUB
| SLJIT_SET_E
, CALL_COUNT
, 0, CALL_COUNT
, 0, SLJIT_IMM
, 1);
1768 add_jump(compiler
, &common
->calllimit
, JUMP(SLJIT_C_ZERO
));
1771 static SLJIT_INLINE
void allocate_stack(compiler_common
*common
, int size
)
1773 /* May destroy all locals and registers except TMP2. */
1776 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, size
* sizeof(sljit_sw
));
1777 #ifdef DESTROY_REGISTERS
1778 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 12345);
1779 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
1780 OP1(SLJIT_MOV
, RETURN_ADDR
, 0, TMP1
, 0);
1781 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, TMP1
, 0);
1782 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP1
, 0);
1784 add_stub(common
, stack_alloc
, 0, CMP(SLJIT_C_GREATER
, STACK_TOP
, 0, STACK_LIMIT
, 0));
1787 static SLJIT_INLINE
void free_stack(compiler_common
*common
, int size
)
1790 OP2(SLJIT_SUB
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, size
* sizeof(sljit_sw
));
1793 static SLJIT_INLINE
void reset_ovector(compiler_common
*common
, int length
)
1796 struct sljit_label
*loop
;
1798 /* At this point we can freely use all temporary registers. */
1799 /* TMP1 returns with begin - 1. */
1800 OP2(SLJIT_SUB
, SLJIT_SCRATCH_REG1
, 0, SLJIT_MEM1(SLJIT_SAVED_REG1
), SLJIT_OFFSETOF(jit_arguments
, begin
), SLJIT_IMM
, IN_UCHARS(1));
1803 for (i
= 0; i
< length
; i
++)
1804 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(i
), SLJIT_SCRATCH_REG1
, 0);
1808 GET_LOCAL_BASE(SLJIT_SCRATCH_REG2
, 0, OVECTOR_START
- sizeof(sljit_sw
));
1809 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG3
, 0, SLJIT_IMM
, length
);
1811 OP1(SLJIT_MOVU
, SLJIT_MEM1(SLJIT_SCRATCH_REG2
), sizeof(sljit_sw
), SLJIT_SCRATCH_REG1
, 0);
1812 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_SCRATCH_REG3
, 0, SLJIT_SCRATCH_REG3
, 0, SLJIT_IMM
, 1);
1813 JUMPTO(SLJIT_C_NOT_ZERO
, loop
);
1817 static SLJIT_INLINE
void copy_ovector(compiler_common
*common
, int topbracket
)
1820 struct sljit_label
*loop
;
1821 struct sljit_jump
*earlyexit
;
1823 /* At this point we can freely use all registers. */
1824 OP1(SLJIT_MOV
, SLJIT_SAVED_REG3
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1));
1825 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1), STR_PTR
, 0);
1827 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG1
, 0, ARGUMENTS
, 0);
1828 if (common
->mark_ptr
!= 0)
1829 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG3
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
1830 OP1(SLJIT_MOV_SI
, SLJIT_SCRATCH_REG2
, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1
), SLJIT_OFFSETOF(jit_arguments
, offsetcount
));
1831 if (common
->mark_ptr
!= 0)
1832 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_SCRATCH_REG1
), SLJIT_OFFSETOF(jit_arguments
, mark_ptr
), SLJIT_SCRATCH_REG3
, 0);
1833 OP2(SLJIT_SUB
, SLJIT_SCRATCH_REG3
, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1
), SLJIT_OFFSETOF(jit_arguments
, offsets
), SLJIT_IMM
, sizeof(int));
1834 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG1
, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
1835 GET_LOCAL_BASE(SLJIT_SAVED_REG1
, 0, OVECTOR_START
);
1836 /* Unlikely, but possible */
1837 earlyexit
= CMP(SLJIT_C_EQUAL
, SLJIT_SCRATCH_REG2
, 0, SLJIT_IMM
, 0);
1839 OP2(SLJIT_SUB
, SLJIT_SAVED_REG2
, 0, SLJIT_MEM1(SLJIT_SAVED_REG1
), 0, SLJIT_SCRATCH_REG1
, 0);
1840 OP2(SLJIT_ADD
, SLJIT_SAVED_REG1
, 0, SLJIT_SAVED_REG1
, 0, SLJIT_IMM
, sizeof(sljit_sw
));
1841 /* Copy the integer value to the output buffer */
1842 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1843 OP2(SLJIT_ASHR
, SLJIT_SAVED_REG2
, 0, SLJIT_SAVED_REG2
, 0, SLJIT_IMM
, UCHAR_SHIFT
);
1845 OP1(SLJIT_MOVU_SI
, SLJIT_MEM1(SLJIT_SCRATCH_REG3
), sizeof(int), SLJIT_SAVED_REG2
, 0);
1846 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_SCRATCH_REG2
, 0, SLJIT_SCRATCH_REG2
, 0, SLJIT_IMM
, 1);
1847 JUMPTO(SLJIT_C_NOT_ZERO
, loop
);
1848 JUMPHERE(earlyexit
);
1850 /* Calculate the return value, which is the maximum ovector value. */
1853 GET_LOCAL_BASE(SLJIT_SCRATCH_REG1
, 0, OVECTOR_START
+ topbracket
* 2 * sizeof(sljit_sw
));
1854 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG2
, 0, SLJIT_IMM
, topbracket
+ 1);
1856 /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */
1858 OP1(SLJIT_MOVU
, SLJIT_SCRATCH_REG3
, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1
), -(2 * (sljit_sw
)sizeof(sljit_sw
)));
1859 OP2(SLJIT_SUB
, SLJIT_SCRATCH_REG2
, 0, SLJIT_SCRATCH_REG2
, 0, SLJIT_IMM
, 1);
1860 CMPTO(SLJIT_C_EQUAL
, SLJIT_SCRATCH_REG3
, 0, SLJIT_SAVED_REG3
, 0, loop
);
1861 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_SCRATCH_REG2
, 0);
1864 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 1);
1867 static SLJIT_INLINE
void return_with_partial_match(compiler_common
*common
, struct sljit_label
*quit
)
1871 SLJIT_COMPILE_ASSERT(STR_END
== SLJIT_SAVED_REG2
, str_end_must_be_saved_reg2
);
1872 SLJIT_ASSERT(common
->start_used_ptr
!= 0 && (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
? common
->hit_start
!= 0 : common
->hit_start
== 0));
1874 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG2
, 0, ARGUMENTS
, 0);
1875 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_PARTIAL
);
1876 OP1(SLJIT_MOV_SI
, SLJIT_SCRATCH_REG3
, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2
), SLJIT_OFFSETOF(jit_arguments
, offsetcount
));
1877 CMPTO(SLJIT_C_LESS
, SLJIT_SCRATCH_REG3
, 0, SLJIT_IMM
, 2, quit
);
1879 /* Store match begin and end. */
1880 OP1(SLJIT_MOV
, SLJIT_SAVED_REG1
, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2
), SLJIT_OFFSETOF(jit_arguments
, begin
));
1881 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG2
, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2
), SLJIT_OFFSETOF(jit_arguments
, offsets
));
1882 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG3
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mode
== JIT_PARTIAL_HARD_COMPILE
? common
->start_used_ptr
: common
->hit_start
);
1883 OP2(SLJIT_SUB
, SLJIT_SAVED_REG2
, 0, STR_END
, 0, SLJIT_SAVED_REG1
, 0);
1884 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1885 OP2(SLJIT_ASHR
, SLJIT_SAVED_REG2
, 0, SLJIT_SAVED_REG2
, 0, SLJIT_IMM
, UCHAR_SHIFT
);
1887 OP1(SLJIT_MOV_SI
, SLJIT_MEM1(SLJIT_SCRATCH_REG2
), sizeof(int), SLJIT_SAVED_REG2
, 0);
1889 OP2(SLJIT_SUB
, SLJIT_SCRATCH_REG3
, 0, SLJIT_SCRATCH_REG3
, 0, SLJIT_SAVED_REG1
, 0);
1890 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
1891 OP2(SLJIT_ASHR
, SLJIT_SCRATCH_REG3
, 0, SLJIT_SCRATCH_REG3
, 0, SLJIT_IMM
, UCHAR_SHIFT
);
1893 OP1(SLJIT_MOV_SI
, SLJIT_MEM1(SLJIT_SCRATCH_REG2
), 0, SLJIT_SCRATCH_REG3
, 0);
1895 JUMPTO(SLJIT_JUMP
, quit
);
1898 static SLJIT_INLINE
void check_start_used_ptr(compiler_common
*common
)
1900 /* May destroy TMP1. */
1902 struct sljit_jump
*jump
;
1904 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
1906 /* The value of -1 must be kept for start_used_ptr! */
1907 OP2(SLJIT_ADD
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, SLJIT_IMM
, 1);
1908 /* Jumps if start_used_ptr < STR_PTR, or start_used_ptr == -1. Although overwriting
1909 is not necessary if start_used_ptr == STR_PTR, it does not hurt as well. */
1910 jump
= CMP(SLJIT_C_LESS_EQUAL
, TMP1
, 0, STR_PTR
, 0);
1911 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1914 else if (common
->mode
== JIT_PARTIAL_HARD_COMPILE
)
1916 jump
= CMP(SLJIT_C_LESS_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1917 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
1922 static SLJIT_INLINE BOOL
char_has_othercase(compiler_common
*common
, pcre_uchar
* cc
)
1924 /* Detects if the character has an othercase. */
1934 return c
!= UCD_OTHERCASE(c
);
1939 #ifndef COMPILE_PCRE8
1940 return common
->fcc
[c
] != c
;
1946 return MAX_255(c
) ? common
->fcc
[c
] != c
: FALSE
;
1949 static SLJIT_INLINE
unsigned int char_othercase(compiler_common
*common
, unsigned int c
)
1951 /* Returns with the othercase. */
1953 if (common
->utf
&& c
> 127)
1956 return UCD_OTHERCASE(c
);
1962 return TABLE_GET(c
, common
->fcc
, c
);
1965 static unsigned int char_get_othercase_bit(compiler_common
*common
, pcre_uchar
* cc
)
1967 /* Detects if the character and its othercase has only 1 bit difference. */
1968 unsigned int c
, oc
, bit
;
1969 #if defined SUPPORT_UTF && defined COMPILE_PCRE8
1978 oc
= common
->fcc
[c
];
1982 oc
= UCD_OTHERCASE(c
);
1991 oc
= TABLE_GET(c
, common
->fcc
, c
);
1995 oc
= TABLE_GET(c
, common
->fcc
, c
);
1998 SLJIT_ASSERT(c
!= oc
);
2001 /* Optimized for English alphabet. */
2002 if (c
<= 127 && bit
== 0x20)
2003 return (0 << 8) | 0x20;
2005 /* Since c != oc, they must have at least 1 bit difference. */
2006 if (!is_powerof2(bit
))
2009 #if defined COMPILE_PCRE8
2012 if (common
->utf
&& c
> 127)
2014 n
= GET_EXTRALEN(*cc
);
2015 while ((bit
& 0x3f) == 0)
2020 return (n
<< 8) | bit
;
2022 #endif /* SUPPORT_UTF */
2023 return (0 << 8) | bit
;
2025 #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
2028 if (common
->utf
&& c
> 65535)
2030 if (bit
>= (1 << 10))
2033 return (bit
< 256) ? ((2 << 8) | bit
) : ((3 << 8) | (bit
>> 8));
2035 #endif /* SUPPORT_UTF */
2036 return (bit
< 256) ? ((0 << 8) | bit
) : ((1 << 8) | (bit
>> 8));
2038 #endif /* COMPILE_PCRE[8|16|32] */
2041 static void check_partial(compiler_common
*common
, BOOL force
)
2043 /* Checks whether a partial matching is occured. Does not modify registers. */
2045 struct sljit_jump
*jump
= NULL
;
2047 SLJIT_ASSERT(!force
|| common
->mode
!= JIT_COMPILE
);
2049 if (common
->mode
== JIT_COMPILE
)
2053 jump
= CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
2054 else if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
2055 jump
= CMP(SLJIT_C_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, SLJIT_IMM
, -1);
2057 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
2058 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
2061 if (common
->partialmatchlabel
!= NULL
)
2062 JUMPTO(SLJIT_JUMP
, common
->partialmatchlabel
);
2064 add_jump(compiler
, &common
->partialmatch
, JUMP(SLJIT_JUMP
));
2071 static struct sljit_jump
*check_str_end(compiler_common
*common
)
2073 /* Does not affect registers. Usually used in a tight spot. */
2075 struct sljit_jump
*jump
;
2076 struct sljit_jump
*nohit
;
2077 struct sljit_jump
*return_value
;
2079 if (common
->mode
== JIT_COMPILE
)
2080 return CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2082 jump
= CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
2083 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
2085 nohit
= CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
2086 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
2088 return_value
= JUMP(SLJIT_JUMP
);
2092 return_value
= CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
2093 if (common
->partialmatchlabel
!= NULL
)
2094 JUMPTO(SLJIT_JUMP
, common
->partialmatchlabel
);
2096 add_jump(compiler
, &common
->partialmatch
, JUMP(SLJIT_JUMP
));
2099 return return_value
;
2102 static void detect_partial_match(compiler_common
*common
, jump_list
**backtracks
)
2105 struct sljit_jump
*jump
;
2107 if (common
->mode
== JIT_COMPILE
)
2109 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0));
2113 /* Partial matching mode. */
2114 jump
= CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
2115 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0));
2116 if (common
->mode
== JIT_PARTIAL_SOFT_COMPILE
)
2118 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
2119 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
2123 if (common
->partialmatchlabel
!= NULL
)
2124 JUMPTO(SLJIT_JUMP
, common
->partialmatchlabel
);
2126 add_jump(compiler
, &common
->partialmatch
, JUMP(SLJIT_JUMP
));
2131 static void read_char(compiler_common
*common
)
2133 /* Reads the character into TMP1, updates STR_PTR.
2134 Does not check STR_END. TMP2 Destroyed. */
2136 #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2137 struct sljit_jump
*jump
;
2140 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2141 #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2144 #if defined COMPILE_PCRE8
2145 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
2146 #elif defined COMPILE_PCRE16
2147 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
2148 #endif /* COMPILE_PCRE[8|16] */
2149 add_jump(compiler
, &common
->utfreadchar
, JUMP(SLJIT_FAST_CALL
));
2152 #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
2153 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2156 static void peek_char(compiler_common
*common
)
2158 /* Reads the character into TMP1, keeps STR_PTR.
2159 Does not check STR_END. TMP2 Destroyed. */
2161 #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2162 struct sljit_jump
*jump
;
2165 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2166 #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2169 #if defined COMPILE_PCRE8
2170 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
2171 #elif defined COMPILE_PCRE16
2172 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
2173 #endif /* COMPILE_PCRE[8|16] */
2174 add_jump(compiler
, &common
->utfreadchar
, JUMP(SLJIT_FAST_CALL
));
2175 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
2178 #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
2181 static void read_char8_type(compiler_common
*common
)
2183 /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */
2185 #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
2186 struct sljit_jump
*jump
;
2192 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), 0);
2193 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2194 #if defined COMPILE_PCRE8
2195 /* This can be an extra read in some situations, but hopefully
2196 it is needed in most cases. */
2197 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
2198 jump
= CMP(SLJIT_C_LESS
, TMP2
, 0, SLJIT_IMM
, 0xc0);
2199 add_jump(compiler
, &common
->utfreadtype8
, JUMP(SLJIT_FAST_CALL
));
2201 #elif defined COMPILE_PCRE16
2202 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
2203 jump
= CMP(SLJIT_C_GREATER
, TMP2
, 0, SLJIT_IMM
, 255);
2204 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
2206 /* Skip low surrogate if necessary. */
2207 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0xfc00);
2208 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP2
, 0, SLJIT_IMM
, 0xd800);
2209 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
2210 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 1);
2211 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
2212 #elif defined COMPILE_PCRE32
2213 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
2214 jump
= CMP(SLJIT_C_GREATER
, TMP2
, 0, SLJIT_IMM
, 255);
2215 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
2217 #endif /* COMPILE_PCRE[8|16|32] */
2220 #endif /* SUPPORT_UTF */
2221 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), 0);
2222 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2223 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
2224 /* The ctypes array contains only 256 values. */
2225 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
2226 jump
= CMP(SLJIT_C_GREATER
, TMP2
, 0, SLJIT_IMM
, 255);
2228 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
2229 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
2234 static void skip_char_back(compiler_common
*common
)
2236 /* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */
2238 #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2239 #if defined COMPILE_PCRE8
2240 struct sljit_label
*label
;
2245 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -IN_UCHARS(1));
2246 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2247 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xc0);
2248 CMPTO(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0x80, label
);
2251 #elif defined COMPILE_PCRE16
2254 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -IN_UCHARS(1));
2255 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2256 /* Skip low surrogate if necessary. */
2257 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
2258 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xdc00);
2259 OP_FLAGS(SLJIT_MOV
, TMP1
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
2260 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2261 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2264 #endif /* COMPILE_PCRE[8|16] */
2265 #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
2266 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2269 static void check_newlinechar(compiler_common
*common
, int nltype
, jump_list
**backtracks
, BOOL jumpiftrue
)
2271 /* Character comes in TMP1. Checks if it is a newline. TMP2 may be destroyed. */
2274 if (nltype
== NLTYPE_ANY
)
2276 add_jump(compiler
, &common
->anynewline
, JUMP(SLJIT_FAST_CALL
));
2277 add_jump(compiler
, backtracks
, JUMP(jumpiftrue
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
2279 else if (nltype
== NLTYPE_ANYCRLF
)
2281 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
2282 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
2283 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
2284 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
2285 add_jump(compiler
, backtracks
, JUMP(jumpiftrue
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
2289 SLJIT_ASSERT(nltype
== NLTYPE_FIXED
&& common
->newline
< 256);
2290 add_jump(compiler
, backtracks
, CMP(jumpiftrue
? SLJIT_C_EQUAL
: SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, common
->newline
));
2296 #if defined COMPILE_PCRE8
2297 static void do_utfreadchar(compiler_common
*common
)
2299 /* Fast decoding a UTF-8 character. TMP1 contains the first byte
2300 of the character (>= 0xc0). Return char value in TMP1, length - 1 in TMP2. */
2302 struct sljit_jump
*jump
;
2304 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2305 /* Searching for the first zero. */
2306 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x20);
2307 jump
= JUMP(SLJIT_C_NOT_ZERO
);
2308 /* Two byte sequence. */
2309 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
2310 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2311 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x1f);
2312 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 6);
2313 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
2314 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
2315 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
2316 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2319 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x10);
2320 jump
= JUMP(SLJIT_C_NOT_ZERO
);
2321 /* Three byte sequence. */
2322 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
2323 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x0f);
2324 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 12);
2325 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
2326 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 6);
2327 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
2328 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(2));
2329 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
2330 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
2331 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
2332 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(2));
2333 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2336 /* Four byte sequence. */
2337 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
2338 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x07);
2339 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 18);
2340 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
2341 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 12);
2342 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
2343 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(2));
2344 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
2345 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 6);
2346 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
2347 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(3));
2348 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(3));
2349 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3f);
2350 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
2351 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(3));
2352 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2355 static void do_utfreadtype8(compiler_common
*common
)
2357 /* Fast decoding a UTF-8 character type. TMP2 contains the first byte
2358 of the character (>= 0xc0). Return value in TMP1. */
2360 struct sljit_jump
*jump
;
2361 struct sljit_jump
*compare
;
2363 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2365 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP2
, 0, SLJIT_IMM
, 0x20);
2366 jump
= JUMP(SLJIT_C_NOT_ZERO
);
2367 /* Two byte sequence. */
2368 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
2369 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2370 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x1f);
2371 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 6);
2372 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x3f);
2373 OP2(SLJIT_OR
, TMP2
, 0, TMP2
, 0, TMP1
, 0);
2374 compare
= CMP(SLJIT_C_GREATER
, TMP2
, 0, SLJIT_IMM
, 255);
2375 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), common
->ctypes
);
2376 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2379 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
2380 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2383 /* We only have types for characters less than 256. */
2384 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP2
), (sljit_sw
)PRIV(utf8_table4
) - 0xc0);
2385 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2386 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 0);
2387 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2390 #elif defined COMPILE_PCRE16
2392 static void do_utfreadchar(compiler_common
*common
)
2394 /* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char
2395 of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */
2397 struct sljit_jump
*jump
;
2399 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2400 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xdc00);
2401 /* Do nothing, only return. */
2402 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2405 /* Combine two 16 bit characters. */
2406 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
2407 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2408 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x3ff);
2409 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 10);
2410 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 0x3ff);
2411 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
2412 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
2413 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x10000);
2414 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2417 #endif /* COMPILE_PCRE[8|16] */
2419 #endif /* SUPPORT_UTF */
2423 /* UCD_BLOCK_SIZE must be 128 (see the assert below). */
2424 #define UCD_BLOCK_MASK 127
2425 #define UCD_BLOCK_SHIFT 7
2427 static void do_getucd(compiler_common
*common
)
2429 /* Search the UCD record for the character comes in TMP1.
2430 Returns chartype in TMP1 and UCD offset in TMP2. */
2433 SLJIT_ASSERT(UCD_BLOCK_SIZE
== 128 && sizeof(ucd_record
) == 8);
2435 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
2436 OP2(SLJIT_LSHR
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, UCD_BLOCK_SHIFT
);
2437 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), (sljit_sw
)PRIV(ucd_stage1
));
2438 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, UCD_BLOCK_MASK
);
2439 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, UCD_BLOCK_SHIFT
);
2440 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, TMP2
, 0);
2441 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, (sljit_sw
)PRIV(ucd_stage2
));
2442 OP1(SLJIT_MOV_UH
, TMP2
, 0, SLJIT_MEM2(TMP2
, TMP1
), 1);
2443 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, (sljit_sw
)PRIV(ucd_records
) + SLJIT_OFFSETOF(ucd_record
, chartype
));
2444 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM2(TMP1
, TMP2
), 3);
2445 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
2449 static SLJIT_INLINE
struct sljit_label
*mainloop_entry(compiler_common
*common
, BOOL hascrorlf
, BOOL firstline
)
2452 struct sljit_label
*mainloop
;
2453 struct sljit_label
*newlinelabel
= NULL
;
2454 struct sljit_jump
*start
;
2455 struct sljit_jump
*end
= NULL
;
2456 struct sljit_jump
*nl
= NULL
;
2457 #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2458 struct sljit_jump
*singlechar
;
2460 jump_list
*newline
= NULL
;
2461 BOOL newlinecheck
= FALSE
;
2462 BOOL readuchar
= FALSE
;
2464 if (!(hascrorlf
|| firstline
) && (common
->nltype
== NLTYPE_ANY
||
2465 common
->nltype
== NLTYPE_ANYCRLF
|| common
->newline
> 255))
2466 newlinecheck
= TRUE
;
2470 /* Search for the end of the first line. */
2471 SLJIT_ASSERT(common
->first_line_end
!= 0);
2472 OP1(SLJIT_MOV
, TMP3
, 0, STR_PTR
, 0);
2474 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
2477 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2478 end
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2479 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-1));
2480 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
2481 CMPTO(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff, mainloop
);
2482 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff, mainloop
);
2484 OP2(SLJIT_SUB
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2488 end
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2490 /* Continual stores does not cause data dependency. */
2491 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, STR_PTR
, 0);
2493 check_newlinechar(common
, common
->nltype
, &newline
, TRUE
);
2494 CMPTO(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0, mainloop
);
2496 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, STR_PTR
, 0);
2497 set_jumps(newline
, LABEL());
2500 OP1(SLJIT_MOV
, STR_PTR
, 0, TMP3
, 0);
2503 start
= JUMP(SLJIT_JUMP
);
2507 newlinelabel
= LABEL();
2508 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2509 end
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2510 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2511 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, common
->newline
& 0xff);
2512 OP_FLAGS(SLJIT_MOV
, TMP1
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
2513 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
2514 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, UCHAR_SHIFT
);
2516 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2517 nl
= JUMP(SLJIT_JUMP
);
2522 /* Increasing the STR_PTR here requires one less jump in the most common case. */
2524 if (common
->utf
) readuchar
= TRUE
;
2526 if (newlinecheck
) readuchar
= TRUE
;
2529 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2532 CMPTO(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff, newlinelabel
);
2534 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2535 #if defined SUPPORT_UTF && !defined COMPILE_PCRE32
2536 #if defined COMPILE_PCRE8
2539 singlechar
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
2540 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_sw
)PRIV(utf8_table4
) - 0xc0);
2541 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2542 JUMPHERE(singlechar
);
2544 #elif defined COMPILE_PCRE16
2547 singlechar
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
2548 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
2549 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xd800);
2550 OP_FLAGS(SLJIT_MOV
, TMP1
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
2551 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2552 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2553 JUMPHERE(singlechar
);
2555 #endif /* COMPILE_PCRE[8|16] */
2556 #endif /* SUPPORT_UTF && !COMPILE_PCRE32 */
2568 #define MAX_N_CHARS 3
2570 static SLJIT_INLINE BOOL
fast_forward_first_n_chars(compiler_common
*common
, BOOL firstline
)
2573 struct sljit_label
*start
;
2574 struct sljit_jump
*quit
;
2575 pcre_uint32 chars
[MAX_N_CHARS
* 2];
2576 pcre_uchar
*cc
= common
->start
+ 1 + IMM2_SIZE
;
2578 pcre_int32 len
, c
, bit
, caseless
;
2581 /* We do not support alternatives now. */
2582 if (*(common
->start
+ GET(common
->start
, 1)) == OP_ALT
)
2605 case OP_NOT_WORD_BOUNDARY
:
2606 case OP_WORD_BOUNDARY
:
2613 /* Zero width assertions. */
2624 cc
+= 1 + IMM2_SIZE
;
2636 cc
+= 1 + IMM2_SIZE
;
2649 if (common
->utf
&& HAS_EXTRALEN(cc
[0])) len
+= GET_EXTRALEN(cc
[0]);
2652 if (caseless
&& char_has_othercase(common
, cc
))
2654 caseless
= char_get_othercase_bit(common
, cc
);
2657 #ifdef COMPILE_PCRE8
2658 caseless
= ((caseless
& 0xff) << 8) | (len
- (caseless
>> 8));
2660 if ((caseless
& 0x100) != 0)
2661 caseless
= ((caseless
& 0xff) << 16) | (len
- (caseless
>> 9));
2663 caseless
= ((caseless
& 0xff) << 8) | (len
- (caseless
>> 9));
2669 while (len
> 0 && location
< MAX_N_CHARS
* 2)
2673 if (len
== (caseless
& 0xff))
2675 bit
= caseless
>> 8;
2679 chars
[location
] = c
;
2680 chars
[location
+ 1] = bit
;
2687 if (location
>= MAX_N_CHARS
* 2 || must_stop
!= 0)
2691 /* At least two characters are required. */
2692 if (location
< 2 * 2)
2697 SLJIT_ASSERT(common
->first_line_end
!= 0);
2698 OP1(SLJIT_MOV
, TMP3
, 0, STR_END
, 0);
2699 OP2(SLJIT_SUB
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, SLJIT_IMM
, (location
>> 1) - 1);
2702 OP2(SLJIT_SUB
, STR_END
, 0, STR_END
, 0, SLJIT_IMM
, (location
>> 1) - 1);
2705 quit
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2707 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
2708 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
2709 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2711 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, chars
[1]);
2712 CMPTO(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, chars
[0], start
);
2713 if (location
> 2 * 2)
2714 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
2716 OP2(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, chars
[3]);
2717 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, chars
[2], start
);
2718 if (location
> 2 * 2)
2721 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, chars
[5]);
2722 CMPTO(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, chars
[4], start
);
2724 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2729 OP1(SLJIT_MOV
, STR_END
, 0, TMP3
, 0);
2731 OP2(SLJIT_ADD
, STR_END
, 0, STR_END
, 0, SLJIT_IMM
, (location
>> 1) - 1);
2737 static SLJIT_INLINE
void fast_forward_first_char(compiler_common
*common
, pcre_uchar first_char
, BOOL caseless
, BOOL firstline
)
2740 struct sljit_label
*start
;
2741 struct sljit_jump
*quit
;
2742 struct sljit_jump
*found
;
2747 SLJIT_ASSERT(common
->first_line_end
!= 0);
2748 OP1(SLJIT_MOV
, TMP3
, 0, STR_END
, 0);
2749 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
2753 quit
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2754 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2759 oc
= TABLE_GET(first_char
, common
->fcc
, first_char
);
2760 #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
2761 if (first_char
> 127 && common
->utf
)
2762 oc
= UCD_OTHERCASE(first_char
);
2765 if (first_char
== oc
)
2766 found
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, first_char
);
2769 bit
= first_char
^ oc
;
2770 if (is_powerof2(bit
))
2772 OP2(SLJIT_OR
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, bit
);
2773 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, first_char
| bit
);
2777 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, first_char
);
2778 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
2779 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, oc
);
2780 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
2781 found
= JUMP(SLJIT_C_NOT_ZERO
);
2785 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2786 JUMPTO(SLJIT_JUMP
, start
);
2791 OP1(SLJIT_MOV
, STR_END
, 0, TMP3
, 0);
2794 static SLJIT_INLINE
void fast_forward_newline(compiler_common
*common
, BOOL firstline
)
2797 struct sljit_label
*loop
;
2798 struct sljit_jump
*lastchar
;
2799 struct sljit_jump
*firstchar
;
2800 struct sljit_jump
*quit
;
2801 struct sljit_jump
*foundcr
= NULL
;
2802 struct sljit_jump
*notfoundnl
;
2803 jump_list
*newline
= NULL
;
2807 SLJIT_ASSERT(common
->first_line_end
!= 0);
2808 OP1(SLJIT_MOV
, TMP3
, 0, STR_END
, 0);
2809 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
2812 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
2814 lastchar
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2815 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
2816 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
2817 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
2818 firstchar
= CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP2
, 0);
2820 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(2));
2821 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, STR_PTR
, 0, TMP1
, 0);
2822 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_GREATER_EQUAL
);
2823 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
2824 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, UCHAR_SHIFT
);
2826 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
2829 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2830 quit
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2831 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-2));
2832 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-1));
2833 CMPTO(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff, loop
);
2834 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff, loop
);
2837 JUMPHERE(firstchar
);
2841 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
2845 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
2846 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
2847 firstchar
= CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP2
, 0);
2848 skip_char_back(common
);
2852 lastchar
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2853 if (common
->nltype
== NLTYPE_ANY
|| common
->nltype
== NLTYPE_ANYCRLF
)
2854 foundcr
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
2855 check_newlinechar(common
, common
->nltype
, &newline
, FALSE
);
2856 set_jumps(newline
, loop
);
2858 if (common
->nltype
== NLTYPE_ANY
|| common
->nltype
== NLTYPE_ANYCRLF
)
2860 quit
= JUMP(SLJIT_JUMP
);
2862 notfoundnl
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2863 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2864 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
2865 OP_FLAGS(SLJIT_MOV
, TMP1
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
2866 #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
2867 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, UCHAR_SHIFT
);
2869 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2870 JUMPHERE(notfoundnl
);
2874 JUMPHERE(firstchar
);
2877 OP1(SLJIT_MOV
, STR_END
, 0, TMP3
, 0);
2880 static SLJIT_INLINE
void fast_forward_start_bits(compiler_common
*common
, sljit_uw start_bits
, BOOL firstline
)
2883 struct sljit_label
*start
;
2884 struct sljit_jump
*quit
;
2885 struct sljit_jump
*found
;
2886 #ifndef COMPILE_PCRE8
2887 struct sljit_jump
*jump
;
2892 SLJIT_ASSERT(common
->first_line_end
!= 0);
2893 OP1(SLJIT_MOV
, RETURN_ADDR
, 0, STR_END
, 0);
2894 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
2898 quit
= CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
2899 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
2902 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
2904 #ifndef COMPILE_PCRE8
2905 jump
= CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 255);
2906 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, 255);
2909 OP2(SLJIT_AND
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x7);
2910 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3);
2911 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), start_bits
);
2912 OP2(SLJIT_SHL
, TMP2
, 0, SLJIT_IMM
, 1, TMP2
, 0);
2913 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, TMP2
, 0);
2914 found
= JUMP(SLJIT_C_NOT_ZERO
);
2918 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
2920 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2922 #if defined COMPILE_PCRE8
2925 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0, start
);
2926 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_sw
)PRIV(utf8_table4
) - 0xc0);
2927 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2929 #elif defined COMPILE_PCRE16
2932 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800, start
);
2933 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
2934 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xd800);
2935 OP_FLAGS(SLJIT_MOV
, TMP1
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
2936 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
2937 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
2939 #endif /* COMPILE_PCRE[8|16] */
2940 #endif /* SUPPORT_UTF */
2941 JUMPTO(SLJIT_JUMP
, start
);
2946 OP1(SLJIT_MOV
, STR_END
, 0, RETURN_ADDR
, 0);
2949 static SLJIT_INLINE
struct sljit_jump
*search_requested_char(compiler_common
*common
, pcre_uchar req_char
, BOOL caseless
, BOOL has_firstchar
)
2952 struct sljit_label
*loop
;
2953 struct sljit_jump
*toolong
;
2954 struct sljit_jump
*alreadyfound
;
2955 struct sljit_jump
*found
;
2956 struct sljit_jump
*foundoc
= NULL
;
2957 struct sljit_jump
*notfound
;
2958 pcre_uint32 oc
, bit
;
2960 SLJIT_ASSERT(common
->req_char_ptr
!= 0);
2961 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->req_char_ptr
);
2962 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, REQ_BYTE_MAX
);
2963 toolong
= CMP(SLJIT_C_LESS
, TMP1
, 0, STR_END
, 0);
2964 alreadyfound
= CMP(SLJIT_C_LESS
, STR_PTR
, 0, TMP2
, 0);
2967 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
2969 OP1(SLJIT_MOV
, TMP1
, 0, STR_PTR
, 0);
2972 notfound
= CMP(SLJIT_C_GREATER_EQUAL
, TMP1
, 0, STR_END
, 0);
2974 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(TMP1
), 0);
2978 oc
= TABLE_GET(req_char
, common
->fcc
, req_char
);
2979 #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8)
2980 if (req_char
> 127 && common
->utf
)
2981 oc
= UCD_OTHERCASE(req_char
);
2985 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, req_char
);
2988 bit
= req_char
^ oc
;
2989 if (is_powerof2(bit
))
2991 OP2(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, bit
);
2992 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, req_char
| bit
);
2996 found
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, req_char
);
2997 foundoc
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, oc
);
3000 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(1));
3001 JUMPTO(SLJIT_JUMP
, loop
);
3006 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->req_char_ptr
, TMP1
, 0);
3007 JUMPHERE(alreadyfound
);
3012 static void do_revertframes(compiler_common
*common
)
3015 struct sljit_jump
*jump
;
3016 struct sljit_label
*mainloop
;
3018 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
3019 OP1(SLJIT_MOV
, TMP1
, 0, STACK_TOP
, 0);
3020 GET_LOCAL_BASE(TMP3
, 0, 0);
3022 /* Drop frames until we reach STACK_TOP. */
3024 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), 0);
3025 jump
= CMP(SLJIT_C_SIG_LESS_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_end
);
3026 OP2(SLJIT_ADD
, TMP2
, 0, TMP2
, 0, TMP3
, 0);
3027 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP2
), 0, SLJIT_MEM1(TMP1
), sizeof(sljit_sw
));
3028 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP2
), sizeof(sljit_sw
), SLJIT_MEM1(TMP1
), 2 * sizeof(sljit_sw
));
3029 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3 * sizeof(sljit_sw
));
3030 JUMPTO(SLJIT_JUMP
, mainloop
);
3033 jump
= CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_end
);
3034 /* End of dropping frames. */
3035 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
3038 jump
= CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_setstrbegin
);
3039 /* Set string begin. */
3040 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), sizeof(sljit_sw
));
3041 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 2 * sizeof(sljit_sw
));
3042 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), TMP2
, 0);
3043 JUMPTO(SLJIT_JUMP
, mainloop
);
3046 if (common
->mark_ptr
!= 0)
3048 jump
= CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, frame_setmark
);
3049 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), sizeof(sljit_sw
));
3050 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 2 * sizeof(sljit_sw
));
3051 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP2
, 0);
3052 JUMPTO(SLJIT_JUMP
, mainloop
);
3057 /* Unknown command. */
3058 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 2 * sizeof(sljit_sw
));
3059 JUMPTO(SLJIT_JUMP
, mainloop
);
3062 static void check_wordboundary(compiler_common
*common
)
3065 struct sljit_jump
*skipread
;
3066 #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF
3067 struct sljit_jump
*jump
;
3070 SLJIT_COMPILE_ASSERT(ctype_word
== 0x10, ctype_word_must_be_16
);
3072 sljit_emit_fast_enter(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
3073 /* Get type of the previous char, and put it to LOCALS1. */
3074 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
3075 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
3076 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, SLJIT_IMM
, 0);
3077 skipread
= CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP1
, 0);
3078 skip_char_back(common
);
3079 check_start_used_ptr(common
);
3082 /* Testing char type. */
3084 if (common
->use_ucp
)
3086 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 1);
3087 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_UNDERSCORE
);
3088 add_jump(compiler
, &common
->getucd
, JUMP(SLJIT_FAST_CALL
));
3089 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Ll
);
3090 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Lu
- ucp_Ll
);
3091 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_LESS_EQUAL
);
3092 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Nd
- ucp_Ll
);
3093 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_No
- ucp_Nd
);
3094 OP_FLAGS(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3096 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP2
, 0);
3101 #ifndef COMPILE_PCRE8
3102 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
3103 #elif defined SUPPORT_UTF
3104 /* Here LOCALS1 has already been zeroed. */
3107 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
3108 #endif /* COMPILE_PCRE8 */
3109 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), common
->ctypes
);
3110 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 4 /* ctype_word */);
3111 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
3112 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP1
, 0);
3113 #ifndef COMPILE_PCRE8
3115 #elif defined SUPPORT_UTF
3118 #endif /* COMPILE_PCRE8 */
3122 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
3123 skipread
= check_str_end(common
);
3126 /* Testing char type. This is a code duplication. */
3128 if (common
->use_ucp
)
3130 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 1);
3131 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_UNDERSCORE
);
3132 add_jump(compiler
, &common
->getucd
, JUMP(SLJIT_FAST_CALL
));
3133 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Ll
);
3134 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Lu
- ucp_Ll
);
3135 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_LESS_EQUAL
);
3136 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ucp_Nd
- ucp_Ll
);
3137 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ucp_No
- ucp_Nd
);
3138 OP_FLAGS(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3144 #ifndef COMPILE_PCRE8
3145 /* TMP2 may be destroyed by peek_char. */
3146 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
3147 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
3148 #elif defined SUPPORT_UTF
3149 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
3152 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
3154 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), common
->ctypes
);
3155 OP2(SLJIT_LSHR
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 4 /* ctype_word */);
3156 OP2(SLJIT_AND
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 1);
3157 #ifndef COMPILE_PCRE8
3159 #elif defined SUPPORT_UTF
3162 #endif /* COMPILE_PCRE8 */
3166 OP2(SLJIT_XOR
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
3167 sljit_emit_fast_return(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
3173 ranges[0] = length of the range (max MAX_RANGE_SIZE, -1 means invalid range).
3174 ranges[1] = first bit (0 or 1)
3175 ranges[2-length] = position of the bit change (when the current bit is not equal to the previous)
3178 static BOOL
check_ranges(compiler_common
*common
, int *ranges
, jump_list
**backtracks
, BOOL readch
)
3181 struct sljit_jump
*jump
;
3191 add_jump(compiler
, backtracks
, CMP(ranges
[1] == 0 ? SLJIT_C_LESS
: SLJIT_C_GREATER_EQUAL
, TMP1
, 0, SLJIT_IMM
, ranges
[2]));
3197 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ranges
[2]);
3198 add_jump(compiler
, backtracks
, CMP(ranges
[1] != 0 ? SLJIT_C_LESS
: SLJIT_C_GREATER_EQUAL
, TMP1
, 0, SLJIT_IMM
, ranges
[3] - ranges
[2]));
3202 if (ranges
[2] + 1 == ranges
[3] && ranges
[4] + 1 == ranges
[5])
3208 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, ranges
[2]));
3209 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, ranges
[4]));
3213 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, ranges
[2]);
3214 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, ranges
[4]));
3219 if ((ranges
[3] - ranges
[2]) == (ranges
[5] - ranges
[4]) && is_powerof2(ranges
[4] - ranges
[2]))
3223 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ranges
[4] - ranges
[2]);
3224 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, ranges
[4]);
3225 add_jump(compiler
, backtracks
, CMP(ranges
[1] != 0 ? SLJIT_C_LESS
: SLJIT_C_GREATER_EQUAL
, TMP1
, 0, SLJIT_IMM
, ranges
[5] - ranges
[4]));
3235 static void get_ctype_ranges(compiler_common
*common
, int flag
, int *ranges
)
3238 const pcre_uint8
*ctypes
= (const pcre_uint8
*)common
->ctypes
;
3240 bit
= ctypes
[0] & flag
;
3242 ranges
[1] = bit
!= 0 ? 1 : 0;
3245 for (i
= 1; i
< 256; i
++)
3246 if ((ctypes
[i
] & flag
) != bit
)
3248 if (length
>= MAX_RANGE_SIZE
)
3250 ranges
[2 + length
] = i
;
3257 if (length
>= MAX_RANGE_SIZE
)
3259 ranges
[2 + length
] = 256;
3265 static BOOL
check_class_ranges(compiler_common
*common
, const pcre_uint8
*bits
, BOOL nclass
, jump_list
**backtracks
)
3267 int ranges
[2 + MAX_RANGE_SIZE
];
3268 pcre_uint8 bit
, cbit
, all
;
3269 int i
, byte
, length
= 0;
3271 bit
= bits
[0] & 0x1;
3273 /* Can be 0 or 255. */
3276 for (i
= 0; i
< 256; )
3279 if ((i
& 0x7) == 0 && bits
[byte
] == all
)
3283 cbit
= (bits
[byte
] >> (i
& 0x7)) & 0x1;
3286 if (length
>= MAX_RANGE_SIZE
)
3288 ranges
[2 + length
] = i
;
3297 if (((bit
== 0) && nclass
) || ((bit
== 1) && !nclass
))
3299 if (length
>= MAX_RANGE_SIZE
)
3301 ranges
[2 + length
] = 256;
3306 return check_ranges(common
, ranges
, backtracks
, FALSE
);
3309 static void check_anynewline(compiler_common
*common
)
3311 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
3314 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
3316 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x0a);
3317 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x0d - 0x0a);
3318 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_LESS_EQUAL
);
3319 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x85 - 0x0a);
3320 #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
3321 #ifdef COMPILE_PCRE8
3325 OP_FLAGS(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3326 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x1);
3327 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x2029 - 0x0a);
3328 #ifdef COMPILE_PCRE8
3331 #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
3332 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3333 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
3336 static void check_hspace(compiler_common
*common
)
3338 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
3341 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
3343 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x09);
3344 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
3345 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x20);
3346 OP_FLAGS(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3347 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xa0);
3348 #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
3349 #ifdef COMPILE_PCRE8
3353 OP_FLAGS(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3354 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x1680);
3355 OP_FLAGS(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3356 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x180e);
3357 OP_FLAGS(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3358 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x2000);
3359 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x200A - 0x2000);
3360 OP_FLAGS(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3361 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x202f - 0x2000);
3362 OP_FLAGS(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3363 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x205f - 0x2000);
3364 OP_FLAGS(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3365 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x3000 - 0x2000);
3366 #ifdef COMPILE_PCRE8
3369 #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
3370 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3372 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
3375 static void check_vspace(compiler_common
*common
)
3377 /* Check whether TMP1 contains a newline character. TMP2 destroyed. */
3380 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
3382 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x0a);
3383 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x0d - 0x0a);
3384 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_LESS_EQUAL
);
3385 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x85 - 0x0a);
3386 #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
3387 #ifdef COMPILE_PCRE8
3391 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3392 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0x1);
3393 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0x2029 - 0x0a);
3394 #ifdef COMPILE_PCRE8
3397 #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */
3398 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3400 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
3403 #define CHAR1 STR_END
3404 #define CHAR2 STACK_TOP
3406 static void do_casefulcmp(compiler_common
*common
)
3409 struct sljit_jump
*jump
;
3410 struct sljit_label
*label
;
3412 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
3413 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
3414 OP1(SLJIT_MOV
, TMP3
, 0, CHAR1
, 0);
3415 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, CHAR2
, 0);
3416 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(1));
3417 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3420 OP1(MOVU_UCHAR
, CHAR1
, 0, SLJIT_MEM1(TMP1
), IN_UCHARS(1));
3421 OP1(MOVU_UCHAR
, CHAR2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
3422 jump
= CMP(SLJIT_C_NOT_EQUAL
, CHAR1
, 0, CHAR2
, 0);
3423 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
3424 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
3427 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3428 OP1(SLJIT_MOV
, CHAR1
, 0, TMP3
, 0);
3429 OP1(SLJIT_MOV
, CHAR2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
3430 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
3433 #define LCC_TABLE STACK_LIMIT
3435 static void do_caselesscmp(compiler_common
*common
)
3438 struct sljit_jump
*jump
;
3439 struct sljit_label
*label
;
3441 sljit_emit_fast_enter(compiler
, RETURN_ADDR
, 0);
3442 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
3444 OP1(SLJIT_MOV
, TMP3
, 0, LCC_TABLE
, 0);
3445 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, CHAR1
, 0);
3446 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, CHAR2
, 0);
3447 OP1(SLJIT_MOV
, LCC_TABLE
, 0, SLJIT_IMM
, common
->lcc
);
3448 OP2(SLJIT_SUB
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, IN_UCHARS(1));
3449 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3452 OP1(MOVU_UCHAR
, CHAR1
, 0, SLJIT_MEM1(TMP1
), IN_UCHARS(1));
3453 OP1(MOVU_UCHAR
, CHAR2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
3454 #ifndef COMPILE_PCRE8
3455 jump
= CMP(SLJIT_C_GREATER
, CHAR1
, 0, SLJIT_IMM
, 255);
3457 OP1(SLJIT_MOV_UB
, CHAR1
, 0, SLJIT_MEM2(LCC_TABLE
, CHAR1
), 0);
3458 #ifndef COMPILE_PCRE8
3460 jump
= CMP(SLJIT_C_GREATER
, CHAR2
, 0, SLJIT_IMM
, 255);
3462 OP1(SLJIT_MOV_UB
, CHAR2
, 0, SLJIT_MEM2(LCC_TABLE
, CHAR2
), 0);
3463 #ifndef COMPILE_PCRE8
3466 jump
= CMP(SLJIT_C_NOT_EQUAL
, CHAR1
, 0, CHAR2
, 0);
3467 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, IN_UCHARS(1));
3468 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
3471 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
3472 OP1(SLJIT_MOV
, LCC_TABLE
, 0, TMP3
, 0);
3473 OP1(SLJIT_MOV
, CHAR1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
3474 OP1(SLJIT_MOV
, CHAR2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
3475 sljit_emit_fast_return(compiler
, RETURN_ADDR
, 0);
3482 #if defined SUPPORT_UTF && defined SUPPORT_UCP
3484 static const pcre_uchar
*SLJIT_CALL
do_utf_caselesscmp(pcre_uchar
*src1
, jit_arguments
*args
, pcre_uchar
*end1
)
3486 /* This function would be ineffective to do in JIT level. */
3488 const pcre_uchar
*src2
= args
->uchar_ptr
;
3489 const pcre_uchar
*end2
= args
->end
;
3490 const ucd_record
*ur
;
3491 const pcre_uint32
*pp
;
3496 return (pcre_uchar
*)1;
3497 GETCHARINC(c1
, src1
);
3498 GETCHARINC(c2
, src2
);
3500 if (c1
!= c2
&& c1
!= c2
+ ur
->other_case
)
3502 pp
= PRIV(ucd_caseless_sets
) + ur
->caseset
;
3505 if (c1
< *pp
) return NULL
;
3506 if (c1
== *pp
++) break;
3513 #endif /* SUPPORT_UTF && SUPPORT_UCP */
3515 static pcre_uchar
*byte_sequence_compare(compiler_common
*common
, BOOL caseless
, pcre_uchar
*cc
,
3516 compare_context
* context
, jump_list
**backtracks
)
3519 unsigned int othercasebit
= 0;
3520 pcre_uchar
*othercasechar
= NULL
;
3525 if (caseless
&& char_has_othercase(common
, cc
))
3527 othercasebit
= char_get_othercase_bit(common
, cc
);
3528 SLJIT_ASSERT(othercasebit
);
3529 /* Extracting bit difference info. */
3530 #if defined COMPILE_PCRE8
3531 othercasechar
= cc
+ (othercasebit
>> 8);
3532 othercasebit
&= 0xff;
3533 #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
3534 /* Note that this code only handles characters in the BMP. If there
3535 ever are characters outside the BMP whose othercase differs in only one
3536 bit from itself (there currently are none), this code will need to be
3537 revised for COMPILE_PCRE32. */
3538 othercasechar
= cc
+ (othercasebit
>> 9);
3539 if ((othercasebit
& 0x100) != 0)
3540 othercasebit
= (othercasebit
& 0xff) << 8;
3542 othercasebit
&= 0xff;
3543 #endif /* COMPILE_PCRE[8|16|32] */
3546 if (context
->sourcereg
== -1)
3548 #if defined COMPILE_PCRE8
3549 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3550 if (context
->length
>= 4)
3551 OP1(SLJIT_MOV_SI
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3552 else if (context
->length
>= 2)
3553 OP1(SLJIT_MOV_UH
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3556 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3557 #elif defined COMPILE_PCRE16
3558 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3559 if (context
->length
>= 4)
3560 OP1(SLJIT_MOV_SI
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3563 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3564 #elif defined COMPILE_PCRE32
3565 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3566 #endif /* COMPILE_PCRE[8|16|32] */
3567 context
->sourcereg
= TMP2
;
3572 if (common
->utf
&& HAS_EXTRALEN(*cc
))
3573 utflength
+= GET_EXTRALEN(*cc
);
3579 context
->length
-= IN_UCHARS(1);
3580 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
3582 /* Unaligned read is supported. */
3583 if (othercasebit
!= 0 && othercasechar
== cc
)
3585 context
->c
.asuchars
[context
->ucharptr
] = *cc
| othercasebit
;
3586 context
->oc
.asuchars
[context
->ucharptr
] = othercasebit
;
3590 context
->c
.asuchars
[context
->ucharptr
] = *cc
;
3591 context
->oc
.asuchars
[context
->ucharptr
] = 0;
3593 context
->ucharptr
++;
3595 #if defined COMPILE_PCRE8
3596 if (context
->ucharptr
>= 4 || context
->length
== 0 || (context
->ucharptr
== 2 && context
->length
== 1))
3597 #elif defined COMPILE_PCRE16
3598 if (context
->ucharptr
>= 2 || context
->length
== 0)
3599 #elif defined COMPILE_PCRE32
3600 if (1 /* context->ucharptr >= 1 || context->length == 0 */)
3603 #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
3604 if (context
->length
>= 4)
3605 OP1(SLJIT_MOV_SI
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3606 #if defined COMPILE_PCRE8
3607 else if (context
->length
>= 2)
3608 OP1(SLJIT_MOV_UH
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3609 else if (context
->length
>= 1)
3610 OP1(SLJIT_MOV_UB
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3611 #elif defined COMPILE_PCRE16
3612 else if (context
->length
>= 2)
3613 OP1(SLJIT_MOV_UH
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3614 #endif /* COMPILE_PCRE[8|16] */
3615 #elif defined COMPILE_PCRE32
3616 OP1(MOV_UCHAR
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3617 #endif /* COMPILE_PCRE[8|16|32] */
3618 context
->sourcereg
= context
->sourcereg
== TMP1
? TMP2
: TMP1
;
3620 switch(context
->ucharptr
)
3622 case 4 / sizeof(pcre_uchar
):
3623 if (context
->oc
.asint
!= 0)
3624 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, context
->oc
.asint
);
3625 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, context
->c
.asint
| context
->oc
.asint
));
3628 #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
3629 case 2 / sizeof(pcre_uchar
):
3630 if (context
->oc
.asushort
!= 0)
3631 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, context
->oc
.asushort
);
3632 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, context
->c
.asushort
| context
->oc
.asushort
));
3635 #ifdef COMPILE_PCRE8
3637 if (context
->oc
.asbyte
!= 0)
3638 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, context
->oc
.asbyte
);
3639 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, context
->c
.asbyte
| context
->oc
.asbyte
));
3643 #endif /* COMPILE_PCRE[8|16] */
3646 SLJIT_ASSERT_STOP();
3649 context
->ucharptr
= 0;
3654 /* Unaligned read is unsupported. */
3655 if (context
->length
> 0)
3656 OP1(MOV_UCHAR
, context
->sourcereg
, 0, SLJIT_MEM1(STR_PTR
), -context
->length
);
3658 context
->sourcereg
= context
->sourcereg
== TMP1
? TMP2
: TMP1
;
3660 if (othercasebit
!= 0 && othercasechar
== cc
)
3662 OP2(SLJIT_OR
, context
->sourcereg
, 0, context
->sourcereg
, 0, SLJIT_IMM
, othercasebit
);
3663 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, *cc
| othercasebit
));
3666 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, context
->sourcereg
, 0, SLJIT_IMM
, *cc
));
3674 while (utflength
> 0);
3680 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
3682 #define SET_TYPE_OFFSET(value) \
3683 if ((value) != typeoffset) \
3685 if ((value) > typeoffset) \
3686 OP2(SLJIT_SUB, typereg, 0, typereg, 0, SLJIT_IMM, (value) - typeoffset); \
3688 OP2(SLJIT_ADD, typereg, 0, typereg, 0, SLJIT_IMM, typeoffset - (value)); \
3690 typeoffset = (value);
3692 #define SET_CHAR_OFFSET(value) \
3693 if ((value) != charoffset) \
3695 if ((value) > charoffset) \
3696 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, (value) - charoffset); \
3698 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, charoffset - (value)); \
3700 charoffset = (value);
3702 static void compile_xclass_matchingpath(compiler_common
*common
, pcre_uchar
*cc
, jump_list
**backtracks
)
3705 jump_list
*found
= NULL
;
3706 jump_list
**list
= (*cc
& XCL_NOT
) == 0 ? &found
: backtracks
;
3707 pcre_int32 c
, charoffset
;
3708 const pcre_uint32
*other_cases
;
3709 struct sljit_jump
*jump
= NULL
;
3710 pcre_uchar
*ccbegin
;
3711 int compares
, invertcmp
, numberofcmps
;
3713 BOOL needstype
= FALSE
, needsscript
= FALSE
, needschar
= FALSE
;
3714 BOOL charsaved
= FALSE
;
3715 int typereg
= TMP1
, scriptreg
= TMP1
;
3716 pcre_int32 typeoffset
;
3719 /* Although SUPPORT_UTF must be defined, we are
3720 not necessary in utf mode even in 8 bit mode. */
3721 detect_partial_match(common
, backtracks
);
3724 if ((*cc
++ & XCL_MAP
) != 0)
3726 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
3727 #ifndef COMPILE_PCRE8
3728 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
3729 #elif defined SUPPORT_UTF
3731 jump
= CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
3734 if (!check_class_ranges(common
, (const pcre_uint8
*)cc
, TRUE
, list
))
3736 OP2(SLJIT_AND
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x7);
3737 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3);
3738 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_sw
)cc
);
3739 OP2(SLJIT_SHL
, TMP2
, 0, SLJIT_IMM
, 1, TMP2
, 0);
3740 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, TMP2
, 0);
3741 add_jump(compiler
, list
, JUMP(SLJIT_C_NOT_ZERO
));
3744 #ifndef COMPILE_PCRE8
3746 #elif defined SUPPORT_UTF
3750 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
3754 cc
+= 32 / sizeof(pcre_uchar
);
3757 /* Scanning the necessary info. */
3760 while (*cc
!= XCL_END
)
3763 if (*cc
== XCL_SINGLE
)
3767 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
3773 else if (*cc
== XCL_RANGE
)
3777 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
3781 if (common
->utf
&& HAS_EXTRALEN(cc
[-1])) cc
+= GET_EXTRALEN(cc
[-1]);
3790 SLJIT_ASSERT(*cc
== XCL_PROP
|| *cc
== XCL_NOTPROP
);
3820 SLJIT_ASSERT_STOP();
3829 /* Simple register allocation. TMP1 is preferred if possible. */
3830 if (needstype
|| needsscript
)
3832 if (needschar
&& !charsaved
)
3833 OP1(SLJIT_MOV
, TMP3
, 0, TMP1
, 0);
3834 add_jump(compiler
, &common
->getucd
, JUMP(SLJIT_FAST_CALL
));
3839 OP1(SLJIT_MOV
, RETURN_ADDR
, 0, TMP1
, 0);
3840 typereg
= RETURN_ADDR
;
3845 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
3847 else if (needstype
&& needsscript
)
3849 /* In all other cases only one of them was specified, and that can goes to TMP1. */
3853 if (scriptreg
== TMP1
)
3855 OP1(SLJIT_MOV
, scriptreg
, 0, SLJIT_IMM
, (sljit_sw
)PRIV(ucd_records
) + SLJIT_OFFSETOF(ucd_record
, script
));
3856 OP1(SLJIT_MOV_UB
, scriptreg
, 0, SLJIT_MEM2(scriptreg
, TMP2
), 3);
3860 OP2(SLJIT_SHL
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 3);
3861 OP2(SLJIT_ADD
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, (sljit_sw
)PRIV(ucd_records
) + SLJIT_OFFSETOF(ucd_record
, script
));
3862 OP1(SLJIT_MOV_UB
, scriptreg
, 0, SLJIT_MEM1(TMP2
), 0);
3868 /* Generating code. */
3876 while (*cc
!= XCL_END
)
3879 invertcmp
= (compares
== 0 && list
!= backtracks
);
3882 if (*cc
== XCL_SINGLE
)
3894 if (numberofcmps
< 3 && (*cc
== XCL_SINGLE
|| *cc
== XCL_RANGE
))
3896 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3897 OP_FLAGS(numberofcmps
== 0 ? SLJIT_MOV
: SLJIT_OR
, TMP2
, 0, numberofcmps
== 0 ? SLJIT_UNUSED
: TMP2
, 0, SLJIT_C_EQUAL
);
3900 else if (numberofcmps
> 0)
3902 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3903 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3904 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3909 jump
= CMP(SLJIT_C_EQUAL
^ invertcmp
, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3913 else if (*cc
== XCL_RANGE
)
3933 if (numberofcmps
< 3 && (*cc
== XCL_SINGLE
|| *cc
== XCL_RANGE
))
3935 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3936 OP_FLAGS(numberofcmps
== 0 ? SLJIT_MOV
: SLJIT_OR
, TMP2
, 0, numberofcmps
== 0 ? SLJIT_UNUSED
: TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3939 else if (numberofcmps
> 0)
3941 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3942 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
3943 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3948 jump
= CMP(SLJIT_C_LESS_EQUAL
^ invertcmp
, TMP1
, 0, SLJIT_IMM
, c
- charoffset
);
3955 if (*cc
== XCL_NOTPROP
)
3961 if (list
!= backtracks
)
3963 if ((cc
[-1] == XCL_NOTPROP
&& compares
> 0) || (cc
[-1] == XCL_PROP
&& compares
== 0))
3966 else if (cc
[-1] == XCL_NOTPROP
)
3968 jump
= JUMP(SLJIT_JUMP
);
3972 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Lu
- typeoffset
);
3973 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
3974 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Ll
- typeoffset
);
3975 OP_FLAGS(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3976 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Lt
- typeoffset
);
3977 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
3978 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
3982 c
= PRIV(ucp_typerange
)[(int)cc
[1] * 2];
3984 jump
= CMP(SLJIT_C_LESS_EQUAL
^ invertcmp
, typereg
, 0, SLJIT_IMM
, PRIV(ucp_typerange
)[(int)cc
[1] * 2 + 1] - c
);
3988 jump
= CMP(SLJIT_C_EQUAL
^ invertcmp
, typereg
, 0, SLJIT_IMM
, (int)cc
[1] - typeoffset
);
3992 jump
= CMP(SLJIT_C_EQUAL
^ invertcmp
, scriptreg
, 0, SLJIT_IMM
, (int)cc
[1]);
3997 if (*cc
== PT_SPACE
)
3999 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, 0);
4000 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 11 - charoffset
);
4003 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 13 - 9);
4004 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_LESS_EQUAL
);
4005 if (*cc
== PT_SPACE
)
4008 SET_TYPE_OFFSET(ucp_Zl
);
4009 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Zs
- ucp_Zl
);
4010 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
4011 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
4015 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, CHAR_UNDERSCORE
- charoffset
);
4016 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
4017 /* ... fall through */
4020 SET_TYPE_OFFSET(ucp_Ll
);
4021 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_Lu
- ucp_Ll
);
4022 OP_FLAGS((*cc
== PT_ALNUM
) ? SLJIT_MOV
: SLJIT_OR
, TMP2
, 0, (*cc
== PT_ALNUM
) ? SLJIT_UNUSED
: TMP2
, 0, SLJIT_C_LESS_EQUAL
);
4023 SET_TYPE_OFFSET(ucp_Nd
);
4024 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, typereg
, 0, SLJIT_IMM
, ucp_No
- ucp_Nd
);
4025 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_LESS_EQUAL
);
4026 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
4030 other_cases
= PRIV(ucd_caseless_sets
) + cc
[1];
4032 /* At least three characters are required.
4033 Otherwise this case would be handled by the normal code path. */
4034 SLJIT_ASSERT(other_cases
[0] != NOTACHAR
&& other_cases
[1] != NOTACHAR
&& other_cases
[2] != NOTACHAR
);
4035 SLJIT_ASSERT(other_cases
[0] < other_cases
[1] && other_cases
[1] < other_cases
[2]);
4037 /* Optimizing character pairs, if their difference is power of 2. */
4038 if (is_powerof2(other_cases
[1] ^ other_cases
[0]))
4040 if (charoffset
== 0)
4041 OP2(SLJIT_OR
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, other_cases
[1] ^ other_cases
[0]);
4044 OP2(SLJIT_ADD
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, (sljit_sw
)charoffset
);
4045 OP2(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, other_cases
[1] ^ other_cases
[0]);
4047 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP2
, 0, SLJIT_IMM
, other_cases
[1]);
4048 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
4051 else if (is_powerof2(other_cases
[2] ^ other_cases
[1]))
4053 if (charoffset
== 0)
4054 OP2(SLJIT_OR
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, other_cases
[2] ^ other_cases
[1]);
4057 OP2(SLJIT_ADD
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, (sljit_sw
)charoffset
);
4058 OP2(SLJIT_OR
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, other_cases
[1] ^ other_cases
[0]);
4060 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP2
, 0, SLJIT_IMM
, other_cases
[2]);
4061 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
4063 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, other_cases
[0] - charoffset
);
4064 OP_FLAGS(SLJIT_OR
| ((other_cases
[3] == NOTACHAR
) ? SLJIT_SET_E
: 0), TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
4070 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, *other_cases
++ - charoffset
);
4071 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
4074 while (*other_cases
!= NOTACHAR
)
4076 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, *other_cases
++ - charoffset
);
4077 OP_FLAGS(SLJIT_OR
| ((*other_cases
== NOTACHAR
) ? SLJIT_SET_E
: 0), TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
4079 jump
= JUMP(SLJIT_C_NOT_ZERO
^ invertcmp
);
4087 add_jump(compiler
, compares
> 0 ? list
: backtracks
, jump
);
4091 set_jumps(found
, LABEL());
4094 #undef SET_TYPE_OFFSET
4095 #undef SET_CHAR_OFFSET
4099 static pcre_uchar
*compile_char1_matchingpath(compiler_common
*common
, pcre_uchar type
, pcre_uchar
*cc
, jump_list
**backtracks
)
4103 unsigned int c
, oc
, bit
;
4104 compare_context context
;
4105 struct sljit_jump
*jump
[4];
4107 struct sljit_label
*label
;
4109 pcre_uchar propdata
[5];
4116 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
4117 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
4118 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, TMP1
, 0));
4122 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
4123 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
4124 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, TMP1
, 0));
4127 case OP_NOT_WORD_BOUNDARY
:
4128 case OP_WORD_BOUNDARY
:
4129 add_jump(compiler
, &common
->wordboundary
, JUMP(SLJIT_FAST_CALL
));
4130 add_jump(compiler
, backtracks
, JUMP(type
== OP_NOT_WORD_BOUNDARY
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
4135 /* Digits are usually 0-9, so it is worth to optimize them. */
4136 if (common
->digits
[0] == -2)
4137 get_ctype_ranges(common
, ctype_digit
, common
->digits
);
4138 detect_partial_match(common
, backtracks
);
4139 /* Flip the starting bit in the negative case. */
4140 if (type
== OP_NOT_DIGIT
)
4141 common
->digits
[1] ^= 1;
4142 if (!check_ranges(common
, common
->digits
, backtracks
, TRUE
))
4144 read_char8_type(common
);
4145 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ctype_digit
);
4146 add_jump(compiler
, backtracks
, JUMP(type
== OP_DIGIT
? SLJIT_C_ZERO
: SLJIT_C_NOT_ZERO
));
4148 if (type
== OP_NOT_DIGIT
)
4149 common
->digits
[1] ^= 1;
4152 case OP_NOT_WHITESPACE
:
4154 detect_partial_match(common
, backtracks
);
4155 read_char8_type(common
);
4156 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ctype_space
);
4157 add_jump(compiler
, backtracks
, JUMP(type
== OP_WHITESPACE
? SLJIT_C_ZERO
: SLJIT_C_NOT_ZERO
));
4160 case OP_NOT_WORDCHAR
:
4162 detect_partial_match(common
, backtracks
);
4163 read_char8_type(common
);
4164 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, ctype_word
);
4165 add_jump(compiler
, backtracks
, JUMP(type
== OP_WORDCHAR
? SLJIT_C_ZERO
: SLJIT_C_NOT_ZERO
));
4169 detect_partial_match(common
, backtracks
);
4171 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
4173 jump
[0] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff);
4174 if (common
->mode
!= JIT_PARTIAL_HARD_COMPILE
)
4175 jump
[1] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
4177 jump
[1] = check_str_end(common
);
4179 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
4180 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, common
->newline
& 0xff));
4181 if (jump
[1] != NULL
)
4186 check_newlinechar(common
, common
->nltype
, backtracks
, TRUE
);
4190 detect_partial_match(common
, backtracks
);
4194 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
4195 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
4196 #if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
4197 #if defined COMPILE_PCRE8
4198 jump
[0] = CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
4199 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_sw
)PRIV(utf8_table4
) - 0xc0);
4200 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
4201 #elif defined COMPILE_PCRE16
4202 jump
[0] = CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xd800);
4203 OP2(SLJIT_AND
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 0xfc00);
4204 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, 0xd800);
4205 OP_FLAGS(SLJIT_MOV
, TMP1
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
4206 OP2(SLJIT_SHL
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
4207 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
4210 #endif /* COMPILE_PCRE[8|16] */
4214 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
4218 detect_partial_match(common
, backtracks
);
4219 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
4227 propdata
[1] = type
== OP_NOTPROP
? XCL_NOTPROP
: XCL_PROP
;
4228 propdata
[2] = cc
[0];
4229 propdata
[3] = cc
[1];
4230 propdata
[4] = XCL_END
;
4231 compile_xclass_matchingpath(common
, propdata
, backtracks
);
4237 detect_partial_match(common
, backtracks
);
4239 jump
[0] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
4240 /* We don't need to handle soft partial matching case. */
4241 if (common
->mode
!= JIT_PARTIAL_HARD_COMPILE
)
4242 jump
[1] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
4244 jump
[1] = check_str_end(common
);
4245 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
4246 jump
[2] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
4247 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
4248 jump
[3] = JUMP(SLJIT_JUMP
);
4250 check_newlinechar(common
, common
->bsr_nltype
, backtracks
, FALSE
);
4258 detect_partial_match(common
, backtracks
);
4260 add_jump(compiler
, &common
->hspace
, JUMP(SLJIT_FAST_CALL
));
4261 add_jump(compiler
, backtracks
, JUMP(type
== OP_NOT_HSPACE
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
4266 detect_partial_match(common
, backtracks
);
4268 add_jump(compiler
, &common
->vspace
, JUMP(SLJIT_FAST_CALL
));
4269 add_jump(compiler
, backtracks
, JUMP(type
== OP_NOT_VSPACE
? SLJIT_C_NOT_ZERO
: SLJIT_C_ZERO
));
4274 detect_partial_match(common
, backtracks
);
4276 add_jump(compiler
, &common
->getucd
, JUMP(SLJIT_FAST_CALL
));
4277 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, (sljit_sw
)PRIV(ucd_records
) + SLJIT_OFFSETOF(ucd_record
, gbprop
));
4278 /* Optimize register allocation: use a real register. */
4279 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, STACK_TOP
, 0);
4280 OP1(SLJIT_MOV_UB
, STACK_TOP
, 0, SLJIT_MEM2(TMP1
, TMP2
), 3);
4283 jump
[0] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
4284 OP1(SLJIT_MOV
, TMP3
, 0, STR_PTR
, 0);
4286 add_jump(compiler
, &common
->getucd
, JUMP(SLJIT_FAST_CALL
));
4287 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_IMM
, (sljit_sw
)PRIV(ucd_records
) + SLJIT_OFFSETOF(ucd_record
, gbprop
));
4288 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM2(TMP1
, TMP2
), 3);
4290 OP2(SLJIT_SHL
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, 2);
4291 OP1(SLJIT_MOV_UI
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), (sljit_sw
)PRIV(ucp_gbtable
));
4292 OP1(SLJIT_MOV
, STACK_TOP
, 0, TMP2
, 0);
4293 OP2(SLJIT_SHL
, TMP2
, 0, SLJIT_IMM
, 1, TMP2
, 0);
4294 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, TMP2
, 0);
4295 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
4297 OP1(SLJIT_MOV
, STR_PTR
, 0, TMP3
, 0);
4299 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
4301 if (common
->mode
== JIT_PARTIAL_HARD_COMPILE
)
4303 jump
[0] = CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
4304 /* Since we successfully read a char above, partial matching must occure. */
4305 check_partial(common
, TRUE
);
4312 /* Requires rather complex checks. */
4313 jump
[0] = CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0);
4314 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
4316 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
4317 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
4318 if (common
->mode
== JIT_COMPILE
)
4319 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_END
, 0));
4322 jump
[1] = CMP(SLJIT_C_EQUAL
, TMP2
, 0, STR_END
, 0);
4323 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP2
, 0, STR_END
, 0);
4324 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_LESS
);
4325 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff);
4326 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_NOT_EQUAL
);
4327 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_NOT_EQUAL
));
4328 check_partial(common
, TRUE
);
4329 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
4332 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
4333 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
4334 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff));
4336 else if (common
->nltype
== NLTYPE_FIXED
)
4338 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
4339 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
4340 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_END
, 0));
4341 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, common
->newline
));
4345 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
4346 jump
[1] = CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_CR
);
4347 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
4348 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP2
, 0, STR_END
, 0);
4349 jump
[2] = JUMP(SLJIT_C_GREATER
);
4350 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_LESS
));
4352 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
4353 jump
[3] = CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_NL
);
4354 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
4357 if (common
->nltype
== NLTYPE_ANYCRLF
)
4359 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
4360 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, TMP2
, 0, STR_END
, 0));
4361 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, CHAR_NL
));
4365 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, STR_PTR
, 0);
4367 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, STR_END
, 0));
4368 add_jump(compiler
, &common
->anynewline
, JUMP(SLJIT_FAST_CALL
));
4369 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_ZERO
));
4370 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
4376 check_partial(common
, FALSE
);
4380 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0));
4381 check_partial(common
, FALSE
);
4385 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
4386 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, begin
));
4387 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, STR_PTR
, 0, TMP1
, 0));
4388 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, notbol
));
4389 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
4393 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
4394 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, begin
));
4395 jump
[1] = CMP(SLJIT_C_GREATER
, STR_PTR
, 0, TMP1
, 0);
4396 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, notbol
));
4397 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
4398 jump
[0] = JUMP(SLJIT_JUMP
);
4401 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER_EQUAL
, STR_PTR
, 0, STR_END
, 0));
4402 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
4404 OP2(SLJIT_SUB
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
4405 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, TMP2
, 0, TMP1
, 0));
4406 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-2));
4407 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(-1));
4408 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
4409 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff));
4413 skip_char_back(common
);
4415 check_newlinechar(common
, common
->nltype
, backtracks
, FALSE
);
4421 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
4422 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, noteol
));
4423 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
4425 if (!common
->endonly
)
4426 compile_char1_matchingpath(common
, OP_EODN
, cc
, backtracks
);
4429 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0));
4430 check_partial(common
, FALSE
);
4435 jump
[1] = CMP(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0);
4436 OP1(SLJIT_MOV
, TMP2
, 0, ARGUMENTS
, 0);
4437 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(jit_arguments
, noteol
));
4438 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
4439 check_partial(common
, FALSE
);
4440 jump
[0] = JUMP(SLJIT_JUMP
);
4443 if (common
->nltype
== NLTYPE_FIXED
&& common
->newline
> 255)
4445 OP2(SLJIT_ADD
, TMP2
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(2));
4446 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(0));
4447 if (common
->mode
== JIT_COMPILE
)
4448 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, TMP2
, 0, STR_END
, 0));
4451 jump
[1] = CMP(SLJIT_C_LESS_EQUAL
, TMP2
, 0, STR_END
, 0);
4452 /* STR_PTR = STR_END - IN_UCHARS(1) */
4453 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
4454 check_partial(common
, TRUE
);
4455 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
4459 OP1(MOV_UCHAR
, TMP2
, 0, SLJIT_MEM1(STR_PTR
), IN_UCHARS(1));
4460 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, (common
->newline
>> 8) & 0xff));
4461 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, common
->newline
& 0xff));
4466 check_newlinechar(common
, common
->nltype
, backtracks
, FALSE
);
4475 if (common
->utf
&& HAS_EXTRALEN(*cc
)) length
+= GET_EXTRALEN(*cc
);
4477 if (common
->mode
== JIT_COMPILE
&& (type
== OP_CHAR
|| !char_has_othercase(common
, cc
) || char_get_othercase_bit(common
, cc
) != 0))
4479 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(length
));
4480 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, STR_PTR
, 0, STR_END
, 0));
4482 context
.length
= IN_UCHARS(length
);
4483 context
.sourcereg
= -1;
4484 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
4485 context
.ucharptr
= 0;
4487 return byte_sequence_compare(common
, type
== OP_CHARI
, cc
, &context
, backtracks
);
4489 detect_partial_match(common
, backtracks
);
4499 if (type
== OP_CHAR
|| !char_has_othercase(common
, cc
))
4501 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
4504 oc
= char_othercase(common
, c
);
4506 if (is_powerof2(bit
))
4508 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, bit
);
4509 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
| bit
));
4512 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, c
);
4513 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
4514 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_IMM
, oc
);
4515 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
4516 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_ZERO
));
4521 detect_partial_match(common
, backtracks
);
4526 #ifdef COMPILE_PCRE8
4530 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(STR_PTR
), 0);
4531 if (type
== OP_NOT
|| !char_has_othercase(common
, cc
))
4532 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
4535 /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */
4536 OP2(SLJIT_OR
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x20);
4537 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, c
| 0x20));
4539 /* Skip the variable-length character. */
4540 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(1));
4541 jump
[0] = CMP(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, 0xc0);
4542 OP1(MOV_UCHAR
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_sw
)PRIV(utf8_table4
) - 0xc0);
4543 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP1
, 0);
4548 #endif /* COMPILE_PCRE8 */
4550 GETCHARLEN(c
, cc
, length
);
4555 #endif /* SUPPORT_UTF */
4561 if (type
== OP_NOT
|| !char_has_othercase(common
, cc
))
4562 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
4565 oc
= char_othercase(common
, c
);
4567 if (is_powerof2(bit
))
4569 OP2(SLJIT_OR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, bit
);
4570 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
| bit
));
4574 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, c
));
4575 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, oc
));
4582 detect_partial_match(common
, backtracks
);
4584 if (check_class_ranges(common
, (const pcre_uint8
*)cc
, type
== OP_NCLASS
, backtracks
))
4585 return cc
+ 32 / sizeof(pcre_uchar
);
4587 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
4589 #ifdef COMPILE_PCRE8
4590 /* This check only affects 8 bit mode. In other modes, we
4591 always need to compare the value with 255. */
4593 #endif /* COMPILE_PCRE8 */
4595 jump
[0] = CMP(SLJIT_C_GREATER
, TMP1
, 0, SLJIT_IMM
, 255);
4596 if (type
== OP_CLASS
)
4598 add_jump(compiler
, backtracks
, jump
[0]);
4602 #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
4603 OP2(SLJIT_AND
, TMP2
, 0, TMP1
, 0, SLJIT_IMM
, 0x7);
4604 OP2(SLJIT_LSHR
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 3);
4605 OP1(SLJIT_MOV_UB
, TMP1
, 0, SLJIT_MEM1(TMP1
), (sljit_sw
)cc
);
4606 OP2(SLJIT_SHL
, TMP2
, 0, SLJIT_IMM
, 1, TMP2
, 0);
4607 OP2(SLJIT_AND
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, TMP2
, 0);
4608 add_jump(compiler
, backtracks
, JUMP(SLJIT_C_ZERO
));
4609 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
4610 if (jump
[0] != NULL
)
4612 #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */
4613 return cc
+ 32 / sizeof(pcre_uchar
);
4615 #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
4617 compile_xclass_matchingpath(common
, cc
+ LINK_SIZE
, backtracks
);
4618 return cc
+ GET(cc
, 0) - 1;
4622 length
= GET(cc
, 0);
4624 return cc
+ LINK_SIZE
;
4625 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
4629 OP1(SLJIT_MOV
, TMP3
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
4630 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, length
);
4632 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, TMP3
, 0));
4633 skip_char_back(common
);
4634 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_IMM
, 1);
4635 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
4640 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, begin
));
4641 OP2(SLJIT_SUB
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(length
));
4642 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS
, STR_PTR
, 0, TMP1
, 0));
4644 check_start_used_ptr(common
);
4645 return cc
+ LINK_SIZE
;
4647 SLJIT_ASSERT_STOP();
4651 static SLJIT_INLINE pcre_uchar
*compile_charn_matchingpath(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
, jump_list
**backtracks
)
4653 /* This function consumes at least one input character. */
4654 /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */
4656 pcre_uchar
*ccbegin
= cc
;
4657 compare_context context
;
4670 if (common
->utf
&& HAS_EXTRALEN(cc
[1]))
4671 size
+= GET_EXTRALEN(cc
[1]);
4674 else if (*cc
== OP_CHARI
)
4680 if (char_has_othercase(common
, cc
+ 1) && char_get_othercase_bit(common
, cc
+ 1) == 0)
4682 else if (HAS_EXTRALEN(cc
[1]))
4683 size
+= GET_EXTRALEN(cc
[1]);
4687 if (char_has_othercase(common
, cc
+ 1) && char_get_othercase_bit(common
, cc
+ 1) == 0)
4694 context
.length
+= IN_UCHARS(size
);
4696 while (size
> 0 && context
.length
<= 128);
4699 if (context
.length
> 0)
4701 /* We have a fixed-length byte sequence. */
4702 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, SLJIT_IMM
, context
.length
);
4703 add_jump(compiler
, backtracks
, CMP(SLJIT_C_GREATER
, STR_PTR
, 0, STR_END
, 0));
4705 context
.sourcereg
= -1;
4706 #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED
4707 context
.ucharptr
= 0;
4709 do cc
= byte_sequence_compare(common
, *cc
== OP_CHARI
, cc
+ 1, &context
, backtracks
); while (context
.length
> 0);
4713 /* A non-fixed length character will be checked if length == 0. */
4714 return compile_char1_matchingpath(common
, *cc
, cc
+ 1, backtracks
);
4717 static struct sljit_jump
*compile_ref_checks(compiler_common
*common
, pcre_uchar
*cc
, jump_list
**backtracks
)
4720 int offset
= GET2(cc
, 1) << 1;
4722 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
4723 if (!common
->jscript_compat
)
4725 if (backtracks
== NULL
)
4727 /* OVECTOR(1) contains the "string begin - 1" constant. */
4728 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1));
4729 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_EQUAL
);
4730 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_UNUSED
, 0, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
4731 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_EQUAL
);
4732 return JUMP(SLJIT_C_NOT_ZERO
);
4734 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1)));
4736 return CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
4739 /* Forward definitions. */
4740 static void compile_matchingpath(compiler_common
*, pcre_uchar
*, pcre_uchar
*, backtrack_common
*);
4741 static void compile_backtrackingpath(compiler_common
*, struct backtrack_common
*);
4743 #define PUSH_BACKTRACK(size, ccstart, error) \
4746 backtrack = sljit_alloc_memory(compiler, (size)); \
4747 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
4749 memset(backtrack, 0, size); \
4750 backtrack->prev = parent->top; \
4751 backtrack->cc = (ccstart); \
4752 parent->top = backtrack; \
4756 #define PUSH_BACKTRACK_NOVALUE(size, ccstart) \
4759 backtrack = sljit_alloc_memory(compiler, (size)); \
4760 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
4762 memset(backtrack, 0, size); \
4763 backtrack->prev = parent->top; \
4764 backtrack->cc = (ccstart); \
4765 parent->top = backtrack; \
4769 #define BACKTRACK_AS(type) ((type *)backtrack)
4771 static pcre_uchar
*compile_ref_matchingpath(compiler_common
*common
, pcre_uchar
*cc
, jump_list
**backtracks
, BOOL withchecks
, BOOL emptyfail
)
4774 int offset
= GET2(cc
, 1) << 1;
4775 struct sljit_jump
*jump
= NULL
;
4776 struct sljit_jump
*partial
;
4777 struct sljit_jump
*nopartial
;
4779 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
4780 /* OVECTOR(1) contains the "string begin - 1" constant. */
4781 if (withchecks
&& !common
->jscript_compat
)
4782 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1)));
4784 #if defined SUPPORT_UTF && defined SUPPORT_UCP
4785 if (common
->utf
&& *cc
== OP_REFI
)
4787 SLJIT_ASSERT(TMP1
== SLJIT_SCRATCH_REG1
&& STACK_TOP
== SLJIT_SCRATCH_REG2
&& TMP2
== SLJIT_SCRATCH_REG3
);
4788 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
4790 jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, TMP2
, 0);
4792 /* Needed to save important temporary registers. */
4793 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, STACK_TOP
, 0);
4794 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG2
, 0, ARGUMENTS
, 0);
4795 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_SCRATCH_REG2
), SLJIT_OFFSETOF(jit_arguments
, uchar_ptr
), STR_PTR
, 0);
4796 sljit_emit_ijump(compiler
, SLJIT_CALL3
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(do_utf_caselesscmp
));
4797 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
4798 if (common
->mode
== JIT_COMPILE
)
4799 add_jump(compiler
, backtracks
, CMP(SLJIT_C_LESS_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 1));
4802 add_jump(compiler
, backtracks
, CMP(SLJIT_C_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 0));
4803 nopartial
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 1);
4804 check_partial(common
, FALSE
);
4805 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
4806 JUMPHERE(nopartial
);
4808 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_RETURN_REG
, 0);
4811 #endif /* SUPPORT_UTF && SUPPORT_UCP */
4813 OP2(SLJIT_SUB
| SLJIT_SET_E
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), TMP1
, 0);
4815 jump
= JUMP(SLJIT_C_ZERO
);
4817 OP2(SLJIT_ADD
, STR_PTR
, 0, STR_PTR
, 0, TMP2
, 0);
4818 partial
= CMP(SLJIT_C_GREATER
, STR_PTR
, 0, STR_END
, 0);
4819 if (common
->mode
== JIT_COMPILE
)
4820 add_jump(compiler
, backtracks
, partial
);
4822 add_jump(compiler
, *cc
== OP_REF
? &common
->casefulcmp
: &common
->caselesscmp
, JUMP(SLJIT_FAST_CALL
));
4823 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
4825 if (common
->mode
!= JIT_COMPILE
)
4827 nopartial
= JUMP(SLJIT_JUMP
);
4829 /* TMP2 -= STR_END - STR_PTR */
4830 OP2(SLJIT_SUB
, TMP2
, 0, TMP2
, 0, STR_PTR
, 0);
4831 OP2(SLJIT_ADD
, TMP2
, 0, TMP2
, 0, STR_END
, 0);
4832 partial
= CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0);
4833 OP1(SLJIT_MOV
, STR_PTR
, 0, STR_END
, 0);
4834 add_jump(compiler
, *cc
== OP_REF
? &common
->casefulcmp
: &common
->caselesscmp
, JUMP(SLJIT_FAST_CALL
));
4835 add_jump(compiler
, backtracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
4837 check_partial(common
, FALSE
);
4838 add_jump(compiler
, backtracks
, JUMP(SLJIT_JUMP
));
4839 JUMPHERE(nopartial
);
4846 add_jump(compiler
, backtracks
, jump
);
4850 return cc
+ 1 + IMM2_SIZE
;
4853 static SLJIT_INLINE pcre_uchar
*compile_ref_iterator_matchingpath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
4856 backtrack_common
*backtrack
;
4858 struct sljit_label
*label
;
4859 struct sljit_jump
*zerolength
;
4860 struct sljit_jump
*jump
= NULL
;
4861 pcre_uchar
*ccbegin
= cc
;
4862 int min
= 0, max
= 0;
4865 PUSH_BACKTRACK(sizeof(iterator_backtrack
), cc
, NULL
);
4867 type
= cc
[1 + IMM2_SIZE
];
4868 minimize
= (type
& 0x1) != 0;
4875 cc
+= 1 + IMM2_SIZE
+ 1;
4881 cc
+= 1 + IMM2_SIZE
+ 1;
4887 cc
+= 1 + IMM2_SIZE
+ 1;
4891 min
= GET2(cc
, 1 + IMM2_SIZE
+ 1);
4892 max
= GET2(cc
, 1 + IMM2_SIZE
+ 1 + IMM2_SIZE
);
4893 cc
+= 1 + IMM2_SIZE
+ 1 + 2 * IMM2_SIZE
;
4896 SLJIT_ASSERT_STOP();
4904 allocate_stack(common
, 2);
4905 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4906 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 0);
4907 /* Temporary release of STR_PTR. */
4908 OP2(SLJIT_SUB
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_sw
));
4909 zerolength
= compile_ref_checks(common
, ccbegin
, NULL
);
4910 /* Restore if not zero length. */
4911 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_sw
));
4915 allocate_stack(common
, 1);
4916 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4917 zerolength
= compile_ref_checks(common
, ccbegin
, &backtrack
->topbacktracks
);
4920 if (min
> 1 || max
> 1)
4921 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 0);
4924 compile_ref_matchingpath(common
, ccbegin
, &backtrack
->topbacktracks
, FALSE
, FALSE
);
4926 if (min
> 1 || max
> 1)
4928 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
4929 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
4930 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, TMP1
, 0);
4932 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, min
, label
);
4935 jump
= CMP(SLJIT_C_GREATER_EQUAL
, TMP1
, 0, SLJIT_IMM
, max
);
4936 allocate_stack(common
, 1);
4937 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4938 JUMPTO(SLJIT_JUMP
, label
);
4945 /* Includes min > 1 case as well. */
4946 allocate_stack(common
, 1);
4947 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4948 JUMPTO(SLJIT_JUMP
, label
);
4951 JUMPHERE(zerolength
);
4952 BACKTRACK_AS(iterator_backtrack
)->matchingpath
= LABEL();
4954 decrease_call_count(common
);
4958 allocate_stack(common
, 2);
4959 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
4960 if (type
!= OP_CRMINSTAR
)
4961 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 0);
4965 zerolength
= compile_ref_checks(common
, ccbegin
, NULL
);
4966 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4967 jump
= JUMP(SLJIT_JUMP
);
4970 zerolength
= compile_ref_checks(common
, ccbegin
, &backtrack
->topbacktracks
);
4972 BACKTRACK_AS(iterator_backtrack
)->matchingpath
= LABEL();
4974 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_GREATER_EQUAL
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, max
));
4976 compile_ref_matchingpath(common
, ccbegin
, &backtrack
->topbacktracks
, TRUE
, TRUE
);
4977 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
4981 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
4982 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
4983 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
4984 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, min
, BACKTRACK_AS(iterator_backtrack
)->matchingpath
);
4987 OP2(SLJIT_ADD
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 1);
4991 JUMPHERE(zerolength
);
4993 decrease_call_count(common
);
4997 static SLJIT_INLINE pcre_uchar
*compile_recurse_matchingpath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
5000 backtrack_common
*backtrack
;
5001 recurse_entry
*entry
= common
->entries
;
5002 recurse_entry
*prev
= NULL
;
5003 int start
= GET(cc
, 1);
5005 PUSH_BACKTRACK(sizeof(recurse_backtrack
), cc
, NULL
);
5006 while (entry
!= NULL
)
5008 if (entry
->start
== start
)
5011 entry
= entry
->next
;
5016 entry
= sljit_alloc_memory(compiler
, sizeof(recurse_entry
));
5017 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
5020 entry
->entry
= NULL
;
5021 entry
->calls
= NULL
;
5022 entry
->start
= start
;
5027 common
->entries
= entry
;
5030 if (common
->has_set_som
&& common
->mark_ptr
!= 0)
5032 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
5033 allocate_stack(common
, 2);
5034 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
5035 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
5036 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
5038 else if (common
->has_set_som
|| common
->mark_ptr
!= 0)
5040 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->has_set_som
? (int)(OVECTOR(0)) : common
->mark_ptr
);
5041 allocate_stack(common
, 1);
5042 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
5045 if (entry
->entry
== NULL
)
5046 add_jump(compiler
, &entry
->calls
, JUMP(SLJIT_FAST_CALL
));
5048 JUMPTO(SLJIT_FAST_CALL
, entry
->entry
);
5049 /* Leave if the match is failed. */
5050 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0));
5051 return cc
+ 1 + LINK_SIZE
;
5054 static pcre_uchar
*compile_assert_matchingpath(compiler_common
*common
, pcre_uchar
*cc
, assert_backtrack
*backtrack
, BOOL conditional
)
5058 int private_data_ptr
;
5059 backtrack_common altbacktrack
;
5060 pcre_uchar
*ccbegin
;
5062 pcre_uchar bra
= OP_BRA
;
5063 jump_list
*tmp
= NULL
;
5064 jump_list
**target
= (conditional
) ? &backtrack
->condfailed
: &backtrack
->common
.topbacktracks
;
5066 /* Saving previous accept variables. */
5067 struct sljit_label
*save_quitlabel
= common
->quitlabel
;
5068 struct sljit_label
*save_acceptlabel
= common
->acceptlabel
;
5069 jump_list
*save_quit
= common
->quit
;
5070 jump_list
*save_accept
= common
->accept
;
5071 struct sljit_jump
*jump
;
5072 struct sljit_jump
*brajump
= NULL
;
5074 if (*cc
== OP_BRAZERO
|| *cc
== OP_BRAMINZERO
)
5076 SLJIT_ASSERT(!conditional
);
5080 private_data_ptr
= PRIVATE_DATA(cc
);
5081 SLJIT_ASSERT(private_data_ptr
!= 0);
5082 framesize
= get_framesize(common
, cc
, FALSE
);
5083 backtrack
->framesize
= framesize
;
5084 backtrack
->private_data_ptr
= private_data_ptr
;
5086 SLJIT_ASSERT(opcode
>= OP_ASSERT
&& opcode
<= OP_ASSERTBACK_NOT
);
5087 found
= (opcode
== OP_ASSERT
|| opcode
== OP_ASSERTBACK
) ? &tmp
: target
;
5091 if (bra
== OP_BRAMINZERO
)
5093 /* This is a braminzero backtrack path. */
5094 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5095 free_stack(common
, 1);
5096 brajump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
5101 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, STACK_TOP
, 0);
5102 allocate_stack(common
, 1);
5103 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5107 allocate_stack(common
, framesize
+ 2);
5108 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5109 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(framesize
+ 1));
5110 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, TMP2
, 0);
5111 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5112 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
5113 init_frame(common
, ccbegin
, framesize
+ 1, 2, FALSE
);
5116 memset(&altbacktrack
, 0, sizeof(backtrack_common
));
5117 common
->quitlabel
= NULL
;
5118 common
->quit
= NULL
;
5121 common
->acceptlabel
= NULL
;
5122 common
->accept
= NULL
;
5123 altbacktrack
.top
= NULL
;
5124 altbacktrack
.topbacktracks
= NULL
;
5126 if (*ccbegin
== OP_ALT
)
5127 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5129 altbacktrack
.cc
= ccbegin
;
5130 compile_matchingpath(common
, ccbegin
+ 1 + LINK_SIZE
, cc
, &altbacktrack
);
5131 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
5133 common
->quitlabel
= save_quitlabel
;
5134 common
->acceptlabel
= save_acceptlabel
;
5135 common
->quit
= save_quit
;
5136 common
->accept
= save_accept
;
5139 common
->acceptlabel
= LABEL();
5140 if (common
->accept
!= NULL
)
5141 set_jumps(common
->accept
, common
->acceptlabel
);
5145 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5147 if ((opcode
!= OP_ASSERT_NOT
&& opcode
!= OP_ASSERTBACK_NOT
) || conditional
)
5149 /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
5150 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_IMM
, (framesize
+ 1) * sizeof(sljit_sw
));
5154 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5155 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
5159 if (opcode
== OP_ASSERT_NOT
|| opcode
== OP_ASSERTBACK_NOT
)
5161 /* We know that STR_PTR was stored on the top of the stack. */
5163 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
5164 else if (bra
== OP_BRAZERO
)
5167 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
5170 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), framesize
* sizeof(sljit_sw
));
5171 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), (framesize
+ 1) * sizeof(sljit_sw
));
5172 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, TMP1
, 0);
5174 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_sw
));
5175 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5177 else if (framesize
>= 0)
5179 /* For OP_BRA and OP_BRAMINZERO. */
5180 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_MEM1(STACK_TOP
), framesize
* sizeof(sljit_sw
));
5183 add_jump(compiler
, found
, JUMP(SLJIT_JUMP
));
5185 compile_backtrackingpath(common
, altbacktrack
.top
);
5186 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
5188 common
->quitlabel
= save_quitlabel
;
5189 common
->acceptlabel
= save_acceptlabel
;
5190 common
->quit
= save_quit
;
5191 common
->accept
= save_accept
;
5194 set_jumps(altbacktrack
.topbacktracks
, LABEL());
5202 /* None of them matched. */
5203 if (common
->quit
!= NULL
)
5204 set_jumps(common
->quit
, LABEL());
5206 if (opcode
== OP_ASSERT
|| opcode
== OP_ASSERTBACK
)
5208 /* Assert is failed. */
5209 if (conditional
|| bra
== OP_BRAZERO
)
5210 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5214 /* The topmost item should be 0. */
5215 if (bra
== OP_BRAZERO
)
5216 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5218 free_stack(common
, 1);
5222 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
5223 /* The topmost item should be 0. */
5224 if (bra
== OP_BRAZERO
)
5226 free_stack(common
, framesize
+ 1);
5227 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5230 free_stack(common
, framesize
+ 2);
5231 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, TMP1
, 0);
5233 jump
= JUMP(SLJIT_JUMP
);
5234 if (bra
!= OP_BRAZERO
)
5235 add_jump(compiler
, target
, jump
);
5237 /* Assert is successful. */
5238 set_jumps(tmp
, LABEL());
5241 /* We know that STR_PTR was stored on the top of the stack. */
5242 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
5243 /* Keep the STR_PTR on the top of the stack. */
5244 if (bra
== OP_BRAZERO
)
5245 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_sw
));
5246 else if (bra
== OP_BRAMINZERO
)
5248 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_sw
));
5249 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5256 /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
5257 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_IMM
, (framesize
+ 1) * sizeof(sljit_sw
));
5258 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), 0);
5262 /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */
5263 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_IMM
, (framesize
+ 2) * sizeof(sljit_sw
));
5264 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5265 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), bra
== OP_BRAZERO
? STR_PTR
: SLJIT_IMM
, 0);
5269 if (bra
== OP_BRAZERO
)
5271 backtrack
->matchingpath
= LABEL();
5272 sljit_set_label(jump
, backtrack
->matchingpath
);
5274 else if (bra
== OP_BRAMINZERO
)
5276 JUMPTO(SLJIT_JUMP
, backtrack
->matchingpath
);
5280 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5281 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
5282 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_MEM1(STACK_TOP
), framesize
* sizeof(sljit_sw
));
5284 set_jumps(backtrack
->common
.topbacktracks
, LABEL());
5289 /* AssertNot is successful. */
5292 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5294 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5296 free_stack(common
, 1);
5300 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5301 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
5302 /* The topmost item should be 0. */
5305 free_stack(common
, framesize
+ 1);
5306 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
5309 free_stack(common
, framesize
+ 2);
5310 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, TMP1
, 0);
5313 if (bra
== OP_BRAZERO
)
5314 backtrack
->matchingpath
= LABEL();
5315 else if (bra
== OP_BRAMINZERO
)
5317 JUMPTO(SLJIT_JUMP
, backtrack
->matchingpath
);
5323 SLJIT_ASSERT(found
== &backtrack
->common
.topbacktracks
);
5324 set_jumps(backtrack
->common
.topbacktracks
, LABEL());
5325 backtrack
->common
.topbacktracks
= NULL
;
5329 common
->quitlabel
= save_quitlabel
;
5330 common
->acceptlabel
= save_acceptlabel
;
5331 common
->quit
= save_quit
;
5332 common
->accept
= save_accept
;
5333 return cc
+ 1 + LINK_SIZE
;
5336 static sljit_sw SLJIT_CALL
do_searchovector(sljit_uw refno
, sljit_sw
* locals
, pcre_uchar
*name_table
)
5338 int condition
= FALSE
;
5339 pcre_uchar
*slotA
= name_table
;
5341 sljit_sw name_count
= locals
[LOCALS0
/ sizeof(sljit_sw
)];
5342 sljit_sw name_entry_size
= locals
[LOCALS1
/ sizeof(sljit_sw
)];
5343 sljit_sw no_capture
;
5346 locals
+= refno
& 0xff;
5348 no_capture
= locals
[1];
5350 for (i
= 0; i
< name_count
; i
++)
5352 if (GET2(slotA
, 0) == refno
) break;
5353 slotA
+= name_entry_size
;
5358 /* Found a name for the number - there can be only one; duplicate names
5359 for different numbers are allowed, but not vice versa. First scan down
5363 while (slotB
> name_table
)
5365 slotB
-= name_entry_size
;
5366 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
5368 condition
= locals
[GET2(slotB
, 0) << 1] != no_capture
;
5369 if (condition
) break;
5374 /* Scan up for duplicates */
5378 for (i
++; i
< name_count
; i
++)
5380 slotB
+= name_entry_size
;
5381 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
5383 condition
= locals
[GET2(slotB
, 0) << 1] != no_capture
;
5384 if (condition
) break;
5393 static sljit_sw SLJIT_CALL
do_searchgroups(sljit_uw recno
, sljit_uw
* locals
, pcre_uchar
*name_table
)
5395 int condition
= FALSE
;
5396 pcre_uchar
*slotA
= name_table
;
5398 sljit_uw name_count
= locals
[LOCALS0
/ sizeof(sljit_sw
)];
5399 sljit_uw name_entry_size
= locals
[LOCALS1
/ sizeof(sljit_sw
)];
5400 sljit_uw group_num
= locals
[POSSESSIVE0
/ sizeof(sljit_sw
)];
5403 for (i
= 0; i
< name_count
; i
++)
5405 if (GET2(slotA
, 0) == recno
) break;
5406 slotA
+= name_entry_size
;
5411 /* Found a name for the number - there can be only one; duplicate
5412 names for different numbers are allowed, but not vice versa. First
5413 scan down for duplicates. */
5416 while (slotB
> name_table
)
5418 slotB
-= name_entry_size
;
5419 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
5421 condition
= GET2(slotB
, 0) == group_num
;
5422 if (condition
) break;
5427 /* Scan up for duplicates */
5431 for (i
++; i
< name_count
; i
++)
5433 slotB
+= name_entry_size
;
5434 if (STRCMP_UC_UC(slotA
+ IMM2_SIZE
, slotB
+ IMM2_SIZE
) == 0)
5436 condition
= GET2(slotB
, 0) == group_num
;
5437 if (condition
) break;
5447 Handling bracketed expressions is probably the most complex part.
5449 Stack layout naming characters:
5450 S - Push the current STR_PTR
5452 A - Push the current STR_PTR. Needed for restoring the STR_PTR
5453 before the next alternative. Not pushed if there are no alternatives.
5454 M - Any values pushed by the current alternative. Can be empty, or anything.
5455 C - Push the previous OVECTOR(i), OVECTOR(i+1) and OVECTOR_PRIV(i) to the stack.
5456 L - Push the previous local (pointed by localptr) to the stack
5457 () - opional values stored on the stack
5458 ()* - optonal, can be stored multiple times
5460 The following list shows the regular expression templates, their PCRE byte codes
5461 and stack layout supported by pcre-sljit.
5463 (?:) OP_BRA | OP_KET A M
5464 () OP_CBRA | OP_KET C M
5465 (?:)+ OP_BRA | OP_KETRMAX 0 A M S ( A M S )*
5466 OP_SBRA | OP_KETRMAX 0 L M S ( L M S )*
5467 (?:)+? OP_BRA | OP_KETRMIN 0 A M S ( A M S )*
5468 OP_SBRA | OP_KETRMIN 0 L M S ( L M S )*
5469 ()+ OP_CBRA | OP_KETRMAX 0 C M S ( C M S )*
5470 OP_SCBRA | OP_KETRMAX 0 C M S ( C M S )*
5471 ()+? OP_CBRA | OP_KETRMIN 0 C M S ( C M S )*
5472 OP_SCBRA | OP_KETRMIN 0 C M S ( C M S )*
5473 (?:)? OP_BRAZERO | OP_BRA | OP_KET S ( A M 0 )
5474 (?:)?? OP_BRAMINZERO | OP_BRA | OP_KET S ( A M 0 )
5475 ()? OP_BRAZERO | OP_CBRA | OP_KET S ( C M 0 )
5476 ()?? OP_BRAMINZERO | OP_CBRA | OP_KET S ( C M 0 )
5477 (?:)* OP_BRAZERO | OP_BRA | OP_KETRMAX S 0 ( A M S )*
5478 OP_BRAZERO | OP_SBRA | OP_KETRMAX S 0 ( L M S )*
5479 (?:)*? OP_BRAMINZERO | OP_BRA | OP_KETRMIN S 0 ( A M S )*
5480 OP_BRAMINZERO | OP_SBRA | OP_KETRMIN S 0 ( L M S )*
5481 ()* OP_BRAZERO | OP_CBRA | OP_KETRMAX S 0 ( C M S )*
5482 OP_BRAZERO | OP_SCBRA | OP_KETRMAX S 0 ( C M S )*
5483 ()*? OP_BRAMINZERO | OP_CBRA | OP_KETRMIN S 0 ( C M S )*
5484 OP_BRAMINZERO | OP_SCBRA | OP_KETRMIN S 0 ( C M S )*
5487 Stack layout naming characters:
5488 A - Push the alternative index (starting from 0) on the stack.
5489 Not pushed if there is no alternatives.
5490 M - Any values pushed by the current alternative. Can be empty, or anything.
5492 The next list shows the possible content of a bracket:
5493 (|) OP_*BRA | OP_ALT ... M A
5494 (?()|) OP_*COND | OP_ALT M A
5495 (?>|) OP_ONCE | OP_ALT ... [stack trace] M A
5496 (?>|) OP_ONCE_NC | OP_ALT ... [stack trace] M A
5497 Or nothing, if trace is unnecessary
5500 static pcre_uchar
*compile_bracket_matchingpath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
5503 backtrack_common
*backtrack
;
5505 int private_data_ptr
= 0;
5508 pcre_uchar
*ccbegin
;
5509 pcre_uchar
*matchingpath
;
5510 pcre_uchar bra
= OP_BRA
;
5512 assert_backtrack
*assert;
5513 BOOL has_alternatives
;
5514 struct sljit_jump
*jump
;
5515 struct sljit_jump
*skip
;
5516 struct sljit_label
*rmaxlabel
= NULL
;
5517 struct sljit_jump
*braminzerojump
= NULL
;
5519 PUSH_BACKTRACK(sizeof(bracket_backtrack
), cc
, NULL
);
5521 if (*cc
== OP_BRAZERO
|| *cc
== OP_BRAMINZERO
)
5530 matchingpath
= ccbegin
+ 1 + LINK_SIZE
;
5532 if ((opcode
== OP_COND
|| opcode
== OP_SCOND
) && cc
[1 + LINK_SIZE
] == OP_DEF
)
5534 /* Drop this bracket_backtrack. */
5535 parent
->top
= backtrack
->prev
;
5536 return bracketend(cc
);
5539 ket
= *(bracketend(cc
) - 1 - LINK_SIZE
);
5540 SLJIT_ASSERT(ket
== OP_KET
|| ket
== OP_KETRMAX
|| ket
== OP_KETRMIN
);
5541 SLJIT_ASSERT(!((bra
== OP_BRAZERO
&& ket
== OP_KETRMIN
) || (bra
== OP_BRAMINZERO
&& ket
== OP_KETRMAX
)));
5544 has_alternatives
= *cc
== OP_ALT
;
5545 if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
5547 has_alternatives
= (*matchingpath
== OP_RREF
) ? FALSE
: TRUE
;
5548 if (*matchingpath
== OP_NRREF
)
5550 stacksize
= GET2(matchingpath
, 1);
5551 if (common
->currententry
== NULL
|| stacksize
== RREF_ANY
)
5552 has_alternatives
= FALSE
;
5553 else if (common
->currententry
->start
== 0)
5554 has_alternatives
= stacksize
!= 0;
5556 has_alternatives
= stacksize
!= (int)GET2(common
->start
, common
->currententry
->start
+ 1 + LINK_SIZE
);
5560 if (SLJIT_UNLIKELY(opcode
== OP_COND
) && (*cc
== OP_KETRMAX
|| *cc
== OP_KETRMIN
))
5562 if (SLJIT_UNLIKELY(opcode
== OP_ONCE_NC
))
5565 if (opcode
== OP_CBRA
|| opcode
== OP_SCBRA
)
5567 /* Capturing brackets has a pre-allocated space. */
5568 offset
= GET2(ccbegin
, 1 + LINK_SIZE
);
5569 if (common
->optimized_cbracket
[offset
] == 0)
5571 private_data_ptr
= OVECTOR_PRIV(offset
);
5577 private_data_ptr
= OVECTOR(offset
);
5579 BACKTRACK_AS(bracket_backtrack
)->private_data_ptr
= private_data_ptr
;
5580 matchingpath
+= IMM2_SIZE
;
5582 else if (opcode
== OP_ONCE
|| opcode
== OP_SBRA
|| opcode
== OP_SCOND
)
5584 /* Other brackets simply allocate the next entry. */
5585 private_data_ptr
= PRIVATE_DATA(ccbegin
);
5586 SLJIT_ASSERT(private_data_ptr
!= 0);
5587 BACKTRACK_AS(bracket_backtrack
)->private_data_ptr
= private_data_ptr
;
5588 if (opcode
== OP_ONCE
)
5589 BACKTRACK_AS(bracket_backtrack
)->u
.framesize
= get_framesize(common
, ccbegin
, FALSE
);
5592 /* Instructions before the first alternative. */
5594 if ((ket
== OP_KETRMAX
) || (ket
== OP_KETRMIN
&& bra
!= OP_BRAMINZERO
))
5596 if (bra
== OP_BRAZERO
)
5600 allocate_stack(common
, stacksize
);
5603 if ((ket
== OP_KETRMAX
) || (ket
== OP_KETRMIN
&& bra
!= OP_BRAMINZERO
))
5605 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
5609 if (bra
== OP_BRAZERO
)
5610 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), STR_PTR
, 0);
5612 if (bra
== OP_BRAMINZERO
)
5614 /* This is a backtrack path! (Since the try-path of OP_BRAMINZERO matches to the empty string) */
5615 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5616 if (ket
!= OP_KETRMIN
)
5618 free_stack(common
, 1);
5619 braminzerojump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
5623 if (opcode
== OP_ONCE
|| opcode
>= OP_SBRA
)
5625 jump
= CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
5626 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
5627 /* Nothing stored during the first run. */
5628 skip
= JUMP(SLJIT_JUMP
);
5630 /* Checking zero-length iteration. */
5631 if (opcode
!= OP_ONCE
|| BACKTRACK_AS(bracket_backtrack
)->u
.framesize
< 0)
5633 /* When we come from outside, private_data_ptr contains the previous STR_PTR. */
5634 braminzerojump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5638 /* Except when the whole stack frame must be saved. */
5639 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5640 braminzerojump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(TMP1
), (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1) * sizeof(sljit_sw
));
5646 jump
= CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
5647 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
5653 if (ket
== OP_KETRMIN
)
5654 BACKTRACK_AS(bracket_backtrack
)->recursive_matchingpath
= LABEL();
5656 if (ket
== OP_KETRMAX
)
5658 rmaxlabel
= LABEL();
5659 if (has_alternatives
&& opcode
!= OP_ONCE
&& opcode
< OP_SBRA
)
5660 BACKTRACK_AS(bracket_backtrack
)->alternative_matchingpath
= rmaxlabel
;
5663 /* Handling capturing brackets and alternatives. */
5664 if (opcode
== OP_ONCE
)
5666 if (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
< 0)
5668 /* Neither capturing brackets nor recursions are not found in the block. */
5669 if (ket
== OP_KETRMIN
)
5671 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5672 allocate_stack(common
, 2);
5673 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5674 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP2
, 0);
5675 OP2(SLJIT_SUB
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_sw
));
5677 else if (ket
== OP_KETRMAX
|| has_alternatives
)
5679 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, STACK_TOP
, 0);
5680 allocate_stack(common
, 1);
5681 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5684 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, STACK_TOP
, 0);
5688 if (ket
== OP_KETRMIN
|| ket
== OP_KETRMAX
|| has_alternatives
)
5690 allocate_stack(common
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 2);
5691 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5692 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1));
5693 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5694 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, TMP2
, 0);
5695 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP1
, 0);
5696 init_frame(common
, ccbegin
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1, 2, FALSE
);
5700 allocate_stack(common
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ 1);
5701 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5702 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(BACKTRACK_AS(bracket_backtrack
)->u
.framesize
));
5703 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, TMP2
, 0);
5704 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP1
, 0);
5705 init_frame(common
, ccbegin
, BACKTRACK_AS(bracket_backtrack
)->u
.framesize
, 1, FALSE
);
5709 else if (opcode
== OP_CBRA
|| opcode
== OP_SCBRA
)
5711 /* Saving the previous values. */
5712 if (common
->optimized_cbracket
[offset
>> 1] == 0)
5714 allocate_stack(common
, 3);
5715 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
5716 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
5717 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP1
, 0);
5718 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5719 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP2
, 0);
5720 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, STR_PTR
, 0);
5721 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(2), TMP1
, 0);
5725 SLJIT_ASSERT(private_data_ptr
== OVECTOR(offset
));
5726 allocate_stack(common
, 2);
5727 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5728 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
+ sizeof(sljit_sw
));
5729 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, STR_PTR
, 0);
5730 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP1
, 0);
5731 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP2
, 0);
5734 else if (opcode
== OP_SBRA
|| opcode
== OP_SCOND
)
5736 /* Saving the previous value. */
5737 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5738 allocate_stack(common
, 1);
5739 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, STR_PTR
, 0);
5740 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
5742 else if (has_alternatives
)
5744 /* Pushing the starting string pointer. */
5745 allocate_stack(common
, 1);
5746 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
5749 /* Generating code for the first alternative. */
5750 if (opcode
== OP_COND
|| opcode
== OP_SCOND
)
5752 if (*matchingpath
== OP_CREF
)
5754 SLJIT_ASSERT(has_alternatives
);
5755 add_jump(compiler
, &(BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
),
5756 CMP(SLJIT_C_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(GET2(matchingpath
, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1)));
5757 matchingpath
+= 1 + IMM2_SIZE
;
5759 else if (*matchingpath
== OP_NCREF
)
5761 SLJIT_ASSERT(has_alternatives
);
5762 stacksize
= GET2(matchingpath
, 1);
5763 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(stacksize
<< 1), SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(1));
5765 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STACK_TOP
, 0);
5766 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, SLJIT_IMM
, common
->name_count
);
5767 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, SLJIT_IMM
, common
->name_entry_size
);
5768 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG1
, 0, SLJIT_IMM
, (stacksize
<< 8) | (common
->ovector_start
/ sizeof(sljit_sw
)));
5769 GET_LOCAL_BASE(SLJIT_SCRATCH_REG2
, 0, 0);
5770 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG3
, 0, SLJIT_IMM
, common
->name_table
);
5771 sljit_emit_ijump(compiler
, SLJIT_CALL3
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(do_searchovector
));
5772 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
);
5773 add_jump(compiler
, &(BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
), CMP(SLJIT_C_EQUAL
, SLJIT_SCRATCH_REG1
, 0, SLJIT_IMM
, 0));
5776 matchingpath
+= 1 + IMM2_SIZE
;
5778 else if (*matchingpath
== OP_RREF
|| *matchingpath
== OP_NRREF
)
5780 /* Never has other case. */
5781 BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
= NULL
;
5783 stacksize
= GET2(matchingpath
, 1);
5784 if (common
->currententry
== NULL
)
5786 else if (stacksize
== RREF_ANY
)
5788 else if (common
->currententry
->start
== 0)
5789 stacksize
= stacksize
== 0;
5791 stacksize
= stacksize
== (int)GET2(common
->start
, common
->currententry
->start
+ 1 + LINK_SIZE
);
5793 if (*matchingpath
== OP_RREF
|| stacksize
|| common
->currententry
== NULL
)
5795 SLJIT_ASSERT(!has_alternatives
);
5797 matchingpath
+= 1 + IMM2_SIZE
;
5802 matchingpath
= cc
+ 1 + LINK_SIZE
;
5811 SLJIT_ASSERT(has_alternatives
);
5813 stacksize
= GET2(matchingpath
, 1);
5814 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, STACK_TOP
, 0);
5815 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
, SLJIT_IMM
, common
->name_count
);
5816 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, SLJIT_IMM
, common
->name_entry_size
);
5817 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, GET2(common
->start
, common
->currententry
->start
+ 1 + LINK_SIZE
));
5818 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG1
, 0, SLJIT_IMM
, stacksize
);
5819 GET_LOCAL_BASE(SLJIT_SCRATCH_REG2
, 0, 0);
5820 OP1(SLJIT_MOV
, SLJIT_SCRATCH_REG3
, 0, SLJIT_IMM
, common
->name_table
);
5821 sljit_emit_ijump(compiler
, SLJIT_CALL3
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(do_searchgroups
));
5822 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
);
5823 add_jump(compiler
, &(BACKTRACK_AS(bracket_backtrack
)->u
.condfailed
), CMP(SLJIT_C_EQUAL
, SLJIT_SCRATCH_REG1
, 0, SLJIT_IMM
, 0));
5824 matchingpath
+= 1 + IMM2_SIZE
;
5829 SLJIT_ASSERT(has_alternatives
&& *matchingpath
>= OP_ASSERT
&& *matchingpath
<= OP_ASSERTBACK_NOT
);
5830 /* Similar code as PUSH_BACKTRACK macro. */
5831 assert = sljit_alloc_memory(compiler
, sizeof(assert_backtrack
));
5832 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
5834 memset(assert, 0, sizeof(assert_backtrack
));
5835 assert->common
.cc
= matchingpath
;
5836 BACKTRACK_AS(bracket_backtrack
)->u
.assert = assert;
5837 matchingpath
= compile_assert_matchingpath(common
, matchingpath
, assert, TRUE
);
5841 compile_matchingpath(common
, matchingpath
, cc
, backtrack
);
5842 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
5845 if (opcode
== OP_ONCE
)
5847 if (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
< 0)
5849 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5850 /* TMP2 which is set here used by OP_KETRMAX below. */
5851 if (ket
== OP_KETRMAX
)
5852 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), 0);
5853 else if (ket
== OP_KETRMIN
)
5855 /* Move the STR_PTR to the private_data_ptr. */
5856 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_MEM1(STACK_TOP
), 0);
5861 stacksize
= (ket
== OP_KETRMIN
|| ket
== OP_KETRMAX
|| has_alternatives
) ? 2 : 1;
5862 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_IMM
, (BACKTRACK_AS(bracket_backtrack
)->u
.framesize
+ stacksize
) * sizeof(sljit_sw
));
5863 if (ket
== OP_KETRMAX
)
5865 /* TMP2 which is set here used by OP_KETRMAX below. */
5866 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
5872 if (ket
!= OP_KET
|| bra
!= OP_BRA
)
5874 if (has_alternatives
&& opcode
!= OP_ONCE
)
5878 allocate_stack(common
, stacksize
);
5883 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), STR_PTR
, 0);
5886 else if (bra
!= OP_BRA
)
5888 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
5892 if (has_alternatives
)
5894 if (opcode
!= OP_ONCE
)
5895 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
5896 if (ket
!= OP_KETRMAX
)
5897 BACKTRACK_AS(bracket_backtrack
)->alternative_matchingpath
= LABEL();
5900 /* Must be after the matchingpath label. */
5903 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5904 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
5905 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 0), TMP1
, 0);
5908 if (ket
== OP_KETRMAX
)
5910 if (opcode
== OP_ONCE
|| opcode
>= OP_SBRA
)
5912 if (has_alternatives
)
5913 BACKTRACK_AS(bracket_backtrack
)->alternative_matchingpath
= LABEL();
5914 /* Checking zero-length iteration. */
5915 if (opcode
!= OP_ONCE
)
5917 CMPTO(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, STR_PTR
, 0, rmaxlabel
);
5918 /* Drop STR_PTR for greedy plus quantifier. */
5919 if (bra
!= OP_BRAZERO
)
5920 free_stack(common
, 1);
5923 /* TMP2 must contain the starting STR_PTR. */
5924 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0, rmaxlabel
);
5927 JUMPTO(SLJIT_JUMP
, rmaxlabel
);
5928 BACKTRACK_AS(bracket_backtrack
)->recursive_matchingpath
= LABEL();
5931 if (bra
== OP_BRAZERO
)
5932 BACKTRACK_AS(bracket_backtrack
)->zero_matchingpath
= LABEL();
5934 if (bra
== OP_BRAMINZERO
)
5936 /* This is a backtrack path! (From the viewpoint of OP_BRAMINZERO) */
5937 JUMPTO(SLJIT_JUMP
, ((braminzero_backtrack
*)parent
)->matchingpath
);
5938 if (braminzerojump
!= NULL
)
5940 JUMPHERE(braminzerojump
);
5941 /* We need to release the end pointer to perform the
5942 backtrack for the zero-length iteration. When
5943 framesize is < 0, OP_ONCE will do the release itself. */
5944 if (opcode
== OP_ONCE
&& BACKTRACK_AS(bracket_backtrack
)->u
.framesize
>= 0)
5946 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
5947 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
5949 else if (ket
== OP_KETRMIN
&& opcode
!= OP_ONCE
)
5950 free_stack(common
, 1);
5952 /* Continue to the normal backtrack. */
5955 if ((ket
!= OP_KET
&& bra
!= OP_BRAMINZERO
) || bra
== OP_BRAZERO
)
5956 decrease_call_count(common
);
5958 /* Skip the other alternatives. */
5959 while (*cc
== OP_ALT
)
5961 cc
+= 1 + LINK_SIZE
;
5965 static pcre_uchar
*compile_bracketpos_matchingpath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
5968 backtrack_common
*backtrack
;
5970 int private_data_ptr
;
5971 int cbraprivptr
= 0;
5976 pcre_uchar
*ccbegin
= NULL
;
5978 struct sljit_label
*loop
= NULL
;
5979 struct jump_list
*emptymatch
= NULL
;
5981 PUSH_BACKTRACK(sizeof(bracketpos_backtrack
), cc
, NULL
);
5982 if (*cc
== OP_BRAPOSZERO
)
5989 private_data_ptr
= PRIVATE_DATA(cc
);
5990 SLJIT_ASSERT(private_data_ptr
!= 0);
5991 BACKTRACK_AS(bracketpos_backtrack
)->private_data_ptr
= private_data_ptr
;
5996 ccbegin
= cc
+ 1 + LINK_SIZE
;
6001 offset
= GET2(cc
, 1 + LINK_SIZE
);
6002 /* This case cannot be optimized in the same was as
6003 normal capturing brackets. */
6004 SLJIT_ASSERT(common
->optimized_cbracket
[offset
] == 0);
6005 cbraprivptr
= OVECTOR_PRIV(offset
);
6007 ccbegin
= cc
+ 1 + LINK_SIZE
+ IMM2_SIZE
;
6011 SLJIT_ASSERT_STOP();
6015 framesize
= get_framesize(common
, cc
, FALSE
);
6016 BACKTRACK_AS(bracketpos_backtrack
)->framesize
= framesize
;
6019 stacksize
= (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
) ? 2 : 1;
6022 BACKTRACK_AS(bracketpos_backtrack
)->stacksize
= stacksize
;
6023 allocate_stack(common
, stacksize
);
6024 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, STACK_TOP
, 0);
6026 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
6028 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
));
6029 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1));
6030 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP1
, 0);
6031 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), TMP2
, 0);
6034 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
6037 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 1);
6041 stacksize
= framesize
+ 1;
6044 if (opcode
== OP_BRAPOS
|| opcode
== OP_SBRAPOS
)
6046 BACKTRACK_AS(bracketpos_backtrack
)->stacksize
= stacksize
;
6047 allocate_stack(common
, stacksize
);
6049 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
6050 OP2(SLJIT_SUB
, TMP2
, 0, STACK_TOP
, 0, SLJIT_IMM
, -STACK(stacksize
- 1));
6051 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, TMP2
, 0);
6055 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 1);
6058 if (opcode
== OP_BRAPOS
|| opcode
== OP_SBRAPOS
)
6060 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stack
), STR_PTR
, 0);
6063 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stack
), TMP1
, 0);
6064 init_frame(common
, cc
, stacksize
- 1, stacksize
- framesize
, FALSE
);
6067 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
6068 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
, STR_PTR
, 0);
6071 while (*cc
!= OP_KETRPOS
)
6073 backtrack
->top
= NULL
;
6074 backtrack
->topbacktracks
= NULL
;
6077 compile_matchingpath(common
, ccbegin
, cc
, backtrack
);
6078 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
6083 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
6085 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
6087 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
6088 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
6089 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
, STR_PTR
, 0);
6090 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
6094 if (opcode
== OP_SBRAPOS
)
6095 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6096 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
6099 if (opcode
== OP_SBRAPOS
|| opcode
== OP_SCBRAPOS
)
6100 add_jump(compiler
, &emptymatch
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, STR_PTR
, 0));
6103 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 0);
6107 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
6109 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_IMM
, stacksize
* sizeof(sljit_sw
));
6110 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
6111 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
6112 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
, STR_PTR
, 0);
6113 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
6117 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
6118 OP2(SLJIT_ADD
, STACK_TOP
, 0, TMP2
, 0, SLJIT_IMM
, stacksize
* sizeof(sljit_sw
));
6119 if (opcode
== OP_SBRAPOS
)
6120 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP2
), (framesize
+ 1) * sizeof(sljit_sw
));
6121 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP2
), (framesize
+ 1) * sizeof(sljit_sw
), STR_PTR
, 0);
6124 if (opcode
== OP_SBRAPOS
|| opcode
== OP_SCBRAPOS
)
6125 add_jump(compiler
, &emptymatch
, CMP(SLJIT_C_EQUAL
, TMP1
, 0, STR_PTR
, 0));
6130 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 0);
6132 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6135 JUMPTO(SLJIT_JUMP
, loop
);
6136 flush_stubs(common
);
6138 compile_backtrackingpath(common
, backtrack
->top
);
6139 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
6141 set_jumps(backtrack
->topbacktracks
, LABEL());
6145 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
6146 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
6148 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6152 if (opcode
== OP_CBRAPOS
|| opcode
== OP_SCBRAPOS
)
6154 /* Last alternative. */
6155 if (*cc
== OP_KETRPOS
)
6156 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
6157 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), cbraprivptr
);
6161 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
6162 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(TMP2
), (framesize
+ 1) * sizeof(sljit_sw
));
6166 if (*cc
== OP_KETRPOS
)
6168 ccbegin
= cc
+ 1 + LINK_SIZE
;
6171 backtrack
->topbacktracks
= NULL
;
6175 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
- 1), SLJIT_IMM
, 0));
6176 else /* TMP2 is set to [private_data_ptr] above. */
6177 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(TMP2
), (stacksize
- 1) * sizeof(sljit_sw
), SLJIT_IMM
, 0));
6180 /* None of them matched. */
6181 set_jumps(emptymatch
, LABEL());
6182 decrease_call_count(common
);
6183 return cc
+ 1 + LINK_SIZE
;
6186 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
)
6191 if (*opcode
>= OP_STAR
&& *opcode
<= OP_POSUPTO
)
6196 else if (*opcode
>= OP_STARI
&& *opcode
<= OP_POSUPTOI
)
6200 *opcode
-= OP_STARI
- OP_STAR
;
6202 else if (*opcode
>= OP_NOTSTAR
&& *opcode
<= OP_NOTPOSUPTO
)
6206 *opcode
-= OP_NOTSTAR
- OP_STAR
;
6208 else if (*opcode
>= OP_NOTSTARI
&& *opcode
<= OP_NOTPOSUPTOI
)
6212 *opcode
-= OP_NOTSTARI
- OP_STAR
;
6214 else if (*opcode
>= OP_TYPESTAR
&& *opcode
<= OP_TYPEPOSUPTO
)
6217 *opcode
-= OP_TYPESTAR
- OP_STAR
;
6222 SLJIT_ASSERT(*opcode
>= OP_CLASS
|| *opcode
<= OP_XCLASS
);
6225 class_len
= (*type
< OP_XCLASS
) ? (int)(1 + (32 / sizeof(pcre_uchar
))) : GET(cc
, 0);
6226 *opcode
= cc
[class_len
- 1];
6227 if (*opcode
>= OP_CRSTAR
&& *opcode
<= OP_CRMINQUERY
)
6229 *opcode
-= OP_CRSTAR
- OP_STAR
;
6231 *end
= cc
+ class_len
;
6235 SLJIT_ASSERT(*opcode
== OP_CRRANGE
|| *opcode
== OP_CRMINRANGE
);
6236 *arg1
= GET2(cc
, (class_len
+ IMM2_SIZE
));
6237 *arg2
= GET2(cc
, class_len
);
6241 SLJIT_ASSERT(*arg1
!= 0);
6242 *opcode
= (*opcode
== OP_CRRANGE
) ? OP_UPTO
: OP_MINUPTO
;
6248 *end
= cc
+ class_len
+ 2 * IMM2_SIZE
;
6253 if (*opcode
== OP_UPTO
|| *opcode
== OP_MINUPTO
|| *opcode
== OP_EXACT
|| *opcode
== OP_POSUPTO
)
6255 *arg1
= GET2(cc
, 0);
6263 *end
= next_opcode(common
, cc
);
6272 if (common
->utf
&& HAS_EXTRALEN(*cc
)) *end
+= GET_EXTRALEN(*cc
);
6278 static pcre_uchar
*compile_iterator_matchingpath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
6281 backtrack_common
*backtrack
;
6284 int arg1
= -1, arg2
= -1;
6286 jump_list
*nomatch
= NULL
;
6287 struct sljit_jump
*jump
= NULL
;
6288 struct sljit_label
*label
;
6289 int private_data_ptr
= PRIVATE_DATA(cc
);
6290 int base
= (private_data_ptr
== 0) ? SLJIT_MEM1(STACK_TOP
) : SLJIT_MEM1(SLJIT_LOCALS_REG
);
6291 int offset0
= (private_data_ptr
== 0) ? STACK(0) : private_data_ptr
;
6292 int offset1
= (private_data_ptr
== 0) ? STACK(1) : private_data_ptr
+ (int)sizeof(sljit_sw
);
6293 int tmp_base
, tmp_offset
;
6295 PUSH_BACKTRACK(sizeof(iterator_backtrack
), cc
, NULL
);
6297 cc
= get_iterator_parameters(common
, cc
, &opcode
, &type
, &arg1
, &arg2
, &end
);
6303 case OP_NOT_WHITESPACE
:
6305 case OP_NOT_WORDCHAR
:
6326 SLJIT_ASSERT_STOP();
6333 tmp_base
= SLJIT_MEM1(SLJIT_LOCALS_REG
);
6334 tmp_offset
= POSSESSIVE0
;
6344 if (type
== OP_ANYNL
|| type
== OP_EXTUNI
)
6346 SLJIT_ASSERT(private_data_ptr
== 0);
6347 if (opcode
== OP_STAR
|| opcode
== OP_UPTO
)
6349 allocate_stack(common
, 2);
6350 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
6351 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), SLJIT_IMM
, 0);
6355 allocate_stack(common
, 1);
6356 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6359 if (opcode
== OP_UPTO
|| opcode
== OP_CRRANGE
)
6360 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, SLJIT_IMM
, 0);
6363 compile_char1_matchingpath(common
, type
, cc
, &backtrack
->topbacktracks
);
6364 if (opcode
== OP_UPTO
|| opcode
== OP_CRRANGE
)
6366 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
);
6367 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
6368 if (opcode
== OP_CRRANGE
&& arg2
> 0)
6369 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg2
, label
);
6370 if (opcode
== OP_UPTO
|| (opcode
== OP_CRRANGE
&& arg1
> 0))
6371 jump
= CMP(SLJIT_C_GREATER_EQUAL
, TMP1
, 0, SLJIT_IMM
, arg1
);
6372 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE0
, TMP1
, 0);
6375 /* We cannot use TMP3 because of this allocate_stack. */
6376 allocate_stack(common
, 1);
6377 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
6378 JUMPTO(SLJIT_JUMP
, label
);
6384 if (opcode
== OP_PLUS
)
6385 compile_char1_matchingpath(common
, type
, cc
, &backtrack
->topbacktracks
);
6386 if (private_data_ptr
== 0)
6387 allocate_stack(common
, 2);
6388 OP1(SLJIT_MOV
, base
, offset0
, STR_PTR
, 0);
6389 if (opcode
<= OP_PLUS
)
6390 OP1(SLJIT_MOV
, base
, offset1
, STR_PTR
, 0);
6392 OP1(SLJIT_MOV
, base
, offset1
, SLJIT_IMM
, 1);
6394 compile_char1_matchingpath(common
, type
, cc
, &nomatch
);
6395 OP1(SLJIT_MOV
, base
, offset0
, STR_PTR
, 0);
6396 if (opcode
<= OP_PLUS
)
6397 JUMPTO(SLJIT_JUMP
, label
);
6398 else if (opcode
== OP_CRRANGE
&& arg1
== 0)
6400 OP2(SLJIT_ADD
, base
, offset1
, base
, offset1
, SLJIT_IMM
, 1);
6401 JUMPTO(SLJIT_JUMP
, label
);
6405 OP1(SLJIT_MOV
, TMP1
, 0, base
, offset1
);
6406 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
6407 OP1(SLJIT_MOV
, base
, offset1
, TMP1
, 0);
6408 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg1
+ 1, label
);
6410 set_jumps(nomatch
, LABEL());
6411 if (opcode
== OP_CRRANGE
)
6412 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_LESS
, base
, offset1
, SLJIT_IMM
, arg2
+ 1));
6413 OP1(SLJIT_MOV
, STR_PTR
, 0, base
, offset0
);
6415 BACKTRACK_AS(iterator_backtrack
)->matchingpath
= LABEL();
6420 if (opcode
== OP_MINPLUS
)
6421 compile_char1_matchingpath(common
, type
, cc
, &backtrack
->topbacktracks
);
6422 if (private_data_ptr
== 0)
6423 allocate_stack(common
, 1);
6424 OP1(SLJIT_MOV
, base
, offset0
, STR_PTR
, 0);
6425 BACKTRACK_AS(iterator_backtrack
)->matchingpath
= LABEL();
6430 if (private_data_ptr
== 0)
6431 allocate_stack(common
, 2);
6432 OP1(SLJIT_MOV
, base
, offset0
, STR_PTR
, 0);
6433 OP1(SLJIT_MOV
, base
, offset1
, SLJIT_IMM
, 1);
6434 if (opcode
== OP_CRMINRANGE
)
6435 add_jump(compiler
, &backtrack
->topbacktracks
, JUMP(SLJIT_JUMP
));
6436 BACKTRACK_AS(iterator_backtrack
)->matchingpath
= LABEL();
6441 if (private_data_ptr
== 0)
6442 allocate_stack(common
, 1);
6443 OP1(SLJIT_MOV
, base
, offset0
, STR_PTR
, 0);
6444 if (opcode
== OP_QUERY
)
6445 compile_char1_matchingpath(common
, type
, cc
, &backtrack
->topbacktracks
);
6446 BACKTRACK_AS(iterator_backtrack
)->matchingpath
= LABEL();
6450 OP1(SLJIT_MOV
, tmp_base
, tmp_offset
, SLJIT_IMM
, arg1
);
6452 compile_char1_matchingpath(common
, type
, cc
, &backtrack
->topbacktracks
);
6453 OP2(SLJIT_SUB
| SLJIT_SET_E
, tmp_base
, tmp_offset
, tmp_base
, tmp_offset
, SLJIT_IMM
, 1);
6454 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
6460 if (opcode
== OP_POSPLUS
)
6461 compile_char1_matchingpath(common
, type
, cc
, &backtrack
->topbacktracks
);
6462 if (opcode
== OP_POSUPTO
)
6463 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, SLJIT_IMM
, arg1
);
6464 OP1(SLJIT_MOV
, tmp_base
, tmp_offset
, STR_PTR
, 0);
6466 compile_char1_matchingpath(common
, type
, cc
, &nomatch
);
6467 OP1(SLJIT_MOV
, tmp_base
, tmp_offset
, STR_PTR
, 0);
6468 if (opcode
!= OP_POSUPTO
)
6469 JUMPTO(SLJIT_JUMP
, label
);
6472 OP2(SLJIT_SUB
| SLJIT_SET_E
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, SLJIT_MEM1(SLJIT_LOCALS_REG
), POSSESSIVE1
, SLJIT_IMM
, 1);
6473 JUMPTO(SLJIT_C_NOT_ZERO
, label
);
6475 set_jumps(nomatch
, LABEL());
6476 OP1(SLJIT_MOV
, STR_PTR
, 0, tmp_base
, tmp_offset
);
6480 OP1(SLJIT_MOV
, tmp_base
, tmp_offset
, STR_PTR
, 0);
6481 compile_char1_matchingpath(common
, type
, cc
, &nomatch
);
6482 OP1(SLJIT_MOV
, tmp_base
, tmp_offset
, STR_PTR
, 0);
6483 set_jumps(nomatch
, LABEL());
6484 OP1(SLJIT_MOV
, STR_PTR
, 0, tmp_base
, tmp_offset
);
6488 SLJIT_ASSERT_STOP();
6492 decrease_call_count(common
);
6496 static SLJIT_INLINE pcre_uchar
*compile_fail_accept_matchingpath(compiler_common
*common
, pcre_uchar
*cc
, backtrack_common
*parent
)
6499 backtrack_common
*backtrack
;
6501 PUSH_BACKTRACK(sizeof(bracket_backtrack
), cc
, NULL
);
6505 add_jump(compiler
, &backtrack
->topbacktracks
, JUMP(SLJIT_JUMP
));
6509 if (*cc
== OP_ASSERT_ACCEPT
|| common
->currententry
!= NULL
)
6511 /* No need to check notempty conditions. */
6512 if (common
->acceptlabel
== NULL
)
6513 add_jump(compiler
, &common
->accept
, JUMP(SLJIT_JUMP
));
6515 JUMPTO(SLJIT_JUMP
, common
->acceptlabel
);
6519 if (common
->acceptlabel
== NULL
)
6520 add_jump(compiler
, &common
->accept
, CMP(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0)));
6522 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), common
->acceptlabel
);
6523 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
6524 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty
));
6525 add_jump(compiler
, &backtrack
->topbacktracks
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
6526 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty_atstart
));
6527 if (common
->acceptlabel
== NULL
)
6528 add_jump(compiler
, &common
->accept
, CMP(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0));
6530 CMPTO(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0, common
->acceptlabel
);
6531 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
6532 if (common
->acceptlabel
== NULL
)
6533 add_jump(compiler
, &common
->accept
, CMP(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0));
6535 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0, common
->acceptlabel
);
6536 add_jump(compiler
, &backtrack
->topbacktracks
, JUMP(SLJIT_JUMP
));
6540 static SLJIT_INLINE pcre_uchar
*compile_close_matchingpath(compiler_common
*common
, pcre_uchar
*cc
)
6543 int offset
= GET2(cc
, 1);
6544 BOOL optimized_cbracket
= common
->optimized_cbracket
[offset
] != 0;
6546 /* Data will be discarded anyway... */
6547 if (common
->currententry
!= NULL
)
6548 return cc
+ 1 + IMM2_SIZE
;
6550 if (!optimized_cbracket
)
6551 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR_PRIV(offset
));
6553 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
6554 if (!optimized_cbracket
)
6555 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
6556 return cc
+ 1 + IMM2_SIZE
;
6559 static void compile_matchingpath(compiler_common
*common
, pcre_uchar
*cc
, pcre_uchar
*ccend
, backtrack_common
*parent
)
6562 backtrack_common
*backtrack
;
6570 case OP_NOT_WORD_BOUNDARY
:
6571 case OP_WORD_BOUNDARY
:
6574 case OP_NOT_WHITESPACE
:
6576 case OP_NOT_WORDCHAR
:
6598 cc
= compile_char1_matchingpath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
6602 PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common
), cc
);
6603 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
6604 allocate_stack(common
, 1);
6605 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), STR_PTR
, 0);
6606 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
6612 if (common
->mode
== JIT_COMPILE
)
6613 cc
= compile_charn_matchingpath(common
, cc
, ccend
, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
6615 cc
= compile_char1_matchingpath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
6649 case OP_NOTMINQUERY
:
6655 case OP_NOTPOSQUERY
:
6658 case OP_NOTMINSTARI
:
6660 case OP_NOTMINPLUSI
:
6662 case OP_NOTMINQUERYI
:
6664 case OP_NOTMINUPTOI
:
6666 case OP_NOTPOSSTARI
:
6667 case OP_NOTPOSPLUSI
:
6668 case OP_NOTPOSQUERYI
:
6669 case OP_NOTPOSUPTOI
:
6671 case OP_TYPEMINSTAR
:
6673 case OP_TYPEMINPLUS
:
6675 case OP_TYPEMINQUERY
:
6677 case OP_TYPEMINUPTO
:
6679 case OP_TYPEPOSSTAR
:
6680 case OP_TYPEPOSPLUS
:
6681 case OP_TYPEPOSQUERY
:
6682 case OP_TYPEPOSUPTO
:
6683 cc
= compile_iterator_matchingpath(common
, cc
, parent
);
6688 if (cc
[1 + (32 / sizeof(pcre_uchar
))] >= OP_CRSTAR
&& cc
[1 + (32 / sizeof(pcre_uchar
))] <= OP_CRMINRANGE
)
6689 cc
= compile_iterator_matchingpath(common
, cc
, parent
);
6691 cc
= compile_char1_matchingpath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
6694 #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
6696 if (*(cc
+ GET(cc
, 1)) >= OP_CRSTAR
&& *(cc
+ GET(cc
, 1)) <= OP_CRMINRANGE
)
6697 cc
= compile_iterator_matchingpath(common
, cc
, parent
);
6699 cc
= compile_char1_matchingpath(common
, *cc
, cc
+ 1, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
);
6705 if (cc
[1 + IMM2_SIZE
] >= OP_CRSTAR
&& cc
[1 + IMM2_SIZE
] <= OP_CRMINRANGE
)
6706 cc
= compile_ref_iterator_matchingpath(common
, cc
, parent
);
6708 cc
= compile_ref_matchingpath(common
, cc
, parent
->top
!= NULL
? &parent
->top
->nextbacktracks
: &parent
->topbacktracks
, TRUE
, FALSE
);
6712 cc
= compile_recurse_matchingpath(common
, cc
, parent
);
6718 case OP_ASSERTBACK_NOT
:
6719 PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack
), cc
);
6720 cc
= compile_assert_matchingpath(common
, cc
, BACKTRACK_AS(assert_backtrack
), FALSE
);
6724 PUSH_BACKTRACK_NOVALUE(sizeof(braminzero_backtrack
), cc
);
6725 cc
= bracketend(cc
+ 1);
6726 if (*(cc
- 1 - LINK_SIZE
) != OP_KETRMIN
)
6728 allocate_stack(common
, 1);
6729 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
6733 allocate_stack(common
, 2);
6734 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
6735 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(1), STR_PTR
, 0);
6737 BACKTRACK_AS(braminzero_backtrack
)->matchingpath
= LABEL();
6738 if (cc
[1] > OP_ASSERTBACK_NOT
)
6739 decrease_call_count(common
);
6750 cc
= compile_bracket_matchingpath(common
, cc
, parent
);
6754 if (cc
[1] > OP_ASSERTBACK_NOT
)
6755 cc
= compile_bracket_matchingpath(common
, cc
, parent
);
6758 PUSH_BACKTRACK_NOVALUE(sizeof(assert_backtrack
), cc
);
6759 cc
= compile_assert_matchingpath(common
, cc
, BACKTRACK_AS(assert_backtrack
), FALSE
);
6768 cc
= compile_bracketpos_matchingpath(common
, cc
, parent
);
6772 PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common
), cc
);
6773 SLJIT_ASSERT(common
->mark_ptr
!= 0);
6774 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
);
6775 allocate_stack(common
, 1);
6776 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
6777 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), TMP2
, 0);
6778 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_IMM
, (sljit_sw
)(cc
+ 2));
6779 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP2
, 0);
6780 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, mark_ptr
), TMP2
, 0);
6781 cc
+= 1 + 2 + cc
[1];
6785 PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common
), cc
);
6791 case OP_ASSERT_ACCEPT
:
6792 cc
= compile_fail_accept_matchingpath(common
, cc
, parent
);
6796 cc
= compile_close_matchingpath(common
, cc
);
6800 cc
= bracketend(cc
+ 1);
6804 SLJIT_ASSERT_STOP();
6810 SLJIT_ASSERT(cc
== ccend
);
6813 #undef PUSH_BACKTRACK
6814 #undef PUSH_BACKTRACK_NOVALUE
6817 #define COMPILE_BACKTRACKINGPATH(current) \
6820 compile_backtrackingpath(common, (current)); \
6821 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) \
6826 #define CURRENT_AS(type) ((type *)current)
6828 static void compile_iterator_backtrackingpath(compiler_common
*common
, struct backtrack_common
*current
)
6831 pcre_uchar
*cc
= current
->cc
;
6834 int arg1
= -1, arg2
= -1;
6835 struct sljit_label
*label
= NULL
;
6836 struct sljit_jump
*jump
= NULL
;
6837 jump_list
*jumplist
= NULL
;
6838 int private_data_ptr
= PRIVATE_DATA(cc
);
6839 int base
= (private_data_ptr
== 0) ? SLJIT_MEM1(STACK_TOP
) : SLJIT_MEM1(SLJIT_LOCALS_REG
);
6840 int offset0
= (private_data_ptr
== 0) ? STACK(0) : private_data_ptr
;
6841 int offset1
= (private_data_ptr
== 0) ? STACK(1) : private_data_ptr
+ (int)sizeof(sljit_sw
);
6843 cc
= get_iterator_parameters(common
, cc
, &opcode
, &type
, &arg1
, &arg2
, NULL
);
6851 if (type
== OP_ANYNL
|| type
== OP_EXTUNI
)
6853 SLJIT_ASSERT(private_data_ptr
== 0);
6854 set_jumps(current
->topbacktracks
, LABEL());
6855 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6856 free_stack(common
, 1);
6857 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->matchingpath
);
6861 if (opcode
== OP_UPTO
)
6863 if (opcode
<= OP_PLUS
)
6865 OP1(SLJIT_MOV
, STR_PTR
, 0, base
, offset0
);
6866 jump
= CMP(SLJIT_C_LESS_EQUAL
, STR_PTR
, 0, base
, offset1
);
6870 OP1(SLJIT_MOV
, TMP1
, 0, base
, offset1
);
6871 OP1(SLJIT_MOV
, STR_PTR
, 0, base
, offset0
);
6872 jump
= CMP(SLJIT_C_LESS_EQUAL
, TMP1
, 0, SLJIT_IMM
, arg2
+ 1);
6873 OP2(SLJIT_SUB
, base
, offset1
, TMP1
, 0, SLJIT_IMM
, 1);
6875 skip_char_back(common
);
6876 OP1(SLJIT_MOV
, base
, offset0
, STR_PTR
, 0);
6877 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->matchingpath
);
6878 if (opcode
== OP_CRRANGE
)
6879 set_jumps(current
->topbacktracks
, LABEL());
6881 if (private_data_ptr
== 0)
6882 free_stack(common
, 2);
6883 if (opcode
== OP_PLUS
)
6884 set_jumps(current
->topbacktracks
, LABEL());
6890 OP1(SLJIT_MOV
, STR_PTR
, 0, base
, offset0
);
6891 compile_char1_matchingpath(common
, type
, cc
, &jumplist
);
6892 OP1(SLJIT_MOV
, base
, offset0
, STR_PTR
, 0);
6893 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->matchingpath
);
6894 set_jumps(jumplist
, LABEL());
6895 if (private_data_ptr
== 0)
6896 free_stack(common
, 1);
6897 if (opcode
== OP_MINPLUS
)
6898 set_jumps(current
->topbacktracks
, LABEL());
6903 if (opcode
== OP_CRMINRANGE
)
6906 set_jumps(current
->topbacktracks
, label
);
6908 OP1(SLJIT_MOV
, STR_PTR
, 0, base
, offset0
);
6909 compile_char1_matchingpath(common
, type
, cc
, &jumplist
);
6911 OP1(SLJIT_MOV
, TMP1
, 0, base
, offset1
);
6912 OP1(SLJIT_MOV
, base
, offset0
, STR_PTR
, 0);
6913 OP2(SLJIT_ADD
, TMP1
, 0, TMP1
, 0, SLJIT_IMM
, 1);
6914 OP1(SLJIT_MOV
, base
, offset1
, TMP1
, 0);
6916 if (opcode
== OP_CRMINRANGE
)
6917 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg2
+ 1, label
);
6919 if (opcode
== OP_CRMINRANGE
&& arg1
== 0)
6920 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->matchingpath
);
6922 CMPTO(SLJIT_C_LESS
, TMP1
, 0, SLJIT_IMM
, arg1
+ 2, CURRENT_AS(iterator_backtrack
)->matchingpath
);
6924 set_jumps(jumplist
, LABEL());
6925 if (private_data_ptr
== 0)
6926 free_stack(common
, 2);
6930 OP1(SLJIT_MOV
, STR_PTR
, 0, base
, offset0
);
6931 OP1(SLJIT_MOV
, base
, offset0
, SLJIT_IMM
, 0);
6932 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->matchingpath
);
6933 jump
= JUMP(SLJIT_JUMP
);
6934 set_jumps(current
->topbacktracks
, LABEL());
6935 OP1(SLJIT_MOV
, STR_PTR
, 0, base
, offset0
);
6936 OP1(SLJIT_MOV
, base
, offset0
, SLJIT_IMM
, 0);
6937 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->matchingpath
);
6939 if (private_data_ptr
== 0)
6940 free_stack(common
, 1);
6944 OP1(SLJIT_MOV
, STR_PTR
, 0, base
, offset0
);
6945 OP1(SLJIT_MOV
, base
, offset0
, SLJIT_IMM
, 0);
6946 jump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
6947 compile_char1_matchingpath(common
, type
, cc
, &jumplist
);
6948 JUMPTO(SLJIT_JUMP
, CURRENT_AS(iterator_backtrack
)->matchingpath
);
6949 set_jumps(jumplist
, LABEL());
6951 if (private_data_ptr
== 0)
6952 free_stack(common
, 1);
6957 set_jumps(current
->topbacktracks
, LABEL());
6966 SLJIT_ASSERT_STOP();
6971 static void compile_ref_iterator_backtrackingpath(compiler_common
*common
, struct backtrack_common
*current
)
6974 pcre_uchar
*cc
= current
->cc
;
6977 type
= cc
[1 + IMM2_SIZE
];
6978 if ((type
& 0x1) == 0)
6980 set_jumps(current
->topbacktracks
, LABEL());
6981 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6982 free_stack(common
, 1);
6983 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->matchingpath
);
6987 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
6988 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(iterator_backtrack
)->matchingpath
);
6989 set_jumps(current
->topbacktracks
, LABEL());
6990 free_stack(common
, 2);
6993 static void compile_recurse_backtrackingpath(compiler_common
*common
, struct backtrack_common
*current
)
6997 set_jumps(current
->topbacktracks
, LABEL());
6999 if (common
->has_set_som
&& common
->mark_ptr
!= 0)
7001 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7002 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
7003 free_stack(common
, 2);
7004 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), TMP2
, 0);
7005 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP1
, 0);
7007 else if (common
->has_set_som
|| common
->mark_ptr
!= 0)
7009 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7010 free_stack(common
, 1);
7011 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->has_set_som
? (int)(OVECTOR(0)) : common
->mark_ptr
, TMP2
, 0);
7015 static void compile_assert_backtrackingpath(compiler_common
*common
, struct backtrack_common
*current
)
7018 pcre_uchar
*cc
= current
->cc
;
7019 pcre_uchar bra
= OP_BRA
;
7020 struct sljit_jump
*brajump
= NULL
;
7022 SLJIT_ASSERT(*cc
!= OP_BRAMINZERO
);
7023 if (*cc
== OP_BRAZERO
)
7029 if (bra
== OP_BRAZERO
)
7031 SLJIT_ASSERT(current
->topbacktracks
== NULL
);
7032 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7035 if (CURRENT_AS(assert_backtrack
)->framesize
< 0)
7037 set_jumps(current
->topbacktracks
, LABEL());
7039 if (bra
== OP_BRAZERO
)
7041 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
7042 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(assert_backtrack
)->matchingpath
);
7043 free_stack(common
, 1);
7048 if (bra
== OP_BRAZERO
)
7050 if (*cc
== OP_ASSERT_NOT
|| *cc
== OP_ASSERTBACK_NOT
)
7052 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
7053 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(assert_backtrack
)->matchingpath
);
7054 free_stack(common
, 1);
7057 free_stack(common
, 1);
7058 brajump
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0);
7061 if (*cc
== OP_ASSERT
|| *cc
== OP_ASSERTBACK
)
7063 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), CURRENT_AS(assert_backtrack
)->private_data_ptr
);
7064 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
7065 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), CURRENT_AS(assert_backtrack
)->private_data_ptr
, SLJIT_MEM1(STACK_TOP
), CURRENT_AS(assert_backtrack
)->framesize
* sizeof(sljit_sw
));
7067 set_jumps(current
->topbacktracks
, LABEL());
7070 set_jumps(current
->topbacktracks
, LABEL());
7072 if (bra
== OP_BRAZERO
)
7074 /* We know there is enough place on the stack. */
7075 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_sw
));
7076 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), SLJIT_IMM
, 0);
7077 JUMPTO(SLJIT_JUMP
, CURRENT_AS(assert_backtrack
)->matchingpath
);
7082 static void compile_bracket_backtrackingpath(compiler_common
*common
, struct backtrack_common
*current
)
7087 int private_data_ptr
= CURRENT_AS(bracket_backtrack
)->private_data_ptr
;
7090 pcre_uchar
*cc
= current
->cc
;
7091 pcre_uchar
*ccbegin
;
7093 jump_list
*jumplist
= NULL
;
7094 jump_list
*jumplistitem
= NULL
;
7095 pcre_uchar bra
= OP_BRA
;
7097 assert_backtrack
*assert;
7098 BOOL has_alternatives
;
7099 struct sljit_jump
*brazero
= NULL
;
7100 struct sljit_jump
*once
= NULL
;
7101 struct sljit_jump
*cond
= NULL
;
7102 struct sljit_label
*rminlabel
= NULL
;
7104 if (*cc
== OP_BRAZERO
|| *cc
== OP_BRAMINZERO
)
7112 ket
= *(bracketend(ccbegin
) - 1 - LINK_SIZE
);
7114 has_alternatives
= *cc
== OP_ALT
;
7115 if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
7116 has_alternatives
= (ccbegin
[1 + LINK_SIZE
] >= OP_ASSERT
&& ccbegin
[1 + LINK_SIZE
] <= OP_ASSERTBACK_NOT
) || CURRENT_AS(bracket_backtrack
)->u
.condfailed
!= NULL
;
7117 if (opcode
== OP_CBRA
|| opcode
== OP_SCBRA
)
7118 offset
= (GET2(ccbegin
, 1 + LINK_SIZE
)) << 1;
7119 if (SLJIT_UNLIKELY(opcode
== OP_COND
) && (*cc
== OP_KETRMAX
|| *cc
== OP_KETRMIN
))
7121 if (SLJIT_UNLIKELY(opcode
== OP_ONCE_NC
))
7124 if (ket
== OP_KETRMAX
)
7126 if (bra
== OP_BRAZERO
)
7128 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7129 free_stack(common
, 1);
7130 brazero
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0);
7133 else if (ket
== OP_KETRMIN
)
7135 if (bra
!= OP_BRAMINZERO
)
7137 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7138 if (opcode
>= OP_SBRA
|| opcode
== OP_ONCE
)
7140 /* Checking zero-length iteration. */
7141 if (opcode
!= OP_ONCE
|| CURRENT_AS(bracket_backtrack
)->u
.framesize
< 0)
7142 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, CURRENT_AS(bracket_backtrack
)->recursive_matchingpath
);
7145 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
7146 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(TMP1
), (CURRENT_AS(bracket_backtrack
)->u
.framesize
+ 1) * sizeof(sljit_sw
), CURRENT_AS(bracket_backtrack
)->recursive_matchingpath
);
7148 if (opcode
!= OP_ONCE
)
7149 free_stack(common
, 1);
7152 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->recursive_matchingpath
);
7154 rminlabel
= LABEL();
7156 else if (bra
== OP_BRAZERO
)
7158 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7159 free_stack(common
, 1);
7160 brazero
= CMP(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0);
7163 if (SLJIT_UNLIKELY(opcode
== OP_ONCE
))
7165 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
7167 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
7168 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
7170 once
= JUMP(SLJIT_JUMP
);
7172 else if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
7174 if (has_alternatives
)
7176 /* Always exactly one alternative. */
7177 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7178 free_stack(common
, 1);
7180 jumplistitem
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
7181 if (SLJIT_UNLIKELY(!jumplistitem
))
7183 jumplist
= jumplistitem
;
7184 jumplistitem
->next
= NULL
;
7185 jumplistitem
->jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, 1);
7188 else if (*cc
== OP_ALT
)
7190 /* Build a jump list. Get the last successfully matched branch index. */
7191 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7192 free_stack(common
, 1);
7196 /* Append as the last item. */
7197 if (jumplist
!= NULL
)
7199 jumplistitem
->next
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
7200 jumplistitem
= jumplistitem
->next
;
7204 jumplistitem
= sljit_alloc_memory(compiler
, sizeof(jump_list
));
7205 jumplist
= jumplistitem
;
7208 if (SLJIT_UNLIKELY(!jumplistitem
))
7211 jumplistitem
->next
= NULL
;
7212 jumplistitem
->jump
= CMP(SLJIT_C_EQUAL
, TMP1
, 0, SLJIT_IMM
, count
++);
7215 while (*cc
== OP_ALT
);
7217 cc
= ccbegin
+ GET(ccbegin
, 1);
7220 COMPILE_BACKTRACKINGPATH(current
->top
);
7221 if (current
->topbacktracks
)
7222 set_jumps(current
->topbacktracks
, LABEL());
7224 if (SLJIT_UNLIKELY(opcode
== OP_COND
) || SLJIT_UNLIKELY(opcode
== OP_SCOND
))
7226 /* Conditional block always has at most one alternative. */
7227 if (ccbegin
[1 + LINK_SIZE
] >= OP_ASSERT
&& ccbegin
[1 + LINK_SIZE
] <= OP_ASSERTBACK_NOT
)
7229 SLJIT_ASSERT(has_alternatives
);
7230 assert = CURRENT_AS(bracket_backtrack
)->u
.assert;
7231 if (assert->framesize
>= 0 && (ccbegin
[1 + LINK_SIZE
] == OP_ASSERT
|| ccbegin
[1 + LINK_SIZE
] == OP_ASSERTBACK
))
7233 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->private_data_ptr
);
7234 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
7235 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->private_data_ptr
, SLJIT_MEM1(STACK_TOP
), assert->framesize
* sizeof(sljit_sw
));
7237 cond
= JUMP(SLJIT_JUMP
);
7238 set_jumps(CURRENT_AS(bracket_backtrack
)->u
.assert->condfailed
, LABEL());
7240 else if (CURRENT_AS(bracket_backtrack
)->u
.condfailed
!= NULL
)
7242 SLJIT_ASSERT(has_alternatives
);
7243 cond
= JUMP(SLJIT_JUMP
);
7244 set_jumps(CURRENT_AS(bracket_backtrack
)->u
.condfailed
, LABEL());
7247 SLJIT_ASSERT(!has_alternatives
);
7250 if (has_alternatives
)
7255 current
->top
= NULL
;
7256 current
->topbacktracks
= NULL
;
7257 current
->nextbacktracks
= NULL
;
7260 ccprev
= cc
+ 1 + LINK_SIZE
;
7262 if (opcode
!= OP_COND
&& opcode
!= OP_SCOND
)
7264 if (private_data_ptr
!= 0 && opcode
!= OP_ONCE
)
7265 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
7267 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7269 compile_matchingpath(common
, ccprev
, cc
, current
);
7270 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
7274 /* Instructions after the current alternative is succesfully matched. */
7275 /* There is a similar code in compile_bracket_matchingpath. */
7276 if (opcode
== OP_ONCE
)
7278 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
< 0)
7280 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
7281 /* TMP2 which is set here used by OP_KETRMAX below. */
7282 if (ket
== OP_KETRMAX
)
7283 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), 0);
7284 else if (ket
== OP_KETRMIN
)
7286 /* Move the STR_PTR to the private_data_ptr. */
7287 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_MEM1(STACK_TOP
), 0);
7292 OP2(SLJIT_ADD
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_IMM
, (CURRENT_AS(bracket_backtrack
)->u
.framesize
+ 2) * sizeof(sljit_sw
));
7293 if (ket
== OP_KETRMAX
)
7295 /* TMP2 which is set here used by OP_KETRMAX below. */
7296 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7302 if (opcode
!= OP_ONCE
)
7304 if (ket
!= OP_KET
|| bra
!= OP_BRA
)
7307 if (stacksize
> 0) {
7308 if (opcode
!= OP_ONCE
|| CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
7309 allocate_stack(common
, stacksize
);
7312 /* We know we have place at least for one item on the top of the stack. */
7313 SLJIT_ASSERT(stacksize
== 1);
7314 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, sizeof(sljit_sw
));
7319 if (ket
!= OP_KET
|| bra
!= OP_BRA
)
7322 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), STR_PTR
, 0);
7324 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, 0);
7328 if (opcode
!= OP_ONCE
)
7329 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(stacksize
), SLJIT_IMM
, count
++);
7333 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
);
7334 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), STR_PTR
, 0);
7335 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 0), TMP1
, 0);
7338 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->alternative_matchingpath
);
7340 if (opcode
!= OP_ONCE
)
7342 SLJIT_ASSERT(jumplist
);
7343 JUMPHERE(jumplist
->jump
);
7344 jumplist
= jumplist
->next
;
7347 COMPILE_BACKTRACKINGPATH(current
->top
);
7348 if (current
->topbacktracks
)
7349 set_jumps(current
->topbacktracks
, LABEL());
7350 SLJIT_ASSERT(!current
->nextbacktracks
);
7352 while (*cc
== OP_ALT
);
7353 SLJIT_ASSERT(!jumplist
);
7357 SLJIT_ASSERT(opcode
== OP_COND
|| opcode
== OP_SCOND
);
7358 assert = CURRENT_AS(bracket_backtrack
)->u
.assert;
7359 if ((ccbegin
[1 + LINK_SIZE
] == OP_ASSERT_NOT
|| ccbegin
[1 + LINK_SIZE
] == OP_ASSERTBACK_NOT
) && assert->framesize
>= 0)
7362 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->private_data_ptr
);
7363 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
7364 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), assert->private_data_ptr
, SLJIT_MEM1(STACK_TOP
), assert->framesize
* sizeof(sljit_sw
));
7369 /* Free the STR_PTR. */
7370 if (private_data_ptr
== 0)
7371 free_stack(common
, 1);
7376 /* Using both tmp register is better for instruction scheduling. */
7377 if (common
->optimized_cbracket
[offset
>> 1] == 0)
7379 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7380 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
7381 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
7382 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(2));
7383 free_stack(common
, 3);
7384 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), TMP2
, 0);
7385 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, TMP1
, 0);
7389 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7390 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
7391 free_stack(common
, 2);
7392 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
7393 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), TMP2
, 0);
7396 else if (opcode
== OP_SBRA
|| opcode
== OP_SCOND
)
7398 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_MEM1(STACK_TOP
), STACK(0));
7399 free_stack(common
, 1);
7401 else if (opcode
== OP_ONCE
)
7403 cc
= ccbegin
+ GET(ccbegin
, 1);
7404 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
7406 /* Reset head and drop saved frame. */
7407 stacksize
= (ket
== OP_KETRMAX
|| ket
== OP_KETRMIN
|| *cc
== OP_ALT
) ? 2 : 1;
7408 free_stack(common
, CURRENT_AS(bracket_backtrack
)->u
.framesize
+ stacksize
);
7410 else if (ket
== OP_KETRMAX
|| (*cc
== OP_ALT
&& ket
!= OP_KETRMIN
))
7412 /* The STR_PTR must be released. */
7413 free_stack(common
, 1);
7417 /* Restore previous private_data_ptr */
7418 if (CURRENT_AS(bracket_backtrack
)->u
.framesize
>= 0)
7419 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, SLJIT_MEM1(STACK_TOP
), CURRENT_AS(bracket_backtrack
)->u
.framesize
* sizeof(sljit_sw
));
7420 else if (ket
== OP_KETRMIN
)
7422 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
7423 /* See the comment below. */
7424 free_stack(common
, 2);
7425 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), private_data_ptr
, TMP1
, 0);
7429 if (ket
== OP_KETRMAX
)
7431 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7432 if (bra
!= OP_BRAZERO
)
7433 free_stack(common
, 1);
7434 CMPTO(SLJIT_C_NOT_EQUAL
, STR_PTR
, 0, SLJIT_IMM
, 0, CURRENT_AS(bracket_backtrack
)->recursive_matchingpath
);
7435 if (bra
== OP_BRAZERO
)
7437 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
7438 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->zero_matchingpath
);
7440 free_stack(common
, 1);
7443 else if (ket
== OP_KETRMIN
)
7445 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7447 /* OP_ONCE removes everything in case of a backtrack, so we don't
7448 need to explicitly release the STR_PTR. The extra release would
7449 affect badly the free_stack(2) above. */
7450 if (opcode
!= OP_ONCE
)
7451 free_stack(common
, 1);
7452 CMPTO(SLJIT_C_NOT_EQUAL
, TMP1
, 0, SLJIT_IMM
, 0, rminlabel
);
7453 if (opcode
== OP_ONCE
)
7454 free_stack(common
, bra
== OP_BRAMINZERO
? 2 : 1);
7455 else if (bra
== OP_BRAMINZERO
)
7456 free_stack(common
, 1);
7458 else if (bra
== OP_BRAZERO
)
7460 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7461 JUMPTO(SLJIT_JUMP
, CURRENT_AS(bracket_backtrack
)->zero_matchingpath
);
7466 static void compile_bracketpos_backtrackingpath(compiler_common
*common
, struct backtrack_common
*current
)
7470 struct sljit_jump
*jump
;
7472 if (CURRENT_AS(bracketpos_backtrack
)->framesize
< 0)
7474 if (*current
->cc
== OP_CBRAPOS
|| *current
->cc
== OP_SCBRAPOS
)
7476 offset
= (GET2(current
->cc
, 1 + LINK_SIZE
)) << 1;
7477 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7478 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), STACK(1));
7479 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
), TMP1
, 0);
7480 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(offset
+ 1), TMP2
, 0);
7482 set_jumps(current
->topbacktracks
, LABEL());
7483 free_stack(common
, CURRENT_AS(bracketpos_backtrack
)->stacksize
);
7487 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), CURRENT_AS(bracketpos_backtrack
)->private_data_ptr
);
7488 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
7490 if (current
->topbacktracks
)
7492 jump
= JUMP(SLJIT_JUMP
);
7493 set_jumps(current
->topbacktracks
, LABEL());
7494 /* Drop the stack frame. */
7495 free_stack(common
, CURRENT_AS(bracketpos_backtrack
)->stacksize
);
7498 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), CURRENT_AS(bracketpos_backtrack
)->private_data_ptr
, SLJIT_MEM1(STACK_TOP
), CURRENT_AS(bracketpos_backtrack
)->framesize
* sizeof(sljit_sw
));
7501 static void compile_braminzero_backtrackingpath(compiler_common
*common
, struct backtrack_common
*current
)
7503 assert_backtrack backtrack
;
7505 current
->top
= NULL
;
7506 current
->topbacktracks
= NULL
;
7507 current
->nextbacktracks
= NULL
;
7508 if (current
->cc
[1] > OP_ASSERTBACK_NOT
)
7510 /* Manual call of compile_bracket_matchingpath and compile_bracket_backtrackingpath. */
7511 compile_bracket_matchingpath(common
, current
->cc
, current
);
7512 compile_bracket_backtrackingpath(common
, current
->top
);
7516 memset(&backtrack
, 0, sizeof(backtrack
));
7517 backtrack
.common
.cc
= current
->cc
;
7518 backtrack
.matchingpath
= CURRENT_AS(braminzero_backtrack
)->matchingpath
;
7519 /* Manual call of compile_assert_matchingpath. */
7520 compile_assert_matchingpath(common
, current
->cc
, &backtrack
, FALSE
);
7522 SLJIT_ASSERT(!current
->nextbacktracks
&& !current
->topbacktracks
);
7525 static void compile_backtrackingpath(compiler_common
*common
, struct backtrack_common
*current
)
7531 if (current
->nextbacktracks
!= NULL
)
7532 set_jumps(current
->nextbacktracks
, LABEL());
7533 switch(*current
->cc
)
7536 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7537 free_stack(common
, 1);
7538 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), TMP1
, 0);
7572 case OP_NOTMINQUERY
:
7578 case OP_NOTPOSQUERY
:
7581 case OP_NOTMINSTARI
:
7583 case OP_NOTMINPLUSI
:
7585 case OP_NOTMINQUERYI
:
7587 case OP_NOTMINUPTOI
:
7589 case OP_NOTPOSSTARI
:
7590 case OP_NOTPOSPLUSI
:
7591 case OP_NOTPOSQUERYI
:
7592 case OP_NOTPOSUPTOI
:
7594 case OP_TYPEMINSTAR
:
7596 case OP_TYPEMINPLUS
:
7598 case OP_TYPEMINQUERY
:
7600 case OP_TYPEMINUPTO
:
7602 case OP_TYPEPOSSTAR
:
7603 case OP_TYPEPOSPLUS
:
7604 case OP_TYPEPOSQUERY
:
7605 case OP_TYPEPOSUPTO
:
7608 #if defined SUPPORT_UTF || !defined COMPILE_PCRE8
7611 compile_iterator_backtrackingpath(common
, current
);
7616 compile_ref_iterator_backtrackingpath(common
, current
);
7620 compile_recurse_backtrackingpath(common
, current
);
7626 case OP_ASSERTBACK_NOT
:
7627 compile_assert_backtrackingpath(common
, current
);
7638 compile_bracket_backtrackingpath(common
, current
);
7642 if (current
->cc
[1] > OP_ASSERTBACK_NOT
)
7643 compile_bracket_backtrackingpath(common
, current
);
7645 compile_assert_backtrackingpath(common
, current
);
7653 compile_bracketpos_backtrackingpath(common
, current
);
7657 compile_braminzero_backtrackingpath(common
, current
);
7661 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7662 free_stack(common
, 1);
7663 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, TMP1
, 0);
7667 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_NOMATCH
);
7668 if (common
->quitlabel
== NULL
)
7669 add_jump(compiler
, &common
->quit
, JUMP(SLJIT_JUMP
));
7671 JUMPTO(SLJIT_JUMP
, common
->quitlabel
);
7676 case OP_ASSERT_ACCEPT
:
7677 set_jumps(current
->topbacktracks
, LABEL());
7681 SLJIT_ASSERT_STOP();
7684 current
= current
->prev
;
7688 static SLJIT_INLINE
void compile_recurse(compiler_common
*common
)
7691 pcre_uchar
*cc
= common
->start
+ common
->currententry
->start
;
7692 pcre_uchar
*ccbegin
= cc
+ 1 + LINK_SIZE
+ (*cc
== OP_BRA
? 0 : IMM2_SIZE
);
7693 pcre_uchar
*ccend
= bracketend(cc
);
7694 int private_data_size
= get_private_data_length_for_copy(common
, ccbegin
, ccend
);
7695 int framesize
= get_framesize(common
, cc
, TRUE
);
7696 int alternativesize
;
7698 backtrack_common altbacktrack
;
7699 struct sljit_label
*save_quitlabel
= common
->quitlabel
;
7700 jump_list
*save_quit
= common
->quit
;
7701 struct sljit_jump
*jump
;
7703 SLJIT_ASSERT(*cc
== OP_BRA
|| *cc
== OP_CBRA
|| *cc
== OP_CBRAPOS
|| *cc
== OP_SCBRA
|| *cc
== OP_SCBRAPOS
);
7704 needsframe
= framesize
>= 0;
7707 alternativesize
= *(cc
+ GET(cc
, 1)) == OP_ALT
? 1 : 0;
7709 SLJIT_ASSERT(common
->currententry
->entry
== NULL
&& common
->recursive_head
!= 0);
7710 common
->currententry
->entry
= LABEL();
7711 set_jumps(common
->currententry
->calls
, common
->currententry
->entry
);
7713 sljit_emit_fast_enter(compiler
, TMP2
, 0);
7714 allocate_stack(common
, private_data_size
+ framesize
+ alternativesize
);
7715 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(private_data_size
+ framesize
+ alternativesize
- 1), TMP2
, 0);
7716 copy_private_data(common
, ccbegin
, ccend
, TRUE
, private_data_size
+ framesize
+ alternativesize
, framesize
+ alternativesize
);
7717 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->recursive_head
, STACK_TOP
, 0);
7719 init_frame(common
, cc
, framesize
+ alternativesize
- 1, alternativesize
, TRUE
);
7721 if (alternativesize
> 0)
7722 OP1(SLJIT_MOV
, SLJIT_MEM1(STACK_TOP
), STACK(0), STR_PTR
, 0);
7724 memset(&altbacktrack
, 0, sizeof(backtrack_common
));
7725 common
->quitlabel
= NULL
;
7726 common
->acceptlabel
= NULL
;
7727 common
->quit
= NULL
;
7728 common
->accept
= NULL
;
7729 altbacktrack
.cc
= ccbegin
;
7733 altbacktrack
.top
= NULL
;
7734 altbacktrack
.topbacktracks
= NULL
;
7736 if (altbacktrack
.cc
!= ccbegin
)
7737 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(STACK_TOP
), STACK(0));
7739 compile_matchingpath(common
, altbacktrack
.cc
, cc
, &altbacktrack
);
7740 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
7742 common
->quitlabel
= save_quitlabel
;
7743 common
->quit
= save_quit
;
7747 add_jump(compiler
, &common
->accept
, JUMP(SLJIT_JUMP
));
7749 compile_backtrackingpath(common
, altbacktrack
.top
);
7750 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
7752 common
->quitlabel
= save_quitlabel
;
7753 common
->quit
= save_quit
;
7756 set_jumps(altbacktrack
.topbacktracks
, LABEL());
7761 altbacktrack
.cc
= cc
+ 1 + LINK_SIZE
;
7764 /* None of them matched. */
7765 if (common
->quit
!= NULL
)
7766 set_jumps(common
->quit
, LABEL());
7768 OP1(SLJIT_MOV
, TMP3
, 0, SLJIT_IMM
, 0);
7769 jump
= JUMP(SLJIT_JUMP
);
7771 set_jumps(common
->accept
, LABEL());
7772 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->recursive_head
);
7775 OP2(SLJIT_SUB
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, (framesize
+ alternativesize
) * sizeof(sljit_sw
));
7776 add_jump(compiler
, &common
->revertframes
, JUMP(SLJIT_FAST_CALL
));
7777 OP2(SLJIT_ADD
, STACK_TOP
, 0, STACK_TOP
, 0, SLJIT_IMM
, (framesize
+ alternativesize
) * sizeof(sljit_sw
));
7779 OP1(SLJIT_MOV
, TMP3
, 0, SLJIT_IMM
, 1);
7782 copy_private_data(common
, ccbegin
, ccend
, FALSE
, private_data_size
+ framesize
+ alternativesize
, framesize
+ alternativesize
);
7783 free_stack(common
, private_data_size
+ framesize
+ alternativesize
);
7784 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(STACK_TOP
), sizeof(sljit_sw
));
7785 OP1(SLJIT_MOV
, TMP1
, 0, TMP3
, 0);
7786 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->recursive_head
, TMP2
, 0);
7787 sljit_emit_fast_return(compiler
, SLJIT_MEM1(STACK_TOP
), 0);
7789 common
->quitlabel
= save_quitlabel
;
7790 common
->quit
= save_quit
;
7793 #undef COMPILE_BACKTRACKINGPATH
7797 PRIV(jit_compile
)(const REAL_PCRE
*re
, PUBL(extra
) *extra
, int mode
)
7799 struct sljit_compiler
*compiler
;
7800 backtrack_common rootbacktrack
;
7801 compiler_common common_data
;
7802 compiler_common
*common
= &common_data
;
7803 const pcre_uint8
*tables
= re
->tables
;
7804 pcre_study_data
*study
;
7805 int private_data_size
;
7807 executable_functions
*functions
;
7808 void *executable_func
;
7809 sljit_uw executable_size
;
7810 struct sljit_label
*mainloop
= NULL
;
7811 struct sljit_label
*empty_match_found
;
7812 struct sljit_label
*empty_match_backtrack
;
7813 struct sljit_jump
*jump
;
7814 struct sljit_jump
*reqbyte_notfound
= NULL
;
7815 struct sljit_jump
*empty_match
;
7817 SLJIT_ASSERT((extra
->flags
& PCRE_EXTRA_STUDY_DATA
) != 0);
7818 study
= extra
->study_data
;
7821 tables
= PRIV(default_tables
);
7823 memset(&rootbacktrack
, 0, sizeof(backtrack_common
));
7824 memset(common
, 0, sizeof(compiler_common
));
7825 rootbacktrack
.cc
= (pcre_uchar
*)re
+ re
->name_table_offset
+ re
->name_count
* re
->name_entry_size
;
7827 common
->start
= rootbacktrack
.cc
;
7828 common
->fcc
= tables
+ fcc_offset
;
7829 common
->lcc
= (sljit_sw
)(tables
+ lcc_offset
);
7830 common
->mode
= mode
;
7831 common
->nltype
= NLTYPE_FIXED
;
7832 switch(re
->options
& PCRE_NEWLINE_BITS
)
7835 /* Compile-time default */
7838 case -1: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANY
; break;
7839 case -2: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANYCRLF
; break;
7840 default: common
->newline
= NEWLINE
; break;
7843 case PCRE_NEWLINE_CR
: common
->newline
= CHAR_CR
; break;
7844 case PCRE_NEWLINE_LF
: common
->newline
= CHAR_NL
; break;
7845 case PCRE_NEWLINE_CR
+
7846 PCRE_NEWLINE_LF
: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; break;
7847 case PCRE_NEWLINE_ANY
: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANY
; break;
7848 case PCRE_NEWLINE_ANYCRLF
: common
->newline
= (CHAR_CR
<< 8) | CHAR_NL
; common
->nltype
= NLTYPE_ANYCRLF
; break;
7851 if ((re
->options
& PCRE_BSR_ANYCRLF
) != 0)
7852 common
->bsr_nltype
= NLTYPE_ANYCRLF
;
7853 else if ((re
->options
& PCRE_BSR_UNICODE
) != 0)
7854 common
->bsr_nltype
= NLTYPE_ANY
;
7858 common
->bsr_nltype
= NLTYPE_ANYCRLF
;
7860 common
->bsr_nltype
= NLTYPE_ANY
;
7863 common
->endonly
= (re
->options
& PCRE_DOLLAR_ENDONLY
) != 0;
7864 common
->ctypes
= (sljit_sw
)(tables
+ ctypes_offset
);
7865 common
->digits
[0] = -2;
7866 common
->name_table
= (sljit_sw
)((pcre_uchar
*)re
+ re
->name_table_offset
);
7867 common
->name_count
= re
->name_count
;
7868 common
->name_entry_size
= re
->name_entry_size
;
7869 common
->jscript_compat
= (re
->options
& PCRE_JAVASCRIPT_COMPAT
) != 0;
7871 /* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */
7872 common
->utf
= (re
->options
& PCRE_UTF8
) != 0;
7874 common
->use_ucp
= (re
->options
& PCRE_UCP
) != 0;
7876 #endif /* SUPPORT_UTF */
7877 ccend
= bracketend(rootbacktrack
.cc
);
7879 /* Calculate the local space size on the stack. */
7880 common
->ovector_start
= CALL_LIMIT
+ sizeof(sljit_sw
);
7881 common
->optimized_cbracket
= (pcre_uint8
*)SLJIT_MALLOC(re
->top_bracket
+ 1);
7882 if (!common
->optimized_cbracket
)
7884 memset(common
->optimized_cbracket
, 1, re
->top_bracket
+ 1);
7886 SLJIT_ASSERT(*rootbacktrack
.cc
== OP_BRA
&& ccend
[-(1 + LINK_SIZE
)] == OP_KET
);
7887 private_data_size
= get_private_data_length(common
, rootbacktrack
.cc
, ccend
);
7888 if (private_data_size
< 0)
7890 SLJIT_FREE(common
->optimized_cbracket
);
7894 /* Checking flags and updating ovector_start. */
7895 if (mode
== JIT_COMPILE
&& (re
->flags
& PCRE_REQCHSET
) != 0 && (re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
7897 common
->req_char_ptr
= common
->ovector_start
;
7898 common
->ovector_start
+= sizeof(sljit_sw
);
7900 if (mode
!= JIT_COMPILE
)
7902 common
->start_used_ptr
= common
->ovector_start
;
7903 common
->ovector_start
+= sizeof(sljit_sw
);
7904 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
7906 common
->hit_start
= common
->ovector_start
;
7907 common
->ovector_start
+= sizeof(sljit_sw
);
7910 if ((re
->options
& PCRE_FIRSTLINE
) != 0)
7912 common
->first_line_end
= common
->ovector_start
;
7913 common
->ovector_start
+= sizeof(sljit_sw
);
7916 /* Aligning ovector to even number of sljit words. */
7917 if ((common
->ovector_start
& sizeof(sljit_sw
)) != 0)
7918 common
->ovector_start
+= sizeof(sljit_sw
);
7920 SLJIT_ASSERT(!(common
->req_char_ptr
!= 0 && common
->start_used_ptr
!= 0));
7921 common
->cbraptr
= OVECTOR_START
+ (re
->top_bracket
+ 1) * 2 * sizeof(sljit_sw
);
7922 private_data_size
+= common
->cbraptr
+ (re
->top_bracket
+ 1) * sizeof(sljit_sw
);
7923 if (private_data_size
> SLJIT_MAX_LOCAL_SIZE
)
7925 SLJIT_FREE(common
->optimized_cbracket
);
7928 common
->private_data_ptrs
= (int *)SLJIT_MALLOC((ccend
- rootbacktrack
.cc
) * sizeof(int));
7929 if (!common
->private_data_ptrs
)
7931 SLJIT_FREE(common
->optimized_cbracket
);
7934 memset(common
->private_data_ptrs
, 0, (ccend
- rootbacktrack
.cc
) * sizeof(int));
7935 set_private_data_ptrs(common
, common
->cbraptr
+ (re
->top_bracket
+ 1) * sizeof(sljit_sw
), ccend
);
7937 compiler
= sljit_create_compiler();
7940 SLJIT_FREE(common
->optimized_cbracket
);
7941 SLJIT_FREE(common
->private_data_ptrs
);
7944 common
->compiler
= compiler
;
7946 /* Main pcre_jit_exec entry. */
7947 sljit_emit_enter(compiler
, 1, 5, 5, private_data_size
);
7949 /* Register init. */
7950 reset_ovector(common
, (re
->top_bracket
+ 1) * 2);
7951 if (common
->req_char_ptr
!= 0)
7952 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->req_char_ptr
, SLJIT_SCRATCH_REG1
, 0);
7954 OP1(SLJIT_MOV
, ARGUMENTS
, 0, SLJIT_SAVED_REG1
, 0);
7955 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_SAVED_REG1
, 0);
7956 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
7957 OP1(SLJIT_MOV
, STR_END
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, end
));
7958 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, stack
));
7959 OP1(SLJIT_MOV_SI
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, calllimit
));
7960 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(struct sljit_stack
, base
));
7961 OP1(SLJIT_MOV
, STACK_LIMIT
, 0, SLJIT_MEM1(TMP2
), SLJIT_OFFSETOF(struct sljit_stack
, limit
));
7962 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), CALL_LIMIT
, TMP1
, 0);
7964 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
7965 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, 0);
7967 /* Main part of the matching */
7968 if ((re
->options
& PCRE_ANCHORED
) == 0)
7970 mainloop
= mainloop_entry(common
, (re
->flags
& PCRE_HASCRORLF
) != 0, (re
->options
& PCRE_FIRSTLINE
) != 0);
7971 /* Forward search if possible. */
7972 if ((re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
7974 if (mode
== JIT_COMPILE
&& fast_forward_first_n_chars(common
, (re
->options
& PCRE_FIRSTLINE
) != 0))
7975 { /* Do nothing */ }
7976 else if ((re
->flags
& PCRE_FIRSTSET
) != 0)
7977 fast_forward_first_char(common
, (pcre_uchar
)re
->first_char
, (re
->flags
& PCRE_FCH_CASELESS
) != 0, (re
->options
& PCRE_FIRSTLINE
) != 0);
7978 else if ((re
->flags
& PCRE_STARTLINE
) != 0)
7979 fast_forward_newline(common
, (re
->options
& PCRE_FIRSTLINE
) != 0);
7980 else if ((re
->flags
& PCRE_STARTLINE
) == 0 && study
!= NULL
&& (study
->flags
& PCRE_STUDY_MAPPED
) != 0)
7981 fast_forward_start_bits(common
, (sljit_uw
)study
->start_bits
, (re
->options
& PCRE_FIRSTLINE
) != 0);
7984 if (common
->req_char_ptr
!= 0)
7985 reqbyte_notfound
= search_requested_char(common
, (pcre_uchar
)re
->req_char
, (re
->flags
& PCRE_RCH_CASELESS
) != 0, (re
->flags
& PCRE_FIRSTSET
) != 0);
7987 /* Store the current STR_PTR in OVECTOR(0). */
7988 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0), STR_PTR
, 0);
7989 /* Copy the limit of allowed recursions. */
7990 OP1(SLJIT_MOV
, CALL_COUNT
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), CALL_LIMIT
);
7991 if (common
->mark_ptr
!= 0)
7992 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->mark_ptr
, SLJIT_IMM
, 0);
7993 /* Copy the beginning of the string. */
7994 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
7996 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, 0);
7997 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
8000 else if (mode
== JIT_PARTIAL_HARD_COMPILE
)
8001 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, STR_PTR
, 0);
8003 compile_matchingpath(common
, rootbacktrack
.cc
, ccend
, &rootbacktrack
);
8004 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
8006 sljit_free_compiler(compiler
);
8007 SLJIT_FREE(common
->optimized_cbracket
);
8008 SLJIT_FREE(common
->private_data_ptrs
);
8012 empty_match
= CMP(SLJIT_C_EQUAL
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
8013 empty_match_found
= LABEL();
8015 common
->acceptlabel
= LABEL();
8016 if (common
->accept
!= NULL
)
8017 set_jumps(common
->accept
, common
->acceptlabel
);
8019 /* This means we have a match. Update the ovector. */
8020 copy_ovector(common
, re
->top_bracket
+ 1);
8021 common
->quitlabel
= LABEL();
8022 if (common
->quit
!= NULL
)
8023 set_jumps(common
->quit
, common
->quitlabel
);
8024 sljit_emit_return(compiler
, SLJIT_MOV
, SLJIT_RETURN_REG
, 0);
8026 if (mode
!= JIT_COMPILE
)
8028 common
->partialmatchlabel
= LABEL();
8029 set_jumps(common
->partialmatch
, common
->partialmatchlabel
);
8030 return_with_partial_match(common
, common
->quitlabel
);
8033 empty_match_backtrack
= LABEL();
8034 compile_backtrackingpath(common
, rootbacktrack
.top
);
8035 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
8037 sljit_free_compiler(compiler
);
8038 SLJIT_FREE(common
->optimized_cbracket
);
8039 SLJIT_FREE(common
->private_data_ptrs
);
8043 SLJIT_ASSERT(rootbacktrack
.prev
== NULL
);
8045 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
8047 /* Update hit_start only in the first time. */
8048 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, -1);
8049 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
);
8050 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->start_used_ptr
, SLJIT_IMM
, -1);
8051 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, TMP1
, 0);
8055 /* Check we have remaining characters. */
8056 OP1(SLJIT_MOV
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), OVECTOR(0));
8058 if ((re
->options
& PCRE_ANCHORED
) == 0)
8060 if ((re
->options
& PCRE_FIRSTLINE
) == 0)
8062 if (mode
== JIT_COMPILE
&& study
!= NULL
&& study
->minlength
> 1 && (re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
8064 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(study
->minlength
+ 1));
8065 CMPTO(SLJIT_C_LESS_EQUAL
, TMP1
, 0, STR_END
, 0, mainloop
);
8068 CMPTO(SLJIT_C_LESS
, STR_PTR
, 0, STR_END
, 0, mainloop
);
8072 SLJIT_ASSERT(common
->first_line_end
!= 0);
8073 if (mode
== JIT_COMPILE
&& study
!= NULL
&& study
->minlength
> 1 && (re
->options
& PCRE_NO_START_OPTIMIZE
) == 0)
8075 OP2(SLJIT_ADD
, TMP1
, 0, STR_PTR
, 0, SLJIT_IMM
, IN_UCHARS(study
->minlength
+ 1));
8076 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, TMP1
, 0, STR_END
, 0);
8077 OP_FLAGS(SLJIT_MOV
, TMP2
, 0, SLJIT_UNUSED
, 0, SLJIT_C_GREATER
);
8078 OP2(SLJIT_SUB
| SLJIT_SET_U
, SLJIT_UNUSED
, 0, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
);
8079 OP_FLAGS(SLJIT_OR
| SLJIT_SET_E
, TMP2
, 0, TMP2
, 0, SLJIT_C_GREATER_EQUAL
);
8080 JUMPTO(SLJIT_C_ZERO
, mainloop
);
8083 CMPTO(SLJIT_C_LESS
, STR_PTR
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->first_line_end
, mainloop
);
8087 /* No more remaining characters. */
8088 if (reqbyte_notfound
!= NULL
)
8089 JUMPHERE(reqbyte_notfound
);
8091 if (mode
== JIT_PARTIAL_SOFT_COMPILE
)
8092 CMPTO(SLJIT_C_NOT_EQUAL
, SLJIT_MEM1(SLJIT_LOCALS_REG
), common
->hit_start
, SLJIT_IMM
, 0, common
->partialmatchlabel
);
8094 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_NOMATCH
);
8095 JUMPTO(SLJIT_JUMP
, common
->quitlabel
);
8097 flush_stubs(common
);
8099 JUMPHERE(empty_match
);
8100 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
8101 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty
));
8102 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0, empty_match_backtrack
);
8103 OP1(SLJIT_MOV_UB
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, notempty_atstart
));
8104 CMPTO(SLJIT_C_EQUAL
, TMP2
, 0, SLJIT_IMM
, 0, empty_match_found
);
8105 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, str
));
8106 CMPTO(SLJIT_C_NOT_EQUAL
, TMP2
, 0, STR_PTR
, 0, empty_match_found
);
8107 JUMPTO(SLJIT_JUMP
, empty_match_backtrack
);
8109 common
->currententry
= common
->entries
;
8110 while (common
->currententry
!= NULL
)
8112 /* Might add new entries. */
8113 compile_recurse(common
);
8114 if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler
)))
8116 sljit_free_compiler(compiler
);
8117 SLJIT_FREE(common
->optimized_cbracket
);
8118 SLJIT_FREE(common
->private_data_ptrs
);
8121 flush_stubs(common
);
8122 common
->currententry
= common
->currententry
->next
;
8125 /* Allocating stack, returns with PCRE_ERROR_JIT_STACKLIMIT if fails. */
8126 /* This is a (really) rare case. */
8127 set_jumps(common
->stackalloc
, LABEL());
8128 /* RETURN_ADDR is not a saved register. */
8129 sljit_emit_fast_enter(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
8130 OP1(SLJIT_MOV
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
, TMP2
, 0);
8131 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
8132 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, stack
));
8133 OP1(SLJIT_MOV
, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, top
), STACK_TOP
, 0);
8134 OP2(SLJIT_ADD
, TMP2
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, limit
), SLJIT_IMM
, STACK_GROWTH_RATE
);
8136 sljit_emit_ijump(compiler
, SLJIT_CALL2
, SLJIT_IMM
, SLJIT_FUNC_OFFSET(sljit_stack_resize
));
8137 jump
= CMP(SLJIT_C_NOT_EQUAL
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, 0);
8138 OP1(SLJIT_MOV
, TMP1
, 0, ARGUMENTS
, 0);
8139 OP1(SLJIT_MOV
, TMP1
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(jit_arguments
, stack
));
8140 OP1(SLJIT_MOV
, STACK_TOP
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, top
));
8141 OP1(SLJIT_MOV
, STACK_LIMIT
, 0, SLJIT_MEM1(TMP1
), SLJIT_OFFSETOF(struct sljit_stack
, limit
));
8142 OP1(SLJIT_MOV
, TMP2
, 0, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS1
);
8143 sljit_emit_fast_return(compiler
, SLJIT_MEM1(SLJIT_LOCALS_REG
), LOCALS0
);
8145 /* Allocation failed. */
8147 /* We break the return address cache here, but this is a really rare case. */
8148 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_JIT_STACKLIMIT
);
8149 JUMPTO(SLJIT_JUMP
, common
->quitlabel
);
8151 /* Call limit reached. */
8152 set_jumps(common
->calllimit
, LABEL());
8153 OP1(SLJIT_MOV
, SLJIT_RETURN_REG
, 0, SLJIT_IMM
, PCRE_ERROR_MATCHLIMIT
);
8154 JUMPTO(SLJIT_JUMP
, common
->quitlabel
);
8156 if (common
->revertframes
!= NULL
)
8158 set_jumps(common
->revertframes
, LABEL());
8159 do_revertframes(common
);
8161 if (common
->wordboundary
!= NULL
)
8163 set_jumps(common
->wordboundary
, LABEL());
8164 check_wordboundary(common
);
8166 if (common
->anynewline
!= NULL
)
8168 set_jumps(common
->anynewline
, LABEL());
8169 check_anynewline(common
);
8171 if (common
->hspace
!= NULL
)
8173 set_jumps(common
->hspace
, LABEL());
8174 check_hspace(common
);
8176 if (common
->vspace
!= NULL
)
8178 set_jumps(common
->vspace
, LABEL());
8179 check_vspace(common
);
8181 if (common
->casefulcmp
!= NULL
)
8183 set_jumps(common
->casefulcmp
, LABEL());
8184 do_casefulcmp(common
);
8186 if (common
->caselesscmp
!= NULL
)
8188 set_jumps(common
->caselesscmp
, LABEL());
8189 do_caselesscmp(common
);
8192 #ifndef COMPILE_PCRE32
8193 if (common
->utfreadchar
!= NULL
)
8195 set_jumps(common
->utfreadchar
, LABEL());
8196 do_utfreadchar(common
);
8198 #endif /* !COMPILE_PCRE32 */
8199 #ifdef COMPILE_PCRE8
8200 if (common
->utfreadtype8
!= NULL
)
8202 set_jumps(common
->utfreadtype8
, LABEL());
8203 do_utfreadtype8(common
);
8205 #endif /* COMPILE_PCRE8 */
8206 #endif /* SUPPORT_UTF */
8208 if (common
->getucd
!= NULL
)
8210 set_jumps(common
->getucd
, LABEL());
8215 SLJIT_FREE(common
->optimized_cbracket
);
8216 SLJIT_FREE(common
->private_data_ptrs
);
8217 executable_func
= sljit_generate_code(compiler
);
8218 executable_size
= sljit_get_generated_code_size(compiler
);
8219 sljit_free_compiler(compiler
);
8220 if (executable_func
== NULL
)
8223 /* Reuse the function descriptor if possible. */
8224 if ((extra
->flags
& PCRE_EXTRA_EXECUTABLE_JIT
) != 0 && extra
->executable_jit
!= NULL
)
8225 functions
= (executable_functions
*)extra
->executable_jit
;
8228 /* Note: If your memory-checker has flagged the allocation below as a
8229 * memory leak, it is probably because you either forgot to call
8230 * pcre_free_study() (or pcre16_free_study()) on the pcre_extra (or
8231 * pcre16_extra) object, or you called said function after having
8232 * cleared the PCRE_EXTRA_EXECUTABLE_JIT bit from the "flags" field
8233 * of the object. (The function will only free the JIT data if the
8234 * bit remains set, as the bit indicates that the pointer to the data
8237 functions
= SLJIT_MALLOC(sizeof(executable_functions
));
8238 if (functions
== NULL
)
8240 /* This case is highly unlikely since we just recently
8241 freed a lot of memory. Although not impossible. */
8242 sljit_free_code(executable_func
);
8245 memset(functions
, 0, sizeof(executable_functions
));
8246 functions
->top_bracket
= (re
->top_bracket
+ 1) * 2;
8247 extra
->executable_jit
= functions
;
8248 extra
->flags
|= PCRE_EXTRA_EXECUTABLE_JIT
;
8251 functions
->executable_funcs
[mode
] = executable_func
;
8252 functions
->executable_sizes
[mode
] = executable_size
;
8255 static int jit_machine_stack_exec(jit_arguments
*arguments
, void* executable_func
)
8258 void* executable_func
;
8259 jit_function call_executable_func
;
8260 } convert_executable_func
;
8261 pcre_uint8 local_space
[MACHINE_STACK_SIZE
];
8262 struct sljit_stack local_stack
;
8264 local_stack
.top
= (sljit_sw
)&local_space
;
8265 local_stack
.base
= local_stack
.top
;
8266 local_stack
.limit
= local_stack
.base
+ MACHINE_STACK_SIZE
;
8267 local_stack
.max_limit
= local_stack
.limit
;
8268 arguments
->stack
= &local_stack
;
8269 convert_executable_func
.executable_func
= executable_func
;
8270 return convert_executable_func
.call_executable_func(arguments
);
8274 PRIV(jit_exec
)(const PUBL(extra
) *extra_data
, const pcre_uchar
*subject
,
8275 int length
, int start_offset
, int options
, int *offsets
, int offsetcount
)
8277 executable_functions
*functions
= (executable_functions
*)extra_data
->executable_jit
;
8279 void* executable_func
;
8280 jit_function call_executable_func
;
8281 } convert_executable_func
;
8282 jit_arguments arguments
;
8285 int mode
= JIT_COMPILE
;
8287 if ((options
& PCRE_PARTIAL_HARD
) != 0)
8288 mode
= JIT_PARTIAL_HARD_COMPILE
;
8289 else if ((options
& PCRE_PARTIAL_SOFT
) != 0)
8290 mode
= JIT_PARTIAL_SOFT_COMPILE
;
8292 if (functions
->executable_funcs
[mode
] == NULL
)
8293 return PCRE_ERROR_JIT_BADOPTION
;
8295 /* Sanity checks should be handled by pcre_exec. */
8296 arguments
.str
= subject
+ start_offset
;
8297 arguments
.begin
= subject
;
8298 arguments
.end
= subject
+ length
;
8299 arguments
.mark_ptr
= NULL
;
8300 /* JIT decreases this value less frequently than the interpreter. */
8301 arguments
.calllimit
= ((extra_data
->flags
& PCRE_EXTRA_MATCH_LIMIT
) == 0) ? MATCH_LIMIT
: extra_data
->match_limit
;
8302 arguments
.notbol
= (options
& PCRE_NOTBOL
) != 0;
8303 arguments
.noteol
= (options
& PCRE_NOTEOL
) != 0;
8304 arguments
.notempty
= (options
& PCRE_NOTEMPTY
) != 0;
8305 arguments
.notempty_atstart
= (options
& PCRE_NOTEMPTY_ATSTART
) != 0;
8306 arguments
.offsets
= offsets
;
8308 /* pcre_exec() rounds offsetcount to a multiple of 3, and then uses only 2/3 of
8309 the output vector for storing captured strings, with the remainder used as
8310 workspace. We don't need the workspace here. For compatibility, we limit the
8311 number of captured strings in the same way as pcre_exec(), so that the user
8312 gets the same result with and without JIT. */
8314 if (offsetcount
!= 2)
8315 offsetcount
= ((offsetcount
- (offsetcount
% 3)) * 2) / 3;
8316 maxoffsetcount
= functions
->top_bracket
;
8317 if (offsetcount
> maxoffsetcount
)
8318 offsetcount
= maxoffsetcount
;
8319 arguments
.offsetcount
= offsetcount
;
8321 if (functions
->callback
)
8322 arguments
.stack
= (struct sljit_stack
*)functions
->callback(functions
->userdata
);
8324 arguments
.stack
= (struct sljit_stack
*)functions
->userdata
;
8326 if (arguments
.stack
== NULL
)
8327 retval
= jit_machine_stack_exec(&arguments
, functions
->executable_funcs
[mode
]);
8330 convert_executable_func
.executable_func
= functions
->executable_funcs
[mode
];
8331 retval
= convert_executable_func
.call_executable_func(&arguments
);
8334 if (retval
* 2 > offsetcount
)
8336 if ((extra_data
->flags
& PCRE_EXTRA_MARK
) != 0)
8337 *(extra_data
->mark
) = arguments
.mark_ptr
;
8342 #if defined COMPILE_PCRE8
8343 PCRE_EXP_DEFN
int PCRE_CALL_CONVENTION
8344 pcre_jit_exec(const pcre
*argument_re
, const pcre_extra
*extra_data
,
8345 PCRE_SPTR subject
, int length
, int start_offset
, int options
,
8346 int *offsets
, int offsetcount
, pcre_jit_stack
*stack
)
8347 #elif defined COMPILE_PCRE16
8348 PCRE_EXP_DEFN
int PCRE_CALL_CONVENTION
8349 pcre16_jit_exec(const pcre16
*argument_re
, const pcre16_extra
*extra_data
,
8350 PCRE_SPTR16 subject
, int length
, int start_offset
, int options
,
8351 int *offsets
, int offsetcount
, pcre16_jit_stack
*stack
)
8352 #elif defined COMPILE_PCRE32
8353 PCRE_EXP_DEFN
int PCRE_CALL_CONVENTION
8354 pcre32_jit_exec(const pcre32
*argument_re
, const pcre32_extra
*extra_data
,
8355 PCRE_SPTR32 subject
, int length
, int start_offset
, int options
,
8356 int *offsets
, int offsetcount
, pcre32_jit_stack
*stack
)
8359 pcre_uchar
*subject_ptr
= (pcre_uchar
*)subject
;
8360 executable_functions
*functions
= (executable_functions
*)extra_data
->executable_jit
;
8362 void* executable_func
;
8363 jit_function call_executable_func
;
8364 } convert_executable_func
;
8365 jit_arguments arguments
;
8368 int mode
= JIT_COMPILE
;
8370 SLJIT_UNUSED_ARG(argument_re
);
8372 /* Plausibility checks */
8373 if ((options
& ~PUBLIC_JIT_EXEC_OPTIONS
) != 0) return PCRE_ERROR_JIT_BADOPTION
;
8375 if ((options
& PCRE_PARTIAL_HARD
) != 0)
8376 mode
= JIT_PARTIAL_HARD_COMPILE
;
8377 else if ((options
& PCRE_PARTIAL_SOFT
) != 0)
8378 mode
= JIT_PARTIAL_SOFT_COMPILE
;
8380 if (functions
->executable_funcs
[mode
] == NULL
)
8381 return PCRE_ERROR_JIT_BADOPTION
;
8383 /* Sanity checks should be handled by pcre_exec. */
8384 arguments
.stack
= (struct sljit_stack
*)stack
;
8385 arguments
.str
= subject_ptr
+ start_offset
;
8386 arguments
.begin
= subject_ptr
;
8387 arguments
.end
= subject_ptr
+ length
;
8388 arguments
.mark_ptr
= NULL
;
8389 /* JIT decreases this value less frequently than the interpreter. */
8390 arguments
.calllimit
= ((extra_data
->flags
& PCRE_EXTRA_MATCH_LIMIT
) == 0) ? MATCH_LIMIT
: extra_data
->match_limit
;
8391 arguments
.notbol
= (options
& PCRE_NOTBOL
) != 0;
8392 arguments
.noteol
= (options
& PCRE_NOTEOL
) != 0;
8393 arguments
.notempty
= (options
& PCRE_NOTEMPTY
) != 0;
8394 arguments
.notempty_atstart
= (options
& PCRE_NOTEMPTY_ATSTART
) != 0;
8395 arguments
.offsets
= offsets
;
8397 /* pcre_exec() rounds offsetcount to a multiple of 3, and then uses only 2/3 of
8398 the output vector for storing captured strings, with the remainder used as
8399 workspace. We don't need the workspace here. For compatibility, we limit the
8400 number of captured strings in the same way as pcre_exec(), so that the user
8401 gets the same result with and without JIT. */
8403 if (offsetcount
!= 2)
8404 offsetcount
= ((offsetcount
- (offsetcount
% 3)) * 2) / 3;
8405 maxoffsetcount
= functions
->top_bracket
;
8406 if (offsetcount
> maxoffsetcount
)
8407 offsetcount
= maxoffsetcount
;
8408 arguments
.offsetcount
= offsetcount
;
8410 convert_executable_func
.executable_func
= functions
->executable_funcs
[mode
];
8411 retval
= convert_executable_func
.call_executable_func(&arguments
);
8413 if (retval
* 2 > offsetcount
)
8415 if ((extra_data
->flags
& PCRE_EXTRA_MARK
) != 0)
8416 *(extra_data
->mark
) = arguments
.mark_ptr
;
8422 PRIV(jit_free
)(void *executable_funcs
)
8425 executable_functions
*functions
= (executable_functions
*)executable_funcs
;
8426 for (i
= 0; i
< JIT_NUMBER_OF_COMPILE_MODES
; i
++)
8428 if (functions
->executable_funcs
[i
] != NULL
)
8429 sljit_free_code(functions
->executable_funcs
[i
]);
8431 SLJIT_FREE(functions
);
8435 PRIV(jit_get_size
)(void *executable_funcs
)
8439 sljit_uw
*executable_sizes
= ((executable_functions
*)executable_funcs
)->executable_sizes
;
8440 for (i
= 0; i
< JIT_NUMBER_OF_COMPILE_MODES
; i
++)
8441 size
+= executable_sizes
[i
];
8446 PRIV(jit_get_target
)(void)
8448 return sljit_get_platform_name();
8451 #if defined COMPILE_PCRE8
8452 PCRE_EXP_DECL pcre_jit_stack
*
8453 pcre_jit_stack_alloc(int startsize
, int maxsize
)
8454 #elif defined COMPILE_PCRE16
8455 PCRE_EXP_DECL pcre16_jit_stack
*
8456 pcre16_jit_stack_alloc(int startsize
, int maxsize
)
8457 #elif defined COMPILE_PCRE32
8458 PCRE_EXP_DECL pcre32_jit_stack
*
8459 pcre32_jit_stack_alloc(int startsize
, int maxsize
)
8462 if (startsize
< 1 || maxsize
< 1)
8464 if (startsize
> maxsize
)
8465 startsize
= maxsize
;
8466 startsize
= (startsize
+ STACK_GROWTH_RATE
- 1) & ~(STACK_GROWTH_RATE
- 1);
8467 maxsize
= (maxsize
+ STACK_GROWTH_RATE
- 1) & ~(STACK_GROWTH_RATE
- 1);
8468 return (PUBL(jit_stack
)*)sljit_allocate_stack(startsize
, maxsize
);
8471 #if defined COMPILE_PCRE8
8473 pcre_jit_stack_free(pcre_jit_stack
*stack
)
8474 #elif defined COMPILE_PCRE16
8476 pcre16_jit_stack_free(pcre16_jit_stack
*stack
)
8477 #elif defined COMPILE_PCRE32
8479 pcre32_jit_stack_free(pcre32_jit_stack
*stack
)
8482 sljit_free_stack((struct sljit_stack
*)stack
);
8485 #if defined COMPILE_PCRE8
8487 pcre_assign_jit_stack(pcre_extra
*extra
, pcre_jit_callback callback
, void *userdata
)
8488 #elif defined COMPILE_PCRE16
8490 pcre16_assign_jit_stack(pcre16_extra
*extra
, pcre16_jit_callback callback
, void *userdata
)
8491 #elif defined COMPILE_PCRE32
8493 pcre32_assign_jit_stack(pcre32_extra
*extra
, pcre32_jit_callback callback
, void *userdata
)
8496 executable_functions
*functions
;
8497 if (extra
!= NULL
&&
8498 (extra
->flags
& PCRE_EXTRA_EXECUTABLE_JIT
) != 0 &&
8499 extra
->executable_jit
!= NULL
)
8501 functions
= (executable_functions
*)extra
->executable_jit
;
8502 functions
->callback
= callback
;
8503 functions
->userdata
= userdata
;
8507 #else /* SUPPORT_JIT */
8509 /* These are dummy functions to avoid linking errors when JIT support is not
8512 #if defined COMPILE_PCRE8
8513 PCRE_EXP_DECL pcre_jit_stack
*
8514 pcre_jit_stack_alloc(int startsize
, int maxsize
)
8515 #elif defined COMPILE_PCRE16
8516 PCRE_EXP_DECL pcre16_jit_stack
*
8517 pcre16_jit_stack_alloc(int startsize
, int maxsize
)
8518 #elif defined COMPILE_PCRE32
8519 PCRE_EXP_DECL pcre32_jit_stack
*
8520 pcre32_jit_stack_alloc(int startsize
, int maxsize
)
8528 #if defined COMPILE_PCRE8
8530 pcre_jit_stack_free(pcre_jit_stack
*stack
)
8531 #elif defined COMPILE_PCRE16
8533 pcre16_jit_stack_free(pcre16_jit_stack
*stack
)
8534 #elif defined COMPILE_PCRE32
8536 pcre32_jit_stack_free(pcre32_jit_stack
*stack
)
8542 #if defined COMPILE_PCRE8
8544 pcre_assign_jit_stack(pcre_extra
*extra
, pcre_jit_callback callback
, void *userdata
)
8545 #elif defined COMPILE_PCRE16
8547 pcre16_assign_jit_stack(pcre16_extra
*extra
, pcre16_jit_callback callback
, void *userdata
)
8548 #elif defined COMPILE_PCRE32
8550 pcre32_assign_jit_stack(pcre32_extra
*extra
, pcre32_jit_callback callback
, void *userdata
)
8560 /* End of pcre_jit_compile.c */