Parent Directory
|
Revision Log
|
Patch
revision 1195 by zherczeg, Thu Nov 1 15:21:27 2012 UTC | revision 1303 by zherczeg, Fri Mar 29 09:01:20 2013 UTC | |
---|---|---|
# | Line 6 | Line 6 |
6 | and semantics are as close as possible to those of the Perl 5 language. | and semantics are as close as possible to those of the Perl 5 language. |
7 | ||
8 | Written by Philip Hazel | Written by Philip Hazel |
9 | Copyright (c) 1997-2012 University of Cambridge | Copyright (c) 1997-2013 University of Cambridge |
10 | ||
11 | The machine code generator part (this module) was written by Zoltan Herczeg | The machine code generator part (this module) was written by Zoltan Herczeg |
12 | Copyright (c) 2010-2012 | Copyright (c) 2010-2013 |
13 | ||
14 | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
15 | Redistribution and use in source and binary forms, with or without | Redistribution and use in source and binary forms, with or without |
# | Line 65 system files. */ | Line 65 system files. */ |
65 | #error Unsupported architecture | #error Unsupported architecture |
66 | #endif | #endif |
67 | ||
68 | /* Defines for debugging purposes. */ | |
69 | ||
70 | /* 1 - Use unoptimized capturing brackets. | |
71 | 2 - Enable capture_last_ptr (includes option 1). */ | |
72 | /* #define DEBUG_FORCE_UNOPTIMIZED_CBRAS 2 */ | |
73 | ||
74 | /* 1 - Always have a control head. */ | |
75 | /* #define DEBUG_FORCE_CONTROL_HEAD 1 */ | |
76 | ||
77 | /* Allocate memory for the regex stack on the real machine stack. | /* Allocate memory for the regex stack on the real machine stack. |
78 | Fast, but limited size. */ | Fast, but limited size. */ |
79 | #define MACHINE_STACK_SIZE 32768 | #define MACHINE_STACK_SIZE 32768 |
# | Line 157 typedef struct jit_arguments { | Line 166 typedef struct jit_arguments { |
166 | int *offsets; | int *offsets; |
167 | pcre_uchar *uchar_ptr; | pcre_uchar *uchar_ptr; |
168 | pcre_uchar *mark_ptr; | pcre_uchar *mark_ptr; |
169 | void *callout_data; | |
170 | /* Everything else after. */ | /* Everything else after. */ |
171 | int offsetcount; | int real_offset_count; |
172 | int calllimit; | int offset_count; |
173 | int call_limit; | |
174 | pcre_uint8 notbol; | pcre_uint8 notbol; |
175 | pcre_uint8 noteol; | pcre_uint8 noteol; |
176 | pcre_uint8 notempty; | pcre_uint8 notempty; |
# | Line 179 typedef struct jump_list { | Line 190 typedef struct jump_list { |
190 | struct jump_list *next; | struct jump_list *next; |
191 | } jump_list; | } jump_list; |
192 | ||
enum stub_types { stack_alloc }; | ||
193 | typedef struct stub_list { | typedef struct stub_list { |
enum stub_types type; | ||
int data; | ||
194 | struct sljit_jump *start; | struct sljit_jump *start; |
195 | struct sljit_label *quit; | struct sljit_label *quit; |
196 | struct stub_list *next; | struct stub_list *next; |
197 | } stub_list; | } stub_list; |
198 | ||
199 | enum frame_types { | |
200 | no_frame = -1, | |
201 | no_stack = -2 | |
202 | }; | |
203 | ||
204 | enum control_types { | |
205 | type_mark = 0, | |
206 | type_then_trap = 1 | |
207 | }; | |
208 | ||
209 | typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); | typedef int (SLJIT_CALL *jit_function)(jit_arguments *args); |
210 | ||
211 | /* The following structure is the key data type for the recursive | /* The following structure is the key data type for the recursive |
# | Line 209 typedef struct backtrack_common { | Line 226 typedef struct backtrack_common { |
226 | typedef struct assert_backtrack { | typedef struct assert_backtrack { |
227 | backtrack_common common; | backtrack_common common; |
228 | jump_list *condfailed; | jump_list *condfailed; |
229 | /* Less than 0 (-1) if a frame is not needed. */ | /* Less than 0 if a frame is not needed. */ |
230 | int framesize; | int framesize; |
231 | /* Points to our private memory word on the stack. */ | /* Points to our private memory word on the stack. */ |
232 | int private_data_ptr; | int private_data_ptr; |
# | Line 230 typedef struct bracket_backtrack { | Line 247 typedef struct bracket_backtrack { |
247 | /* Both for OP_COND, OP_SCOND. */ | /* Both for OP_COND, OP_SCOND. */ |
248 | jump_list *condfailed; | jump_list *condfailed; |
249 | assert_backtrack *assert; | assert_backtrack *assert; |
250 | /* For OP_ONCE. -1 if not needed. */ | /* For OP_ONCE. Less than 0 if not needed. */ |
251 | int framesize; | int framesize; |
252 | } u; | } u; |
253 | /* Points to our private memory word on the stack. */ | /* Points to our private memory word on the stack. */ |
# | Line 265 typedef struct recurse_entry { | Line 282 typedef struct recurse_entry { |
282 | /* Collects the calls until the function is not created. */ | /* Collects the calls until the function is not created. */ |
283 | jump_list *calls; | jump_list *calls; |
284 | /* Points to the starting opcode. */ | /* Points to the starting opcode. */ |
285 | int start; | sljit_sw start; |
286 | } recurse_entry; | } recurse_entry; |
287 | ||
288 | typedef struct recurse_backtrack { | typedef struct recurse_backtrack { |
289 | backtrack_common common; | backtrack_common common; |
290 | BOOL inlined_pattern; | |
291 | } recurse_backtrack; | } recurse_backtrack; |
292 | ||
293 | #define OP_THEN_TRAP OP_TABLE_LENGTH | |
294 | ||
295 | typedef struct then_trap_backtrack { | |
296 | backtrack_common common; | |
297 | /* If then_trap is not NULL, this structure contains the real | |
298 | then_trap for the backtracking path. */ | |
299 | struct then_trap_backtrack *then_trap; | |
300 | /* Points to the starting opcode. */ | |
301 | sljit_sw start; | |
302 | /* Exit point for the then opcodes of this alternative. */ | |
303 | jump_list *quit; | |
304 | /* Frame size of the current alternative. */ | |
305 | int framesize; | |
306 | } then_trap_backtrack; | |
307 | ||
308 | #define MAX_RANGE_SIZE 6 | #define MAX_RANGE_SIZE 6 |
309 | ||
310 | typedef struct compiler_common { | typedef struct compiler_common { |
311 | /* The sljit ceneric compiler. */ | |
312 | struct sljit_compiler *compiler; | struct sljit_compiler *compiler; |
313 | /* First byte code. */ | |
314 | pcre_uchar *start; | pcre_uchar *start; |
315 | /* Maps private data offset to each opcode. */ | /* Maps private data offset to each opcode. */ |
316 | int *private_data_ptrs; | int *private_data_ptrs; |
317 | /* Tells whether the capturing bracket is optimized. */ | /* Tells whether the capturing bracket is optimized. */ |
318 | pcre_uint8 *optimized_cbracket; | pcre_uint8 *optimized_cbracket; |
319 | /* Tells whether the starting offset is a target of then. */ | |
320 | pcre_uint8 *then_offsets; | |
321 | /* Current position where a THEN must jump. */ | |
322 | then_trap_backtrack *then_trap; | |
323 | /* Starting offset of private data for capturing brackets. */ | /* Starting offset of private data for capturing brackets. */ |
324 | int cbraptr; | int cbra_ptr; |
325 | /* OVector starting point. Must be divisible by 2. */ | /* Output vector starting point. Must be divisible by 2. */ |
326 | int ovector_start; | int ovector_start; |
327 | /* Last known position of the requested byte. */ | /* Last known position of the requested byte. */ |
328 | int req_char_ptr; | int req_char_ptr; |
329 | /* Head of the last recursion. */ | /* Head of the last recursion. */ |
330 | int recursive_head; | int recursive_head_ptr; |
331 | /* First inspected character for partial matching. */ | /* First inspected character for partial matching. */ |
332 | int start_used_ptr; | int start_used_ptr; |
333 | /* Starting pointer for partial soft matches. */ | /* Starting pointer for partial soft matches. */ |
# | Line 298 typedef struct compiler_common { | Line 336 typedef struct compiler_common { |
336 | int first_line_end; | int first_line_end; |
337 | /* Points to the marked string. */ | /* Points to the marked string. */ |
338 | int mark_ptr; | int mark_ptr; |
339 | /* Recursive control verb management chain. */ | |
340 | int control_head_ptr; | |
341 | /* Points to the last matched capture block index. */ | |
342 | int capture_last_ptr; | |
343 | /* Points to the starting position of the current match. */ | |
344 | int start_ptr; | |
345 | ||
346 | /* Flipped and lower case tables. */ | /* Flipped and lower case tables. */ |
347 | const pcre_uint8 *fcc; | const pcre_uint8 *fcc; |
348 | sljit_sw lcc; | sljit_sw lcc; |
349 | /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */ | /* Mode can be PCRE_STUDY_JIT_COMPILE and others. */ |
350 | int mode; | int mode; |
351 | /* \K is found in the pattern. */ | |
352 | BOOL has_set_som; | |
353 | /* (*SKIP:arg) is found in the pattern. */ | |
354 | BOOL has_skip_arg; | |
355 | /* (*THEN) is found in the pattern. */ | |
356 | BOOL has_then; | |
357 | /* Needs to know the start position anytime. */ | |
358 | BOOL needs_start_ptr; | |
359 | /* Currently in recurse or negative assert. */ | |
360 | BOOL local_exit; | |
361 | /* Currently in a positive assert. */ | |
362 | BOOL positive_assert; | |
363 | /* Newline control. */ | /* Newline control. */ |
364 | int nltype; | int nltype; |
365 | int newline; | int newline; |
366 | int bsr_nltype; | int bsr_nltype; |
367 | /* Dollar endonly. */ | /* Dollar endonly. */ |
368 | int endonly; | int endonly; |
BOOL has_set_som; | ||
369 | /* Tables. */ | /* Tables. */ |
370 | sljit_sw ctypes; | sljit_sw ctypes; |
371 | int digits[2 + MAX_RANGE_SIZE]; | int digits[2 + MAX_RANGE_SIZE]; |
# | Line 321 typedef struct compiler_common { | Line 376 typedef struct compiler_common { |
376 | ||
377 | /* Labels and jump lists. */ | /* Labels and jump lists. */ |
378 | struct sljit_label *partialmatchlabel; | struct sljit_label *partialmatchlabel; |
379 | struct sljit_label *quitlabel; | struct sljit_label *quit_label; |
380 | struct sljit_label *acceptlabel; | struct sljit_label *forced_quit_label; |
381 | struct sljit_label *accept_label; | |
382 | stub_list *stubs; | stub_list *stubs; |
383 | recurse_entry *entries; | recurse_entry *entries; |
384 | recurse_entry *currententry; | recurse_entry *currententry; |
385 | jump_list *partialmatch; | jump_list *partialmatch; |
386 | jump_list *quit; | jump_list *quit; |
387 | jump_list *positive_assert_quit; | |
388 | jump_list *forced_quit; | |
389 | jump_list *accept; | jump_list *accept; |
390 | jump_list *calllimit; | jump_list *calllimit; |
391 | jump_list *stackalloc; | jump_list *stackalloc; |
# | Line 338 typedef struct compiler_common { | Line 396 typedef struct compiler_common { |
396 | jump_list *vspace; | jump_list *vspace; |
397 | jump_list *casefulcmp; | jump_list *casefulcmp; |
398 | jump_list *caselesscmp; | jump_list *caselesscmp; |
399 | jump_list *reset_match; | |
400 | BOOL jscript_compat; | BOOL jscript_compat; |
401 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
402 | BOOL utf; | BOOL utf; |
# | Line 390 typedef struct compare_context { | Line 449 typedef struct compare_context { |
449 | #endif | #endif |
450 | } compare_context; | } compare_context; |
451 | ||
enum { | ||
frame_end = 0, | ||
frame_setstrbegin = -1, | ||
frame_setmark = -2 | ||
}; | ||
452 | /* Undefine sljit macros. */ | /* Undefine sljit macros. */ |
453 | #undef CMP | #undef CMP |
454 | ||
455 | /* Used for accessing the elements of the stack. */ | /* Used for accessing the elements of the stack. */ |
456 | #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_sw)) | #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_sw)) |
457 | ||
458 | #define TMP1 SLJIT_TEMPORARY_REG1 | #define TMP1 SLJIT_SCRATCH_REG1 |
459 | #define TMP2 SLJIT_TEMPORARY_REG3 | #define TMP2 SLJIT_SCRATCH_REG3 |
460 | #define TMP3 SLJIT_TEMPORARY_EREG2 | #define TMP3 SLJIT_TEMPORARY_EREG2 |
461 | #define STR_PTR SLJIT_SAVED_REG1 | #define STR_PTR SLJIT_SAVED_REG1 |
462 | #define STR_END SLJIT_SAVED_REG2 | #define STR_END SLJIT_SAVED_REG2 |
463 | #define STACK_TOP SLJIT_TEMPORARY_REG2 | #define STACK_TOP SLJIT_SCRATCH_REG2 |
464 | #define STACK_LIMIT SLJIT_SAVED_REG3 | #define STACK_LIMIT SLJIT_SAVED_REG3 |
465 | #define ARGUMENTS SLJIT_SAVED_EREG1 | #define ARGUMENTS SLJIT_SAVED_EREG1 |
466 | #define CALL_COUNT SLJIT_SAVED_EREG2 | #define CALL_COUNT SLJIT_SAVED_EREG2 |
# | Line 428 group contains the start / end character | Line 481 group contains the start / end character |
481 | the start pointers when the end of the capturing group has not yet reached. */ | the start pointers when the end of the capturing group has not yet reached. */ |
482 | #define OVECTOR_START (common->ovector_start) | #define OVECTOR_START (common->ovector_start) |
483 | #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_sw)) | #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_sw)) |
484 | #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_sw)) | #define OVECTOR_PRIV(i) (common->cbra_ptr + (i) * sizeof(sljit_sw)) |
485 | #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start]) | #define PRIVATE_DATA(cc) (common->private_data_ptrs[(cc) - common->start]) |
486 | ||
487 | #if defined COMPILE_PCRE8 | #if defined COMPILE_PCRE8 |
# | Line 459 the start pointers when the end of the c | Line 512 the start pointers when the end of the c |
512 | sljit_set_label(sljit_emit_jump(compiler, (type)), (label)) | sljit_set_label(sljit_emit_jump(compiler, (type)), (label)) |
513 | #define JUMPHERE(jump) \ | #define JUMPHERE(jump) \ |
514 | sljit_set_label((jump), sljit_emit_label(compiler)) | sljit_set_label((jump), sljit_emit_label(compiler)) |
515 | #define SET_LABEL(jump, label) \ | |
516 | sljit_set_label((jump), (label)) | |
517 | #define CMP(type, src1, src1w, src2, src2w) \ | #define CMP(type, src1, src1w, src2, src2w) \ |
518 | sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)) | sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)) |
519 | #define CMPTO(type, src1, src1w, src2, src2w, label) \ | #define CMPTO(type, src1, src1w, src2, src2w, label) \ |
520 | sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label)) | sljit_set_label(sljit_emit_cmp(compiler, (type), (src1), (src1w), (src2), (src2w)), (label)) |
521 | #define COND_VALUE(op, dst, dstw, type) \ | #define OP_FLAGS(op, dst, dstw, src, srcw, type) \ |
522 | sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type)) | sljit_emit_op_flags(compiler, (op), (dst), (dstw), (src), (srcw), (type)) |
523 | #define GET_LOCAL_BASE(dst, dstw, offset) \ | #define GET_LOCAL_BASE(dst, dstw, offset) \ |
524 | sljit_get_local_base(compiler, (dst), (dstw), (offset)) | sljit_get_local_base(compiler, (dst), (dstw), (offset)) |
525 | ||
# | Line 483 return cc; | Line 538 return cc; |
538 | set_private_data_ptrs | set_private_data_ptrs |
539 | get_framesize | get_framesize |
540 | init_frame | init_frame |
541 | get_private_data_length_for_copy | get_private_data_copy_length |
542 | copy_private_data | copy_private_data |
543 | compile_matchingpath | compile_matchingpath |
544 | compile_backtrackingpath | compile_backtrackingpath |
# | Line 507 switch(*cc) | Line 562 switch(*cc) |
562 | case OP_WORDCHAR: | case OP_WORDCHAR: |
563 | case OP_ANY: | case OP_ANY: |
564 | case OP_ALLANY: | case OP_ALLANY: |
565 | case OP_NOTPROP: | |
566 | case OP_PROP: | |
567 | case OP_ANYNL: | case OP_ANYNL: |
568 | case OP_NOT_HSPACE: | case OP_NOT_HSPACE: |
569 | case OP_HSPACE: | case OP_HSPACE: |
# | Line 519 switch(*cc) | Line 576 switch(*cc) |
576 | case OP_CIRCM: | case OP_CIRCM: |
577 | case OP_DOLL: | case OP_DOLL: |
578 | case OP_DOLLM: | case OP_DOLLM: |
case OP_TYPESTAR: | ||
case OP_TYPEMINSTAR: | ||
case OP_TYPEPLUS: | ||
case OP_TYPEMINPLUS: | ||
case OP_TYPEQUERY: | ||
case OP_TYPEMINQUERY: | ||
case OP_TYPEPOSSTAR: | ||
case OP_TYPEPOSPLUS: | ||
case OP_TYPEPOSQUERY: | ||
579 | case OP_CRSTAR: | case OP_CRSTAR: |
580 | case OP_CRMINSTAR: | case OP_CRMINSTAR: |
581 | case OP_CRPLUS: | case OP_CRPLUS: |
582 | case OP_CRMINPLUS: | case OP_CRMINPLUS: |
583 | case OP_CRQUERY: | case OP_CRQUERY: |
584 | case OP_CRMINQUERY: | case OP_CRMINQUERY: |
585 | case OP_CRRANGE: | |
586 | case OP_CRMINRANGE: | |
587 | case OP_CLASS: | |
588 | case OP_NCLASS: | |
589 | case OP_REF: | |
590 | case OP_REFI: | |
591 | case OP_RECURSE: | |
592 | case OP_CALLOUT: | |
593 | case OP_ALT: | |
594 | case OP_KET: | |
595 | case OP_KETRMAX: | |
596 | case OP_KETRMIN: | |
597 | case OP_KETRPOS: | |
598 | case OP_REVERSE: | |
599 | case OP_ASSERT: | |
600 | case OP_ASSERT_NOT: | |
601 | case OP_ASSERTBACK: | |
602 | case OP_ASSERTBACK_NOT: | |
603 | case OP_ONCE: | |
604 | case OP_ONCE_NC: | |
605 | case OP_BRA: | |
606 | case OP_BRAPOS: | |
607 | case OP_CBRA: | |
608 | case OP_CBRAPOS: | |
609 | case OP_COND: | |
610 | case OP_SBRA: | |
611 | case OP_SBRAPOS: | |
612 | case OP_SCBRA: | |
613 | case OP_SCBRAPOS: | |
614 | case OP_SCOND: | |
615 | case OP_CREF: | |
616 | case OP_NCREF: | |
617 | case OP_RREF: | |
618 | case OP_NRREF: | |
619 | case OP_DEF: | case OP_DEF: |
620 | case OP_BRAZERO: | case OP_BRAZERO: |
621 | case OP_BRAMINZERO: | case OP_BRAMINZERO: |
622 | case OP_BRAPOSZERO: | case OP_BRAPOSZERO: |
623 | case OP_PRUNE: | |
624 | case OP_SKIP: | |
625 | case OP_THEN: | |
626 | case OP_COMMIT: | case OP_COMMIT: |
627 | case OP_FAIL: | case OP_FAIL: |
628 | case OP_ACCEPT: | case OP_ACCEPT: |
629 | case OP_ASSERT_ACCEPT: | case OP_ASSERT_ACCEPT: |
630 | case OP_CLOSE: | |
631 | case OP_SKIPZERO: | case OP_SKIPZERO: |
632 | return cc + 1; | return cc + PRIV(OP_lengths)[*cc]; |
case OP_ANYBYTE: | ||
#ifdef SUPPORT_UTF | ||
if (common->utf) return NULL; | ||
#endif | ||
return cc + 1; | ||
633 | ||
634 | case OP_CHAR: | case OP_CHAR: |
635 | case OP_CHARI: | case OP_CHARI: |
# | Line 561 switch(*cc) | Line 641 switch(*cc) |
641 | case OP_MINPLUS: | case OP_MINPLUS: |
642 | case OP_QUERY: | case OP_QUERY: |
643 | case OP_MINQUERY: | case OP_MINQUERY: |
644 | case OP_UPTO: | |
645 | case OP_MINUPTO: | |
646 | case OP_EXACT: | |
647 | case OP_POSSTAR: | case OP_POSSTAR: |
648 | case OP_POSPLUS: | case OP_POSPLUS: |
649 | case OP_POSQUERY: | case OP_POSQUERY: |
650 | case OP_POSUPTO: | |
651 | case OP_STARI: | case OP_STARI: |
652 | case OP_MINSTARI: | case OP_MINSTARI: |
653 | case OP_PLUSI: | case OP_PLUSI: |
654 | case OP_MINPLUSI: | case OP_MINPLUSI: |
655 | case OP_QUERYI: | case OP_QUERYI: |
656 | case OP_MINQUERYI: | case OP_MINQUERYI: |
657 | case OP_UPTOI: | |
658 | case OP_MINUPTOI: | |
659 | case OP_EXACTI: | |
660 | case OP_POSSTARI: | case OP_POSSTARI: |
661 | case OP_POSPLUSI: | case OP_POSPLUSI: |
662 | case OP_POSQUERYI: | case OP_POSQUERYI: |
663 | case OP_POSUPTOI: | |
664 | case OP_NOTSTAR: | case OP_NOTSTAR: |
665 | case OP_NOTMINSTAR: | case OP_NOTMINSTAR: |
666 | case OP_NOTPLUS: | case OP_NOTPLUS: |
667 | case OP_NOTMINPLUS: | case OP_NOTMINPLUS: |
668 | case OP_NOTQUERY: | case OP_NOTQUERY: |
669 | case OP_NOTMINQUERY: | case OP_NOTMINQUERY: |
670 | case OP_NOTUPTO: | |
671 | case OP_NOTMINUPTO: | |
672 | case OP_NOTEXACT: | |
673 | case OP_NOTPOSSTAR: | case OP_NOTPOSSTAR: |
674 | case OP_NOTPOSPLUS: | case OP_NOTPOSPLUS: |
675 | case OP_NOTPOSQUERY: | case OP_NOTPOSQUERY: |
676 | case OP_NOTPOSUPTO: | |
677 | case OP_NOTSTARI: | case OP_NOTSTARI: |
678 | case OP_NOTMINSTARI: | case OP_NOTMINSTARI: |
679 | case OP_NOTPLUSI: | case OP_NOTPLUSI: |
680 | case OP_NOTMINPLUSI: | case OP_NOTMINPLUSI: |
681 | case OP_NOTQUERYI: | case OP_NOTQUERYI: |
682 | case OP_NOTMINQUERYI: | case OP_NOTMINQUERYI: |
case OP_NOTPOSSTARI: | ||
case OP_NOTPOSPLUSI: | ||
case OP_NOTPOSQUERYI: | ||
cc += 2; | ||
#ifdef SUPPORT_UTF | ||
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); | ||
#endif | ||
return cc; | ||
case OP_UPTO: | ||
case OP_MINUPTO: | ||
case OP_EXACT: | ||
case OP_POSUPTO: | ||
case OP_UPTOI: | ||
case OP_MINUPTOI: | ||
case OP_EXACTI: | ||
case OP_POSUPTOI: | ||
case OP_NOTUPTO: | ||
case OP_NOTMINUPTO: | ||
case OP_NOTEXACT: | ||
case OP_NOTPOSUPTO: | ||
683 | case OP_NOTUPTOI: | case OP_NOTUPTOI: |
684 | case OP_NOTMINUPTOI: | case OP_NOTMINUPTOI: |
685 | case OP_NOTEXACTI: | case OP_NOTEXACTI: |
686 | case OP_NOTPOSSTARI: | |
687 | case OP_NOTPOSPLUSI: | |
688 | case OP_NOTPOSQUERYI: | |
689 | case OP_NOTPOSUPTOI: | case OP_NOTPOSUPTOI: |
690 | cc += 2 + IMM2_SIZE; | cc += PRIV(OP_lengths)[*cc]; |
691 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
692 | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); |
693 | #endif | #endif |
694 | return cc; | return cc; |
695 | ||
696 | case OP_NOTPROP: | /* Special cases. */ |
697 | case OP_PROP: | case OP_TYPESTAR: |
698 | return cc + 1 + 2; | case OP_TYPEMINSTAR: |
699 | case OP_TYPEPLUS: | |
700 | case OP_TYPEMINPLUS: | |
701 | case OP_TYPEQUERY: | |
702 | case OP_TYPEMINQUERY: | |
703 | case OP_TYPEUPTO: | case OP_TYPEUPTO: |
704 | case OP_TYPEMINUPTO: | case OP_TYPEMINUPTO: |
705 | case OP_TYPEEXACT: | case OP_TYPEEXACT: |
706 | case OP_TYPEPOSSTAR: | |
707 | case OP_TYPEPOSPLUS: | |
708 | case OP_TYPEPOSQUERY: | |
709 | case OP_TYPEPOSUPTO: | case OP_TYPEPOSUPTO: |
710 | case OP_REF: | return cc + PRIV(OP_lengths)[*cc] - 1; |
case OP_REFI: | ||
case OP_CREF: | ||
case OP_NCREF: | ||
case OP_RREF: | ||
case OP_NRREF: | ||
case OP_CLOSE: | ||
cc += 1 + IMM2_SIZE; | ||
return cc; | ||
case OP_CRRANGE: | ||
case OP_CRMINRANGE: | ||
return cc + 1 + 2 * IMM2_SIZE; | ||
711 | ||
712 | case OP_CLASS: | case OP_ANYBYTE: |
713 | case OP_NCLASS: | #ifdef SUPPORT_UTF |
714 | return cc + 1 + 32 / sizeof(pcre_uchar); | if (common->utf) return NULL; |
715 | #endif | |
716 | return cc + 1; | |
717 | ||
718 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
719 | case OP_XCLASS: | case OP_XCLASS: |
720 | return cc + GET(cc, 1); | return cc + GET(cc, 1); |
721 | #endif | #endif |
722 | ||
case OP_RECURSE: | ||
case OP_ASSERT: | ||
case OP_ASSERT_NOT: | ||
case OP_ASSERTBACK: | ||
case OP_ASSERTBACK_NOT: | ||
case OP_REVERSE: | ||
case OP_ONCE: | ||
case OP_ONCE_NC: | ||
case OP_BRA: | ||
case OP_BRAPOS: | ||
case OP_COND: | ||
case OP_SBRA: | ||
case OP_SBRAPOS: | ||
case OP_SCOND: | ||
case OP_ALT: | ||
case OP_KET: | ||
case OP_KETRMAX: | ||
case OP_KETRMIN: | ||
case OP_KETRPOS: | ||
return cc + 1 + LINK_SIZE; | ||
case OP_CBRA: | ||
case OP_CBRAPOS: | ||
case OP_SCBRA: | ||
case OP_SCBRAPOS: | ||
return cc + 1 + LINK_SIZE + IMM2_SIZE; | ||
723 | case OP_MARK: | case OP_MARK: |
724 | case OP_PRUNE_ARG: | |
725 | case OP_SKIP_ARG: | |
726 | case OP_THEN_ARG: | |
727 | return cc + 1 + 2 + cc[1]; | return cc + 1 + 2 + cc[1]; |
728 | ||
729 | default: | default: |
730 | /* All opcodes are supported now! */ | |
731 | SLJIT_ASSERT_STOP(); | |
732 | return NULL; | return NULL; |
733 | } | } |
734 | } | } |
# | Line 812 while (cc < ccend) | Line 860 while (cc < ccend) |
860 | ||
861 | case OP_COND: | case OP_COND: |
862 | case OP_SCOND: | case OP_SCOND: |
863 | bracketlen = cc[1 + LINK_SIZE]; | /* Only AUTO_CALLOUT can insert this opcode. We do |
864 | if (bracketlen == OP_CREF) | not intend to support this case. */ |
865 | { | if (cc[1 + LINK_SIZE] == OP_CALLOUT) |
866 | bracketlen = GET2(cc, 1 + LINK_SIZE + 1); | return -1; |
common->optimized_cbracket[bracketlen] = 0; | ||
} | ||
else if (bracketlen == OP_NCREF) | ||
{ | ||
bracketlen = GET2(cc, 1 + LINK_SIZE + 1); | ||
name = (pcre_uchar *)common->name_table; | ||
alternative = name; | ||
for (i = 0; i < common->name_count; i++) | ||
{ | ||
if (GET2(name, 0) == bracketlen) break; | ||
name += common->name_entry_size; | ||
} | ||
SLJIT_ASSERT(i != common->name_count); | ||
for (i = 0; i < common->name_count; i++) | ||
{ | ||
if (STRCMP_UC_UC(alternative + IMM2_SIZE, name + IMM2_SIZE) == 0) | ||
common->optimized_cbracket[GET2(alternative, 0)] = 0; | ||
alternative += common->name_entry_size; | ||
} | ||
} | ||
867 | ||
868 | if (*cc == OP_COND) | if (*cc == OP_COND) |
869 | { | { |
# | Line 850 while (cc < ccend) | Line 877 while (cc < ccend) |
877 | bracketlen = 1 + LINK_SIZE; | bracketlen = 1 + LINK_SIZE; |
878 | break; | break; |
879 | ||
880 | case OP_CREF: | |
881 | i = GET2(cc, 1); | |
882 | common->optimized_cbracket[i] = 0; | |
883 | cc += 1 + IMM2_SIZE; | |
884 | break; | |
885 | ||
886 | case OP_NCREF: | |
887 | bracketlen = GET2(cc, 1); | |
888 | name = (pcre_uchar *)common->name_table; | |
889 | alternative = name; | |
890 | for (i = 0; i < common->name_count; i++) | |
891 | { | |
892 | if (GET2(name, 0) == bracketlen) break; | |
893 | name += common->name_entry_size; | |
894 | } | |
895 | SLJIT_ASSERT(i != common->name_count); | |
896 | ||
897 | for (i = 0; i < common->name_count; i++) | |
898 | { | |
899 | if (STRCMP_UC_UC(alternative + IMM2_SIZE, name + IMM2_SIZE) == 0) | |
900 | common->optimized_cbracket[GET2(alternative, 0)] = 0; | |
901 | alternative += common->name_entry_size; | |
902 | } | |
903 | bracketlen = 0; | |
904 | cc += 1 + IMM2_SIZE; | |
905 | break; | |
906 | ||
907 | case OP_BRA: | case OP_BRA: |
908 | bracketlen = 1 + LINK_SIZE; | bracketlen = 1 + LINK_SIZE; |
909 | break; | break; |
# | Line 906 while (cc < ccend) | Line 960 while (cc < ccend) |
960 | ||
961 | case OP_RECURSE: | case OP_RECURSE: |
962 | /* Set its value only once. */ | /* Set its value only once. */ |
963 | if (common->recursive_head == 0) | if (common->recursive_head_ptr == 0) |
964 | { | { |
965 | common->recursive_head = common->ovector_start; | common->recursive_head_ptr = common->ovector_start; |
966 | common->ovector_start += sizeof(sljit_sw); | common->ovector_start += sizeof(sljit_sw); |
967 | } | } |
968 | cc += 1 + LINK_SIZE; | cc += 1 + LINK_SIZE; |
969 | break; | break; |
970 | ||
971 | case OP_CALLOUT: | |
972 | if (common->capture_last_ptr == 0) | |
973 | { | |
974 | common->capture_last_ptr = common->ovector_start; | |
975 | common->ovector_start += sizeof(sljit_sw); | |
976 | } | |
977 | cc += 2 + 2 * LINK_SIZE; | |
978 | break; | |
979 | ||
980 | case OP_THEN_ARG: | |
981 | common->has_then = TRUE; | |
982 | common->control_head_ptr = 1; | |
983 | /* Fall through. */ | |
984 | ||
985 | case OP_PRUNE_ARG: | |
986 | common->needs_start_ptr = TRUE; | |
987 | /* Fall through. */ | |
988 | ||
989 | case OP_MARK: | case OP_MARK: |
990 | if (common->mark_ptr == 0) | if (common->mark_ptr == 0) |
991 | { | { |
# | Line 923 while (cc < ccend) | Line 995 while (cc < ccend) |
995 | cc += 1 + 2 + cc[1]; | cc += 1 + 2 + cc[1]; |
996 | break; | break; |
997 | ||
998 | case OP_THEN: | |
999 | common->has_then = TRUE; | |
1000 | common->control_head_ptr = 1; | |
1001 | /* Fall through. */ | |
1002 | ||
1003 | case OP_PRUNE: | |
1004 | case OP_SKIP: | |
1005 | common->needs_start_ptr = TRUE; | |
1006 | cc += 1; | |
1007 | break; | |
1008 | ||
1009 | case OP_SKIP_ARG: | |
1010 | common->control_head_ptr = 1; | |
1011 | common->has_skip_arg = TRUE; | |
1012 | cc += 1 + 2 + cc[1]; | |
1013 | break; | |
1014 | ||
1015 | default: | default: |
1016 | cc = next_opcode(common, cc); | cc = next_opcode(common, cc); |
1017 | if (cc == NULL) | if (cc == NULL) |
# | Line 1099 while (cc < ccend) | Line 1188 while (cc < ccend) |
1188 | } | } |
1189 | } | } |
1190 | ||
1191 | /* Returns with -1 if no need for frame. */ | /* Returns with a frame_types (always < 0) if no need for frame. */ |
1192 | static int get_framesize(compiler_common *common, pcre_uchar *cc, BOOL recursive) | static int get_framesize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL recursive, BOOL* needs_control_head) |
1193 | { | { |
pcre_uchar *ccend = bracketend(cc); | ||
1194 | int length = 0; | int length = 0; |
1195 | BOOL possessive = FALSE; | int possessive = 0; |
1196 | BOOL stack_restore = FALSE; | |
1197 | BOOL setsom_found = recursive; | BOOL setsom_found = recursive; |
1198 | BOOL setmark_found = recursive; | BOOL setmark_found = recursive; |
1199 | /* The last capture is a local variable even for recursions. */ | |
1200 | BOOL capture_last_found = FALSE; | |
1201 | ||
1202 | if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)) | #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD |
1203 | SLJIT_ASSERT(common->control_head_ptr != 0); | |
1204 | *needs_control_head = TRUE; | |
1205 | #else | |
1206 | *needs_control_head = FALSE; | |
1207 | #endif | |
1208 | ||
1209 | if (ccend == NULL) | |
1210 | { | { |
1211 | length = 3; | ccend = bracketend(cc) - (1 + LINK_SIZE); |
1212 | possessive = TRUE; | if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)) |
1213 | { | |
1214 | possessive = length = (common->capture_last_ptr != 0) ? 5 : 3; | |
1215 | /* This is correct regardless of common->capture_last_ptr. */ | |
1216 | capture_last_found = TRUE; | |
1217 | } | |
1218 | cc = next_opcode(common, cc); | |
1219 | } | } |
1220 | ||
cc = next_opcode(common, cc); | ||
1221 | SLJIT_ASSERT(cc != NULL); | SLJIT_ASSERT(cc != NULL); |
1222 | while (cc < ccend) | while (cc < ccend) |
1223 | switch(*cc) | switch(*cc) |
1224 | { | { |
1225 | case OP_SET_SOM: | case OP_SET_SOM: |
1226 | SLJIT_ASSERT(common->has_set_som); | SLJIT_ASSERT(common->has_set_som); |
1227 | stack_restore = TRUE; | |
1228 | if (!setsom_found) | if (!setsom_found) |
1229 | { | { |
1230 | length += 2; | length += 2; |
# | Line 1130 while (cc < ccend) | Line 1234 while (cc < ccend) |
1234 | break; | break; |
1235 | ||
1236 | case OP_MARK: | case OP_MARK: |
1237 | case OP_PRUNE_ARG: | |
1238 | case OP_THEN_ARG: | |
1239 | SLJIT_ASSERT(common->mark_ptr != 0); | SLJIT_ASSERT(common->mark_ptr != 0); |
1240 | stack_restore = TRUE; | |
1241 | if (!setmark_found) | if (!setmark_found) |
1242 | { | { |
1243 | length += 2; | length += 2; |
1244 | setmark_found = TRUE; | setmark_found = TRUE; |
1245 | } | } |
1246 | if (common->control_head_ptr != 0) | |
1247 | *needs_control_head = TRUE; | |
1248 | cc += 1 + 2 + cc[1]; | cc += 1 + 2 + cc[1]; |
1249 | break; | break; |
1250 | ||
1251 | case OP_RECURSE: | case OP_RECURSE: |
1252 | stack_restore = TRUE; | |
1253 | if (common->has_set_som && !setsom_found) | if (common->has_set_som && !setsom_found) |
1254 | { | { |
1255 | length += 2; | length += 2; |
# | Line 1150 while (cc < ccend) | Line 1260 while (cc < ccend) |
1260 | length += 2; | length += 2; |
1261 | setmark_found = TRUE; | setmark_found = TRUE; |
1262 | } | } |
1263 | if (common->capture_last_ptr != 0 && !capture_last_found) | |
1264 | { | |
1265 | length += 2; | |
1266 | capture_last_found = TRUE; | |
1267 | } | |
1268 | cc += 1 + LINK_SIZE; | cc += 1 + LINK_SIZE; |
1269 | break; | break; |
1270 | ||
# | Line 1157 while (cc < ccend) | Line 1272 while (cc < ccend) |
1272 | case OP_CBRAPOS: | case OP_CBRAPOS: |
1273 | case OP_SCBRA: | case OP_SCBRA: |
1274 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
1275 | stack_restore = TRUE; | |
1276 | if (common->capture_last_ptr != 0 && !capture_last_found) | |
1277 | { | |
1278 | length += 2; | |
1279 | capture_last_found = TRUE; | |
1280 | } | |
1281 | length += 3; | length += 3; |
1282 | cc += 1 + LINK_SIZE + IMM2_SIZE; | cc += 1 + LINK_SIZE + IMM2_SIZE; |
1283 | break; | break; |
1284 | ||
1285 | default: | default: |
1286 | stack_restore = TRUE; | |
1287 | /* Fall through. */ | |
1288 | ||
1289 | case OP_NOT_WORD_BOUNDARY: | |
1290 | case OP_WORD_BOUNDARY: | |
1291 | case OP_NOT_DIGIT: | |
1292 | case OP_DIGIT: | |
1293 | case OP_NOT_WHITESPACE: | |
1294 | case OP_WHITESPACE: | |
1295 | case OP_NOT_WORDCHAR: | |
1296 | case OP_WORDCHAR: | |
1297 | case OP_ANY: | |
1298 | case OP_ALLANY: | |
1299 | case OP_ANYBYTE: | |
1300 | case OP_NOTPROP: | |
1301 | case OP_PROP: | |
1302 | case OP_ANYNL: | |
1303 | case OP_NOT_HSPACE: | |
1304 | case OP_HSPACE: | |
1305 | case OP_NOT_VSPACE: | |
1306 | case OP_VSPACE: | |
1307 | case OP_EXTUNI: | |
1308 | case OP_EODN: | |
1309 | case OP_EOD: | |
1310 | case OP_CIRC: | |
1311 | case OP_CIRCM: | |
1312 | case OP_DOLL: | |
1313 | case OP_DOLLM: | |
1314 | case OP_CHAR: | |
1315 | case OP_CHARI: | |
1316 | case OP_NOT: | |
1317 | case OP_NOTI: | |
1318 | ||
1319 | case OP_EXACT: | |
1320 | case OP_POSSTAR: | |
1321 | case OP_POSPLUS: | |
1322 | case OP_POSQUERY: | |
1323 | case OP_POSUPTO: | |
1324 | ||
1325 | case OP_EXACTI: | |
1326 | case OP_POSSTARI: | |
1327 | case OP_POSPLUSI: | |
1328 | case OP_POSQUERYI: | |
1329 | case OP_POSUPTOI: | |
1330 | ||
1331 | case OP_NOTEXACT: | |
1332 | case OP_NOTPOSSTAR: | |
1333 | case OP_NOTPOSPLUS: | |
1334 | case OP_NOTPOSQUERY: | |
1335 | case OP_NOTPOSUPTO: | |
1336 | ||
1337 | case OP_NOTEXACTI: | |
1338 | case OP_NOTPOSSTARI: | |
1339 | case OP_NOTPOSPLUSI: | |
1340 | case OP_NOTPOSQUERYI: | |
1341 | case OP_NOTPOSUPTOI: | |
1342 | ||
1343 | case OP_TYPEEXACT: | |
1344 | case OP_TYPEPOSSTAR: | |
1345 | case OP_TYPEPOSPLUS: | |
1346 | case OP_TYPEPOSQUERY: | |
1347 | case OP_TYPEPOSUPTO: | |
1348 | ||
1349 | case OP_CLASS: | |
1350 | case OP_NCLASS: | |
1351 | case OP_XCLASS: | |
1352 | ||
1353 | cc = next_opcode(common, cc); | cc = next_opcode(common, cc); |
1354 | SLJIT_ASSERT(cc != NULL); | SLJIT_ASSERT(cc != NULL); |
1355 | break; | break; |
1356 | } | } |
1357 | ||
1358 | /* Possessive quantifiers can use a special case. */ | /* Possessive quantifiers can use a special case. */ |
1359 | if (SLJIT_UNLIKELY(possessive) && length == 3) | if (SLJIT_UNLIKELY(possessive == length)) |
1360 | return -1; | return stack_restore ? no_frame : no_stack; |
1361 | ||
1362 | if (length > 0) | if (length > 0) |
1363 | return length + 1; | return length + 1; |
1364 | return -1; | return stack_restore ? no_frame : no_stack; |
1365 | } | } |
1366 | ||
1367 | static void init_frame(compiler_common *common, pcre_uchar *cc, int stackpos, int stacktop, BOOL recursive) | static void init_frame(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, int stackpos, int stacktop, BOOL recursive) |
1368 | { | { |
1369 | DEFINE_COMPILER; | DEFINE_COMPILER; |
pcre_uchar *ccend = bracketend(cc); | ||
1370 | BOOL setsom_found = recursive; | BOOL setsom_found = recursive; |
1371 | BOOL setmark_found = recursive; | BOOL setmark_found = recursive; |
1372 | /* The last capture is a local variable even for recursions. */ | |
1373 | BOOL capture_last_found = FALSE; | |
1374 | int offset; | int offset; |
1375 | ||
1376 | /* >= 1 + shortest item size (2) */ | /* >= 1 + shortest item size (2) */ |
# | Line 1189 SLJIT_UNUSED_ARG(stacktop); | Line 1378 SLJIT_UNUSED_ARG(stacktop); |
1378 | SLJIT_ASSERT(stackpos >= stacktop + 2); | SLJIT_ASSERT(stackpos >= stacktop + 2); |
1379 | ||
1380 | stackpos = STACK(stackpos); | stackpos = STACK(stackpos); |
1381 | if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)) | if (ccend == NULL) |
1382 | cc = next_opcode(common, cc); | { |
1383 | ccend = bracketend(cc) - (1 + LINK_SIZE); | |
1384 | if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)) | |
1385 | cc = next_opcode(common, cc); | |
1386 | } | |
1387 | ||
1388 | SLJIT_ASSERT(cc != NULL); | SLJIT_ASSERT(cc != NULL); |
1389 | while (cc < ccend) | while (cc < ccend) |
1390 | switch(*cc) | switch(*cc) |
# | Line 1200 while (cc < ccend) | Line 1394 while (cc < ccend) |
1394 | if (!setsom_found) | if (!setsom_found) |
1395 | { | { |
1396 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
1397 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); |
1398 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1399 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); |
1400 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
# | Line 1210 while (cc < ccend) | Line 1404 while (cc < ccend) |
1404 | break; | break; |
1405 | ||
1406 | case OP_MARK: | case OP_MARK: |
1407 | case OP_PRUNE_ARG: | |
1408 | case OP_THEN_ARG: | |
1409 | SLJIT_ASSERT(common->mark_ptr != 0); | SLJIT_ASSERT(common->mark_ptr != 0); |
1410 | if (!setmark_found) | if (!setmark_found) |
1411 | { | { |
1412 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); |
1413 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); |
1414 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1415 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); |
1416 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
# | Line 1227 while (cc < ccend) | Line 1423 while (cc < ccend) |
1423 | if (common->has_set_som && !setsom_found) | if (common->has_set_som && !setsom_found) |
1424 | { | { |
1425 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); |
1426 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setstrbegin); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -OVECTOR(0)); |
1427 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1428 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); |
1429 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
# | Line 1236 while (cc < ccend) | Line 1432 while (cc < ccend) |
1432 | if (common->mark_ptr != 0 && !setmark_found) | if (common->mark_ptr != 0 && !setmark_found) |
1433 | { | { |
1434 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); |
1435 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_setmark); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->mark_ptr); |
1436 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1437 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); |
1438 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
1439 | setmark_found = TRUE; | setmark_found = TRUE; |
1440 | } | } |
1441 | if (common->capture_last_ptr != 0 && !capture_last_found) | |
1442 | { | |
1443 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); | |
1444 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); | |
1445 | stackpos += (int)sizeof(sljit_sw); | |
1446 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | |
1447 | stackpos += (int)sizeof(sljit_sw); | |
1448 | capture_last_found = TRUE; | |
1449 | } | |
1450 | cc += 1 + LINK_SIZE; | cc += 1 + LINK_SIZE; |
1451 | break; | break; |
1452 | ||
# | Line 1249 while (cc < ccend) | Line 1454 while (cc < ccend) |
1454 | case OP_CBRAPOS: | case OP_CBRAPOS: |
1455 | case OP_SCBRA: | case OP_SCBRA: |
1456 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
1457 | if (common->capture_last_ptr != 0 && !capture_last_found) | |
1458 | { | |
1459 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); | |
1460 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, -common->capture_last_ptr); | |
1461 | stackpos += (int)sizeof(sljit_sw); | |
1462 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0); | |
1463 | stackpos += (int)sizeof(sljit_sw); | |
1464 | capture_last_found = TRUE; | |
1465 | } | |
1466 | offset = (GET2(cc, 1 + LINK_SIZE)) << 1; | offset = (GET2(cc, 1 + LINK_SIZE)) << 1; |
1467 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset)); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset)); |
1468 | stackpos += (int)sizeof(sljit_sw); | stackpos += (int)sizeof(sljit_sw); |
# | Line 1268 while (cc < ccend) | Line 1482 while (cc < ccend) |
1482 | break; | break; |
1483 | } | } |
1484 | ||
1485 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_end); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, 0); |
1486 | SLJIT_ASSERT(stackpos == STACK(stacktop)); | SLJIT_ASSERT(stackpos == STACK(stacktop)); |
1487 | } | } |
1488 | ||
1489 | static SLJIT_INLINE int get_private_data_length_for_copy(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) | static SLJIT_INLINE int get_private_data_copy_length(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, BOOL needs_control_head) |
1490 | { | { |
1491 | int private_data_length = 2; | int private_data_length = needs_control_head ? 3 : 2; |
1492 | int size; | int size; |
1493 | pcre_uchar *alternative; | pcre_uchar *alternative; |
1494 | /* Calculate the sum of the private machine words. */ | /* Calculate the sum of the private machine words. */ |
# | Line 1387 return private_data_length; | Line 1601 return private_data_length; |
1601 | } | } |
1602 | ||
1603 | static void copy_private_data(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, | static void copy_private_data(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, |
1604 | BOOL save, int stackptr, int stacktop) | BOOL save, int stackptr, int stacktop, BOOL needs_control_head) |
1605 | { | { |
1606 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1607 | int srcw[2]; | int srcw[2]; |
# | Line 1408 stacktop = STACK(stacktop - 1); | Line 1622 stacktop = STACK(stacktop - 1); |
1622 | ||
1623 | if (!save) | if (!save) |
1624 | { | { |
1625 | stackptr += sizeof(sljit_sw); | stackptr += (needs_control_head ? 2 : 1) * sizeof(sljit_sw); |
1626 | if (stackptr < stacktop) | if (stackptr < stacktop) |
1627 | { | { |
1628 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), stackptr); |
# | Line 1424 if (!save) | Line 1638 if (!save) |
1638 | /* The tmp1next must be TRUE in either way. */ | /* The tmp1next must be TRUE in either way. */ |
1639 | } | } |
1640 | ||
1641 | while (status != end) | do |
1642 | { | { |
1643 | count = 0; | count = 0; |
1644 | switch(status) | switch(status) |
1645 | { | { |
1646 | case start: | case start: |
1647 | SLJIT_ASSERT(save && common->recursive_head != 0); | SLJIT_ASSERT(save && common->recursive_head_ptr != 0); |
1648 | count = 1; | count = 1; |
1649 | srcw[0] = common->recursive_head; | srcw[0] = common->recursive_head_ptr; |
1650 | if (needs_control_head) | |
1651 | { | |
1652 | SLJIT_ASSERT(common->control_head_ptr != 0); | |
1653 | count = 2; | |
1654 | srcw[1] = common->control_head_ptr; | |
1655 | } | |
1656 | status = loop; | status = loop; |
1657 | break; | break; |
1658 | ||
# | Line 1657 while (status != end) | Line 1877 while (status != end) |
1877 | } | } |
1878 | } | } |
1879 | } | } |
1880 | while (status != end); | |
1881 | ||
1882 | if (save) | if (save) |
1883 | { | { |
# | Line 1690 if (save) | Line 1911 if (save) |
1911 | SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty))); | SLJIT_ASSERT(cc == ccend && stackptr == stacktop && (save || (tmp1empty && tmp2empty))); |
1912 | } | } |
1913 | ||
1914 | static SLJIT_INLINE pcre_uchar *set_then_offsets(compiler_common *common, pcre_uchar *cc, pcre_uint8 *current_offset) | |
1915 | { | |
1916 | pcre_uchar *end = bracketend(cc); | |
1917 | BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT; | |
1918 | ||
1919 | /* Assert captures then. */ | |
1920 | if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) | |
1921 | current_offset = NULL; | |
1922 | /* Conditional block does not. */ | |
1923 | if (*cc == OP_COND || *cc == OP_SCOND) | |
1924 | has_alternatives = FALSE; | |
1925 | ||
1926 | cc = next_opcode(common, cc); | |
1927 | if (has_alternatives) | |
1928 | current_offset = common->then_offsets + (cc - common->start); | |
1929 | ||
1930 | while (cc < end) | |
1931 | { | |
1932 | if ((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)) | |
1933 | cc = set_then_offsets(common, cc, current_offset); | |
1934 | else | |
1935 | { | |
1936 | if (*cc == OP_ALT && has_alternatives) | |
1937 | current_offset = common->then_offsets + (cc + 1 + LINK_SIZE - common->start); | |
1938 | if (*cc >= OP_THEN && *cc <= OP_THEN_ARG && current_offset != NULL) | |
1939 | *current_offset = 1; | |
1940 | cc = next_opcode(common, cc); | |
1941 | } | |
1942 | } | |
1943 | ||
1944 | return end; | |
1945 | } | |
1946 | ||
1947 | #undef CASE_ITERATOR_PRIVATE_DATA_1 | #undef CASE_ITERATOR_PRIVATE_DATA_1 |
1948 | #undef CASE_ITERATOR_PRIVATE_DATA_2A | #undef CASE_ITERATOR_PRIVATE_DATA_2A |
1949 | #undef CASE_ITERATOR_PRIVATE_DATA_2B | #undef CASE_ITERATOR_PRIVATE_DATA_2B |
# | Line 1708 while (list) | Line 1962 while (list) |
1962 | { | { |
1963 | /* sljit_set_label is clever enough to do nothing | /* sljit_set_label is clever enough to do nothing |
1964 | if either the jump or the label is NULL. */ | if either the jump or the label is NULL. */ |
1965 | sljit_set_label(list->jump, label); | SET_LABEL(list->jump, label); |
1966 | list = list->next; | list = list->next; |
1967 | } | } |
1968 | } | } |
# | Line 1724 if (list_item) | Line 1978 if (list_item) |
1978 | } | } |
1979 | } | } |
1980 | ||
1981 | static void add_stub(compiler_common *common, enum stub_types type, int data, struct sljit_jump *start) | static void add_stub(compiler_common *common, struct sljit_jump *start) |
1982 | { | { |
1983 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1984 | stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list)); | stub_list* list_item = sljit_alloc_memory(compiler, sizeof(stub_list)); |
1985 | ||
1986 | if (list_item) | if (list_item) |
1987 | { | { |
list_item->type = type; | ||
list_item->data = data; | ||
1988 | list_item->start = start; | list_item->start = start; |
1989 | list_item->quit = LABEL(); | list_item->quit = LABEL(); |
1990 | list_item->next = common->stubs; | list_item->next = common->stubs; |
# | Line 1748 stub_list* list_item = common->stubs; | Line 2000 stub_list* list_item = common->stubs; |
2000 | while (list_item) | while (list_item) |
2001 | { | { |
2002 | JUMPHERE(list_item->start); | JUMPHERE(list_item->start); |
2003 | switch(list_item->type) | add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL)); |
{ | ||
case stack_alloc: | ||
add_jump(compiler, &common->stackalloc, JUMP(SLJIT_FAST_CALL)); | ||
break; | ||
} | ||
2004 | JUMPTO(SLJIT_JUMP, list_item->quit); | JUMPTO(SLJIT_JUMP, list_item->quit); |
2005 | list_item = list_item->next; | list_item = list_item->next; |
2006 | } | } |
# | Line 1781 OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); | Line 2028 OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); |
2028 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, TMP1, 0); |
2029 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); |
2030 | #endif | #endif |
2031 | add_stub(common, stack_alloc, 0, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0)); | add_stub(common, CMP(SLJIT_C_GREATER, STACK_TOP, 0, STACK_LIMIT, 0)); |
2032 | } | } |
2033 | ||
2034 | static SLJIT_INLINE void free_stack(compiler_common *common, int size) | static SLJIT_INLINE void free_stack(compiler_common *common, int size) |
# | Line 1795 static SLJIT_INLINE void reset_ovector(c | Line 2042 static SLJIT_INLINE void reset_ovector(c |
2042 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2043 | struct sljit_label *loop; | struct sljit_label *loop; |
2044 | int i; | int i; |
2045 | ||
2046 | /* At this point we can freely use all temporary registers. */ | /* At this point we can freely use all temporary registers. */ |
2047 | SLJIT_ASSERT(length > 1); | |
2048 | /* TMP1 returns with begin - 1. */ | /* TMP1 returns with begin - 1. */ |
2049 | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_SUB, SLJIT_SCRATCH_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); |
2050 | if (length < 8) | |
2051 | { | |
2052 | for (i = 1; i < length; i++) | |
2053 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_SCRATCH_REG1, 0); | |
2054 | } | |
2055 | else | |
2056 | { | |
2057 | GET_LOCAL_BASE(SLJIT_SCRATCH_REG2, 0, OVECTOR_START); | |
2058 | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, length - 1); | |
2059 | loop = LABEL(); | |
2060 | OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_SCRATCH_REG2), sizeof(sljit_sw), SLJIT_SCRATCH_REG1, 0); | |
2061 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 1); | |
2062 | JUMPTO(SLJIT_C_NOT_ZERO, loop); | |
2063 | } | |
2064 | } | |
2065 | ||
2066 | static SLJIT_INLINE void do_reset_match(compiler_common *common, int length) | |
2067 | { | |
2068 | DEFINE_COMPILER; | |
2069 | struct sljit_label *loop; | |
2070 | int i; | |
2071 | ||
2072 | SLJIT_ASSERT(length > 1); | |
2073 | /* OVECTOR(1) contains the "string begin - 1" constant. */ | |
2074 | if (length > 2) | |
2075 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); | |
2076 | if (length < 8) | if (length < 8) |
2077 | { | { |
2078 | for (i = 0; i < length; i++) | for (i = 2; i < length; i++) |
2079 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), SLJIT_TEMPORARY_REG1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(i), TMP1, 0); |
2080 | } | } |
2081 | else | else |
2082 | { | { |
2083 | GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, OVECTOR_START - sizeof(sljit_sw)); | GET_LOCAL_BASE(TMP2, 0, OVECTOR_START + sizeof(sljit_sw)); |
2084 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, length); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_IMM, length - 2); |
2085 | loop = LABEL(); | loop = LABEL(); |
2086 | OP1(SLJIT_MOVU, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(sljit_sw), SLJIT_TEMPORARY_REG1, 0); | OP1(SLJIT_MOVU, SLJIT_MEM1(TMP2), sizeof(sljit_sw), TMP1, 0); |
2087 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, 1); |
2088 | JUMPTO(SLJIT_C_NOT_ZERO, loop); | JUMPTO(SLJIT_C_NOT_ZERO, loop); |
2089 | } | } |
2090 | ||
2091 | OP1(SLJIT_MOV, STACK_TOP, 0, ARGUMENTS, 0); | |
2092 | if (common->mark_ptr != 0) | |
2093 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, SLJIT_IMM, 0); | |
2094 | if (common->control_head_ptr != 0) | |
2095 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); | |
2096 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(jit_arguments, stack)); | |
2097 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_ptr); | |
2098 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), SLJIT_OFFSETOF(struct sljit_stack, base)); | |
2099 | } | |
2100 | ||
2101 | static sljit_sw SLJIT_CALL do_search_mark(sljit_sw *current, const pcre_uchar *skip_arg) | |
2102 | { | |
2103 | while (current != NULL) | |
2104 | { | |
2105 | switch (current[-2]) | |
2106 | { | |
2107 | case type_then_trap: | |
2108 | break; | |
2109 | ||
2110 | case type_mark: | |
2111 | if (STRCMP_UC_UC(skip_arg, (pcre_uchar *)current[-3]) == 0) | |
2112 | return current[-4]; | |
2113 | break; | |
2114 | ||
2115 | default: | |
2116 | SLJIT_ASSERT_STOP(); | |
2117 | break; | |
2118 | } | |
2119 | current = (sljit_sw*)current[-1]; | |
2120 | } | |
2121 | return -1; | |
2122 | } | } |
2123 | ||
2124 | static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket) | static SLJIT_INLINE void copy_ovector(compiler_common *common, int topbracket) |
2125 | { | { |
2126 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2127 | struct sljit_label *loop; | struct sljit_label *loop; |
2128 | struct sljit_jump *earlyexit; | struct sljit_jump *early_quit; |
2129 | ||
2130 | /* At this point we can freely use all registers. */ | /* At this point we can freely use all registers. */ |
2131 | OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); | OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
2132 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1), STR_PTR, 0); |
2133 | ||
2134 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG1, 0, ARGUMENTS, 0); |
2135 | if (common->mark_ptr != 0) | if (common->mark_ptr != 0) |
2136 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); |
2137 | OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount)); | OP1(SLJIT_MOV_SI, SLJIT_SCRATCH_REG2, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, offset_count)); |
2138 | if (common->mark_ptr != 0) | if (common->mark_ptr != 0) |
2139 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_TEMPORARY_REG3, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), SLJIT_SCRATCH_REG3, 0); |
2140 | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); | OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); |
2141 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG1, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); |
2142 | GET_LOCAL_BASE(SLJIT_SAVED_REG1, 0, OVECTOR_START); | GET_LOCAL_BASE(SLJIT_SAVED_REG1, 0, OVECTOR_START); |
2143 | /* Unlikely, but possible */ | /* Unlikely, but possible */ |
2144 | earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0); | early_quit = CMP(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 0); |
2145 | loop = LABEL(); | loop = LABEL(); |
2146 | OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_TEMPORARY_REG1, 0); | OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_SCRATCH_REG1, 0); |
2147 | OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_sw)); | OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_sw)); |
2148 | /* Copy the integer value to the output buffer */ | /* Copy the integer value to the output buffer */ |
2149 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
2150 | OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, UCHAR_SHIFT); |
2151 | #endif | #endif |
2152 | OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_SAVED_REG2, 0); | OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG3), sizeof(int), SLJIT_SAVED_REG2, 0); |
2153 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 1); |
2154 | JUMPTO(SLJIT_C_NOT_ZERO, loop); | JUMPTO(SLJIT_C_NOT_ZERO, loop); |
2155 | JUMPHERE(earlyexit); | JUMPHERE(early_quit); |
2156 | ||
2157 | /* Calculate the return value, which is the maximum ovector value. */ | /* Calculate the return value, which is the maximum ovector value. */ |
2158 | if (topbracket > 1) | if (topbracket > 1) |
2159 | { | { |
2160 | GET_LOCAL_BASE(SLJIT_TEMPORARY_REG1, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw)); | GET_LOCAL_BASE(SLJIT_SCRATCH_REG1, 0, OVECTOR_START + topbracket * 2 * sizeof(sljit_sw)); |
2161 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1); | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, topbracket + 1); |
2162 | ||
2163 | /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */ | /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */ |
2164 | loop = LABEL(); | loop = LABEL(); |
2165 | OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_sw)sizeof(sljit_sw))); | OP1(SLJIT_MOVU, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG1), -(2 * (sljit_sw)sizeof(sljit_sw))); |
2166 | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB, SLJIT_SCRATCH_REG2, 0, SLJIT_SCRATCH_REG2, 0, SLJIT_IMM, 1); |
2167 | CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG3, 0, loop); | CMPTO(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG3, 0, SLJIT_SAVED_REG3, 0, loop); |
2168 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_SCRATCH_REG2, 0); |
2169 | } | } |
2170 | else | else |
2171 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); |
# | Line 1867 else | Line 2174 else |
2174 | static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *quit) | static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *quit) |
2175 | { | { |
2176 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2177 | struct sljit_jump *jump; | |
2178 | ||
2179 | SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2); | SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2); |
2180 | SLJIT_ASSERT(common->start_used_ptr != 0 && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0)); | SLJIT_ASSERT(common->start_used_ptr != 0 && common->start_ptr != 0 |
2181 | && (common->mode == JIT_PARTIAL_SOFT_COMPILE ? common->hit_start != 0 : common->hit_start == 0)); | |
2182 | ||
2183 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, ARGUMENTS, 0); |
2184 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); |
2185 | OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsetcount)); | OP1(SLJIT_MOV_SI, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, real_offset_count)); |
2186 | CMPTO(SLJIT_C_LESS, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 2, quit); | CMPTO(SLJIT_C_SIG_LESS, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 2, quit); |
2187 | ||
2188 | /* Store match begin and end. */ | /* Store match begin and end. */ |
2189 | OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, begin)); |
2190 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsets)); | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, offsets)); |
2191 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_used_ptr : common->hit_start); | |
2192 | jump = CMP(SLJIT_C_SIG_LESS, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, 3); | |
2193 | OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? common->start_ptr : (common->hit_start + (int)sizeof(sljit_sw)), SLJIT_SAVED_REG1, 0); | |
2194 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | |
2195 | OP2(SLJIT_ASHR, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, UCHAR_SHIFT); | |
2196 | #endif | |
2197 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), 2 * sizeof(int), SLJIT_SCRATCH_REG3, 0); | |
2198 | JUMPHERE(jump); | |
2199 | ||
2200 | 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); | |
2201 | OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0); | OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0); |
2202 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
2203 | OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, UCHAR_SHIFT); |
2204 | #endif | #endif |
2205 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(int), SLJIT_SAVED_REG2, 0); | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), sizeof(int), SLJIT_SAVED_REG2, 0); |
2206 | ||
2207 | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG1, 0); | OP2(SLJIT_SUB, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_SAVED_REG1, 0); |
2208 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
2209 | OP2(SLJIT_ASHR, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_ASHR, SLJIT_SCRATCH_REG3, 0, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, UCHAR_SHIFT); |
2210 | #endif | #endif |
2211 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), 0, SLJIT_TEMPORARY_REG3, 0); | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_SCRATCH_REG2), 0, SLJIT_SCRATCH_REG3, 0); |
2212 | ||
2213 | JUMPTO(SLJIT_JUMP, quit); | JUMPTO(SLJIT_JUMP, quit); |
2214 | } | } |
# | Line 2055 else if (common->mode == JIT_PARTIAL_SOF | Line 2373 else if (common->mode == JIT_PARTIAL_SOF |
2373 | jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); | jump = CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, SLJIT_IMM, -1); |
2374 | ||
2375 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2376 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); |
2377 | else | else |
2378 | { | { |
2379 | if (common->partialmatchlabel != NULL) | if (common->partialmatchlabel != NULL) |
# | Line 2068 if (jump != NULL) | Line 2386 if (jump != NULL) |
2386 | JUMPHERE(jump); | JUMPHERE(jump); |
2387 | } | } |
2388 | ||
2389 | static struct sljit_jump *check_str_end(compiler_common *common) | static void check_str_end(compiler_common *common, jump_list **end_reached) |
2390 | { | { |
2391 | /* Does not affect registers. Usually used in a tight spot. */ | /* Does not affect registers. Usually used in a tight spot. */ |
2392 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2393 | struct sljit_jump *jump; | struct sljit_jump *jump; |
struct sljit_jump *nohit; | ||
struct sljit_jump *return_value; | ||
2394 | ||
2395 | if (common->mode == JIT_COMPILE) | if (common->mode == JIT_COMPILE) |
2396 | return CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | { |
2397 | add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); | |
2398 | return; | |
2399 | } | |
2400 | ||
2401 | jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); |
2402 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2403 | { | { |
2404 | nohit = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); |
2405 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); |
2406 | JUMPHERE(nohit); | add_jump(compiler, end_reached, JUMP(SLJIT_JUMP)); |
return_value = JUMP(SLJIT_JUMP); | ||
2407 | } | } |
2408 | else | else |
2409 | { | { |
2410 | return_value = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0); | add_jump(compiler, end_reached, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); |
2411 | if (common->partialmatchlabel != NULL) | if (common->partialmatchlabel != NULL) |
2412 | JUMPTO(SLJIT_JUMP, common->partialmatchlabel); | JUMPTO(SLJIT_JUMP, common->partialmatchlabel); |
2413 | else | else |
2414 | add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); | add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); |
2415 | } | } |
2416 | JUMPHERE(jump); | JUMPHERE(jump); |
return return_value; | ||
2417 | } | } |
2418 | ||
2419 | static void detect_partial_match(compiler_common *common, jump_list **backtracks) | static void detect_partial_match(compiler_common *common, jump_list **backtracks) |
# | Line 2115 jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR | Line 2432 jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR |
2432 | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); | add_jump(compiler, backtracks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), common->start_used_ptr, STR_PTR, 0)); |
2433 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) |
2434 | { | { |
2435 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, -1); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->hit_start, SLJIT_IMM, 0); |
2436 | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
2437 | } | } |
2438 | else | else |
# | Line 2206 if (common->utf) | Line 2523 if (common->utf) |
2523 | /* Skip low surrogate if necessary. */ | /* Skip low surrogate if necessary. */ |
2524 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xfc00); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xfc00); |
2525 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xd800); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xd800); |
2526 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
2527 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); |
2528 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
2529 | #elif defined COMPILE_PCRE32 | #elif defined COMPILE_PCRE32 |
# | Line 2256 if (common->utf) | Line 2573 if (common->utf) |
2573 | /* Skip low surrogate if necessary. */ | /* Skip low surrogate if necessary. */ |
2574 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); |
2575 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00); |
2576 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
2577 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
2578 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
2579 | return; | return; |
# | Line 2279 if (nltype == NLTYPE_ANY) | Line 2596 if (nltype == NLTYPE_ANY) |
2596 | else if (nltype == NLTYPE_ANYCRLF) | else if (nltype == NLTYPE_ANYCRLF) |
2597 | { | { |
2598 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_CR); |
2599 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
2600 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); |
2601 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
2602 | add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(jumpiftrue ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
2603 | } | } |
2604 | else | else |
# | Line 2509 if (newlinecheck) | Line 2826 if (newlinecheck) |
2826 | end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
2827 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
2828 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff); |
2829 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
2830 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
2831 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); |
2832 | #endif | #endif |
# | Line 2547 if (common->utf) | Line 2864 if (common->utf) |
2864 | singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); | singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); |
2865 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); |
2866 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); |
2867 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
2868 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
2869 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
2870 | JUMPHERE(singlechar); | JUMPHERE(singlechar); |
# | Line 2573 DEFINE_COMPILER; | Line 2890 DEFINE_COMPILER; |
2890 | struct sljit_label *start; | struct sljit_label *start; |
2891 | struct sljit_jump *quit; | struct sljit_jump *quit; |
2892 | pcre_uint32 chars[MAX_N_CHARS * 2]; | pcre_uint32 chars[MAX_N_CHARS * 2]; |
2893 | pcre_uchar *cc = common->start + 1 + IMM2_SIZE; | pcre_uchar *cc = common->start + 1 + LINK_SIZE; |
2894 | int location = 0; | int location = 0; |
2895 | pcre_int32 len, c, bit, caseless; | pcre_int32 len, c, bit, caseless; |
2896 | int must_stop; | int must_stop; |
# | Line 2696 if (firstline) | Line 3013 if (firstline) |
3013 | { | { |
3014 | SLJIT_ASSERT(common->first_line_end != 0); | SLJIT_ASSERT(common->first_line_end != 0); |
3015 | OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); | OP1(SLJIT_MOV, TMP3, 0, STR_END, 0); |
3016 | OP2(SLJIT_SUB, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, SLJIT_IMM, (location >> 1) - 1); | OP2(SLJIT_SUB, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->first_line_end, SLJIT_IMM, IN_UCHARS((location >> 1) - 1)); |
3017 | } | } |
3018 | else | else |
3019 | OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, (location >> 1) - 1); | OP2(SLJIT_SUB, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS((location >> 1) - 1)); |
3020 | ||
3021 | start = LABEL(); | start = LABEL(); |
3022 | quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | quit = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
# | Line 2728 JUMPHERE(quit); | Line 3045 JUMPHERE(quit); |
3045 | if (firstline) | if (firstline) |
3046 | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); |
3047 | else | else |
3048 | OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, (location >> 1) - 1); | OP2(SLJIT_ADD, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS((location >> 1) - 1)); |
3049 | return TRUE; | return TRUE; |
3050 | } | } |
3051 | ||
# | Line 2775 else | Line 3092 else |
3092 | else | else |
3093 | { | { |
3094 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char); |
3095 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
3096 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc); |
3097 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3098 | found = JUMP(SLJIT_C_NOT_ZERO); | found = JUMP(SLJIT_C_NOT_ZERO); |
3099 | } | } |
3100 | } | } |
# | Line 2819 if (common->nltype == NLTYPE_FIXED && co | Line 3136 if (common->nltype == NLTYPE_FIXED && co |
3136 | ||
3137 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); |
3138 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); |
3139 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_GREATER_EQUAL); |
3140 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
3141 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT); |
3142 | #endif | #endif |
# | Line 2862 if (common->nltype == NLTYPE_ANY || comm | Line 3179 if (common->nltype == NLTYPE_ANY || comm |
3179 | notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
3180 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
3181 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); |
3182 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
3183 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
3184 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); |
3185 | #endif | #endif |
# | Line 2877 if (firstline) | Line 3194 if (firstline) |
3194 | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); | OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); |
3195 | } | } |
3196 | ||
3197 | static BOOL check_class_ranges(compiler_common *common, const pcre_uint8 *bits, BOOL nclass, jump_list **backtracks); | |
3198 | ||
3199 | static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline) | static SLJIT_INLINE void fast_forward_start_bits(compiler_common *common, sljit_uw start_bits, BOOL firstline) |
3200 | { | { |
3201 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3202 | struct sljit_label *start; | struct sljit_label *start; |
3203 | struct sljit_jump *quit; | struct sljit_jump *quit; |
3204 | struct sljit_jump *found; | struct sljit_jump *found = NULL; |
3205 | jump_list *matches = NULL; | |
3206 | pcre_uint8 inverted_start_bits[32]; | |
3207 | int i; | |
3208 | #ifndef COMPILE_PCRE8 | #ifndef COMPILE_PCRE8 |
3209 | struct sljit_jump *jump; | struct sljit_jump *jump; |
3210 | #endif | #endif |
3211 | ||
3212 | for (i = 0; i < 32; ++i) | |
3213 | inverted_start_bits[i] = ~(((pcre_uint8*)start_bits)[i]); | |
3214 | ||
3215 | if (firstline) | if (firstline) |
3216 | { | { |
3217 | SLJIT_ASSERT(common->first_line_end != 0); | SLJIT_ASSERT(common->first_line_end != 0); |
# | Line 2901 OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_P | Line 3226 OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_P |
3226 | if (common->utf) | if (common->utf) |
3227 | OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); | OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); |
3228 | #endif | #endif |
3229 | ||
3230 | if (!check_class_ranges(common, inverted_start_bits, (inverted_start_bits[31] & 0x80) != 0, &matches)) | |
3231 | { | |
3232 | #ifndef COMPILE_PCRE8 | #ifndef COMPILE_PCRE8 |
3233 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255); | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255); |
3234 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255); |
3235 | JUMPHERE(jump); | JUMPHERE(jump); |
3236 | #endif | #endif |
3237 | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); |
3238 | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); |
3239 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), start_bits); |
3240 | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); |
3241 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); |
3242 | found = JUMP(SLJIT_C_NOT_ZERO); | found = JUMP(SLJIT_C_NOT_ZERO); |
3243 | } | |
3244 | ||
3245 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
3246 | if (common->utf) | if (common->utf) |
# | Line 2932 if (common->utf) | Line 3261 if (common->utf) |
3261 | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); |
3262 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); |
3263 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); |
3264 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
3265 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
3266 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
3267 | } | } |
3268 | #endif /* COMPILE_PCRE[8|16] */ | #endif /* COMPILE_PCRE[8|16] */ |
3269 | #endif /* SUPPORT_UTF */ | #endif /* SUPPORT_UTF */ |
3270 | JUMPTO(SLJIT_JUMP, start); | JUMPTO(SLJIT_JUMP, start); |
3271 | JUMPHERE(found); | if (found != NULL) |
3272 | JUMPHERE(found); | |
3273 | if (matches != NULL) | |
3274 | set_jumps(matches, LABEL()); | |
3275 | JUMPHERE(quit); | JUMPHERE(quit); |
3276 | ||
3277 | if (firstline) | if (firstline) |
# | Line 3022 GET_LOCAL_BASE(TMP3, 0, 0); | Line 3354 GET_LOCAL_BASE(TMP3, 0, 0); |
3354 | /* Drop frames until we reach STACK_TOP. */ | /* Drop frames until we reach STACK_TOP. */ |
3355 | mainloop = LABEL(); | mainloop = LABEL(); |
3356 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); |
3357 | jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); | OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0); |
3358 | jump = JUMP(SLJIT_C_SIG_LESS_EQUAL); | |
3359 | ||
3360 | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0); | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0); |
3361 | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw)); | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw)); |
3362 | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_sw)); | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), sizeof(sljit_sw), SLJIT_MEM1(TMP1), 2 * sizeof(sljit_sw)); |
# | Line 3030 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_I | Line 3364 OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_I |
3364 | JUMPTO(SLJIT_JUMP, mainloop); | JUMPTO(SLJIT_JUMP, mainloop); |
3365 | ||
3366 | JUMPHERE(jump); | JUMPHERE(jump); |
3367 | jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); | jump = JUMP(SLJIT_C_SIG_LESS); |
3368 | /* End of dropping frames. */ | /* End of dropping frames. */ |
3369 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
3370 | ||
3371 | JUMPHERE(jump); | JUMPHERE(jump); |
3372 | jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setstrbegin); | OP1(SLJIT_NEG, TMP2, 0, TMP2, 0); |
3373 | /* Set string begin. */ | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP3, 0); |
3374 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw)); | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw)); |
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), TMP2, 0); | ||
JUMPTO(SLJIT_JUMP, mainloop); | ||
JUMPHERE(jump); | ||
if (common->mark_ptr != 0) | ||
{ | ||
jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_setmark); | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), sizeof(sljit_sw)); | ||
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); | ||
JUMPTO(SLJIT_JUMP, mainloop); | ||
JUMPHERE(jump); | ||
} | ||
/* Unknown command. */ | ||
3375 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2 * sizeof(sljit_sw)); |
3376 | JUMPTO(SLJIT_JUMP, mainloop); | JUMPTO(SLJIT_JUMP, mainloop); |
3377 | } | } |
# | Line 3063 static void check_wordboundary(compiler_ | Line 3380 static void check_wordboundary(compiler_ |
3380 | { | { |
3381 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3382 | struct sljit_jump *skipread; | struct sljit_jump *skipread; |
3383 | jump_list *skipread_list = NULL; | |
3384 | #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF | #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF |
3385 | struct sljit_jump *jump; | struct sljit_jump *jump; |
3386 | #endif | #endif |
# | Line 3088 if (common->use_ucp) | Line 3406 if (common->use_ucp) |
3406 | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); |
3407 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); |
3408 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); |
3409 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); |
3410 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); |
3411 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); |
3412 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); |
3413 | JUMPHERE(jump); | JUMPHERE(jump); |
3414 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP2, 0); |
3415 | } | } |
# | Line 3120 else | Line 3438 else |
3438 | JUMPHERE(skipread); | JUMPHERE(skipread); |
3439 | ||
3440 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); |
3441 | skipread = check_str_end(common); | check_str_end(common, &skipread_list); |
3442 | peek_char(common); | peek_char(common); |
3443 | ||
3444 | /* Testing char type. This is a code duplication. */ | /* Testing char type. This is a code duplication. */ |
# | Line 3132 if (common->use_ucp) | Line 3450 if (common->use_ucp) |
3450 | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); |
3451 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll); |
3452 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); |
3453 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); |
3454 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll); |
3455 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd); |
3456 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); |
3457 | JUMPHERE(jump); | JUMPHERE(jump); |
3458 | } | } |
3459 | else | else |
# | Line 3161 else | Line 3479 else |
3479 | JUMPHERE(jump); | JUMPHERE(jump); |
3480 | #endif /* COMPILE_PCRE8 */ | #endif /* COMPILE_PCRE8 */ |
3481 | } | } |
3482 | JUMPHERE(skipread); | set_jumps(skipread_list, LABEL()); |
3483 | ||
3484 | OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); | OP2(SLJIT_XOR | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); |
3485 | sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
# | Line 3315 sljit_emit_fast_enter(compiler, RETURN_A | Line 3633 sljit_emit_fast_enter(compiler, RETURN_A |
3633 | ||
3634 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); |
3635 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); |
3636 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); |
3637 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); |
3638 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
3639 | #ifdef COMPILE_PCRE8 | #ifdef COMPILE_PCRE8 |
3640 | if (common->utf) | if (common->utf) |
3641 | { | { |
3642 | #endif | #endif |
3643 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3644 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); |
3645 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); |
3646 | #ifdef COMPILE_PCRE8 | #ifdef COMPILE_PCRE8 |
3647 | } | } |
3648 | #endif | #endif |
3649 | #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ | #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ |
3650 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3651 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
3652 | } | } |
3653 | ||
# | Line 3341 DEFINE_COMPILER; | Line 3659 DEFINE_COMPILER; |
3659 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0); |
3660 | ||
3661 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09); |
3662 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
3663 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); |
3664 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3665 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0); |
3666 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
3667 | #ifdef COMPILE_PCRE8 | #ifdef COMPILE_PCRE8 |
3668 | if (common->utf) | if (common->utf) |
3669 | { | { |
3670 | #endif | #endif |
3671 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3672 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680); |
3673 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3674 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e); |
3675 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3676 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000); |
3677 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000); |
3678 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); |
3679 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000); |
3680 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3681 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000); |
3682 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3683 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000); |
3684 | #ifdef COMPILE_PCRE8 | #ifdef COMPILE_PCRE8 |
3685 | } | } |
3686 | #endif | #endif |
3687 | #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ | #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ |
3688 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3689 | ||
3690 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
3691 | } | } |
# | Line 3381 sljit_emit_fast_enter(compiler, RETURN_A | Line 3699 sljit_emit_fast_enter(compiler, RETURN_A |
3699 | ||
3700 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a); |
3701 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a); |
3702 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); |
3703 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a); |
3704 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
3705 | #ifdef COMPILE_PCRE8 | #ifdef COMPILE_PCRE8 |
3706 | if (common->utf) | if (common->utf) |
3707 | { | { |
3708 | #endif | #endif |
3709 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3710 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); |
3711 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a); |
3712 | #ifdef COMPILE_PCRE8 | #ifdef COMPILE_PCRE8 |
3713 | } | } |
3714 | #endif | #endif |
3715 | #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ | #endif /* SUPPORT_UTF || COMPILE_PCRE16 || COMPILE_PCRE32 */ |
3716 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
3717 | ||
3718 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
3719 | } | } |
# | Line 3481 sljit_emit_fast_return(compiler, RETURN_ | Line 3799 sljit_emit_fast_return(compiler, RETURN_ |
3799 | ||
3800 | #if defined SUPPORT_UTF && defined SUPPORT_UCP | #if defined SUPPORT_UTF && defined SUPPORT_UCP |
3801 | ||
3802 | static const pcre_uchar *SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1) | static const pcre_uchar * SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1) |
3803 | { | { |
3804 | /* This function would be ineffective to do in JIT level. */ | /* This function would be ineffective to do in JIT level. */ |
3805 | pcre_uint32 c1, c2; | pcre_uint32 c1, c2; |
# | Line 3532 if (caseless && char_has_othercase(commo | Line 3850 if (caseless && char_has_othercase(commo |
3850 | othercasebit &= 0xff; | othercasebit &= 0xff; |
3851 | #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32 | #elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32 |
3852 | /* Note that this code only handles characters in the BMP. If there | /* Note that this code only handles characters in the BMP. If there |
3853 | ever are characters outside the BMP whose othercase differs in only one | ever are characters outside the BMP whose othercase differs in only one |
3854 | bit from itself (there currently are none), this code will need to be | bit from itself (there currently are none), this code will need to be |
3855 | revised for COMPILE_PCRE32. */ | revised for COMPILE_PCRE32. */ |
3856 | othercasechar = cc + (othercasebit >> 9); | othercasechar = cc + (othercasebit >> 9); |
# | Line 3577 do | Line 3895 do |
3895 | #endif | #endif |
3896 | ||
3897 | context->length -= IN_UCHARS(1); | context->length -= IN_UCHARS(1); |
3898 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | #if (defined SLJIT_UNALIGNED && SLJIT_UNALIGNED) && (defined COMPILE_PCRE8 || defined COMPILE_PCRE16) |
3899 | ||
3900 | /* Unaligned read is supported. */ | /* Unaligned read is supported. */ |
3901 | if (othercasebit != 0 && othercasechar == cc) | if (othercasebit != 0 && othercasechar == cc) |
# | Line 3594 do | Line 3912 do |
3912 | ||
3913 | #if defined COMPILE_PCRE8 | #if defined COMPILE_PCRE8 |
3914 | if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1)) | if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1)) |
3915 | #elif defined COMPILE_PCRE16 | #else |
3916 | if (context->ucharptr >= 2 || context->length == 0) | if (context->ucharptr >= 2 || context->length == 0) |
#elif defined COMPILE_PCRE32 | ||
if (1 /* context->ucharptr >= 1 || context->length == 0 */) | ||
3917 | #endif | #endif |
3918 | { | { |
#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16 | ||
3919 | if (context->length >= 4) | if (context->length >= 4) |
3920 | OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); | OP1(SLJIT_MOV_SI, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); |
#if defined COMPILE_PCRE8 | ||
3921 | else if (context->length >= 2) | else if (context->length >= 2) |
3922 | OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); | OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); |
3923 | #if defined COMPILE_PCRE8 | |
3924 | else if (context->length >= 1) | else if (context->length >= 1) |
3925 | OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); | OP1(SLJIT_MOV_UB, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); |
3926 | #elif defined COMPILE_PCRE16 | #endif /* COMPILE_PCRE8 */ |
else if (context->length >= 2) | ||
OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); | ||
#endif /* COMPILE_PCRE[8|16] */ | ||
#elif defined COMPILE_PCRE32 | ||
OP1(MOV_UCHAR, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); | ||
#endif /* COMPILE_PCRE[8|16|32] */ | ||
3927 | context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; | context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; |
3928 | ||
3929 | switch(context->ucharptr) | switch(context->ucharptr) |
# | Line 3625 do | Line 3934 do |
3934 | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); | add_jump(compiler, backtracks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); |
3935 | break; | break; |
3936 | ||
#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16 | ||
3937 | case 2 / sizeof(pcre_uchar): | case 2 / sizeof(pcre_uchar): |
3938 | if (context->oc.asushort != 0) | if (context->oc.asushort != 0) |
3939 | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort); | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort); |
# | Line 3640 do | Line 3948 do |
3948 | break; | break; |
3949 | #endif | #endif |
3950 | ||
#endif /* COMPILE_PCRE[8|16] */ | ||
3951 | default: | default: |
3952 | SLJIT_ASSERT_STOP(); | SLJIT_ASSERT_STOP(); |
3953 | break; | break; |
# | Line 3651 do | Line 3957 do |
3957 | ||
3958 | #else | #else |
3959 | ||
3960 | /* Unaligned read is unsupported. */ | /* Unaligned read is unsupported or in 32 bit mode. */ |
3961 | if (context->length > 0) | if (context->length >= 1) |
3962 | OP1(MOV_UCHAR, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); | OP1(MOV_UCHAR, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); |
3963 | ||
3964 | context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; | context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; |
# | Line 3813 while (*cc != XCL_END) | Line 4119 while (*cc != XCL_END) |
4119 | break; | break; |
4120 | ||
4121 | case PT_CLIST: | case PT_CLIST: |
4122 | case PT_UCNC: | |
4123 | needschar = TRUE; | needschar = TRUE; |
4124 | break; | break; |
4125 | ||
# | Line 3894 while (*cc != XCL_END) | Line 4201 while (*cc != XCL_END) |
4201 | if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) | if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) |
4202 | { | { |
4203 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); |
4204 | COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_C_EQUAL); |
4205 | numberofcmps++; | numberofcmps++; |
4206 | } | } |
4207 | else if (numberofcmps > 0) | else if (numberofcmps > 0) |
4208 | { | { |
4209 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); |
4210 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
4211 | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); |
4212 | numberofcmps = 0; | numberofcmps = 0; |
4213 | } | } |
# | Line 3933 while (*cc != XCL_END) | Line 4240 while (*cc != XCL_END) |
4240 | if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) | if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE)) |
4241 | { | { |
4242 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); |
4243 | COND_VALUE(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, numberofcmps == 0 ? SLJIT_UNUSED : TMP2, 0, SLJIT_C_LESS_EQUAL); |
4244 | numberofcmps++; | numberofcmps++; |
4245 | } | } |
4246 | else if (numberofcmps > 0) | else if (numberofcmps > 0) |
4247 | { | { |
4248 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c - charoffset); |
4249 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); |
4250 | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); |
4251 | numberofcmps = 0; | numberofcmps = 0; |
4252 | } | } |
# | Line 3970 while (*cc != XCL_END) | Line 4277 while (*cc != XCL_END) |
4277 | ||
4278 | case PT_LAMP: | case PT_LAMP: |
4279 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset); |
4280 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
4281 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset); |
4282 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
4283 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset); |
4284 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
4285 | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); |
4286 | break; | break; |
4287 | ||
# | Line 4001 while (*cc != XCL_END) | Line 4308 while (*cc != XCL_END) |
4308 | } | } |
4309 | SET_CHAR_OFFSET(9); | SET_CHAR_OFFSET(9); |
4310 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 13 - 9); |
4311 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS_EQUAL); |
4312 | if (*cc == PT_SPACE) | if (*cc == PT_SPACE) |
4313 | JUMPHERE(jump); | JUMPHERE(jump); |
4314 | ||
4315 | SET_TYPE_OFFSET(ucp_Zl); | SET_TYPE_OFFSET(ucp_Zl); |
4316 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl); |
4317 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); |
4318 | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); |
4319 | break; | break; |
4320 | ||
4321 | case PT_WORD: | case PT_WORD: |
4322 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE - charoffset); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE - charoffset); |
4323 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
4324 | /* ... fall through */ | /* Fall through. */ |
4325 | ||
4326 | case PT_ALNUM: | case PT_ALNUM: |
4327 | SET_TYPE_OFFSET(ucp_Ll); | SET_TYPE_OFFSET(ucp_Ll); |
4328 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll); |
4329 | COND_VALUE((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, (*cc == PT_ALNUM) ? SLJIT_UNUSED : TMP2, 0, SLJIT_C_LESS_EQUAL); |
4330 | SET_TYPE_OFFSET(ucp_Nd); | SET_TYPE_OFFSET(ucp_Nd); |
4331 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd); |
4332 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_LESS_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); |
4333 | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); |
4334 | break; | break; |
4335 | ||
# | Line 4045 while (*cc != XCL_END) | Line 4352 while (*cc != XCL_END) |
4352 | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); |
4353 | } | } |
4354 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]); |
4355 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
4356 | other_cases += 2; | other_cases += 2; |
4357 | } | } |
4358 | else if (is_powerof2(other_cases[2] ^ other_cases[1])) | else if (is_powerof2(other_cases[2] ^ other_cases[1])) |
# | Line 4058 while (*cc != XCL_END) | Line 4365 while (*cc != XCL_END) |
4365 | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]); |
4366 | } | } |
4367 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]); |
4368 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
4369 | ||
4370 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, other_cases[0] - charoffset); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, other_cases[0] - charoffset); |
4371 | COND_VALUE(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
4372 | ||
4373 | other_cases += 3; | other_cases += 3; |
4374 | } | } |
4375 | else | else |
4376 | { | { |
4377 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, *other_cases++ - charoffset); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, *other_cases++ - charoffset); |
4378 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
4379 | } | } |
4380 | ||
4381 | while (*other_cases != NOTACHAR) | while (*other_cases != NOTACHAR) |
4382 | { | { |
4383 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, *other_cases++ - charoffset); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, *other_cases++ - charoffset); |
4384 | COND_VALUE(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_E : 0), TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
4385 | } | } |
4386 | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); |
4387 | break; | break; |
4388 | ||
4389 | case PT_UCNC: | |
4390 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_DOLLAR_SIGN - charoffset); | |
4391 | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); | |
4392 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_COMMERCIAL_AT - charoffset); | |
4393 | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); | |
4394 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_GRAVE_ACCENT - charoffset); | |
4395 | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); | |
4396 | ||
4397 | SET_CHAR_OFFSET(0xa0); | |
4398 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd7ff - charoffset); | |
4399 | OP_FLAGS(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_C_LESS_EQUAL); | |
4400 | SET_CHAR_OFFSET(0); | |
4401 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0); | |
4402 | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_GREATER_EQUAL); | |
4403 | jump = JUMP(SLJIT_C_NOT_ZERO ^ invertcmp); | |
4404 | break; | |
4405 | } | } |
4406 | cc += 2; | cc += 2; |
4407 | } | } |
# | Line 4103 int length; | Line 4427 int length; |
4427 | unsigned int c, oc, bit; | unsigned int c, oc, bit; |
4428 | compare_context context; | compare_context context; |
4429 | struct sljit_jump *jump[4]; | struct sljit_jump *jump[4]; |
4430 | jump_list *end_list; | |
4431 | #ifdef SUPPORT_UTF | #ifdef SUPPORT_UTF |
4432 | struct sljit_label *label; | struct sljit_label *label; |
4433 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
# | Line 4171 switch(type) | Line 4496 switch(type) |
4496 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
4497 | { | { |
4498 | jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); | jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); |
4499 | end_list = NULL; | |
4500 | if (common->mode != JIT_PARTIAL_HARD_COMPILE) | if (common->mode != JIT_PARTIAL_HARD_COMPILE) |
4501 | jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | add_jump(compiler, &end_list, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
4502 | else | else |
4503 | jump[1] = check_str_end(common); | check_str_end(common, &end_list); |
4504 | ||
4505 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
4506 | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); |
4507 | if (jump[1] != NULL) | set_jumps(end_list, LABEL()); |
JUMPHERE(jump[1]); | ||
4508 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
4509 | } | } |
4510 | else | else |
# | Line 4202 switch(type) | Line 4527 switch(type) |
4527 | jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); | jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); |
4528 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); |
4529 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); |
4530 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
4531 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
4532 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
4533 | #endif | #endif |
# | Line 4238 switch(type) | Line 4563 switch(type) |
4563 | read_char(common); | read_char(common); |
4564 | jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); | jump[0] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); |
4565 | /* We don't need to handle soft partial matching case. */ | /* We don't need to handle soft partial matching case. */ |
4566 | end_list = NULL; | |
4567 | if (common->mode != JIT_PARTIAL_HARD_COMPILE) | if (common->mode != JIT_PARTIAL_HARD_COMPILE) |
4568 | jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | add_jump(compiler, &end_list, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
4569 | else | else |
4570 | jump[1] = check_str_end(common); | check_str_end(common, &end_list); |
4571 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
4572 | jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); | jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); |
4573 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
4574 | jump[3] = JUMP(SLJIT_JUMP); | jump[2] = JUMP(SLJIT_JUMP); |
4575 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
4576 | check_newlinechar(common, common->bsr_nltype, backtracks, FALSE); | check_newlinechar(common, common->bsr_nltype, backtracks, FALSE); |
4577 | set_jumps(end_list, LABEL()); | |
4578 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
4579 | JUMPHERE(jump[2]); | JUMPHERE(jump[2]); |
JUMPHERE(jump[3]); | ||
4580 | return cc; | return cc; |
4581 | ||
4582 | case OP_NOT_HSPACE: | case OP_NOT_HSPACE: |
# | Line 4321 switch(type) | Line 4647 switch(type) |
4647 | { | { |
4648 | jump[1] = CMP(SLJIT_C_EQUAL, TMP2, 0, STR_END, 0); | jump[1] = CMP(SLJIT_C_EQUAL, TMP2, 0, STR_END, 0); |
4649 | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); | OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0); |
4650 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_LESS); |
4651 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff); |
4652 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_NOT_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_NOT_EQUAL); |
4653 | add_jump(compiler, backtracks, JUMP(SLJIT_C_NOT_EQUAL)); | add_jump(compiler, backtracks, JUMP(SLJIT_C_NOT_EQUAL)); |
4654 | check_partial(common, TRUE); | check_partial(common, TRUE); |
4655 | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); | add_jump(compiler, backtracks, JUMP(SLJIT_JUMP)); |
# | Line 4510 switch(type) | Line 4836 switch(type) |
4836 | return cc + length; | return cc + length; |
4837 | } | } |
4838 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, c); |
4839 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
4840 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc); |
4841 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
4842 | add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); | add_jump(compiler, backtracks, JUMP(SLJIT_C_ZERO)); |
4843 | return cc + length; | return cc + length; |
4844 | ||
# | Line 4726 if (!common->jscript_compat) | Line 5052 if (!common->jscript_compat) |
5052 | { | { |
5053 | /* OVECTOR(1) contains the "string begin - 1" constant. */ | /* OVECTOR(1) contains the "string begin - 1" constant. */ |
5054 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
5055 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_C_EQUAL); |
5056 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
5057 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | OP_FLAGS(SLJIT_OR | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_C_EQUAL); |
5058 | return JUMP(SLJIT_C_NOT_ZERO); | return JUMP(SLJIT_C_NOT_ZERO); |
5059 | } | } |
5060 | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); | add_jump(compiler, backtracks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); |
# | Line 4784 if (withchecks && !common->jscript_compa | Line 5110 if (withchecks && !common->jscript_compa |
5110 | #if defined SUPPORT_UTF && defined SUPPORT_UCP | #if defined SUPPORT_UTF && defined SUPPORT_UCP |
5111 | if (common->utf && *cc == OP_REFI) | if (common->utf && *cc == OP_REFI) |
5112 | { | { |
5113 | SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3); | SLJIT_ASSERT(TMP1 == SLJIT_SCRATCH_REG1 && STACK_TOP == SLJIT_SCRATCH_REG2 && TMP2 == SLJIT_SCRATCH_REG3); |
5114 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
5115 | if (withchecks) | if (withchecks) |
5116 | jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0); | jump = CMP(SLJIT_C_EQUAL, TMP1, 0, TMP2, 0); |
5117 | ||
5118 | /* Needed to save important temporary registers. */ | /* Needed to save important temporary registers. */ |
5119 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
5120 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG2, 0, ARGUMENTS, 0); |
5121 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SCRATCH_REG2), SLJIT_OFFSETOF(jit_arguments, uchar_ptr), STR_PTR, 0); |
5122 | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); |
5123 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
5124 | if (common->mode == JIT_COMPILE) | if (common->mode == JIT_COMPILE) |
# | Line 5000 DEFINE_COMPILER; | Line 5326 DEFINE_COMPILER; |
5326 | backtrack_common *backtrack; | backtrack_common *backtrack; |
5327 | recurse_entry *entry = common->entries; | recurse_entry *entry = common->entries; |
5328 | recurse_entry *prev = NULL; | recurse_entry *prev = NULL; |
5329 | int start = GET(cc, 1); | sljit_sw start = GET(cc, 1); |
5330 | pcre_uchar *start_cc; | |
5331 | BOOL needs_control_head; | |
5332 | ||
5333 | PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL); | PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL); |
5334 | ||
5335 | /* Inlining simple patterns. */ | |
5336 | if (get_framesize(common, common->start + start, NULL, TRUE, &needs_control_head) == no_stack) | |
5337 | { | |
5338 | start_cc = common->start + start; | |
5339 | compile_matchingpath(common, next_opcode(common, start_cc), bracketend(start_cc) - (1 + LINK_SIZE), backtrack); | |
5340 | BACKTRACK_AS(recurse_backtrack)->inlined_pattern = TRUE; | |
5341 | return cc + 1 + LINK_SIZE; | |
5342 | } | |
5343 | ||
5344 | while (entry != NULL) | while (entry != NULL) |
5345 | { | { |
5346 | if (entry->start == start) | if (entry->start == start) |
# | Line 5051 add_jump(compiler, &backtrack->topbacktr | Line 5389 add_jump(compiler, &backtrack->topbacktr |
5389 | return cc + 1 + LINK_SIZE; | return cc + 1 + LINK_SIZE; |
5390 | } | } |
5391 | ||
5392 | static int SLJIT_CALL do_callout(struct jit_arguments* arguments, PUBL(callout_block) *callout_block, pcre_uchar **jit_ovector) | |
5393 | { | |
5394 | const pcre_uchar *begin = arguments->begin; | |
5395 | int *offset_vector = arguments->offsets; | |
5396 | int offset_count = arguments->offset_count; | |
5397 | int i; | |
5398 | ||
5399 | if (PUBL(callout) == NULL) | |
5400 | return 0; | |
5401 | ||
5402 | callout_block->version = 2; | |
5403 | callout_block->callout_data = arguments->callout_data; | |
5404 | ||
5405 | /* Offsets in subject. */ | |
5406 | callout_block->subject_length = arguments->end - arguments->begin; | |
5407 | callout_block->start_match = (pcre_uchar*)callout_block->subject - arguments->begin; | |
5408 | callout_block->current_position = (pcre_uchar*)callout_block->offset_vector - arguments->begin; | |
5409 | #if defined COMPILE_PCRE8 | |
5410 | callout_block->subject = (PCRE_SPTR)begin; | |
5411 | #elif defined COMPILE_PCRE16 | |
5412 | callout_block->subject = (PCRE_SPTR16)begin; | |
5413 | #elif defined COMPILE_PCRE32 | |
5414 | callout_block->subject = (PCRE_SPTR32)begin; | |
5415 | #endif | |
5416 | ||
5417 | /* Convert and copy the JIT offset vector to the offset_vector array. */ | |
5418 | callout_block->capture_top = 0; | |
5419 | callout_block->offset_vector = offset_vector; | |
5420 | for (i = 2; i < offset_count; i += 2) | |
5421 | { | |
5422 | offset_vector[i] = jit_ovector[i] - begin; | |
5423 | offset_vector[i + 1] = jit_ovector[i + 1] - begin; | |
5424 | if (jit_ovector[i] >= begin) | |
5425 | callout_block->capture_top = i; | |
5426 | } | |
5427 | ||
5428 | callout_block->capture_top = (callout_block->capture_top >> 1) + 1; | |
5429 | if (offset_count > 0) | |
5430 | offset_vector[0] = -1; | |
5431 | if (offset_count > 1) | |
5432 | offset_vector[1] = -1; | |
5433 | return (*PUBL(callout))(callout_block); | |
5434 | } | |
5435 | ||
5436 | /* Aligning to 8 byte. */ | |
5437 | #define CALLOUT_ARG_SIZE \ | |
5438 | (((int)sizeof(PUBL(callout_block)) + 7) & ~7) | |
5439 | ||
5440 | #define CALLOUT_ARG_OFFSET(arg) \ | |
5441 | (-CALLOUT_ARG_SIZE + SLJIT_OFFSETOF(PUBL(callout_block), arg)) | |
5442 | ||
5443 | static SLJIT_INLINE pcre_uchar *compile_callout_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) | |
5444 | { | |
5445 | DEFINE_COMPILER; | |
5446 | backtrack_common *backtrack; | |
5447 | ||
5448 | PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); | |
5449 | ||
5450 | allocate_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw)); | |
5451 | ||
5452 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); | |
5453 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | |
5454 | SLJIT_ASSERT(common->capture_last_ptr != 0); | |
5455 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(callout_number), SLJIT_IMM, cc[1]); | |
5456 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(capture_last), TMP2, 0); | |
5457 | ||
5458 | /* These pointer sized fields temporarly stores internal variables. */ | |
5459 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0)); | |
5460 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(offset_vector), STR_PTR, 0); | |
5461 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(subject), TMP2, 0); | |
5462 | ||
5463 | if (common->mark_ptr != 0) | |
5464 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr)); | |
5465 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(pattern_position), SLJIT_IMM, GET(cc, 2)); | |
5466 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(next_item_length), SLJIT_IMM, GET(cc, 2 + LINK_SIZE)); | |
5467 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), CALLOUT_ARG_OFFSET(mark), (common->mark_ptr != 0) ? TMP2 : SLJIT_IMM, 0); | |
5468 | ||
5469 | /* Needed to save important temporary registers. */ | |
5470 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); | |
5471 | OP2(SLJIT_SUB, SLJIT_SCRATCH_REG2, 0, STACK_TOP, 0, SLJIT_IMM, CALLOUT_ARG_SIZE); | |
5472 | GET_LOCAL_BASE(SLJIT_SCRATCH_REG3, 0, OVECTOR_START); | |
5473 | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout)); | |
5474 | OP1(SLJIT_MOV_SI, SLJIT_RETURN_REG, 0, SLJIT_RETURN_REG, 0); | |
5475 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | |
5476 | free_stack(common, CALLOUT_ARG_SIZE / sizeof(sljit_sw)); | |
5477 | ||
5478 | /* Check return value. */ | |
5479 | OP2(SLJIT_SUB | SLJIT_SET_S, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0); | |
5480 | add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_C_SIG_GREATER)); | |
5481 | if (common->forced_quit_label == NULL) | |
5482 | add_jump(compiler, &common->forced_quit, JUMP(SLJIT_C_SIG_LESS)); | |
5483 | else | |
5484 | JUMPTO(SLJIT_C_SIG_LESS, common->forced_quit_label); | |
5485 | return cc + 2 + 2 * LINK_SIZE; | |
5486 | } | |
5487 | ||
5488 | #undef CALLOUT_ARG_SIZE | |
5489 | #undef CALLOUT_ARG_OFFSET | |
5490 | ||
5491 | static pcre_uchar *compile_assert_matchingpath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional) | static pcre_uchar *compile_assert_matchingpath(compiler_common *common, pcre_uchar *cc, assert_backtrack *backtrack, BOOL conditional) |
5492 | { | { |
5493 | DEFINE_COMPILER; | DEFINE_COMPILER; |
5494 | int framesize; | int framesize; |
5495 | int extrasize; | |
5496 | BOOL needs_control_head; | |
5497 | int private_data_ptr; | int private_data_ptr; |
5498 | backtrack_common altbacktrack; | backtrack_common altbacktrack; |
5499 | pcre_uchar *ccbegin; | pcre_uchar *ccbegin; |
# | Line 5064 jump_list *tmp = NULL; | Line 5503 jump_list *tmp = NULL; |
5503 | jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks; | jump_list **target = (conditional) ? &backtrack->condfailed : &backtrack->common.topbacktracks; |
5504 | jump_list **found; | jump_list **found; |
5505 | /* Saving previous accept variables. */ | /* Saving previous accept variables. */ |
5506 | struct sljit_label *save_quitlabel = common->quitlabel; | BOOL save_local_exit = common->local_exit; |
5507 | struct sljit_label *save_acceptlabel = common->acceptlabel; | BOOL save_positive_assert = common->positive_assert; |
5508 | then_trap_backtrack *save_then_trap = common->then_trap; | |
5509 | struct sljit_label *save_quit_label = common->quit_label; | |
5510 | struct sljit_label *save_accept_label = common->accept_label; | |
5511 | jump_list *save_quit = common->quit; | jump_list *save_quit = common->quit; |
5512 | jump_list *save_positive_assert_quit = common->positive_assert_quit; | |
5513 | jump_list *save_accept = common->accept; | jump_list *save_accept = common->accept; |
5514 | struct sljit_jump *jump; | struct sljit_jump *jump; |
5515 | struct sljit_jump *brajump = NULL; | struct sljit_jump *brajump = NULL; |
5516 | ||
5517 | /* Assert captures then. */ | |
5518 | common->then_trap = NULL; | |
5519 | ||
5520 | if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) | if (*cc == OP_BRAZERO || *cc == OP_BRAMINZERO) |
5521 | { | { |
5522 | SLJIT_ASSERT(!conditional); | SLJIT_ASSERT(!conditional); |
# | Line 5079 if (*cc == OP_BRAZERO || *cc == OP_BRAMI | Line 5525 if (*cc == OP_BRAZERO || *cc == OP_BRAMI |
5525 | } | } |
5526 | private_data_ptr = PRIVATE_DATA(cc); | private_data_ptr = PRIVATE_DATA(cc); |
5527 | SLJIT_ASSERT(private_data_ptr != 0); | SLJIT_ASSERT(private_data_ptr != 0); |
5528 | framesize = get_framesize(common, cc, FALSE); | framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head); |
5529 | backtrack->framesize = framesize; | backtrack->framesize = framesize; |
5530 | backtrack->private_data_ptr = private_data_ptr; | backtrack->private_data_ptr = private_data_ptr; |
5531 | opcode = *cc; | opcode = *cc; |
# | Line 5098 if (bra == OP_BRAMINZERO) | Line 5544 if (bra == OP_BRAMINZERO) |
5544 | ||
5545 | if (framesize < 0) | if (framesize < 0) |
5546 | { | { |
5547 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); | extrasize = needs_control_head ? 2 : 1; |
5548 | allocate_stack(common, 1); | if (framesize == no_frame) |
5549 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); | |
5550 | allocate_stack(common, extrasize); | |
5551 | if (needs_control_head) | |
5552 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); | |
5553 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
5554 | if (needs_control_head) | |
5555 | { | |
5556 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); | |
5557 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); | |
5558 | } | |
5559 | } | } |
5560 | else | else |
5561 | { | { |
5562 | allocate_stack(common, framesize + 2); | extrasize = needs_control_head ? 3 : 2; |
5563 | allocate_stack(common, framesize + extrasize); | |
5564 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
5565 | OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(framesize + 1)); | OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw)); |
5566 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); |
5567 | if (needs_control_head) | |
5568 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); | |
5569 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
5570 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); | if (needs_control_head) |
5571 | init_frame(common, ccbegin, framesize + 1, 2, FALSE); | { |
5572 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); | |
5573 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); | |
5574 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_IMM, 0); | |
5575 | } | |
5576 | else | |
5577 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); | |
5578 | init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize, FALSE); | |
5579 | } | } |
5580 | ||
5581 | memset(&altbacktrack, 0, sizeof(backtrack_common)); | memset(&altbacktrack, 0, sizeof(backtrack_common)); |
5582 | common->quitlabel = NULL; | if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5583 | common->quit = NULL; | { |
5584 | /* Negative assert is stronger than positive assert. */ | |
5585 | common->local_exit = TRUE; | |
5586 | common->quit_label = NULL; | |
5587 | common->quit = NULL; | |
5588 | common->positive_assert = FALSE; | |
5589 | } | |
5590 | else | |
5591 | common->positive_assert = TRUE; | |
5592 | common->positive_assert_quit = NULL; | |
5593 | ||
5594 | while (1) | while (1) |
5595 | { | { |
5596 | common->acceptlabel = NULL; | common->accept_label = NULL; |
5597 | common->accept = NULL; | common->accept = NULL; |
5598 | altbacktrack.top = NULL; | altbacktrack.top = NULL; |
5599 | altbacktrack.topbacktracks = NULL; | altbacktrack.topbacktracks = NULL; |
# | Line 5130 while (1) | Line 5605 while (1) |
5605 | compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack); | compile_matchingpath(common, ccbegin + 1 + LINK_SIZE, cc, &altbacktrack); |
5606 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
5607 | { | { |
5608 | common->quitlabel = save_quitlabel; | if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5609 | common->acceptlabel = save_acceptlabel; | { |
5610 | common->quit = save_quit; | common->local_exit = save_local_exit; |
5611 | common->quit_label = save_quit_label; | |
5612 | common->quit = save_quit; | |
5613 | } | |
5614 | common->positive_assert = save_positive_assert; | |
5615 | common->then_trap = save_then_trap; | |
5616 | common->accept_label = save_accept_label; | |
5617 | common->positive_assert_quit = save_positive_assert_quit; | |
5618 | common->accept = save_accept; | common->accept = save_accept; |
5619 | return NULL; | return NULL; |
5620 | } | } |
5621 | common->acceptlabel = LABEL(); | common->accept_label = LABEL(); |
5622 | if (common->accept != NULL) | if (common->accept != NULL) |
5623 | set_jumps(common->accept, common->acceptlabel); | set_jumps(common->accept, common->accept_label); |
5624 | ||
5625 | /* Reset stack. */ | /* Reset stack. */ |
5626 | if (framesize < 0) | if (framesize < 0) |
5627 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | { |
5628 | else { | if (framesize == no_frame) |
5629 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | |
5630 | else | |
5631 | free_stack(common, extrasize); | |
5632 | if (needs_control_head) | |
5633 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0); | |
5634 | } | |
5635 | else | |
5636 | { | |
5637 | if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional) | if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional) |
5638 | { | { |
5639 | /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ | /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ |
5640 | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); |
5641 | if (needs_control_head) | |
5642 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0); | |
5643 | } | } |
5644 | else | else |
5645 | { | { |
5646 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
5647 | if (needs_control_head) | |
5648 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_sw)); | |
5649 | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
5650 | } | } |
5651 | } | } |
5652 | ||
5653 | if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) | if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5654 | { | { |
5655 | /* We know that STR_PTR was stored on the top of the stack. */ | /* We know that STR_PTR was stored on the top of the stack. */ |
5656 | if (conditional) | if (conditional) |
5657 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0); |
5658 | else if (bra == OP_BRAZERO) | else if (bra == OP_BRAZERO) |
5659 | { | { |
5660 | if (framesize < 0) | if (framesize < 0) |
5661 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw)); |
5662 | else | else |
5663 | { | { |
5664 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_sw)); |
5665 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_sw)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + extrasize - 1) * sizeof(sljit_sw)); |
5666 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); |
5667 | } | } |
5668 | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
# | Line 5185 while (1) | Line 5679 while (1) |
5679 | compile_backtrackingpath(common, altbacktrack.top); | compile_backtrackingpath(common, altbacktrack.top); |
5680 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
5681 | { | { |
5682 | common->quitlabel = save_quitlabel; | if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5683 | common->acceptlabel = save_acceptlabel; | { |
5684 | common->quit = save_quit; | common->local_exit = save_local_exit; |
5685 | common->quit_label = save_quit_label; | |
5686 | common->quit = save_quit; | |
5687 | } | |
5688 | common->positive_assert = save_positive_assert; | |
5689 | common->then_trap = save_then_trap; | |
5690 | common->accept_label = save_accept_label; | |
5691 | common->positive_assert_quit = save_positive_assert_quit; | |
5692 | common->accept = save_accept; | common->accept = save_accept; |
5693 | return NULL; | return NULL; |
5694 | } | } |
# | Line 5199 while (1) | Line 5700 while (1) |
5700 | ccbegin = cc; | ccbegin = cc; |
5701 | cc += GET(cc, 1); | cc += GET(cc, 1); |
5702 | } | } |
5703 | ||
5704 | if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) | |
5705 | { | |
5706 | SLJIT_ASSERT(common->positive_assert_quit == NULL); | |
5707 | /* Makes the check less complicated below. */ | |
5708 | common->positive_assert_quit = common->quit; | |
5709 | } | |
5710 | ||
5711 | /* None of them matched. */ | /* None of them matched. */ |
5712 | if (common->quit != NULL) | if (common->positive_assert_quit != NULL) |
5713 | set_jumps(common->quit, LABEL()); | { |
5714 | jump = JUMP(SLJIT_JUMP); | |
5715 | set_jumps(common->positive_assert_quit, LABEL()); | |
5716 | SLJIT_ASSERT(framesize != no_stack); | |
5717 | if (framesize < 0) | |
5718 | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, extrasize * sizeof(sljit_sw)); | |
5719 | else | |
5720 | { | |
5721 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | |
5722 | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | |
5723 | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw)); | |
5724 | } | |
5725 | JUMPHERE(jump); | |
5726 | } | |
5727 | ||
5728 | if (needs_control_head) | |
5729 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(1)); | |
5730 | ||
5731 | if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) | if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) |
5732 | { | { |
# | Line 5213 if (opcode == OP_ASSERT || opcode == OP_ | Line 5738 if (opcode == OP_ASSERT || opcode == OP_ |
5738 | { | { |
5739 | /* The topmost item should be 0. */ | /* The topmost item should be 0. */ |
5740 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
5741 | { | |
5742 | if (extrasize == 2) | |
5743 | free_stack(common, 1); | |
5744 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
5745 | } | |
5746 | else | else |
5747 | free_stack(common, 1); | free_stack(common, extrasize); |
5748 | } | } |
5749 | else | else |
5750 | { | { |
5751 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1)); |
5752 | /* The topmost item should be 0. */ | /* The topmost item should be 0. */ |
5753 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
5754 | { | { |
5755 | free_stack(common, framesize + 1); | free_stack(common, framesize + extrasize - 1); |
5756 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
5757 | } | } |
5758 | else | else |
5759 | free_stack(common, framesize + 2); | free_stack(common, framesize + extrasize); |
5760 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); |
5761 | } | } |
5762 | jump = JUMP(SLJIT_JUMP); | jump = JUMP(SLJIT_JUMP); |
# | Line 5239 if (opcode == OP_ASSERT || opcode == OP_ | Line 5768 if (opcode == OP_ASSERT || opcode == OP_ |
5768 | if (framesize < 0) | if (framesize < 0) |
5769 | { | { |
5770 | /* We know that STR_PTR was stored on the top of the stack. */ | /* We know that STR_PTR was stored on the top of the stack. */ |
5771 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw)); |
5772 | /* Keep the STR_PTR on the top of the stack. */ | /* Keep the STR_PTR on the top of the stack. */ |
5773 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
5774 | { | |
5775 | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
5776 | if (extrasize == 2) | |
5777 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | |
5778 | } | |
5779 | else if (bra == OP_BRAMINZERO) | else if (bra == OP_BRAMINZERO) |
5780 | { | { |
5781 | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
# | Line 5255 if (opcode == OP_ASSERT || opcode == OP_ | Line 5788 if (opcode == OP_ASSERT || opcode == OP_ |
5788 | { | { |
5789 | /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ | /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ |
5790 | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_sw)); |
5791 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 2) * sizeof(sljit_sw)); |
5792 | } | } |
5793 | else | else |
5794 | { | { |
5795 | /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ | /* We don't need to keep the STR_PTR, only the previous private_data_ptr. */ |
5796 | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw)); | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_sw)); |
5797 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | if (extrasize == 2) |
5798 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0); | { |
5799 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | |
5800 | if (bra == OP_BRAMINZERO) | |
5801 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | |
5802 | } | |
5803 | else | |
5804 | { | |
5805 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); | |
5806 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0); | |
5807 | } | |
5808 | } | } |
5809 | } | } |
5810 | ||
5811 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
5812 | { | { |
5813 | backtrack->matchingpath = LABEL(); | backtrack->matchingpath = LABEL(); |
5814 | sljit_set_label(jump, backtrack->matchingpath); | SET_LABEL(jump, backtrack->matchingpath); |
5815 | } | } |
5816 | else if (bra == OP_BRAMINZERO) | else if (bra == OP_BRAMINZERO) |
5817 | { | { |
# | Line 5291 else | Line 5833 else |
5833 | { | { |
5834 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
5835 | if (bra != OP_BRA) | if (bra != OP_BRA) |
5836 | { | |
5837 | if (extrasize == 2) | |
5838 | free_stack(common, 1); | |
5839 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
5840 | } | |
5841 | else | else |
5842 | free_stack(common, 1); | free_stack(common, extrasize); |
5843 | } | } |
5844 | else | else |
5845 | { | { |
5846 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
5847 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(extrasize - 1)); |
5848 | /* The topmost item should be 0. */ | /* The topmost item should be 0. */ |
5849 | if (bra != OP_BRA) | if (bra != OP_BRA) |
5850 | { | { |
5851 | free_stack(common, framesize + 1); | free_stack(common, framesize + extrasize - 1); |
5852 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
5853 | } | } |
5854 | else | else |
5855 | free_stack(common, framesize + 2); | free_stack(common, framesize + extrasize); |
5856 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); |
5857 | } | } |
5858 | ||
# | Line 5326 else | Line 5872 else |
5872 | } | } |
5873 | } | } |
5874 | ||
5875 | common->quitlabel = save_quitlabel; | if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
5876 | common->acceptlabel = save_acceptlabel; | { |
5877 | common->quit = save_quit; | common->local_exit = save_local_exit; |
5878 | common->quit_label = save_quit_label; | |
5879 | common->quit = save_quit; | |
5880 | } | |
5881 | common->positive_assert = save_positive_assert; | |
5882 | common->then_trap = save_then_trap; | |
5883 | common->accept_label = save_accept_label; | |
5884 | common->positive_assert_quit = save_positive_assert_quit; | |
5885 | common->accept = save_accept; | common->accept = save_accept; |
5886 | return cc + 1 + LINK_SIZE; | return cc + 1 + LINK_SIZE; |
5887 | } | } |
# | Line 5443 if (i < name_count) | Line 5996 if (i < name_count) |
5996 | return condition; | return condition; |
5997 | } | } |
5998 | ||
5999 | static SLJIT_INLINE void match_once_common(compiler_common *common, pcre_uchar ket, int framesize, int private_data_ptr, BOOL has_alternatives, BOOL needs_control_head) | |
6000 | { | |
6001 | DEFINE_COMPILER; | |
6002 | int stacksize; | |
6003 | ||
6004 | if (framesize < 0) | |
6005 | { | |
6006 | if (framesize == no_frame) | |
6007 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | |
6008 | else | |
6009 | { | |
6010 | stacksize = needs_control_head ? 1 : 0; | |
6011 | if (ket != OP_KET || has_alternatives) | |
6012 | stacksize++; | |
6013 | free_stack(common, stacksize); | |
6014 | } | |
6015 | ||
6016 | if (needs_control_head) | |
6017 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), (ket != OP_KET || has_alternatives) ? sizeof(sljit_sw) : 0); | |
6018 | ||
6019 | /* TMP2 which is set here used by OP_KETRMAX below. */ | |
6020 | if (ket == OP_KETRMAX) | |
6021 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0); | |
6022 | else if (ket == OP_KETRMIN) | |
6023 | { | |
6024 | /* Move the STR_PTR to the private_data_ptr. */ | |
6025 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0); | |
6026 | } | |
6027 | } | |
6028 | else | |
6029 | { | |
6030 | stacksize = (ket != OP_KET || has_alternatives) ? 2 : 1; | |
6031 | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, (framesize + stacksize) * sizeof(sljit_sw)); | |
6032 | if (needs_control_head) | |
6033 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), 0); | |
6034 | ||
6035 | if (ket == OP_KETRMAX) | |
6036 | { | |
6037 | /* TMP2 which is set here used by OP_KETRMAX below. */ | |
6038 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | |
6039 | } | |
6040 | } | |
6041 | if (needs_control_head) | |
6042 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, TMP1, 0); | |
6043 | } | |
6044 | ||
6045 | static SLJIT_INLINE int match_capture_common(compiler_common *common, int stacksize, int offset, int private_data_ptr) | |
6046 | { | |
6047 | DEFINE_COMPILER; | |
6048 | ||
6049 | if (common->capture_last_ptr != 0) | |
6050 | { | |
6051 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); | |
6052 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1); | |
6053 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); | |
6054 | stacksize++; | |
6055 | } | |
6056 | if (common->optimized_cbracket[offset >> 1] == 0) | |
6057 | { | |
6058 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); | |
6059 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); | |
6060 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); | |
6061 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | |
6062 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0); | |
6063 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); | |
6064 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); | |
6065 | stacksize += 2; | |
6066 | } | |
6067 | return stacksize; | |
6068 | } | |
6069 | ||
6070 | /* | /* |
6071 | Handling bracketed expressions is probably the most complex part. | Handling bracketed expressions is probably the most complex part. |
6072 | ||
# | Line 5511 pcre_uchar bra = OP_BRA; | Line 6135 pcre_uchar bra = OP_BRA; |
6135 | pcre_uchar ket; | pcre_uchar ket; |
6136 | assert_backtrack *assert; | assert_backtrack *assert; |
6137 | BOOL has_alternatives; | BOOL has_alternatives; |
6138 | BOOL needs_control_head = FALSE; | |
6139 | struct sljit_jump *jump; | struct sljit_jump *jump; |
6140 | struct sljit_jump *skip; | struct sljit_jump *skip; |
6141 | struct sljit_label *rmaxlabel = NULL; | struct sljit_label *rmaxlabel = NULL; |
# | Line 5586 else if (opcode == OP_ONCE || opcode == | Line 6211 else if (opcode == OP_ONCE || opcode == |
6211 | SLJIT_ASSERT(private_data_ptr != 0); | SLJIT_ASSERT(private_data_ptr != 0); |
6212 | BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr; | BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr; |
6213 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
6214 | BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, FALSE); | BACKTRACK_AS(bracket_backtrack)->u.framesize = get_framesize(common, ccbegin, NULL, FALSE, &needs_control_head); |
6215 | } | } |
6216 | ||
6217 | /* Instructions before the first alternative. */ | /* Instructions before the first alternative. */ |
6218 | stacksize = 0; | stacksize = 0; |
6219 | if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) | if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) |
6220 | stacksize++; | stacksize++; |
6221 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
6222 | stacksize++; | stacksize++; |
# | Line 5600 if (stacksize > 0) | Line 6225 if (stacksize > 0) |
6225 | allocate_stack(common, stacksize); | allocate_stack(common, stacksize); |
6226 | ||
6227 | stacksize = 0; | stacksize = 0; |
6228 | if ((ket == OP_KETRMAX) || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) | if (ket == OP_KETRMAX || (ket == OP_KETRMIN && bra != OP_BRAMINZERO)) |
6229 | { | { |
6230 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); |
6231 | stacksize++; | stacksize++; |
# | Line 5663 if (ket == OP_KETRMAX) | Line 6288 if (ket == OP_KETRMAX) |
6288 | /* Handling capturing brackets and alternatives. */ | /* Handling capturing brackets and alternatives. */ |
6289 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
6290 | { | { |
6291 | stacksize = 0; | |
6292 | if (needs_control_head) | |
6293 | { | |
6294 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); | |
6295 | stacksize++; | |
6296 | } | |
6297 | ||
6298 | if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) | if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) |
6299 | { | { |
6300 | /* Neither capturing brackets nor recursions are not found in the block. */ | /* Neither capturing brackets nor recursions are found in the block. */ |
6301 | if (ket == OP_KETRMIN) | if (ket == OP_KETRMIN) |
6302 | { | { |
6303 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | stacksize += 2; |
6304 | allocate_stack(common, 2); | if (!needs_control_head) |
6305 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); | ||
OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); | ||
6306 | } | } |
6307 | else if (ket == OP_KETRMAX || has_alternatives) | else |
6308 | { | { |
6309 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); | if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame) |
6310 | allocate_stack(common, 1); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); |
6311 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | if (ket == OP_KETRMAX || has_alternatives) |
6312 | stacksize++; | |
6313 | } | } |
6314 | else | |
6315 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); | if (stacksize > 0) |
6316 | allocate_stack(common, stacksize); | |
6317 | ||
6318 | stacksize = 0; | |
6319 | if (needs_control_head) | |
6320 | { | |
6321 | stacksize++; | |
6322 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); | |
6323 | } | |
6324 | ||
6325 | if (ket == OP_KETRMIN) | |
6326 | { | |
6327 | if (needs_control_head) | |
6328 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | |
6329 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); | |
6330 | if (BACKTRACK_AS(bracket_backtrack)->u.framesize == no_frame) | |
6331 | OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, needs_control_head ? (2 * sizeof(sljit_sw)) : sizeof(sljit_sw)); | |
6332 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize + 1), TMP2, 0); | |
6333 | } | |
6334 | else if (ket == OP_KETRMAX || has_alternatives) | |
6335 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); | |
6336 | } | } |
6337 | else | else |
6338 | { | { |
6339 | if (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) | if (ket != OP_KET || has_alternatives) |
6340 | stacksize++; | |
6341 | ||
6342 | stacksize += BACKTRACK_AS(bracket_backtrack)->u.framesize + 1; | |
6343 | allocate_stack(common, stacksize); | |
6344 | ||
6345 | if (needs_control_head) | |
6346 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); | |
6347 | ||
6348 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | |
6349 | OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, stacksize * sizeof(sljit_sw)); | |
6350 | ||
6351 | stacksize = needs_control_head ? 1 : 0; | |
6352 | if (ket != OP_KET || has_alternatives) | |
6353 | { | { |
6354 | allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 2); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | ||
OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize + 1)); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | ||
6355 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); |
6356 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0); | stacksize++; |
6357 | init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1, 2, FALSE); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); |
6358 | } | } |
6359 | else | else |
6360 | { | { |
allocate_stack(common, BACKTRACK_AS(bracket_backtrack)->u.framesize + 1); | ||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | ||
OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(BACKTRACK_AS(bracket_backtrack)->u.framesize)); | ||
6361 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); |
6362 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0); |
init_frame(common, ccbegin, BACKTRACK_AS(bracket_backtrack)->u.framesize, 1, FALSE); | ||
6363 | } | } |
6364 | init_frame(common, ccbegin, NULL, BACKTRACK_AS(bracket_backtrack)->u.framesize + stacksize, stacksize + 1, FALSE); | |
6365 | } | } |
6366 | } | } |
6367 | else if (opcode == OP_CBRA || opcode == OP_SCBRA) | else if (opcode == OP_CBRA || opcode == OP_SCBRA) |
6368 | { | { |
6369 | /* Saving the previous values. */ | /* Saving the previous values. */ |
6370 | if (common->optimized_cbracket[offset >> 1] == 0) | if (common->optimized_cbracket[offset >> 1] != 0) |
{ | ||
allocate_stack(common, 3); | ||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); | ||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); | ||
} | ||
else | ||
6371 | { | { |
6372 | SLJIT_ASSERT(private_data_ptr == OVECTOR(offset)); | SLJIT_ASSERT(private_data_ptr == OVECTOR(offset)); |
6373 | allocate_stack(common, 2); | allocate_stack(common, 2); |
# | Line 5730 else if (opcode == OP_CBRA || opcode == | Line 6377 else if (opcode == OP_CBRA || opcode == |
6377 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); |
6378 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); |
6379 | } | } |
6380 | else | |
6381 | { | |
6382 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | |
6383 | allocate_stack(common, 1); | |
6384 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STR_PTR, 0); | |
6385 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); | |
6386 | } | |
6387 | } | } |
6388 | else if (opcode == OP_SBRA || opcode == OP_SCOND) | else if (opcode == OP_SBRA || opcode == OP_SCOND) |
6389 | { | { |
# | Line 5765 if (opcode == OP_COND || opcode == OP_SC | Line 6419 if (opcode == OP_COND || opcode == OP_SC |
6419 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); |
6420 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); |
6421 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); |
6422 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, (stacksize << 8) | (common->ovector_start / sizeof(sljit_sw))); | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG1, 0, SLJIT_IMM, (stacksize << 8) | (common->ovector_start / sizeof(sljit_sw))); |
6423 | GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0); | GET_LOCAL_BASE(SLJIT_SCRATCH_REG2, 0, 0); |
6424 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, common->name_table); |
6425 | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector)); | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector)); |
6426 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); |
6427 | add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); | add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG1, 0, SLJIT_IMM, 0)); |
6428 | ||
6429 | JUMPHERE(jump); | JUMPHERE(jump); |
6430 | matchingpath += 1 + IMM2_SIZE; | matchingpath += 1 + IMM2_SIZE; |
# | Line 5815 if (opcode == OP_COND || opcode == OP_SC | Line 6469 if (opcode == OP_COND || opcode == OP_SC |
6469 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); |
6470 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); |
6471 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE)); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE)); |
6472 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize); | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG1, 0, SLJIT_IMM, stacksize); |
6473 | GET_LOCAL_BASE(SLJIT_TEMPORARY_REG2, 0, 0); | GET_LOCAL_BASE(SLJIT_SCRATCH_REG2, 0, 0); |
6474 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); | OP1(SLJIT_MOV, SLJIT_SCRATCH_REG3, 0, SLJIT_IMM, common->name_table); |
6475 | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups)); | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups)); |
6476 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); |
6477 | add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); | add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_SCRATCH_REG1, 0, SLJIT_IMM, 0)); |
6478 | matchingpath += 1 + IMM2_SIZE; | matchingpath += 1 + IMM2_SIZE; |
6479 | } | } |
6480 | } | } |
# | Line 5843 if (SLJIT_UNLIKELY(sljit_get_compiler_er | Line 6497 if (SLJIT_UNLIKELY(sljit_get_compiler_er |
6497 | return NULL; | return NULL; |
6498 | ||
6499 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
6500 | { | match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); |
if (BACKTRACK_AS(bracket_backtrack)->u.framesize < 0) | ||
{ | ||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | ||
/* TMP2 which is set here used by OP_KETRMAX below. */ | ||
if (ket == OP_KETRMAX) | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0); | ||
else if (ket == OP_KETRMIN) | ||
{ | ||
/* Move the STR_PTR to the private_data_ptr. */ | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0); | ||
} | ||
} | ||
else | ||
{ | ||
stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1; | ||
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)); | ||
if (ket == OP_KETRMAX) | ||
{ | ||
/* TMP2 which is set here used by OP_KETRMAX below. */ | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | ||
} | ||
} | ||
} | ||
6501 | ||
6502 | stacksize = 0; | stacksize = 0; |
6503 | if (ket != OP_KET || bra != OP_BRA) | if (ket != OP_KET || bra != OP_BRA) |
6504 | stacksize++; | stacksize++; |
6505 | if (offset != 0) | |
6506 | { | |
6507 | if (common->capture_last_ptr != 0) | |
6508 | stacksize++; | |
6509 | if (common->optimized_cbracket[offset >> 1] == 0) | |
6510 | stacksize += 2; | |
6511 | } | |
6512 | if (has_alternatives && opcode != OP_ONCE) | if (has_alternatives && opcode != OP_ONCE) |
6513 | stacksize++; | stacksize++; |
6514 | ||
# | Line 5878 if (stacksize > 0) | Line 6516 if (stacksize > 0) |
6516 | allocate_stack(common, stacksize); | allocate_stack(common, stacksize); |
6517 | ||
6518 | stacksize = 0; | stacksize = 0; |
6519 | if (ket != OP_KET) | if (ket != OP_KET || bra != OP_BRA) |
{ | ||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); | ||
stacksize++; | ||
} | ||
else if (bra != OP_BRA) | ||
6520 | { | { |
6521 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); | if (ket != OP_KET) |
6522 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), STR_PTR, 0); | |
6523 | else | |
6524 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0); | |
6525 | stacksize++; | stacksize++; |
6526 | } | } |
6527 | ||
6528 | if (offset != 0) | |
6529 | stacksize = match_capture_common(common, stacksize, offset, private_data_ptr); | |
6530 | ||
6531 | if (has_alternatives) | if (has_alternatives) |
6532 | { | { |
6533 | if (opcode != OP_ONCE) | if (opcode != OP_ONCE) |
# | Line 5898 if (has_alternatives) | Line 6537 if (has_alternatives) |
6537 | } | } |
6538 | ||
6539 | /* Must be after the matchingpath label. */ | /* Must be after the matchingpath label. */ |
6540 | if (offset != 0) | if (offset != 0 && common->optimized_cbracket[offset >> 1] != 0) |
6541 | { | { |
6542 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0)); |
6543 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0); | ||
6544 | } | } |
6545 | ||
6546 | if (ket == OP_KETRMAX) | if (ket == OP_KETRMAX) |
# | Line 5959 if ((ket != OP_KET && bra != OP_BRAMINZE | Line 6597 if ((ket != OP_KET && bra != OP_BRAMINZE |
6597 | while (*cc == OP_ALT) | while (*cc == OP_ALT) |
6598 | cc += GET(cc, 1); | cc += GET(cc, 1); |
6599 | cc += 1 + LINK_SIZE; | cc += 1 + LINK_SIZE; |
6600 | ||
6601 | /* Temporarily encoding the needs_control_head in framesize. */ | |
6602 | if (opcode == OP_ONCE) | |
6603 | BACKTRACK_AS(bracket_backtrack)->u.framesize = (BACKTRACK_AS(bracket_backtrack)->u.framesize << 1) | (needs_control_head ? 1 : 0); | |
6604 | return cc; | return cc; |
6605 | } | } |
6606 | ||
# | Line 5969 backtrack_common *backtrack; | Line 6611 backtrack_common *backtrack; |
6611 | pcre_uchar opcode; | pcre_uchar opcode; |
6612 | int private_data_ptr; | int private_data_ptr; |
6613 | int cbraprivptr = 0; | int cbraprivptr = 0; |
6614 | BOOL needs_control_head; | |
6615 | int framesize; | int framesize; |
6616 | int stacksize; | int stacksize; |
6617 | int offset = 0; | int offset = 0; |
6618 | BOOL zero = FALSE; | BOOL zero = FALSE; |
6619 | pcre_uchar *ccbegin = NULL; | pcre_uchar *ccbegin = NULL; |
6620 | int stack; | int stack; /* Also contains the offset of control head. */ |
6621 | struct sljit_label *loop = NULL; | struct sljit_label *loop = NULL; |
6622 | struct jump_list *emptymatch = NULL; | struct jump_list *emptymatch = NULL; |
6623 | ||
# | Line 6012 switch(opcode) | Line 6655 switch(opcode) |
6655 | break; | break; |
6656 | } | } |
6657 | ||
6658 | framesize = get_framesize(common, cc, FALSE); | framesize = get_framesize(common, cc, NULL, FALSE, &needs_control_head); |
6659 | BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize; | BACKTRACK_AS(bracketpos_backtrack)->framesize = framesize; |
6660 | if (framesize < 0) | if (framesize < 0) |
6661 | { | { |
6662 | stacksize = (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) ? 2 : 1; | if (offset != 0) |
6663 | { | |
6664 | stacksize = 2; | |
6665 | if (common->capture_last_ptr != 0) | |
6666 | stacksize++; | |
6667 | } | |
6668 | else | |
6669 | stacksize = 1; | |
6670 | ||
6671 | if (needs_control_head) | |
6672 | stacksize++; | |
6673 | if (!zero) | if (!zero) |
6674 | stacksize++; | stacksize++; |
6675 | ||
6676 | BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; | BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; |
6677 | allocate_stack(common, stacksize); | allocate_stack(common, stacksize); |
6678 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); | if (framesize == no_frame) |
6679 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0); | |
6680 | ||
6681 | if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) | stack = 0; |
6682 | if (offset != 0) | |
6683 | { | { |
6684 | stack = 2; | |
6685 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
6686 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1)); |
6687 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); |
6688 | if (common->capture_last_ptr != 0) | |
6689 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr); | |
6690 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP2, 0); |
6691 | if (needs_control_head) | |
6692 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); | |
6693 | if (common->capture_last_ptr != 0) | |
6694 | { | |
6695 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0); | |
6696 | stack = 3; | |
6697 | } | |
6698 | } | } |
6699 | else | else |
6700 | { | |
6701 | if (needs_control_head) | |
6702 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); | |
6703 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); |
6704 | stack = 1; | |
6705 | } | |
6706 | ||
6707 | if (needs_control_head) | |
6708 | stack++; | |
6709 | if (!zero) | if (!zero) |
6710 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 1); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), SLJIT_IMM, 1); |
6711 | if (needs_control_head) | |
6712 | { | |
6713 | stack--; | |
6714 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0); | |
6715 | } | |
6716 | } | } |
6717 | else | else |
6718 | { | { |
6719 | stacksize = framesize + 1; | stacksize = framesize + 1; |
6720 | if (!zero) | if (!zero) |
6721 | stacksize++; | stacksize++; |
6722 | if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) | if (needs_control_head) |
6723 | stacksize++; | |
6724 | if (offset == 0) | |
6725 | stacksize++; | stacksize++; |
6726 | BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; | BACKTRACK_AS(bracketpos_backtrack)->stacksize = stacksize; |
allocate_stack(common, stacksize); | ||
6727 | ||
6728 | allocate_stack(common, stacksize); | |
6729 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); |
6730 | OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1)); | if (needs_control_head) |
6731 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP2, 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); |
6732 | OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, STACK_TOP, 0, SLJIT_IMM, -STACK(stacksize - 1)); | |
6733 | ||
6734 | stack = 0; | stack = 0; |
6735 | if (!zero) | if (!zero) |
6736 | { | { |
6737 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 1); |
6738 | stack = 1; | |
6739 | } | |
6740 | if (needs_control_head) | |
6741 | { | |
6742 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP2, 0); | |
6743 | stack++; | stack++; |
6744 | } | } |
6745 | if (opcode == OP_BRAPOS || opcode == OP_SBRAPOS) | if (offset == 0) |
6746 | { | { |
6747 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), STR_PTR, 0); |
6748 | stack++; | stack++; |
6749 | } | } |
6750 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stack), TMP1, 0); |
6751 | init_frame(common, cc, stacksize - 1, stacksize - framesize, FALSE); | init_frame(common, cc, NULL, stacksize - 1, stacksize - framesize, FALSE); |
6752 | stack -= 1 + (offset == 0); | |
6753 | } | } |
6754 | ||
6755 | if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) | if (offset != 0) |
6756 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); |
6757 | ||
6758 | loop = LABEL(); | loop = LABEL(); |
# | Line 6080 while (*cc != OP_KETRPOS) | Line 6768 while (*cc != OP_KETRPOS) |
6768 | ||
6769 | if (framesize < 0) | if (framesize < 0) |
6770 | { | { |
6771 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | if (framesize == no_frame) |
6772 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | |
6773 | ||
6774 | if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) | if (offset != 0) |
6775 | { | { |
6776 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); |
6777 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); |
6778 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); |
6779 | if (common->capture_last_ptr != 0) | |
6780 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1); | |
6781 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); |
6782 | } | } |
6783 | else | else |
# | Line 6104 while (*cc != OP_KETRPOS) | Line 6795 while (*cc != OP_KETRPOS) |
6795 | } | } |
6796 | else | else |
6797 | { | { |
6798 | if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) | if (offset != 0) |
6799 | { | { |
6800 | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw)); | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_IMM, stacksize * sizeof(sljit_sw)); |
6801 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); |
6802 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); |
6803 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); |
6804 | if (common->capture_last_ptr != 0) | |
6805 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, SLJIT_IMM, offset >> 1); | |
6806 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); |
6807 | } | } |
6808 | else | else |
# | Line 6132 while (*cc != OP_KETRPOS) | Line 6825 while (*cc != OP_KETRPOS) |
6825 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
6826 | } | } |
6827 | } | } |
6828 | ||
6829 | if (needs_control_head) | |
6830 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); | |
6831 | ||
6832 | JUMPTO(SLJIT_JUMP, loop); | JUMPTO(SLJIT_JUMP, loop); |
6833 | flush_stubs(common); | flush_stubs(common); |
6834 | ||
# | Line 6142 while (*cc != OP_KETRPOS) | Line 6839 while (*cc != OP_KETRPOS) |
6839 | ||
6840 | if (framesize < 0) | if (framesize < 0) |
6841 | { | { |
6842 | if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) | if (offset != 0) |
6843 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); |
6844 | else | else |
6845 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
6846 | } | } |
6847 | else | else |
6848 | { | { |
6849 | if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) | if (offset != 0) |
6850 | { | { |
6851 | /* Last alternative. */ | /* Last alternative. */ |
6852 | if (*cc == OP_KETRPOS) | if (*cc == OP_KETRPOS) |
# | Line 6168 while (*cc != OP_KETRPOS) | Line 6865 while (*cc != OP_KETRPOS) |
6865 | ccbegin = cc + 1 + LINK_SIZE; | ccbegin = cc + 1 + LINK_SIZE; |
6866 | } | } |
6867 | ||
6868 | /* We don't have to restore the control head in case of a failed match. */ | |
6869 | ||
6870 | backtrack->topbacktracks = NULL; | backtrack->topbacktracks = NULL; |
6871 | if (!zero) | if (!zero) |
6872 | { | { |
# | Line 6296 PUSH_BACKTRACK(sizeof(iterator_backtrack | Line 6995 PUSH_BACKTRACK(sizeof(iterator_backtrack |
6995 | ||
6996 | cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end); | cc = get_iterator_parameters(common, cc, &opcode, &type, &arg1, &arg2, &end); |
6997 | ||
6998 | switch (type) | switch(type) |
6999 | { | { |
7000 | case OP_NOT_DIGIT: | case OP_NOT_DIGIT: |
7001 | case OP_DIGIT: | case OP_DIGIT: |
# | Line 6498 static SLJIT_INLINE pcre_uchar *compile_ | Line 7197 static SLJIT_INLINE pcre_uchar *compile_ |
7197 | DEFINE_COMPILER; | DEFINE_COMPILER; |
7198 | backtrack_common *backtrack; | backtrack_common *backtrack; |
7199 | ||
7200 | PUSH_BACKTRACK(sizeof(bracket_backtrack), cc, NULL); | PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); |
7201 | ||
7202 | if (*cc == OP_FAIL) | if (*cc == OP_FAIL) |
7203 | { | { |
# | Line 6509 if (*cc == OP_FAIL) | Line 7208 if (*cc == OP_FAIL) |
7208 | if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL) | if (*cc == OP_ASSERT_ACCEPT || common->currententry != NULL) |
7209 | { | { |
7210 | /* No need to check notempty conditions. */ | /* No need to check notempty conditions. */ |
7211 | if (common->acceptlabel == NULL) | if (common->accept_label == NULL) |
7212 | add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); | add_jump(compiler, &common->accept, JUMP(SLJIT_JUMP)); |
7213 | else | else |
7214 | JUMPTO(SLJIT_JUMP, common->acceptlabel); | JUMPTO(SLJIT_JUMP, common->accept_label); |
7215 | return cc + 1; | return cc + 1; |
7216 | } | } |
7217 | ||
7218 | if (common->acceptlabel == NULL) | if (common->accept_label == NULL) |
7219 | add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0))); | add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0))); |
7220 | else | else |
7221 | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->acceptlabel); | CMPTO(SLJIT_C_NOT_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(0), common->accept_label); |
7222 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
7223 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty)); |
7224 | add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
7225 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, notempty_atstart)); |
7226 | if (common->acceptlabel == NULL) | if (common->accept_label == NULL) |
7227 | add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | add_jump(compiler, &common->accept, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
7228 | else | else |
7229 | CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->acceptlabel); | CMPTO(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0, common->accept_label); |
7230 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); |
7231 | if (common->acceptlabel == NULL) | if (common->accept_label == NULL) |
7232 | add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0)); | add_jump(compiler, &common->accept, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0)); |
7233 | else | else |
7234 | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->acceptlabel); | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_PTR, 0, common->accept_label); |
7235 | add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); | add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_JUMP)); |
7236 | return cc + 1; | return cc + 1; |
7237 | } | } |
# | Line 6556 if (!optimized_cbracket) | Line 7255 if (!optimized_cbracket) |
7255 | return cc + 1 + IMM2_SIZE; | return cc + 1 + IMM2_SIZE; |
7256 | } | } |
7257 | ||
7258 | static SLJIT_INLINE pcre_uchar *compile_control_verb_matchingpath(compiler_common *common, pcre_uchar *cc, backtrack_common *parent) | |
7259 | { | |
7260 | DEFINE_COMPILER; | |
7261 | backtrack_common *backtrack; | |
7262 | pcre_uchar opcode = *cc; | |
7263 | pcre_uchar *ccend = cc + 1; | |
7264 | ||
7265 | if (opcode == OP_PRUNE_ARG || opcode == OP_SKIP_ARG || opcode == OP_THEN_ARG) | |
7266 | ccend += 2 + cc[1]; | |
7267 | ||
7268 | PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL); | |
7269 | ||
7270 | if (opcode == OP_SKIP) | |
7271 | { | |
7272 | allocate_stack(common, 1); | |
7273 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | |
7274 | return ccend; | |
7275 | } | |
7276 | ||
7277 | if (opcode == OP_PRUNE_ARG || opcode == OP_THEN_ARG) | |
7278 | { | |
7279 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | |
7280 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2)); | |
7281 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); | |
7282 | OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); | |
7283 | } | |
7284 | ||
7285 | return ccend; | |
7286 | } | |
7287 | ||
7288 | static pcre_uchar then_trap_opcode[1] = { OP_THEN_TRAP }; | |
7289 | ||
7290 | static SLJIT_INLINE void compile_then_trap_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) | |
7291 | { | |
7292 | DEFINE_COMPILER; | |
7293 | backtrack_common *backtrack; | |
7294 | BOOL needs_control_head; | |
7295 | int size; | |
7296 | ||
7297 | PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc); | |
7298 | common->then_trap = BACKTRACK_AS(then_trap_backtrack); | |
7299 | BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode; | |
7300 | BACKTRACK_AS(then_trap_backtrack)->start = (sljit_sw)(cc - common->start); | |
7301 | BACKTRACK_AS(then_trap_backtrack)->framesize = get_framesize(common, cc, ccend, FALSE, &needs_control_head); | |
7302 | ||
7303 | size = BACKTRACK_AS(then_trap_backtrack)->framesize; | |
7304 | size = 3 + (size < 0 ? 0 : size); | |
7305 | ||
7306 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); | |
7307 | allocate_stack(common, size); | |
7308 | if (size > 3) | |
7309 | OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0, SLJIT_IMM, (size - 3) * sizeof(sljit_sw)); | |
7310 | else | |
7311 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0); | |
7312 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 1), SLJIT_IMM, BACKTRACK_AS(then_trap_backtrack)->start); | |
7313 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 2), SLJIT_IMM, type_then_trap); | |
7314 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(size - 3), TMP2, 0); | |
7315 | ||
7316 | size = BACKTRACK_AS(then_trap_backtrack)->framesize; | |
7317 | if (size >= 0) | |
7318 | init_frame(common, cc, ccend, size - 1, 0, FALSE); | |
7319 | } | |
7320 | ||
7321 | static void compile_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) | static void compile_matchingpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, backtrack_common *parent) |
7322 | { | { |
7323 | DEFINE_COMPILER; | DEFINE_COMPILER; |
7324 | backtrack_common *backtrack; | backtrack_common *backtrack; |
7325 | BOOL has_then_trap = FALSE; | |
7326 | then_trap_backtrack *save_then_trap = NULL; | |
7327 | ||
7328 | SLJIT_ASSERT(*ccend == OP_END || (*ccend >= OP_ALT && *ccend <= OP_KETRPOS)); | |
7329 | ||
7330 | if (common->has_then && common->then_offsets[cc - common->start] != 0) | |
7331 | { | |
7332 | SLJIT_ASSERT(*ccend != OP_END && common->control_head_ptr != 0); | |
7333 | has_then_trap = TRUE; | |
7334 | save_then_trap = common->then_trap; | |
7335 | /* Tail item on backtrack. */ | |
7336 | compile_then_trap_matchingpath(common, cc, ccend, parent); | |
7337 | } | |
7338 | ||
7339 | while (cc < ccend) | while (cc < ccend) |
7340 | { | { |
# | Line 6712 while (cc < ccend) | Line 7487 while (cc < ccend) |
7487 | cc = compile_recurse_matchingpath(common, cc, parent); | cc = compile_recurse_matchingpath(common, cc, parent); |
7488 | break; | break; |
7489 | ||
7490 | case OP_CALLOUT: | |
7491 | cc = compile_callout_matchingpath(common, cc, parent); | |
7492 | break; | |
7493 | ||
7494 | case OP_ASSERT: | case OP_ASSERT: |
7495 | case OP_ASSERT_NOT: | case OP_ASSERT_NOT: |
7496 | case OP_ASSERTBACK: | case OP_ASSERTBACK: |
# | Line 6772 while (cc < ccend) | Line 7551 while (cc < ccend) |
7551 | PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); | PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); |
7552 | SLJIT_ASSERT(common->mark_ptr != 0); | SLJIT_ASSERT(common->mark_ptr != 0); |
7553 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr); |
7554 | allocate_stack(common, 1); | allocate_stack(common, common->has_skip_arg ? 5 : 1); |
7555 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
7556 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(common->has_skip_arg ? 4 : 0), TMP2, 0); |
7557 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)(cc + 2)); |
7558 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mark_ptr, TMP2, 0); |
7559 | OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, mark_ptr), TMP2, 0); |
7560 | if (common->has_skip_arg) | |
7561 | { | |
7562 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); | |
7563 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr, STACK_TOP, 0); | |
7564 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, type_mark); | |
7565 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), SLJIT_IMM, (sljit_sw)(cc + 2)); | |
7566 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(3), STR_PTR, 0); | |
7567 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP1, 0); | |
7568 | } | |
7569 | cc += 1 + 2 + cc[1]; | cc += 1 + 2 + cc[1]; |
7570 | break; | break; |
7571 | ||
7572 | case OP_PRUNE: | |
7573 | case OP_PRUNE_ARG: | |
7574 | case OP_SKIP: | |
7575 | case OP_SKIP_ARG: | |
7576 | case OP_THEN: | |
7577 | case OP_THEN_ARG: | |
7578 | case OP_COMMIT: | case OP_COMMIT: |
7579 | PUSH_BACKTRACK_NOVALUE(sizeof(backtrack_common), cc); | cc = compile_control_verb_matchingpath(common, cc, parent); |
cc += 1; | ||
7580 | break; | break; |
7581 | ||
7582 | case OP_FAIL: | case OP_FAIL: |
# | Line 6807 while (cc < ccend) | Line 7600 while (cc < ccend) |
7600 | if (cc == NULL) | if (cc == NULL) |
7601 | return; | return; |
7602 | } | } |
7603 | ||
7604 | if (has_then_trap) | |
7605 | { | |
7606 | /* Head item on backtrack. */ | |
7607 | PUSH_BACKTRACK_NOVALUE(sizeof(then_trap_backtrack), cc); | |
7608 | BACKTRACK_AS(then_trap_backtrack)->common.cc = then_trap_opcode; | |
7609 | BACKTRACK_AS(then_trap_backtrack)->then_trap = common->then_trap; | |
7610 | common->then_trap = save_then_trap; | |
7611 | } | |
7612 | SLJIT_ASSERT(cc == ccend); | SLJIT_ASSERT(cc == ccend); |
7613 | } | } |
7614 | ||
# | Line 6968 switch(opcode) | Line 7770 switch(opcode) |
7770 | } | } |
7771 | } | } |
7772 | ||
7773 | static void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current) | static SLJIT_INLINE void compile_ref_iterator_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
7774 | { | { |
7775 | DEFINE_COMPILER; | DEFINE_COMPILER; |
7776 | pcre_uchar *cc = current->cc; | pcre_uchar *cc = current->cc; |
# | Line 6990 set_jumps(current->topbacktracks, LABEL( | Line 7792 set_jumps(current->topbacktracks, LABEL( |
7792 | free_stack(common, 2); | free_stack(common, 2); |
7793 | } | } |
7794 | ||
7795 | static void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current) | static SLJIT_INLINE void compile_recurse_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
7796 | { | { |
7797 | DEFINE_COMPILER; | DEFINE_COMPILER; |
7798 | ||
7799 | if (CURRENT_AS(recurse_backtrack)->inlined_pattern) | |
7800 | compile_backtrackingpath(common, current->top); | |
7801 | set_jumps(current->topbacktracks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
7802 | if (CURRENT_AS(recurse_backtrack)->inlined_pattern) | |
7803 | return; | |
7804 | ||
7805 | if (common->has_set_som && common->mark_ptr != 0) | if (common->has_set_som && common->mark_ptr != 0) |
7806 | { | { |
# | Line 7096 pcre_uchar bra = OP_BRA; | Line 7902 pcre_uchar bra = OP_BRA; |
7902 | pcre_uchar ket; | pcre_uchar ket; |
7903 | assert_backtrack *assert; | assert_backtrack *assert; |
7904 | BOOL has_alternatives; | BOOL has_alternatives; |
7905 | BOOL needs_control_head = FALSE; | |
7906 | struct sljit_jump *brazero = NULL; | struct sljit_jump *brazero = NULL; |
7907 | struct sljit_jump *once = NULL; | struct sljit_jump *once = NULL; |
7908 | struct sljit_jump *cond = NULL; | struct sljit_jump *cond = NULL; |
# | Line 7121 if (SLJIT_UNLIKELY(opcode == OP_COND) && | Line 7928 if (SLJIT_UNLIKELY(opcode == OP_COND) && |
7928 | if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) | if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) |
7929 | opcode = OP_ONCE; | opcode = OP_ONCE; |
7930 | ||
7931 | /* Decoding the needs_control_head in framesize. */ | |
7932 | if (opcode == OP_ONCE) | |
7933 | { | |
7934 | needs_control_head = (CURRENT_AS(bracket_backtrack)->u.framesize & 0x1) != 0; | |
7935 | CURRENT_AS(bracket_backtrack)->u.framesize >>= 1; | |
7936 | } | |
7937 | ||
7938 | if (ket == OP_KETRMAX) | if (ket == OP_KETRMAX) |
7939 | { | { |
7940 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
# | Line 7160 else if (bra == OP_BRAZERO) | Line 7974 else if (bra == OP_BRAZERO) |
7974 | brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); | brazero = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); |
7975 | } | } |
7976 | ||
7977 | if (offset != 0) | |
7978 | { | |
7979 | if (common->capture_last_ptr != 0) | |
7980 | { | |
7981 | SLJIT_ASSERT(common->optimized_cbracket[offset >> 1] == 0); | |
7982 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | |
7983 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | |
7984 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, TMP1, 0); | |
7985 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); | |
7986 | free_stack(common, 3); | |
7987 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP2, 0); | |
7988 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0); | |
7989 | } | |
7990 | else if (common->optimized_cbracket[offset >> 1] == 0) | |
7991 | { | |
7992 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | |
7993 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | |
7994 | free_stack(common, 2); | |
7995 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); | |
7996 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); | |
7997 | } | |
7998 | } | |
7999 | ||
8000 | if (SLJIT_UNLIKELY(opcode == OP_ONCE)) | if (SLJIT_UNLIKELY(opcode == OP_ONCE)) |
8001 | { | { |
8002 | if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) | if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) |
# | Line 7255 if (has_alternatives) | Line 8092 if (has_alternatives) |
8092 | current->top = NULL; | current->top = NULL; |
8093 | current->topbacktracks = NULL; | current->topbacktracks = NULL; |
8094 | current->nextbacktracks = NULL; | current->nextbacktracks = NULL; |
8095 | /* Conditional blocks always have an additional alternative, even if it is empty. */ | |
8096 | if (*cc == OP_ALT) | if (*cc == OP_ALT) |
8097 | { | { |
8098 | ccprev = cc + 1 + LINK_SIZE; | ccprev = cc + 1 + LINK_SIZE; |
8099 | cc += GET(cc, 1); | cc += GET(cc, 1); |
8100 | if (opcode != OP_COND && opcode != OP_SCOND) | if (opcode != OP_COND && opcode != OP_SCOND) |
8101 | { | { |
8102 | if (private_data_ptr != 0 && opcode != OP_ONCE) | if (opcode != OP_ONCE) |
8103 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | { |
8104 | if (private_data_ptr != 0) | |
8105 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | |
8106 | else | |
8107 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | |
8108 | } | |
8109 | else | else |
8110 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(needs_control_head ? 1 : 0)); |
8111 | } | } |
8112 | compile_matchingpath(common, ccprev, cc, current); | compile_matchingpath(common, ccprev, cc, current); |
8113 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
# | Line 7274 if (has_alternatives) | Line 8117 if (has_alternatives) |
8117 | /* Instructions after the current alternative is succesfully matched. */ | /* Instructions after the current alternative is succesfully matched. */ |
8118 | /* There is a similar code in compile_bracket_matchingpath. */ | /* There is a similar code in compile_bracket_matchingpath. */ |
8119 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
8120 | { | match_once_common(common, ket, CURRENT_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); |
if (CURRENT_AS(bracket_backtrack)->u.framesize < 0) | ||
{ | ||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | ||
/* TMP2 which is set here used by OP_KETRMAX below. */ | ||
if (ket == OP_KETRMAX) | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), 0); | ||
else if (ket == OP_KETRMIN) | ||
{ | ||
/* Move the STR_PTR to the private_data_ptr. */ | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, SLJIT_MEM1(STACK_TOP), 0); | ||
} | ||
} | ||
else | ||
{ | ||
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)); | ||
if (ket == OP_KETRMAX) | ||
{ | ||
/* TMP2 which is set here used by OP_KETRMAX below. */ | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | ||
} | ||
} | ||
} | ||
8121 | ||
8122 | stacksize = 0; | stacksize = 0; |
if (opcode != OP_ONCE) | ||
stacksize++; | ||
8123 | if (ket != OP_KET || bra != OP_BRA) | if (ket != OP_KET || bra != OP_BRA) |
8124 | stacksize++; | stacksize++; |
8125 | if (offset != 0) | |
8126 | { | |
8127 | if (common->capture_last_ptr != 0) | |
8128 | stacksize++; | |
8129 | if (common->optimized_cbracket[offset >> 1] == 0) | |
8130 | stacksize += 2; | |
8131 | } | |
8132 | if (opcode != OP_ONCE) | |
8133 | stacksize++; | |
8134 | ||
8135 | if (stacksize > 0) { | if (stacksize > 0) |
8136 | { | |
8137 | if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0) | if (opcode != OP_ONCE || CURRENT_AS(bracket_backtrack)->u.framesize >= 0) |
8138 | allocate_stack(common, stacksize); | allocate_stack(common, stacksize); |
8139 | else | else |
# | Line 7313 if (has_alternatives) | Line 8142 if (has_alternatives) |
8142 | SLJIT_ASSERT(stacksize == 1); | SLJIT_ASSERT(stacksize == 1); |
8143 | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_sw)); |
8144 | } | } |
8145 | } | } |
8146 | ||
8147 | stacksize = 0; | stacksize = 0; |
8148 | if (ket != OP_KET || bra != OP_BRA) | if (ket != OP_KET || bra != OP_BRA) |
# | Line 7325 if (has_alternatives) | Line 8154 if (has_alternatives) |
8154 | stacksize++; | stacksize++; |
8155 | } | } |
8156 | ||
8157 | if (offset != 0) | |
8158 | stacksize = match_capture_common(common, stacksize, offset, private_data_ptr); | |
8159 | ||
8160 | if (opcode != OP_ONCE) | if (opcode != OP_ONCE) |
8161 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, count++); |
8162 | ||
8163 | if (offset != 0) | if (offset != 0 && ket == OP_KETRMAX && common->optimized_cbracket[offset >> 1] != 0) |
8164 | { | { |
8165 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr); | /* If ket is not OP_KETRMAX, this code path is executed after the jump to alternative_matchingpath. */ |
8166 | SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0)); | |
8167 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), STR_PTR, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 0), TMP1, 0); | ||
8168 | } | } |
8169 | ||
8170 | JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alternative_matchingpath); | JUMPTO(SLJIT_JUMP, CURRENT_AS(bracket_backtrack)->alternative_matchingpath); |
# | Line 7357 if (has_alternatives) | Line 8189 if (has_alternatives) |
8189 | SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND); | SLJIT_ASSERT(opcode == OP_COND || opcode == OP_SCOND); |
8190 | assert = CURRENT_AS(bracket_backtrack)->u.assert; | assert = CURRENT_AS(bracket_backtrack)->u.assert; |
8191 | if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0) | if ((ccbegin[1 + LINK_SIZE] == OP_ASSERT_NOT || ccbegin[1 + LINK_SIZE] == OP_ASSERTBACK_NOT) && assert->framesize >= 0) |
8192 | { | { |
8193 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), assert->private_data_ptr); |
8194 | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); |
# | Line 7374 if (has_alternatives) | Line 8205 if (has_alternatives) |
8205 | if (offset != 0) | if (offset != 0) |
8206 | { | { |
8207 | /* Using both tmp register is better for instruction scheduling. */ | /* Using both tmp register is better for instruction scheduling. */ |
8208 | if (common->optimized_cbracket[offset >> 1] == 0) | if (common->optimized_cbracket[offset >> 1] != 0) |
8209 | { | { |
8210 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8211 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); |
8212 | free_stack(common, 2); | |
8213 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); | ||
free_stack(common, 3); | ||
8214 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); | ||
8215 | } | } |
8216 | else | else |
8217 | { | { |
8218 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8219 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | free_stack(common, 1); |
8220 | free_stack(common, 2); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), private_data_ptr, TMP1, 0); |
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); | ||
8221 | } | } |
8222 | } | } |
8223 | else if (opcode == OP_SBRA || opcode == OP_SCOND) | else if (opcode == OP_SBRA || opcode == OP_SCOND) |
# | Line 7401 else if (opcode == OP_SBRA || opcode == | Line 8228 else if (opcode == OP_SBRA || opcode == |
8228 | else if (opcode == OP_ONCE) | else if (opcode == OP_ONCE) |
8229 | { | { |
8230 | cc = ccbegin + GET(ccbegin, 1); | cc = ccbegin + GET(ccbegin, 1); |
8231 | stacksize = needs_control_head ? 1 : 0; | |
8232 | ||
8233 | if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) | if (CURRENT_AS(bracket_backtrack)->u.framesize >= 0) |
8234 | { | { |
8235 | /* Reset head and drop saved frame. */ | /* Reset head and drop saved frame. */ |
8236 | stacksize = (ket == OP_KETRMAX || ket == OP_KETRMIN || *cc == OP_ALT) ? 2 : 1; | stacksize += CURRENT_AS(bracket_backtrack)->u.framesize + ((ket != OP_KET || *cc == OP_ALT) ? 2 : 1); |
free_stack(common, CURRENT_AS(bracket_backtrack)->u.framesize + stacksize); | ||
8237 | } | } |
8238 | else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN)) | else if (ket == OP_KETRMAX || (*cc == OP_ALT && ket != OP_KETRMIN)) |
8239 | { | { |
8240 | /* The STR_PTR must be released. */ | /* The STR_PTR must be released. */ |
8241 | free_stack(common, 1); | stacksize++; |
8242 | } | } |
8243 | free_stack(common, stacksize); | |
8244 | ||
8245 | JUMPHERE(once); | JUMPHERE(once); |
8246 | /* Restore previous private_data_ptr */ | /* Restore previous private_data_ptr */ |
# | Line 7463 else if (bra == OP_BRAZERO) | Line 8292 else if (bra == OP_BRAZERO) |
8292 | } | } |
8293 | } | } |
8294 | ||
8295 | static void compile_bracketpos_backtrackingpath(compiler_common *common, struct backtrack_common *current) | static SLJIT_INLINE void compile_bracketpos_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
8296 | { | { |
8297 | DEFINE_COMPILER; | DEFINE_COMPILER; |
8298 | int offset; | int offset; |
# | Line 7477 if (CURRENT_AS(bracketpos_backtrack)->fr | Line 8306 if (CURRENT_AS(bracketpos_backtrack)->fr |
8306 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
8307 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); |
8308 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); |
8309 | if (common->capture_last_ptr != 0) | |
8310 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); | |
8311 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP2, 0); |
8312 | if (common->capture_last_ptr != 0) | |
8313 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), common->capture_last_ptr, TMP1, 0); | |
8314 | } | } |
8315 | set_jumps(current->topbacktracks, LABEL()); | set_jumps(current->topbacktracks, LABEL()); |
8316 | free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize); | free_stack(common, CURRENT_AS(bracketpos_backtrack)->stacksize); |
# | Line 7498 if (current->topbacktracks) | Line 8331 if (current->topbacktracks) |
8331 | 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)); | 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)); |
8332 | } | } |
8333 | ||
8334 | static void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current) | static SLJIT_INLINE void compile_braminzero_backtrackingpath(compiler_common *common, struct backtrack_common *current) |
8335 | { | { |
8336 | assert_backtrack backtrack; | assert_backtrack backtrack; |
8337 | ||
# | Line 7522 else | Line 8355 else |
8355 | SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks); | SLJIT_ASSERT(!current->nextbacktracks && !current->topbacktracks); |
8356 | } | } |
8357 | ||
8358 | static SLJIT_INLINE void compile_control_verb_backtrackingpath(compiler_common *common, struct backtrack_common *current) | |
8359 | { | |
8360 | DEFINE_COMPILER; | |
8361 | pcre_uchar opcode = *current->cc; | |
8362 | struct sljit_label *loop; | |
8363 | struct sljit_jump *jump; | |
8364 | ||
8365 | if (opcode == OP_THEN || opcode == OP_THEN_ARG) | |
8366 | { | |
8367 | if (common->then_trap != NULL) | |
8368 | { | |
8369 | SLJIT_ASSERT(common->control_head_ptr != 0); | |
8370 | ||
8371 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->control_head_ptr); | |
8372 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, type_then_trap); | |
8373 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, common->then_trap->start); | |
8374 | jump = JUMP(SLJIT_JUMP); | |
8375 | ||
8376 | loop = LABEL(); | |
8377 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(STACK_TOP), -(int)sizeof(sljit_sw)); | |
8378 | JUMPHERE(jump); | |