Parent Directory
|
Revision Log
|
Patch
revision 708 by ph10, Fri Sep 23 11:03:03 2011 UTC | revision 915 by zherczeg, Tue Feb 14 13:05:39 2012 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-2008 University of Cambridge | Copyright (c) 1997-2012 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-2011 | Copyright (c) 2010-2012 |
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 52 POSSIBILITY OF SUCH DAMAGE. | Line 52 POSSIBILITY OF SUCH DAMAGE. |
52 | we just include it. This way we don't need to touch the build | we just include it. This way we don't need to touch the build |
53 | system files. */ | system files. */ |
54 | ||
55 | #define SLJIT_MALLOC(size) (PUBL(malloc))(size) | |
56 | #define SLJIT_FREE(ptr) (PUBL(free))(ptr) | |
57 | #define SLJIT_CONFIG_AUTO 1 | #define SLJIT_CONFIG_AUTO 1 |
58 | #define SLJIT_CONFIG_STATIC 1 | |
59 | #define SLJIT_VERBOSE 0 | #define SLJIT_VERBOSE 0 |
60 | #define SLJIT_DEBUG 0 | #define SLJIT_DEBUG 0 |
61 | ||
62 | #include "sljit/sljitLir.c" | #include "sljit/sljitLir.c" |
63 | ||
64 | #if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED | #if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED |
65 | #error "Unsupported architecture" | #error Unsupported architecture |
66 | #endif | #endif |
67 | ||
68 | /* Allocate memory on the stack. Fast, but limited size. */ | /* Allocate memory on the stack. Fast, but limited size. */ |
# | Line 145 Thus we can restore the locals to a part | Line 148 Thus we can restore the locals to a part |
148 | typedef struct jit_arguments { | typedef struct jit_arguments { |
149 | /* Pointers first. */ | /* Pointers first. */ |
150 | struct sljit_stack *stack; | struct sljit_stack *stack; |
151 | PCRE_SPTR str; | const pcre_uchar *str; |
152 | PCRE_SPTR begin; | const pcre_uchar *begin; |
153 | PCRE_SPTR end; | const pcre_uchar *end; |
154 | int *offsets; | int *offsets; |
155 | uschar *ptr; | pcre_uchar *ptr; |
156 | /* Everything else after. */ | /* Everything else after. */ |
157 | int offsetcount; | int offsetcount; |
158 | int calllimit; | int calllimit; |
159 | uschar notbol; | pcre_uint8 notbol; |
160 | uschar noteol; | pcre_uint8 noteol; |
161 | uschar notempty; | pcre_uint8 notempty; |
162 | uschar notempty_atstart; | pcre_uint8 notempty_atstart; |
163 | } jit_arguments; | } jit_arguments; |
164 | ||
165 | typedef struct executable_function { | typedef struct executable_functions { |
166 | void *executable_func; | void *executable_funcs[JIT_NUMBER_OF_COMPILE_MODES]; |
167 | pcre_jit_callback callback; | PUBL(jit_callback) callback; |
168 | void *userdata; | void *userdata; |
169 | } executable_function; | sljit_uw executable_sizes[JIT_NUMBER_OF_COMPILE_MODES]; |
170 | } executable_functions; | |
171 | ||
172 | typedef struct jump_list { | typedef struct jump_list { |
173 | struct sljit_jump *jump; | struct sljit_jump *jump; |
# | Line 194 typedef struct fallback_common { | Line 198 typedef struct fallback_common { |
198 | struct fallback_common *top; | struct fallback_common *top; |
199 | jump_list *topfallbacks; | jump_list *topfallbacks; |
200 | /* Opcode pointer. */ | /* Opcode pointer. */ |
201 | uschar *cc; | pcre_uchar *cc; |
202 | } fallback_common; | } fallback_common; |
203 | ||
204 | typedef struct assert_fallback { | typedef struct assert_fallback { |
# | Line 265 typedef struct recurse_fallback { | Line 269 typedef struct recurse_fallback { |
269 | ||
270 | typedef struct compiler_common { | typedef struct compiler_common { |
271 | struct sljit_compiler *compiler; | struct sljit_compiler *compiler; |
272 | uschar *start; | pcre_uchar *start; |
273 | int localsize; | int localsize; |
274 | int *localptrs; | int *localptrs; |
275 | const uschar *fcc; | const pcre_uint8 *fcc; |
276 | sljit_w lcc; | sljit_w lcc; |
277 | int cbraptr; | int cbraptr; |
278 | int mode; | |
279 | int nltype; | int nltype; |
280 | int newline; | int newline; |
281 | int bsr_nltype; | int bsr_nltype; |
282 | int endonly; | int endonly; |
283 | sljit_w ctypes; | sljit_w ctypes; |
284 | sljit_uw name_table; | |
285 | sljit_w name_count; | |
286 | sljit_w name_entry_size; | |
287 | struct sljit_label *partialmatchlabel; | |
288 | struct sljit_label *acceptlabel; | struct sljit_label *acceptlabel; |
289 | stub_list *stubs; | stub_list *stubs; |
290 | recurse_entry *entries; | recurse_entry *entries; |
291 | recurse_entry *currententry; | recurse_entry *currententry; |
292 | jump_list *partialmatch; | |
293 | jump_list *accept; | jump_list *accept; |
294 | jump_list *calllimit; | jump_list *calllimit; |
295 | jump_list *stackalloc; | jump_list *stackalloc; |
# | Line 291 typedef struct compiler_common { | Line 301 typedef struct compiler_common { |
301 | jump_list *casefulcmp; | jump_list *casefulcmp; |
302 | jump_list *caselesscmp; | jump_list *caselesscmp; |
303 | BOOL jscript_compat; | BOOL jscript_compat; |
304 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
305 | BOOL utf8; | BOOL utf; |
306 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
307 | BOOL useucp; | BOOL use_ucp; |
308 | #endif | #endif |
309 | jump_list *utf8readchar; | jump_list *utfreadchar; |
310 | jump_list *utf8readtype8; | #ifdef COMPILE_PCRE8 |
311 | jump_list *utfreadtype8; | |
312 | #endif | #endif |
313 | #endif /* SUPPORT_UTF */ | |
314 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
315 | jump_list *getucd; | jump_list *getucd; |
316 | #endif | #endif |
# | Line 310 typedef struct compare_context { | Line 322 typedef struct compare_context { |
322 | int length; | int length; |
323 | int sourcereg; | int sourcereg; |
324 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED |
325 | int byteptr; | int ucharptr; |
326 | union { | union { |
327 | int asint; | sljit_i asint; |
328 | short asshort; | sljit_uh asushort; |
329 | #ifdef COMPILE_PCRE8 | |
330 | sljit_ub asbyte; | sljit_ub asbyte; |
331 | sljit_ub asbytes[4]; | sljit_ub asuchars[4]; |
332 | #else | |
333 | #ifdef COMPILE_PCRE16 | |
334 | sljit_uh asuchars[2]; | |
335 | #endif | |
336 | #endif | |
337 | } c; | } c; |
338 | union { | union { |
339 | int asint; | sljit_i asint; |
340 | short asshort; | sljit_uh asushort; |
341 | #ifdef COMPILE_PCRE8 | |
342 | sljit_ub asbyte; | sljit_ub asbyte; |
343 | sljit_ub asbytes[4]; | sljit_ub asuchars[4]; |
344 | #else | |
345 | #ifdef COMPILE_PCRE16 | |
346 | sljit_uh asuchars[2]; | |
347 | #endif | |
348 | #endif | |
349 | } oc; | } oc; |
350 | #endif | #endif |
351 | } compare_context; | } compare_context; |
# | Line 331 enum { | Line 355 enum { |
355 | frame_setstrbegin = -1 | frame_setstrbegin = -1 |
356 | }; | }; |
357 | ||
358 | /* Undefine sljit macros. */ | |
359 | #undef CMP | |
360 | ||
361 | /* Used for accessing the elements of the stack. */ | /* Used for accessing the elements of the stack. */ |
362 | #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w)) | #define STACK(i) ((-(i) - 1) * (int)sizeof(sljit_w)) |
363 | ||
364 | #define TMP1 SLJIT_TEMPORARY_REG1 | #define TMP1 SLJIT_TEMPORARY_REG1 |
365 | #define TMP2 SLJIT_TEMPORARY_REG3 | #define TMP2 SLJIT_TEMPORARY_REG3 |
366 | #define TMP3 SLJIT_TEMPORARY_EREG2 | #define TMP3 SLJIT_TEMPORARY_EREG2 |
367 | #define STR_PTR SLJIT_GENERAL_REG1 | #define STR_PTR SLJIT_SAVED_REG1 |
368 | #define STR_END SLJIT_GENERAL_REG2 | #define STR_END SLJIT_SAVED_REG2 |
369 | #define STACK_TOP SLJIT_TEMPORARY_REG2 | #define STACK_TOP SLJIT_TEMPORARY_REG2 |
370 | #define STACK_LIMIT SLJIT_GENERAL_REG3 | #define STACK_LIMIT SLJIT_SAVED_REG3 |
371 | #define ARGUMENTS SLJIT_GENERAL_EREG1 | #define ARGUMENTS SLJIT_SAVED_EREG1 |
372 | #define CALL_COUNT SLJIT_GENERAL_EREG2 | #define CALL_COUNT SLJIT_SAVED_EREG2 |
373 | #define RETURN_ADDR SLJIT_TEMPORARY_EREG1 | #define RETURN_ADDR SLJIT_TEMPORARY_EREG1 |
374 | ||
375 | /* Locals layout. */ | /* Locals layout. */ |
# | Line 352 enum { | Line 379 enum { |
379 | /* Two local variables for possessive quantifiers (char1 cannot use them). */ | /* Two local variables for possessive quantifiers (char1 cannot use them). */ |
380 | #define POSSESSIVE0 (2 * sizeof(sljit_w)) | #define POSSESSIVE0 (2 * sizeof(sljit_w)) |
381 | #define POSSESSIVE1 (3 * sizeof(sljit_w)) | #define POSSESSIVE1 (3 * sizeof(sljit_w)) |
/* Head of the saved local variables */ | ||
#define LOCALS_HEAD (4 * sizeof(sljit_w)) | ||
382 | /* Head of the last recursion. */ | /* Head of the last recursion. */ |
383 | #define RECURSIVE_HEAD (5 * sizeof(sljit_w)) | #define RECURSIVE_HEAD (4 * sizeof(sljit_w)) |
384 | /* Max limit of recursions. */ | /* Max limit of recursions. */ |
385 | #define CALL_LIMIT (7 * sizeof(sljit_w)) | #define CALL_LIMIT (5 * sizeof(sljit_w)) |
386 | /* Last known position of the requested byte. */ | /* Last known position of the requested byte. |
387 | #define REQ_BYTE_PTR (8 * sizeof(sljit_w)) | Same as START_USED_PTR. (Partial matching and req_char are exclusive) */ |
388 | #define REQ_CHAR_PTR (6 * sizeof(sljit_w)) | |
389 | /* First inspected character for partial matching. | |
390 | Same as REQ_CHAR_PTR. (Partial matching and req_char are exclusive) */ | |
391 | #define START_USED_PTR (6 * sizeof(sljit_w)) | |
392 | /* Starting pointer for partial soft matches. */ | |
393 | #define HIT_START (8 * sizeof(sljit_w)) | |
394 | /* End pointer of the first line. */ | /* End pointer of the first line. */ |
395 | #define FIRSTLINE_END (9 * sizeof(sljit_w)) | #define FIRSTLINE_END (9 * sizeof(sljit_w)) |
396 | /* The output vector is stored on the stack, and contains pointers | /* The output vector is stored on the stack, and contains pointers |
# | Line 369 the start pointers when the end of the c | Line 400 the start pointers when the end of the c |
400 | #define OVECTOR_START (10 * sizeof(sljit_w)) | #define OVECTOR_START (10 * sizeof(sljit_w)) |
401 | #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w)) | #define OVECTOR(i) (OVECTOR_START + (i) * sizeof(sljit_w)) |
402 | #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w)) | #define OVECTOR_PRIV(i) (common->cbraptr + (i) * sizeof(sljit_w)) |
403 | #define PRIV(cc) (common->localptrs[(cc) - common->start]) | #define PRIV_DATA(cc) (common->localptrs[(cc) - common->start]) |
404 | ||
405 | #ifdef COMPILE_PCRE8 | |
406 | #define MOV_UCHAR SLJIT_MOV_UB | |
407 | #define MOVU_UCHAR SLJIT_MOVU_UB | |
408 | #else | |
409 | #ifdef COMPILE_PCRE16 | |
410 | #define MOV_UCHAR SLJIT_MOV_UH | |
411 | #define MOVU_UCHAR SLJIT_MOVU_UH | |
412 | #else | |
413 | #error Unsupported compiling mode | |
414 | #endif | |
415 | #endif | |
416 | ||
417 | /* Shortcuts. */ | /* Shortcuts. */ |
418 | #define DEFINE_COMPILER \ | #define DEFINE_COMPILER \ |
# | Line 393 the start pointers when the end of the c | Line 436 the start pointers when the end of the c |
436 | #define COND_VALUE(op, dst, dstw, type) \ | #define COND_VALUE(op, dst, dstw, type) \ |
437 | sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type)) | sljit_emit_cond_value(compiler, (op), (dst), (dstw), (type)) |
438 | ||
439 | static uschar* bracketend(uschar* cc) | static pcre_uchar* bracketend(pcre_uchar* cc) |
440 | { | { |
441 | SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); | SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); |
442 | do cc += GET(cc, 1); while (*cc == OP_ALT); | do cc += GET(cc, 1); while (*cc == OP_ALT); |
# | Line 414 return cc; | Line 457 return cc; |
457 | compile_fallbackpath | compile_fallbackpath |
458 | */ | */ |
459 | ||
460 | static uschar *next_opcode(compiler_common *common, uschar *cc) | static pcre_uchar *next_opcode(compiler_common *common, pcre_uchar *cc) |
461 | { | { |
462 | SLJIT_UNUSED_ARG(common); | SLJIT_UNUSED_ARG(common); |
463 | switch(*cc) | switch(*cc) |
# | Line 469 switch(*cc) | Line 512 switch(*cc) |
512 | case OP_SKIPZERO: | case OP_SKIPZERO: |
513 | return cc + 1; | return cc + 1; |
514 | ||
515 | case OP_ANYBYTE: | |
516 | #ifdef SUPPORT_UTF | |
517 | if (common->utf) return NULL; | |
518 | #endif | |
519 | return cc + 1; | |
520 | ||
521 | case OP_CHAR: | case OP_CHAR: |
522 | case OP_CHARI: | case OP_CHARI: |
523 | case OP_NOT: | case OP_NOT: |
524 | case OP_NOTI: | case OP_NOTI: |
525 | case OP_STAR: | case OP_STAR: |
526 | case OP_MINSTAR: | case OP_MINSTAR: |
527 | case OP_PLUS: | case OP_PLUS: |
# | Line 511 switch(*cc) | Line 559 switch(*cc) |
559 | case OP_NOTPOSPLUSI: | case OP_NOTPOSPLUSI: |
560 | case OP_NOTPOSQUERYI: | case OP_NOTPOSQUERYI: |
561 | cc += 2; | cc += 2; |
562 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
563 | if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f]; | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); |
564 | #endif | #endif |
565 | return cc; | return cc; |
566 | ||
# | Line 532 switch(*cc) | Line 580 switch(*cc) |
580 | case OP_NOTMINUPTOI: | case OP_NOTMINUPTOI: |
581 | case OP_NOTEXACTI: | case OP_NOTEXACTI: |
582 | case OP_NOTPOSUPTOI: | case OP_NOTPOSUPTOI: |
583 | cc += 4; | cc += 2 + IMM2_SIZE; |
584 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
585 | if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f]; | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); |
586 | #endif | #endif |
587 | return cc; | return cc; |
588 | ||
589 | case OP_NOTPROP: | case OP_NOTPROP: |
590 | case OP_PROP: | case OP_PROP: |
591 | return cc + 1 + 2; | |
592 | ||
593 | case OP_TYPEUPTO: | case OP_TYPEUPTO: |
594 | case OP_TYPEMINUPTO: | case OP_TYPEMINUPTO: |
595 | case OP_TYPEEXACT: | case OP_TYPEEXACT: |
# | Line 547 switch(*cc) | Line 597 switch(*cc) |
597 | case OP_REF: | case OP_REF: |
598 | case OP_REFI: | case OP_REFI: |
599 | case OP_CREF: | case OP_CREF: |
600 | case OP_NCREF: | |
601 | case OP_RREF: | |
602 | case OP_NRREF: | |
603 | case OP_CLOSE: | case OP_CLOSE: |
604 | cc += 3; | cc += 1 + IMM2_SIZE; |
605 | return cc; | return cc; |
606 | ||
607 | case OP_CRRANGE: | case OP_CRRANGE: |
608 | case OP_CRMINRANGE: | case OP_CRMINRANGE: |
609 | return cc + 5; | return cc + 1 + 2 * IMM2_SIZE; |
610 | ||
611 | case OP_CLASS: | case OP_CLASS: |
612 | case OP_NCLASS: | case OP_NCLASS: |
613 | return cc + 33; | return cc + 1 + 32 / sizeof(pcre_uchar); |
614 | ||
615 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
616 | case OP_XCLASS: | case OP_XCLASS: |
617 | return cc + GET(cc, 1); | return cc + GET(cc, 1); |
618 | #endif | #endif |
# | Line 571 switch(*cc) | Line 624 switch(*cc) |
624 | case OP_ASSERTBACK_NOT: | case OP_ASSERTBACK_NOT: |
625 | case OP_REVERSE: | case OP_REVERSE: |
626 | case OP_ONCE: | case OP_ONCE: |
627 | case OP_ONCE_NC: | |
628 | case OP_BRA: | case OP_BRA: |
629 | case OP_BRAPOS: | case OP_BRAPOS: |
630 | case OP_COND: | case OP_COND: |
# | Line 588 switch(*cc) | Line 642 switch(*cc) |
642 | case OP_CBRAPOS: | case OP_CBRAPOS: |
643 | case OP_SCBRA: | case OP_SCBRA: |
644 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
645 | return cc + 1 + LINK_SIZE + 2; | return cc + 1 + LINK_SIZE + IMM2_SIZE; |
646 | ||
647 | default: | default: |
648 | return NULL; | return NULL; |
649 | } | } |
650 | } | } |
651 | ||
652 | static int get_localspace(compiler_common *common, uschar *cc, uschar *ccend) | static int get_localspace(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) |
653 | { | { |
654 | int localspace = 0; | int localspace = 0; |
655 | uschar *alternative; | pcre_uchar *alternative; |
656 | /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ | /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ |
657 | while (cc < ccend) | while (cc < ccend) |
658 | { | { |
# | Line 609 while (cc < ccend) | Line 663 while (cc < ccend) |
663 | case OP_ASSERTBACK: | case OP_ASSERTBACK: |
664 | case OP_ASSERTBACK_NOT: | case OP_ASSERTBACK_NOT: |
665 | case OP_ONCE: | case OP_ONCE: |
666 | case OP_ONCE_NC: | |
667 | case OP_BRAPOS: | case OP_BRAPOS: |
668 | case OP_SBRA: | case OP_SBRA: |
669 | case OP_SBRAPOS: | case OP_SBRAPOS: |
# | Line 620 while (cc < ccend) | Line 675 while (cc < ccend) |
675 | case OP_CBRAPOS: | case OP_CBRAPOS: |
676 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
677 | localspace += sizeof(sljit_w); | localspace += sizeof(sljit_w); |
678 | cc += 1 + LINK_SIZE + 2; | cc += 1 + LINK_SIZE + IMM2_SIZE; |
679 | break; | break; |
680 | ||
681 | case OP_COND: | case OP_COND: |
# | Line 641 while (cc < ccend) | Line 696 while (cc < ccend) |
696 | return localspace; | return localspace; |
697 | } | } |
698 | ||
699 | static void set_localptrs(compiler_common *common, int localptr, uschar *ccend) | static void set_localptrs(compiler_common *common, int localptr, pcre_uchar *ccend) |
700 | { | { |
701 | uschar *cc = common->start; | pcre_uchar *cc = common->start; |
702 | uschar *alternative; | pcre_uchar *alternative; |
703 | while (cc < ccend) | while (cc < ccend) |
704 | { | { |
705 | switch(*cc) | switch(*cc) |
# | Line 654 while (cc < ccend) | Line 709 while (cc < ccend) |
709 | case OP_ASSERTBACK: | case OP_ASSERTBACK: |
710 | case OP_ASSERTBACK_NOT: | case OP_ASSERTBACK_NOT: |
711 | case OP_ONCE: | case OP_ONCE: |
712 | case OP_ONCE_NC: | |
713 | case OP_BRAPOS: | case OP_BRAPOS: |
714 | case OP_SBRA: | case OP_SBRA: |
715 | case OP_SBRAPOS: | case OP_SBRAPOS: |
# | Line 667 while (cc < ccend) | Line 723 while (cc < ccend) |
723 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
724 | common->localptrs[cc - common->start] = localptr; | common->localptrs[cc - common->start] = localptr; |
725 | localptr += sizeof(sljit_w); | localptr += sizeof(sljit_w); |
726 | cc += 1 + LINK_SIZE + 2; | cc += 1 + LINK_SIZE + IMM2_SIZE; |
727 | break; | break; |
728 | ||
729 | case OP_COND: | case OP_COND: |
# | Line 690 while (cc < ccend) | Line 746 while (cc < ccend) |
746 | } | } |
747 | ||
748 | /* Returns with -1 if no need for frame. */ | /* Returns with -1 if no need for frame. */ |
749 | static int get_framesize(compiler_common *common, uschar *cc, BOOL recursive) | static int get_framesize(compiler_common *common, pcre_uchar *cc, BOOL recursive) |
750 | { | { |
751 | uschar *ccend = bracketend(cc); | pcre_uchar *ccend = bracketend(cc); |
uschar *end; | ||
752 | int length = 0; | int length = 0; |
753 | BOOL possessive = FALSE; | BOOL possessive = FALSE; |
BOOL needs_frame = FALSE; | ||
754 | BOOL setsom_found = FALSE; | BOOL setsom_found = FALSE; |
755 | ||
756 | if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)) | if (!recursive && (*cc == OP_CBRAPOS || *cc == OP_SCBRAPOS)) |
# | Line 720 while (cc < ccend) | Line 774 while (cc < ccend) |
774 | cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE; | cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE; |
775 | break; | break; |
776 | ||
case OP_ASSERT: | ||
case OP_ASSERT_NOT: | ||
case OP_ASSERTBACK: | ||
case OP_ASSERTBACK_NOT: | ||
case OP_ONCE: | ||
if (needs_frame || length > 0) | ||
{ | ||
cc = bracketend(cc); | ||
break; | ||
} | ||
/* Check whether a frame must be created. */ | ||
end = bracketend(cc); | ||
while (cc < end) | ||
{ | ||
if (*cc == OP_SET_SOM || *cc == OP_CBRA || *cc == OP_CBRAPOS | ||
|| *cc == OP_SCBRA || *cc == OP_SCBRAPOS || *cc == OP_RECURSE) | ||
needs_frame = TRUE; | ||
cc = next_opcode(common, cc); | ||
SLJIT_ASSERT(cc != NULL); | ||
} | ||
break; | ||
777 | case OP_CBRA: | case OP_CBRA: |
778 | case OP_CBRAPOS: | case OP_CBRAPOS: |
779 | case OP_SCBRA: | case OP_SCBRA: |
780 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
781 | length += 3; | length += 3; |
782 | cc += 1 + LINK_SIZE + 2; | cc += 1 + LINK_SIZE + IMM2_SIZE; |
783 | break; | break; |
784 | ||
785 | default: | default: |
# | Line 757 while (cc < ccend) | Line 789 while (cc < ccend) |
789 | } | } |
790 | ||
791 | /* Possessive quantifiers can use a special case. */ | /* Possessive quantifiers can use a special case. */ |
792 | if (SLJIT_UNLIKELY(possessive) && !needs_frame && length == 3 + 2) | if (SLJIT_UNLIKELY(possessive) && length == 3) |
793 | return -1; | return -1; |
794 | ||
795 | if (length > 0) | if (length > 0) |
796 | return length + 2; | return length + 1; |
797 | return needs_frame ? 0 : -1; | return -1; |
798 | } | } |
799 | ||
800 | static void init_frame(compiler_common *common, uschar *cc, int stackpos, int stacktop, BOOL recursive) | static void init_frame(compiler_common *common, pcre_uchar *cc, int stackpos, int stacktop, BOOL recursive) |
801 | { | { |
/* TMP2 must contain STACK_TOP - (-STACK(stackpos)) */ | ||
802 | DEFINE_COMPILER; | DEFINE_COMPILER; |
803 | uschar *ccend = bracketend(cc); | pcre_uchar *ccend = bracketend(cc); |
804 | BOOL setsom_found = FALSE; | BOOL setsom_found = FALSE; |
805 | int offset; | int offset; |
806 | ||
807 | if (stackpos < stacktop) | /* >= 1 + shortest item size (2) */ |
808 | { | SLJIT_UNUSED_ARG(stacktop); |
809 | SLJIT_ASSERT(stackpos + 1 == stacktop); | SLJIT_ASSERT(stackpos >= stacktop + 2); |
return; | ||
} | ||
810 | ||
811 | stackpos = STACK(stackpos); | stackpos = STACK(stackpos); |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacktop), TMP1, 0); | ||
812 | if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)) | if (recursive || (*cc != OP_CBRAPOS && *cc != OP_SCBRAPOS)) |
813 | cc = next_opcode(common, cc); | cc = next_opcode(common, cc); |
814 | SLJIT_ASSERT(cc != NULL); | SLJIT_ASSERT(cc != NULL); |
# | Line 804 while (cc < ccend) | Line 829 while (cc < ccend) |
829 | cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE; | cc += (*cc == OP_SET_SOM) ? 1 : 1 + LINK_SIZE; |
830 | break; | break; |
831 | ||
case OP_ASSERT: | ||
case OP_ASSERT_NOT: | ||
case OP_ASSERTBACK: | ||
case OP_ASSERTBACK_NOT: | ||
case OP_ONCE: | ||
cc = bracketend(cc); | ||
break; | ||
832 | case OP_CBRA: | case OP_CBRA: |
833 | case OP_CBRAPOS: | case OP_CBRAPOS: |
834 | case OP_SCBRA: | case OP_SCBRA: |
# | Line 826 while (cc < ccend) | Line 843 while (cc < ccend) |
843 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0); |
844 | stackpos += (int)sizeof(sljit_w); | stackpos += (int)sizeof(sljit_w); |
845 | ||
846 | cc += 1 + LINK_SIZE + 2; | cc += 1 + LINK_SIZE + IMM2_SIZE; |
847 | break; | break; |
848 | ||
849 | default: | default: |
# | Line 836 while (cc < ccend) | Line 853 while (cc < ccend) |
853 | } | } |
854 | ||
855 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_end); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, frame_end); |
856 | SLJIT_ASSERT(stackpos == STACK(stacktop + 1)); | SLJIT_ASSERT(stackpos == STACK(stacktop)); |
857 | } | } |
858 | ||
859 | static SLJIT_INLINE int get_localsize(compiler_common *common, uschar *cc, uschar *ccend) | static SLJIT_INLINE int get_localsize(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend) |
860 | { | { |
861 | int localsize = 2; | int localsize = 2; |
862 | uschar *alternative; | pcre_uchar *alternative; |
863 | /* Calculate the sum of the local variables. */ | /* Calculate the sum of the local variables. */ |
864 | while (cc < ccend) | while (cc < ccend) |
865 | { | { |
# | Line 853 while (cc < ccend) | Line 870 while (cc < ccend) |
870 | case OP_ASSERTBACK: | case OP_ASSERTBACK: |
871 | case OP_ASSERTBACK_NOT: | case OP_ASSERTBACK_NOT: |
872 | case OP_ONCE: | case OP_ONCE: |
873 | case OP_ONCE_NC: | |
874 | case OP_BRAPOS: | case OP_BRAPOS: |
875 | case OP_SBRA: | case OP_SBRA: |
876 | case OP_SBRAPOS: | case OP_SBRAPOS: |
# | Line 864 while (cc < ccend) | Line 882 while (cc < ccend) |
882 | case OP_CBRA: | case OP_CBRA: |
883 | case OP_SCBRA: | case OP_SCBRA: |
884 | localsize++; | localsize++; |
885 | cc += 1 + LINK_SIZE + 2; | cc += 1 + LINK_SIZE + IMM2_SIZE; |
886 | break; | break; |
887 | ||
888 | case OP_CBRAPOS: | case OP_CBRAPOS: |
889 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
890 | localsize += 2; | localsize += 2; |
891 | cc += 1 + LINK_SIZE + 2; | cc += 1 + LINK_SIZE + IMM2_SIZE; |
892 | break; | break; |
893 | ||
894 | case OP_COND: | case OP_COND: |
# | Line 891 SLJIT_ASSERT(cc == ccend); | Line 909 SLJIT_ASSERT(cc == ccend); |
909 | return localsize; | return localsize; |
910 | } | } |
911 | ||
912 | static void copy_locals(compiler_common *common, uschar *cc, uschar *ccend, | static void copy_locals(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, |
913 | BOOL save, int stackptr, int stacktop) | BOOL save, int stackptr, int stacktop) |
914 | { | { |
915 | DEFINE_COMPILER; | DEFINE_COMPILER; |
# | Line 900 int count; | Line 918 int count; |
918 | BOOL tmp1next = TRUE; | BOOL tmp1next = TRUE; |
919 | BOOL tmp1empty = TRUE; | BOOL tmp1empty = TRUE; |
920 | BOOL tmp2empty = TRUE; | BOOL tmp2empty = TRUE; |
921 | uschar *alternative; | pcre_uchar *alternative; |
922 | enum { | enum { |
923 | start, | start, |
924 | loop, | loop, |
# | Line 955 while (status != end) | Line 973 while (status != end) |
973 | case OP_ASSERTBACK: | case OP_ASSERTBACK: |
974 | case OP_ASSERTBACK_NOT: | case OP_ASSERTBACK_NOT: |
975 | case OP_ONCE: | case OP_ONCE: |
976 | case OP_ONCE_NC: | |
977 | case OP_BRAPOS: | case OP_BRAPOS: |
978 | case OP_SBRA: | case OP_SBRA: |
979 | case OP_SBRAPOS: | case OP_SBRAPOS: |
980 | case OP_SCOND: | case OP_SCOND: |
981 | count = 1; | count = 1; |
982 | srcw[0] = PRIV(cc); | srcw[0] = PRIV_DATA(cc); |
983 | SLJIT_ASSERT(srcw[0] != 0); | SLJIT_ASSERT(srcw[0] != 0); |
984 | cc += 1 + LINK_SIZE; | cc += 1 + LINK_SIZE; |
985 | break; | break; |
# | Line 969 while (status != end) | Line 988 while (status != end) |
988 | case OP_SCBRA: | case OP_SCBRA: |
989 | count = 1; | count = 1; |
990 | srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); | srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); |
991 | cc += 1 + LINK_SIZE + 2; | cc += 1 + LINK_SIZE + IMM2_SIZE; |
992 | break; | break; |
993 | ||
994 | case OP_CBRAPOS: | case OP_CBRAPOS: |
995 | case OP_SCBRAPOS: | case OP_SCBRAPOS: |
996 | count = 2; | count = 2; |
997 | srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); | srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE)); |
998 | srcw[0] = PRIV(cc); | srcw[0] = PRIV_DATA(cc); |
999 | SLJIT_ASSERT(srcw[0] != 0); | SLJIT_ASSERT(srcw[0] != 0); |
1000 | cc += 1 + LINK_SIZE + 2; | cc += 1 + LINK_SIZE + IMM2_SIZE; |
1001 | break; | break; |
1002 | ||
1003 | case OP_COND: | case OP_COND: |
# | Line 987 while (status != end) | Line 1006 while (status != end) |
1006 | if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) | if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) |
1007 | { | { |
1008 | count = 1; | count = 1; |
1009 | srcw[0] = PRIV(cc); | srcw[0] = PRIV_DATA(cc); |
1010 | SLJIT_ASSERT(srcw[0] != 0); | SLJIT_ASSERT(srcw[0] != 0); |
1011 | } | } |
1012 | cc += 1 + LINK_SIZE; | cc += 1 + LINK_SIZE; |
# | Line 1195 struct sljit_label *loop; | Line 1214 struct sljit_label *loop; |
1214 | int i; | int i; |
1215 | /* At this point we can freely use all temporary registers. */ | /* At this point we can freely use all temporary registers. */ |
1216 | /* TMP1 returns with begin - 1. */ | /* TMP1 returns with begin - 1. */ |
1217 | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, 1); | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), SLJIT_OFFSETOF(jit_arguments, begin), SLJIT_IMM, IN_UCHARS(1)); |
1218 | if (length < 8) | if (length < 8) |
1219 | { | { |
1220 | for (i = 0; i < length; i++) | for (i = 0; i < length; i++) |
# | Line 1219 struct sljit_label *loop; | Line 1238 struct sljit_label *loop; |
1238 | struct sljit_jump *earlyexit; | struct sljit_jump *earlyexit; |
1239 | ||
1240 | /* At this point we can freely use all registers. */ | /* At this point we can freely use all registers. */ |
1241 | OP1(SLJIT_MOV, SLJIT_GENERAL_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); | OP1(SLJIT_MOV, SLJIT_SAVED_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); |
1242 | 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); |
1243 | ||
1244 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, ARGUMENTS, 0); |
1245 | OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount)); | OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsetcount)); |
1246 | 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_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, offsets), SLJIT_IMM, sizeof(int)); |
1247 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), SLJIT_OFFSETOF(jit_arguments, begin)); |
1248 | OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START); | OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START); |
1249 | /* Unlikely, but possible */ | /* Unlikely, but possible */ |
1250 | earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0); | earlyexit = CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 0); |
1251 | loop = LABEL(); | loop = LABEL(); |
1252 | OP2(SLJIT_SUB, SLJIT_GENERAL_REG2, 0, SLJIT_MEM1(SLJIT_GENERAL_REG1), 0, SLJIT_TEMPORARY_REG1, 0); | OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, SLJIT_MEM1(SLJIT_SAVED_REG1), 0, SLJIT_TEMPORARY_REG1, 0); |
1253 | OP2(SLJIT_ADD, SLJIT_GENERAL_REG1, 0, SLJIT_GENERAL_REG1, 0, SLJIT_IMM, sizeof(sljit_w)); | OP2(SLJIT_ADD, SLJIT_SAVED_REG1, 0, SLJIT_SAVED_REG1, 0, SLJIT_IMM, sizeof(sljit_w)); |
1254 | /* Copy the integer value to the output buffer */ | /* Copy the integer value to the output buffer */ |
1255 | OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_GENERAL_REG2, 0); | #ifdef COMPILE_PCRE16 |
1256 | OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1); | |
1257 | #endif | |
1258 | OP1(SLJIT_MOVU_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG3), sizeof(int), SLJIT_SAVED_REG2, 0); | |
1259 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); |
1260 | JUMPTO(SLJIT_C_NOT_ZERO, loop); | JUMPTO(SLJIT_C_NOT_ZERO, loop); |
1261 | JUMPHERE(earlyexit); | JUMPHERE(earlyexit); |
# | Line 1244 if (topbracket > 1) | Line 1266 if (topbracket > 1) |
1266 | OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START + topbracket * 2 * sizeof(sljit_w)); | OP2(SLJIT_ADD, SLJIT_TEMPORARY_REG1, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, OVECTOR_START + topbracket * 2 * sizeof(sljit_w)); |
1267 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, topbracket + 1); |
1268 | ||
1269 | /* OVECTOR(0) is never equal to SLJIT_GENERAL_REG3. */ | /* OVECTOR(0) is never equal to SLJIT_SAVED_REG3. */ |
1270 | loop = LABEL(); | loop = LABEL(); |
1271 | OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * sizeof(sljit_w))); | OP1(SLJIT_MOVU, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG1), -(2 * (sljit_w)sizeof(sljit_w))); |
1272 | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG2, 0, SLJIT_IMM, 1); |
1273 | CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_GENERAL_REG3, 0, loop); | CMPTO(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG3, 0, loop); |
1274 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_TEMPORARY_REG2, 0); |
1275 | } | } |
1276 | else | else |
1277 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); |
1278 | } | } |
1279 | ||
1280 | static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, uschar* cc) | static SLJIT_INLINE void return_with_partial_match(compiler_common *common, struct sljit_label *leave) |
1281 | { | |
1282 | DEFINE_COMPILER; | |
1283 | ||
1284 | SLJIT_COMPILE_ASSERT(STR_END == SLJIT_SAVED_REG2, str_end_must_be_saved_reg2); | |
1285 | ||
1286 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); | |
1287 | OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE_ERROR_PARTIAL); | |
1288 | OP1(SLJIT_MOV_SI, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsetcount)); | |
1289 | CMPTO(SLJIT_C_LESS, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 2, leave); | |
1290 | ||
1291 | /* Store match begin and end. */ | |
1292 | OP1(SLJIT_MOV, SLJIT_SAVED_REG1, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, begin)); | |
1293 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, offsets)); | |
1294 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), common->mode == JIT_PARTIAL_HARD_COMPILE ? START_USED_PTR : HIT_START); | |
1295 | OP2(SLJIT_SUB, SLJIT_SAVED_REG2, 0, STR_END, 0, SLJIT_SAVED_REG1, 0); | |
1296 | #ifdef COMPILE_PCRE16 | |
1297 | OP2(SLJIT_ASHR, SLJIT_SAVED_REG2, 0, SLJIT_SAVED_REG2, 0, SLJIT_IMM, 1); | |
1298 | #endif | |
1299 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), sizeof(int), SLJIT_SAVED_REG2, 0); | |
1300 | ||
1301 | OP2(SLJIT_SUB, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_SAVED_REG1, 0); | |
1302 | #ifdef COMPILE_PCRE16 | |
1303 | OP2(SLJIT_ASHR, SLJIT_TEMPORARY_REG3, 0, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, 1); | |
1304 | #endif | |
1305 | OP1(SLJIT_MOV_SI, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), 0, SLJIT_TEMPORARY_REG3, 0); | |
1306 | ||
1307 | JUMPTO(SLJIT_JUMP, leave); | |
1308 | } | |
1309 | ||
1310 | static SLJIT_INLINE void check_start_used_ptr(compiler_common *common) | |
1311 | { | |
1312 | /* May destroy TMP1. */ | |
1313 | DEFINE_COMPILER; | |
1314 | struct sljit_jump *jump; | |
1315 | ||
1316 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | |
1317 | { | |
1318 | /* The value of -1 must be kept for START_USED_PTR! */ | |
1319 | OP2(SLJIT_ADD, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, SLJIT_IMM, 1); | |
1320 | /* Jumps if START_USED_PTR < STR_PTR, or START_USED_PTR == -1. Although overwriting | |
1321 | is not necessary if START_USED_PTR == STR_PTR, it does not hurt as well. */ | |
1322 | jump = CMP(SLJIT_C_LESS_EQUAL, TMP1, 0, STR_PTR, 0); | |
1323 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); | |
1324 | JUMPHERE(jump); | |
1325 | } | |
1326 | else if (common->mode == JIT_PARTIAL_HARD_COMPILE) | |
1327 | { | |
1328 | jump = CMP(SLJIT_C_LESS_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); | |
1329 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); | |
1330 | JUMPHERE(jump); | |
1331 | } | |
1332 | } | |
1333 | ||
1334 | static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, pcre_uchar* cc) | |
1335 | { | { |
1336 | /* Detects if the character has an othercase. */ | /* Detects if the character has an othercase. */ |
1337 | unsigned int c; | unsigned int c; |
1338 | ||
1339 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
1340 | if (common->utf8) | if (common->utf) |
1341 | { | { |
1342 | GETCHAR(c, cc); | GETCHAR(c, cc); |
1343 | if (c > 127) | if (c > 127) |
# | Line 1272 if (common->utf8) | Line 1348 if (common->utf8) |
1348 | return FALSE; | return FALSE; |
1349 | #endif | #endif |
1350 | } | } |
1351 | #ifndef COMPILE_PCRE8 | |
1352 | return common->fcc[c] != c; | |
1353 | #endif | |
1354 | } | } |
1355 | else | else |
1356 | #endif | #endif |
1357 | c = *cc; | c = *cc; |
1358 | return common->fcc[c] != c; | return MAX_255(c) ? common->fcc[c] != c : FALSE; |
1359 | } | } |
1360 | ||
1361 | static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c) | static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigned int c) |
1362 | { | { |
1363 | /* Returns with the othercase. */ | /* Returns with the othercase. */ |
1364 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
1365 | if (common->utf8 && c > 127) | if (common->utf && c > 127) |
1366 | { | { |
1367 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
1368 | return UCD_OTHERCASE(c); | return UCD_OTHERCASE(c); |
# | Line 1292 if (common->utf8 && c > 127) | Line 1371 if (common->utf8 && c > 127) |
1371 | #endif | #endif |
1372 | } | } |
1373 | #endif | #endif |
1374 | return common->fcc[c]; | return TABLE_GET(c, common->fcc, c); |
1375 | } | } |
1376 | ||
1377 | static unsigned int char_get_othercase_bit(compiler_common *common, uschar* cc) | static unsigned int char_get_othercase_bit(compiler_common *common, pcre_uchar* cc) |
1378 | { | { |
1379 | /* Detects if the character and its othercase has only 1 bit difference. */ | /* Detects if the character and its othercase has only 1 bit difference. */ |
1380 | unsigned int c, oc, bit; | unsigned int c, oc, bit; |
1381 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 |
1382 | int n; | int n; |
1383 | #endif | #endif |
1384 | ||
1385 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
1386 | if (common->utf8) | if (common->utf) |
1387 | { | { |
1388 | GETCHAR(c, cc); | GETCHAR(c, cc); |
1389 | if (c <= 127) | if (c <= 127) |
# | Line 1321 if (common->utf8) | Line 1400 if (common->utf8) |
1400 | else | else |
1401 | { | { |
1402 | c = *cc; | c = *cc; |
1403 | oc = common->fcc[c]; | oc = TABLE_GET(c, common->fcc, c); |
1404 | } | } |
1405 | #else | #else |
1406 | c = *cc; | c = *cc; |
1407 | oc = common->fcc[c]; | oc = TABLE_GET(c, common->fcc, c); |
1408 | #endif | #endif |
1409 | ||
1410 | SLJIT_ASSERT(c != oc); | SLJIT_ASSERT(c != oc); |
# | Line 1339 if (c <= 127 && bit == 0x20) | Line 1418 if (c <= 127 && bit == 0x20) |
1418 | if (!ispowerof2(bit)) | if (!ispowerof2(bit)) |
1419 | return 0; | return 0; |
1420 | ||
1421 | #ifdef SUPPORT_UTF8 | #ifdef COMPILE_PCRE8 |
1422 | if (common->utf8 && c > 127) | |
1423 | #ifdef SUPPORT_UTF | |
1424 | if (common->utf && c > 127) | |
1425 | { | { |
1426 | n = _pcre_utf8_table4[*cc & 0x3f]; | n = GET_EXTRALEN(*cc); |
1427 | while ((bit & 0x3f) == 0) | while ((bit & 0x3f) == 0) |
1428 | { | { |
1429 | n--; | n--; |
# | Line 1350 if (common->utf8 && c > 127) | Line 1431 if (common->utf8 && c > 127) |
1431 | } | } |
1432 | return (n << 8) | bit; | return (n << 8) | bit; |
1433 | } | } |
1434 | #endif | #endif /* SUPPORT_UTF */ |
1435 | return (0 << 8) | bit; | return (0 << 8) | bit; |
1436 | ||
1437 | #else /* COMPILE_PCRE8 */ | |
1438 | ||
1439 | #ifdef COMPILE_PCRE16 | |
1440 | #ifdef SUPPORT_UTF | |
1441 | if (common->utf && c > 65535) | |
1442 | { | |
1443 | if (bit >= (1 << 10)) | |
1444 | bit >>= 10; | |
1445 | else | |
1446 | return (bit < 256) ? ((2 << 8) | bit) : ((3 << 8) | (bit >> 8)); | |
1447 | } | |
1448 | #endif /* SUPPORT_UTF */ | |
1449 | return (bit < 256) ? ((0 << 8) | bit) : ((1 << 8) | (bit >> 8)); | |
1450 | #endif /* COMPILE_PCRE16 */ | |
1451 | ||
1452 | #endif /* COMPILE_PCRE8 */ | |
1453 | } | } |
1454 | ||
1455 | static SLJIT_INLINE void check_input_end(compiler_common *common, jump_list **fallbacks) | static void check_partial(compiler_common *common) |
1456 | { | { |
1457 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1458 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); | struct sljit_jump *jump; |
1459 | ||
1460 | if (common->mode == JIT_COMPILE) | |
1461 | return; | |
1462 | ||
1463 | jump = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); | |
1464 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | |
1465 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), HIT_START, SLJIT_IMM, -1); | |
1466 | else | |
1467 | { | |
1468 | if (common->partialmatchlabel != NULL) | |
1469 | JUMPTO(SLJIT_JUMP, common->partialmatchlabel); | |
1470 | else | |
1471 | add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); | |
1472 | } | |
1473 | JUMPHERE(jump); | |
1474 | } | |
1475 | ||
1476 | static struct sljit_jump *check_str_end(compiler_common *common) | |
1477 | { | |
1478 | /* Does not affect registers. Usually used in a tight spot. */ | |
1479 | DEFINE_COMPILER; | |
1480 | struct sljit_jump *jump; | |
1481 | struct sljit_jump *nohit; | |
1482 | struct sljit_jump *return_value; | |
1483 | ||
1484 | if (common->mode == JIT_COMPILE) | |
1485 | return CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | |
1486 | ||
1487 | jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | |
1488 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | |
1489 | { | |
1490 | nohit = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); | |
1491 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), HIT_START, SLJIT_IMM, -1); | |
1492 | JUMPHERE(nohit); | |
1493 | return_value = JUMP(SLJIT_JUMP); | |
1494 | } | |
1495 | else | |
1496 | { | |
1497 | return_value = CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0); | |
1498 | if (common->partialmatchlabel != NULL) | |
1499 | JUMPTO(SLJIT_JUMP, common->partialmatchlabel); | |
1500 | else | |
1501 | add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); | |
1502 | } | |
1503 | JUMPHERE(jump); | |
1504 | return return_value; | |
1505 | } | |
1506 | ||
1507 | static void fallback_at_str_end(compiler_common *common, jump_list **fallbacks) | |
1508 | { | |
1509 | DEFINE_COMPILER; | |
1510 | struct sljit_jump *jump; | |
1511 | ||
1512 | if (common->mode == JIT_COMPILE) | |
1513 | { | |
1514 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); | |
1515 | return; | |
1516 | } | |
1517 | ||
1518 | /* Partial matching mode. */ | |
1519 | jump = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | |
1520 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), START_USED_PTR, STR_PTR, 0)); | |
1521 | if (common->mode == JIT_PARTIAL_SOFT_COMPILE) | |
1522 | { | |
1523 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), HIT_START, SLJIT_IMM, -1); | |
1524 | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); | |
1525 | } | |
1526 | else | |
1527 | { | |
1528 | if (common->partialmatchlabel != NULL) | |
1529 | JUMPTO(SLJIT_JUMP, common->partialmatchlabel); | |
1530 | else | |
1531 | add_jump(compiler, &common->partialmatch, JUMP(SLJIT_JUMP)); | |
1532 | } | |
1533 | JUMPHERE(jump); | |
1534 | } | } |
1535 | ||
1536 | static void read_char(compiler_common *common) | static void read_char(compiler_common *common) |
# | Line 1365 static void read_char(compiler_common *c | Line 1538 static void read_char(compiler_common *c |
1538 | /* Reads the character into TMP1, updates STR_PTR. | /* Reads the character into TMP1, updates STR_PTR. |
1539 | Does not check STR_END. TMP2 Destroyed. */ | Does not check STR_END. TMP2 Destroyed. */ |
1540 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1541 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
1542 | struct sljit_jump *jump; | struct sljit_jump *jump; |
1543 | #endif | #endif |
1544 | ||
1545 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
1546 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
1547 | if (common->utf8) | if (common->utf) |
1548 | { | { |
1549 | /* Should not found a value between 128 and 192 here. */ | #ifdef COMPILE_PCRE8 |
1550 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 192); | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); |
1551 | add_jump(compiler, &common->utf8readchar, JUMP(SLJIT_FAST_CALL)); | #else |
1552 | #ifdef COMPILE_PCRE16 | |
1553 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); | |
1554 | #endif | |
1555 | #endif /* COMPILE_PCRE8 */ | |
1556 | add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); | |
1557 | JUMPHERE(jump); | JUMPHERE(jump); |
1558 | } | } |
1559 | #endif | #endif |
1560 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
1561 | } | } |
1562 | ||
1563 | static void peek_char(compiler_common *common) | static void peek_char(compiler_common *common) |
# | Line 1387 static void peek_char(compiler_common *c | Line 1565 static void peek_char(compiler_common *c |
1565 | /* Reads the character into TMP1, keeps STR_PTR. | /* Reads the character into TMP1, keeps STR_PTR. |
1566 | Does not check STR_END. TMP2 Destroyed. */ | Does not check STR_END. TMP2 Destroyed. */ |
1567 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1568 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
1569 | struct sljit_jump *jump; | struct sljit_jump *jump; |
1570 | #endif | #endif |
1571 | ||
1572 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
1573 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
1574 | if (common->utf8) | if (common->utf) |
1575 | { | { |
1576 | /* Should not found a value between 128 and 192 here. */ | #ifdef COMPILE_PCRE8 |
1577 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 192); | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); |
1578 | add_jump(compiler, &common->utf8readchar, JUMP(SLJIT_FAST_CALL)); | #else |
1579 | #ifdef COMPILE_PCRE16 | |
1580 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); | |
1581 | #endif | |
1582 | #endif /* COMPILE_PCRE8 */ | |
1583 | add_jump(compiler, &common->utfreadchar, JUMP(SLJIT_FAST_CALL)); | |
1584 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
1585 | JUMPHERE(jump); | JUMPHERE(jump); |
1586 | } | } |
# | Line 1408 static void read_char8_type(compiler_com | Line 1591 static void read_char8_type(compiler_com |
1591 | { | { |
1592 | /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */ | /* Reads the character type into TMP1, updates STR_PTR. Does not check STR_END. */ |
1593 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1594 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 |
1595 | struct sljit_jump *jump; | struct sljit_jump *jump; |
1596 | #endif | #endif |
1597 | ||
1598 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
1599 | if (common->utf8) | if (common->utf) |
1600 | { | { |
1601 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); |
1602 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
1603 | #ifdef COMPILE_PCRE8 | |
1604 | /* This can be an extra read in some situations, but hopefully | /* This can be an extra read in some situations, but hopefully |
1605 | it is a clever early read in most cases. */ | it is needed in most cases. */ |
1606 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); |
1607 | /* Should not found a value between 128 and 192 here. */ | jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 0xc0); |
1608 | jump = CMP(SLJIT_C_LESS, TMP2, 0, SLJIT_IMM, 192); | add_jump(compiler, &common->utfreadtype8, JUMP(SLJIT_FAST_CALL)); |
add_jump(compiler, &common->utf8readtype8, JUMP(SLJIT_FAST_CALL)); | ||
1609 | JUMPHERE(jump); | JUMPHERE(jump); |
1610 | #else | |
1611 | #ifdef COMPILE_PCRE16 | |
1612 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); | |
1613 | jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); | |
1614 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); | |
1615 | JUMPHERE(jump); | |
1616 | /* Skip low surrogate if necessary. */ | |
1617 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xfc00); | |
1618 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xd800); | |
1619 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | |
1620 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); | |
1621 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | |
1622 | #endif | |
1623 | #endif /* COMPILE_PCRE8 */ | |
1624 | return; | return; |
1625 | } | } |
1626 | #endif | #endif |
1627 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); |
1628 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
1629 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes); | #ifdef COMPILE_PCRE16 |
1630 | /* The ctypes array contains only 256 values. */ | |
1631 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); | |
1632 | jump = CMP(SLJIT_C_GREATER, TMP2, 0, SLJIT_IMM, 255); | |
1633 | #endif | |
1634 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); | |
1635 | #ifdef COMPILE_PCRE16 | |
1636 | JUMPHERE(jump); | |
1637 | #endif | |
1638 | } | } |
1639 | ||
1640 | static void skip_char_back(compiler_common *common) | static void skip_char_back(compiler_common *common) |
1641 | { | { |
1642 | /* Goes one character back. Only affects STR_PTR. Does not check begin. */ | /* Goes one character back. Affects STR_PTR and TMP1. Does not check begin. */ |
1643 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1644 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 |
1645 | struct sljit_label *label; | struct sljit_label *label; |
1646 | ||
1647 | if (common->utf8) | if (common->utf) |
1648 | { | { |
1649 | label = LABEL(); | label = LABEL(); |
1650 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1)); |
1651 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
1652 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc0); |
1653 | CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label); | CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, 0x80, label); |
1654 | return; | return; |
1655 | } | } |
1656 | #endif | #endif |
1657 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | #if defined SUPPORT_UTF && defined COMPILE_PCRE16 |
1658 | if (common->utf) | |
1659 | { | |
1660 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), -IN_UCHARS(1)); | |
1661 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
1662 | /* Skip low surrogate if necessary. */ | |
1663 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | |
1664 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00); | |
1665 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | |
1666 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | |
1667 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | |
1668 | return; | |
1669 | } | |
1670 | #endif | |
1671 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
1672 | } | } |
1673 | ||
1674 | static void check_newlinechar(compiler_common *common, int nltype, jump_list **fallbacks, BOOL jumpiftrue) | static void check_newlinechar(compiler_common *common, int nltype, jump_list **fallbacks, BOOL jumpiftrue) |
# | Line 1472 else if (nltype == NLTYPE_ANYCRLF) | Line 1691 else if (nltype == NLTYPE_ANYCRLF) |
1691 | } | } |
1692 | else | else |
1693 | { | { |
1694 | SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline <= 255); | SLJIT_ASSERT(nltype == NLTYPE_FIXED && common->newline < 256); |
1695 | add_jump(compiler, fallbacks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); | add_jump(compiler, fallbacks, CMP(jumpiftrue ? SLJIT_C_EQUAL : SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); |
1696 | } | } |
1697 | } | } |
1698 | ||
1699 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
1700 | static void do_utf8readchar(compiler_common *common) | |
1701 | #ifdef COMPILE_PCRE8 | |
1702 | static void do_utfreadchar(compiler_common *common) | |
1703 | { | { |
1704 | /* Fast decoding an utf8 character. TMP1 contains the first byte | /* Fast decoding a UTF-8 character. TMP1 contains the first byte |
1705 | of the character (>= 192). Return char value in TMP1, length - 1 in TMP2. */ | of the character (>= 0xc0). Return char value in TMP1, length - 1 in TMP2. */ |
1706 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1707 | struct sljit_jump *jump; | struct sljit_jump *jump; |
1708 | ||
# | Line 1489 sljit_emit_fast_enter(compiler, RETURN_A | Line 1710 sljit_emit_fast_enter(compiler, RETURN_A |
1710 | /* Searching for the first zero. */ | /* Searching for the first zero. */ |
1711 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20); |
1712 | jump = JUMP(SLJIT_C_NOT_ZERO); | jump = JUMP(SLJIT_C_NOT_ZERO); |
1713 | /* 2 byte sequence */ | /* Two byte sequence. */ |
1714 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
1715 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
1716 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1f); |
1717 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); |
1718 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
1719 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
1720 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); |
1721 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
1722 | JUMPHERE(jump); | JUMPHERE(jump); |
1723 | ||
1724 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10); |
1725 | jump = JUMP(SLJIT_C_NOT_ZERO); | jump = JUMP(SLJIT_C_NOT_ZERO); |
1726 | /* 3 byte sequence */ | /* Three byte sequence. */ |
1727 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
1728 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0f); |
1729 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 12); |
1730 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
1731 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); |
1732 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
1733 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); |
1734 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 2); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
1735 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
1736 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
1737 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 2); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(2)); |
1738 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
1739 | JUMPHERE(jump); | JUMPHERE(jump); |
1740 | ||
1741 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x08); | /* Four byte sequence. */ |
1742 | jump = JUMP(SLJIT_C_NOT_ZERO); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
/* 4 byte sequence */ | ||
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1); | ||
1743 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x07); |
1744 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18); | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 18); |
1745 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
1746 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12); |
1747 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
1748 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(2)); |
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | ||
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); | ||
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | ||
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 3); | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 3); | ||
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | ||
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 3); | ||
sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | ||
JUMPHERE(jump); | ||
/* 5 byte sequence */ | ||
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1); | ||
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x03); | ||
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 24); | ||
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | ||
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 18); | ||
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | ||
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 2); | ||
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | ||
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 12); | ||
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | ||
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 3); | ||
1749 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
1750 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); |
1751 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
1752 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 4); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(3)); |
1753 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 4); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3)); |
1754 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); |
1755 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); |
1756 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 4); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(3)); |
1757 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
1758 | } | } |
1759 | ||
1760 | static void do_utf8readtype8(compiler_common *common) | static void do_utfreadtype8(compiler_common *common) |
1761 | { | { |
1762 | /* Fast decoding an utf8 character type. TMP2 contains the first byte | /* Fast decoding a UTF-8 character type. TMP2 contains the first byte |
1763 | of the character (>= 192) and TMP1 is destroyed. Return value in TMP1. */ | of the character (>= 0xc0). Return value in TMP1. */ |
1764 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1765 | struct sljit_jump *jump; | struct sljit_jump *jump; |
1766 | struct sljit_jump *compare; | struct sljit_jump *compare; |
# | Line 1573 sljit_emit_fast_enter(compiler, RETURN_A | Line 1769 sljit_emit_fast_enter(compiler, RETURN_A |
1769 | ||
1770 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20); |
1771 | jump = JUMP(SLJIT_C_NOT_ZERO); | jump = JUMP(SLJIT_C_NOT_ZERO); |
1772 | /* 2 byte sequence */ | /* Two byte sequence. */ |
1773 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
1774 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
1775 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x1f); |
1776 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); |
1777 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); |
# | Line 1590 sljit_emit_fast_return(compiler, RETURN_ | Line 1786 sljit_emit_fast_return(compiler, RETURN_ |
1786 | JUMPHERE(jump); | JUMPHERE(jump); |
1787 | ||
1788 | /* We only have types for characters less than 256. */ | /* We only have types for characters less than 256. */ |
1789 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_w)_pcre_utf8_char_sizes); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(utf8_table4) - 0xc0); |
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | ||
1790 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
1791 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); |
1792 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
1793 | } | } |
1794 | ||
1795 | #endif | #else /* COMPILE_PCRE8 */ |
1796 | ||
1797 | #ifdef COMPILE_PCRE16 | |
1798 | static void do_utfreadchar(compiler_common *common) | |
1799 | { | |
1800 | /* Fast decoding a UTF-16 character. TMP1 contains the first 16 bit char | |
1801 | of the character (>= 0xd800). Return char value in TMP1, length - 1 in TMP2. */ | |
1802 | DEFINE_COMPILER; | |
1803 | struct sljit_jump *jump; | |
1804 | ||
1805 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | |
1806 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xdc00); | |
1807 | /* Do nothing, only return. */ | |
1808 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | |
1809 | ||
1810 | JUMPHERE(jump); | |
1811 | /* Combine two 16 bit characters. */ | |
1812 | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | |
1813 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
1814 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3ff); | |
1815 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 10); | |
1816 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3ff); | |
1817 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); | |
1818 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); | |
1819 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000); | |
1820 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | |
1821 | } | |
1822 | #endif /* COMPILE_PCRE16 */ | |
1823 | ||
1824 | #endif /* COMPILE_PCRE8 */ | |
1825 | ||
1826 | #endif /* SUPPORT_UTF */ | |
1827 | ||
1828 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
1829 | ||
# | Line 1615 SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && si | Line 1841 SLJIT_ASSERT(UCD_BLOCK_SIZE == 128 && si |
1841 | ||
1842 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); |
1843 | OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); | OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); |
1844 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)_pcre_ucd_stage1); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_w)PRIV(ucd_stage1)); |
1845 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK); |
1846 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); |
1847 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); |
1848 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_stage2); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_stage2)); |
1849 | OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); | OP1(SLJIT_MOV_UH, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); |
1850 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, chartype)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); |
1851 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); |
1852 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
1853 | } | } |
# | Line 1635 struct sljit_label *newlinelabel = NULL; | Line 1861 struct sljit_label *newlinelabel = NULL; |
1861 | struct sljit_jump *start; | struct sljit_jump *start; |
1862 | struct sljit_jump *end = NULL; | struct sljit_jump *end = NULL; |
1863 | struct sljit_jump *nl = NULL; | struct sljit_jump *nl = NULL; |
1864 | #ifdef SUPPORT_UTF | |
1865 | struct sljit_jump *singlechar; | |
1866 | #endif | |
1867 | jump_list *newline = NULL; | jump_list *newline = NULL; |
1868 | BOOL newlinecheck = FALSE; | BOOL newlinecheck = FALSE; |
1869 | BOOL readbyte = FALSE; | BOOL readuchar = FALSE; |
1870 | ||
1871 | if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY || | if (!(hascrorlf || firstline) && (common->nltype == NLTYPE_ANY || |
1872 | common->nltype == NLTYPE_ANYCRLF || common->newline > 255)) | common->nltype == NLTYPE_ANYCRLF || common->newline > 255)) |
# | Line 1652 if (firstline) | Line 1881 if (firstline) |
1881 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
1882 | { | { |
1883 | mainloop = LABEL(); | mainloop = LABEL(); |
1884 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
1885 | end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
1886 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -1); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); |
1887 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
1888 | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop); | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, mainloop); |
1889 | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop); | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, mainloop); |
1890 | OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB, SLJIT_MEM1(SLJIT_LOCALS_REG), FIRSTLINE_END, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
1891 | } | } |
1892 | else | else |
1893 | { | { |
# | Line 1682 start = JUMP(SLJIT_JUMP); | Line 1911 start = JUMP(SLJIT_JUMP); |
1911 | if (newlinecheck) | if (newlinecheck) |
1912 | { | { |
1913 | newlinelabel = LABEL(); | newlinelabel = LABEL(); |
1914 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
1915 | end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | end = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
1916 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
1917 | 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); |
1918 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); |
1919 | #ifdef COMPILE_PCRE16 | |
1920 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | |
1921 | #endif | |
1922 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
1923 | nl = JUMP(SLJIT_JUMP); | nl = JUMP(SLJIT_JUMP); |
1924 | } | } |
# | Line 1694 if (newlinecheck) | Line 1926 if (newlinecheck) |
1926 | mainloop = LABEL(); | mainloop = LABEL(); |
1927 | ||
1928 | /* Increasing the STR_PTR here requires one less jump in the most common case. */ | /* Increasing the STR_PTR here requires one less jump in the most common case. */ |
1929 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
1930 | if (common->utf8) readbyte = TRUE; | if (common->utf) readuchar = TRUE; |
1931 | #endif | #endif |
1932 | if (newlinecheck) readbyte = TRUE; | if (newlinecheck) readuchar = TRUE; |
1933 | ||
1934 | if (readbyte) | if (readuchar) |
1935 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
1936 | ||
1937 | if (newlinecheck) | if (newlinecheck) |
1938 | CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel); | CMPTO(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, newlinelabel); |
1939 | ||
1940 | #ifdef SUPPORT_UTF8 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
1941 | if (common->utf8) | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 |
1942 | if (common->utf) | |
1943 | { | { |
1944 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes); | singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); |
1945 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); | |
1946 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
1947 | JUMPHERE(singlechar); | |
1948 | } | |
1949 | #endif | |
1950 | #if defined SUPPORT_UTF && defined COMPILE_PCRE16 | |
1951 | if (common->utf) | |
1952 | { | |
1953 | singlechar = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); | |
1954 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | |
1955 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | |
1956 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | |
1957 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | |
1958 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | |
1959 | JUMPHERE(singlechar); | |
1960 | } | } |
else | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | ||
#else | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | ||
1961 | #endif | #endif |
1962 | JUMPHERE(start); | JUMPHERE(start); |
1963 | ||
# | Line 1727 if (newlinecheck) | Line 1970 if (newlinecheck) |
1970 | return mainloop; | return mainloop; |
1971 | } | } |
1972 | ||
1973 | static SLJIT_INLINE void fast_forward_first_byte(compiler_common *common, pcre_uint16 firstbyte, BOOL firstline) | static SLJIT_INLINE void fast_forward_first_char(compiler_common *common, pcre_uchar first_char, BOOL caseless, BOOL firstline) |
1974 | { | { |
1975 | DEFINE_COMPILER; | DEFINE_COMPILER; |
1976 | struct sljit_label *start; | struct sljit_label *start; |
1977 | struct sljit_jump *leave; | struct sljit_jump *leave; |
1978 | struct sljit_jump *found; | struct sljit_jump *found; |
1979 | pcre_uint16 oc, bit; | pcre_uchar oc, bit; |
1980 | ||
1981 | if (firstline) | if (firstline) |
1982 | { | { |
# | Line 1743 if (firstline) | Line 1986 if (firstline) |
1986 | ||
1987 | start = LABEL(); | start = LABEL(); |
1988 | leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
1989 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
1990 | ||
1991 | if ((firstbyte & REQ_CASELESS) == 0) | oc = first_char; |
1992 | found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, firstbyte & 0xff); | if (caseless) |
1993 | { | |
1994 | oc = TABLE_GET(first_char, common->fcc, first_char); | |
1995 | #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) | |
1996 | if (first_char > 127 && common->utf) | |
1997 | oc = UCD_OTHERCASE(first_char); | |
1998 | #endif | |
1999 | } | |
2000 | if (first_char == oc) | |
2001 | found = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, first_char); | |
2002 | else | else |
2003 | { | { |
2004 | firstbyte &= 0xff; | bit = first_char ^ oc; |
oc = common->fcc[firstbyte]; | ||
bit = firstbyte ^ oc; | ||
2005 | if (ispowerof2(bit)) | if (ispowerof2(bit)) |
2006 | { | { |
2007 | OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit); | OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, bit); |
2008 | found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, firstbyte | bit); | found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, first_char | bit); |
2009 | } | } |
2010 | else | else |
2011 | { | { |
2012 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, firstbyte); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, first_char); |
2013 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
2014 | 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); |
2015 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); |
# | Line 1767 else | Line 2017 else |
2017 | } | } |
2018 | } | } |
2019 | ||
2020 | #ifdef SUPPORT_UTF8 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
2021 | if (common->utf8) | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 |
2022 | if (common->utf) | |
2023 | { | { |
2024 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes); | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); |
2025 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); | |
2026 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | |
2027 | } | |
2028 | #endif | |
2029 | #if defined SUPPORT_UTF && defined COMPILE_PCRE16 | |
2030 | if (common->utf) | |
2031 | { | |
2032 | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); | |
2033 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | |
2034 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | |
2035 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | |
2036 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | |
2037 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
2038 | } | } |
else | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | ||
#else | ||
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | ||
2039 | #endif | #endif |
2040 | JUMPTO(SLJIT_JUMP, start); | JUMPTO(SLJIT_JUMP, start); |
2041 | JUMPHERE(found); | JUMPHERE(found); |
# | Line 1811 if (common->nltype == NLTYPE_FIXED && co | Line 2070 if (common->nltype == NLTYPE_FIXED && co |
2070 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); |
2071 | firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0); | firstchar = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP2, 0); |
2072 | ||
2073 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 2); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); |
2074 | 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); |
2075 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_GREATER_EQUAL); |
2076 | #ifdef COMPILE_PCRE16 | |
2077 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); | |
2078 | #endif | |
2079 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
2080 | ||
2081 | loop = LABEL(); | loop = LABEL(); |
2082 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
2083 | leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
2084 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -2); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); |
2085 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), -1); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); |
2086 | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); | CMPTO(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); |
2087 | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); | CMPTO(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); |
2088 | ||
# | Line 1851 if (common->nltype == NLTYPE_ANY || comm | Line 2113 if (common->nltype == NLTYPE_ANY || comm |
2113 | leave = JUMP(SLJIT_JUMP); | leave = JUMP(SLJIT_JUMP); |
2114 | JUMPHERE(foundcr); | JUMPHERE(foundcr); |
2115 | notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | notfoundnl = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
2116 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
2117 | 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); |
2118 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); |
2119 | #ifdef COMPILE_PCRE16 | |
2120 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | |
2121 | #endif | |
2122 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
2123 | JUMPHERE(notfoundnl); | JUMPHERE(notfoundnl); |
2124 | JUMPHERE(leave); | JUMPHERE(leave); |
# | Line 1871 DEFINE_COMPILER; | Line 2136 DEFINE_COMPILER; |
2136 | struct sljit_label *start; | struct sljit_label *start; |
2137 | struct sljit_jump *leave; | struct sljit_jump *leave; |
2138 | struct sljit_jump *found; | struct sljit_jump *found; |
2139 | #ifndef COMPILE_PCRE8 | |
2140 | struct sljit_jump *jump; | |
2141 | #endif | |
2142 | ||
2143 | if (firstline) | if (firstline) |
2144 | { | { |
# | Line 1880 if (firstline) | Line 2148 if (firstline) |
2148 | ||
2149 | start = LABEL(); | start = LABEL(); |
2150 | leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | leave = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
2151 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
2152 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
2153 | if (common->utf8) | if (common->utf) |
2154 | OP1(SLJIT_MOV_UB, TMP3, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes); | OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); |
2155 | #endif | |
2156 | #ifndef COMPILE_PCRE8 | |
2157 | jump = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 255); | |
2158 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 255); | |
2159 | JUMPHERE(jump); | |
2160 | #endif | #endif |
2161 | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); |
2162 | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); |
# | Line 1892 OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TM | Line 2165 OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TM |
2165 | 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); |
2166 | found = JUMP(SLJIT_C_NOT_ZERO); | found = JUMP(SLJIT_C_NOT_ZERO); |
2167 | ||
2168 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
2169 | if (common->utf8) | if (common->utf) |
2170 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP3, 0); | OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); |
2171 | else | #endif |
2172 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
2173 | #else | #if defined SUPPORT_UTF && defined COMPILE_PCRE8 |
2174 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | if (common->utf) |
2175 | { | |
2176 | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0, start); | |
2177 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); | |
2178 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | |
2179 | } | |
2180 | #endif | |
2181 | #if defined SUPPORT_UTF && defined COMPILE_PCRE16 | |
2182 | if (common->utf) | |
2183 | { | |
2184 | CMPTO(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800, start); | |
2185 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | |
2186 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | |
2187 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | |
2188 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | |
2189 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | |
2190 | } | |
2191 | #endif | #endif |
2192 | JUMPTO(SLJIT_JUMP, start); | JUMPTO(SLJIT_JUMP, start); |
2193 | JUMPHERE(found); | JUMPHERE(found); |
# | Line 1908 if (firstline) | Line 2197 if (firstline) |
2197 | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); | OP1(SLJIT_MOV, STR_END, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0); |
2198 | } | } |
2199 | ||
2200 | static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uint16 reqbyte, BOOL has_firstbyte) | static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, pcre_uchar req_char, BOOL caseless, BOOL has_firstchar) |
2201 | { | { |
2202 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2203 | struct sljit_label *loop; | struct sljit_label *loop; |
# | Line 1917 struct sljit_jump *alreadyfound; | Line 2206 struct sljit_jump *alreadyfound; |
2206 | struct sljit_jump *found; | struct sljit_jump *found; |
2207 | struct sljit_jump *foundoc = NULL; | struct sljit_jump *foundoc = NULL; |
2208 | struct sljit_jump *notfound; | struct sljit_jump *notfound; |
2209 | pcre_uint16 oc, bit; | pcre_uchar oc, bit; |
2210 | ||
2211 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_BYTE_PTR); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR); |
2212 | OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX); | OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_BYTE_MAX); |
2213 | toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0); | toolong = CMP(SLJIT_C_LESS, TMP1, 0, STR_END, 0); |
2214 | alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0); | alreadyfound = CMP(SLJIT_C_LESS, STR_PTR, 0, TMP2, 0); |
2215 | ||
2216 | if (has_firstbyte) | if (has_firstchar) |
2217 | OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
2218 | else | else |
2219 | OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0); | OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0); |
2220 | ||
2221 | loop = LABEL(); | loop = LABEL(); |
2222 | notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0); | notfound = CMP(SLJIT_C_GREATER_EQUAL, TMP1, 0, STR_END, 0); |
2223 | ||
2224 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), 0); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0); |
2225 | if ((reqbyte & REQ_CASELESS) == 0) | oc = req_char; |
2226 | found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte & 0xff); | if (caseless) |
2227 | { | |
2228 | oc = TABLE_GET(req_char, common->fcc, req_char); | |
2229 | #if defined SUPPORT_UCP && !(defined COMPILE_PCRE8) | |
2230 | if (req_char > 127 && common->utf) | |
2231 | oc = UCD_OTHERCASE(req_char); | |
2232 | #endif | |
2233 | } | |
2234 | if (req_char == oc) | |
2235 | found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char); | |
2236 | else | else |
2237 | { | { |
2238 | reqbyte &= 0xff; | bit = req_char ^ oc; |
oc = common->fcc[reqbyte]; | ||
bit = reqbyte ^ oc; | ||
2239 | if (ispowerof2(bit)) | if (ispowerof2(bit)) |
2240 | { | { |
2241 | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit); | OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit); |
2242 | found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte | bit); | found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit); |
2243 | } | } |
2244 | else | else |
2245 | { | { |
2246 | found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, reqbyte); | found = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, req_char); |
2247 | foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc); | foundoc = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, oc); |
2248 | } | } |
2249 | } | } |
2250 | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); |
2251 | JUMPTO(SLJIT_JUMP, loop); | JUMPTO(SLJIT_JUMP, loop); |
2252 | ||
2253 | JUMPHERE(found); | JUMPHERE(found); |
2254 | if (foundoc) | if (foundoc) |
2255 | JUMPHERE(foundoc); | JUMPHERE(foundoc); |
2256 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_BYTE_PTR, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), REQ_CHAR_PTR, TMP1, 0); |
2257 | JUMPHERE(alreadyfound); | JUMPHERE(alreadyfound); |
2258 | JUMPHERE(toolong); | JUMPHERE(toolong); |
2259 | return notfound; | return notfound; |
# | Line 1966 return notfound; | Line 2262 return notfound; |
2262 | static void do_revertframes(compiler_common *common) | static void do_revertframes(compiler_common *common) |
2263 | { | { |
2264 | DEFINE_COMPILER; | DEFINE_COMPILER; |
struct sljit_jump *earlyexit; | ||
2265 | struct sljit_jump *jump; | struct sljit_jump *jump; |
2266 | struct sljit_label *mainloop; | struct sljit_label *mainloop; |
2267 | ||
2268 | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, RETURN_ADDR, 0, 1, 5, 5, common->localsize); |
2269 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD); | OP1(SLJIT_MOV, TMP1, 0, STACK_TOP, 0); |
2270 | ||
2271 | /* Drop frames until we reach STACK_TOP. */ | /* Drop frames until we reach STACK_TOP. */ |
earlyexit = CMP(SLJIT_C_LESS, TMP1, 0, STACK_TOP, 0); | ||
2272 | mainloop = LABEL(); | mainloop = LABEL(); |
2273 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), 0); |
2274 | jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); | jump = CMP(SLJIT_C_SIG_LESS_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); |
# | Line 1987 JUMPTO(SLJIT_JUMP, mainloop); | Line 2281 JUMPTO(SLJIT_JUMP, mainloop); |
2281 | JUMPHERE(jump); | JUMPHERE(jump); |
2282 | jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); | jump = CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, frame_end); |
2283 | /* End of dropping frames. */ | /* End of dropping frames. */ |
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), sizeof(sljit_w)); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP1, 0); | ||
CMPTO(SLJIT_C_GREATER_EQUAL, TMP1, 0, STACK_TOP, 0, mainloop); | ||
JUMPHERE(earlyexit); | ||
2284 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
2285 | ||
2286 | JUMPHERE(jump); | JUMPHERE(jump); |
# | Line 2010 JUMPTO(SLJIT_JUMP, mainloop); | Line 2300 JUMPTO(SLJIT_JUMP, mainloop); |
2300 | static void check_wordboundary(compiler_common *common) | static void check_wordboundary(compiler_common *common) |
2301 | { | { |
2302 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2303 | struct sljit_jump *beginend; | struct sljit_jump *skipread; |
2304 | #ifdef SUPPORT_UTF8 | #if !(defined COMPILE_PCRE8) || defined SUPPORT_UTF |
2305 | struct sljit_jump *jump; | struct sljit_jump *jump; |
2306 | #endif | #endif |
2307 | ||
2308 | SLJIT_ASSERT(ctype_word == 0x10); | SLJIT_COMPILE_ASSERT(ctype_word == 0x10, ctype_word_must_be_16); |
2309 | ||
2310 | sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize); | sljit_emit_fast_enter(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, 1, 5, 5, common->localsize); |
2311 | /* Get type of the previous char, and put it to LOCALS1. */ | /* Get type of the previous char, and put it to LOCALS1. */ |
2312 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
2313 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); |
2314 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, 0); |
2315 | beginend = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0); | skipread = CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0); |
2316 | skip_char_back(common); | skip_char_back(common); |
2317 | check_start_used_ptr(common); | |
2318 | read_char(common); | read_char(common); |
2319 | ||
2320 | /* Testing char type. */ | /* Testing char type. */ |
2321 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
2322 | if (common->useucp) | if (common->use_ucp) |
2323 | { | { |
2324 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); |
2325 | jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); | jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); |
# | Line 2045 if (common->useucp) | Line 2336 if (common->useucp) |
2336 | else | else |
2337 | #endif | #endif |
2338 | { | { |
2339 | #ifdef SUPPORT_UTF8 | #ifndef COMPILE_PCRE8 |
2340 | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | |
2341 | #elif defined SUPPORT_UTF | |
2342 | /* Here LOCALS1 has already been zeroed. */ | /* Here LOCALS1 has already been zeroed. */ |
2343 | jump = NULL; | jump = NULL; |
2344 | if (common->utf8) | if (common->utf) |
2345 | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); |
2346 | #endif | #endif /* COMPILE_PCRE8 */ |
2347 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), common->ctypes); |
2348 | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */); | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 4 /* ctype_word */); |
2349 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); |
2350 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, TMP1, 0); |
2351 | #ifdef SUPPORT_UTF8 | #ifndef COMPILE_PCRE8 |
2352 | JUMPHERE(jump); | |
2353 | #elif defined SUPPORT_UTF | |
2354 | if (jump != NULL) | if (jump != NULL) |
2355 | JUMPHERE(jump); | JUMPHERE(jump); |
2356 | #endif | #endif /* COMPILE_PCRE8 */ |
2357 | } | } |
2358 | JUMPHERE(beginend); | JUMPHERE(skipread); |
2359 | ||
2360 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); |
2361 | beginend = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | skipread = check_str_end(common); |
2362 | peek_char(common); | peek_char(common); |
2363 | ||
2364 | /* Testing char type. This is a code duplication. */ | /* Testing char type. This is a code duplication. */ |
2365 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
2366 | if (common->useucp) | if (common->use_ucp) |
2367 | { | { |
2368 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); |
2369 | jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); | jump = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); |
# | Line 2084 if (common->useucp) | Line 2379 if (common->useucp) |
2379 | else | else |
2380 | #endif | #endif |
2381 | { | { |
2382 | #ifdef SUPPORT_UTF8 | #ifndef COMPILE_PCRE8 |
2383 | /* TMP2 may be destroyed by peek_char. */ | |
2384 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); | |
2385 | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | |
2386 | #elif defined SUPPORT_UTF | |
2387 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0); |
2388 | jump = NULL; | jump = NULL; |
2389 | if (common->utf8) | if (common->utf) |
2390 | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); |
2391 | #endif | #endif |
2392 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), common->ctypes); |
2393 | OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */); | OP2(SLJIT_LSHR, TMP2, 0, TMP2, 0, SLJIT_IMM, 4 /* ctype_word */); |
2394 | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); | OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); |
2395 | #ifdef SUPPORT_UTF8 | #ifndef COMPILE_PCRE8 |
2396 | JUMPHERE(jump); | |
2397 | #elif defined SUPPORT_UTF | |
2398 | if (jump != NULL) | if (jump != NULL) |
2399 | JUMPHERE(jump); | JUMPHERE(jump); |
2400 | #endif | #endif /* COMPILE_PCRE8 */ |
2401 | } | } |
2402 | JUMPHERE(beginend); | JUMPHERE(skipread); |
2403 | ||
2404 | 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); |
2405 | sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | sljit_emit_fast_return(compiler, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
# | Line 2115 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_I | Line 2416 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_I |
2416 | 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); |
2417 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); |
2418 | 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); |
2419 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 |
2420 | if (common->utf8) | #ifdef COMPILE_PCRE8 |
2421 | if (common->utf) | |
2422 | { | { |
2423 | #endif | |
2424 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); |
2425 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); |
2426 | 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); |
2427 | #ifdef COMPILE_PCRE8 | |
2428 | } | } |
2429 | #endif | #endif |
2430 | #endif /* SUPPORT_UTF || COMPILE_PCRE16 */ | |
2431 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); |
2432 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
2433 | } | } |
# | Line 2139 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_E | Line 2444 COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_E |
2444 | 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); |
2445 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); |
2446 | 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); |
2447 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 |
2448 | if (common->utf8) | #ifdef COMPILE_PCRE8 |
2449 | if (common->utf) | |
2450 | { | { |
2451 | #endif | |
2452 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); |
2453 | 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); |
2454 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); |
# | Line 2155 if (common->utf8) | Line 2462 if (common->utf8) |
2462 | 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); |
2463 | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR, TMP2, 0, SLJIT_C_EQUAL); |
2464 | 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); |
2465 | #ifdef COMPILE_PCRE8 | |
2466 | } | } |
2467 | #endif | #endif |
2468 | #endif /* SUPPORT_UTF || COMPILE_PCRE16 */ | |
2469 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); |
2470 | ||
2471 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
# | Line 2173 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_I | Line 2482 OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_I |
2482 | 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); |
2483 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_LESS_EQUAL); |
2484 | 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); |
2485 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 |
2486 | if (common->utf8) | #ifdef COMPILE_PCRE8 |
2487 | if (common->utf) | |
2488 | { | { |
2489 | #endif | |
2490 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); |
2491 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1); |
2492 | 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); |
2493 | #ifdef COMPILE_PCRE8 | |
2494 | } | } |
2495 | #endif | #endif |
2496 | #endif /* SUPPORT_UTF || COMPILE_PCRE16 */ | |
2497 | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_OR | SLJIT_SET_E, TMP2, 0, SLJIT_C_EQUAL); |
2498 | ||
2499 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
# | Line 2199 sljit_emit_fast_enter(compiler, RETURN_A | Line 2512 sljit_emit_fast_enter(compiler, RETURN_A |
2512 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
2513 | OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0); | OP1(SLJIT_MOV, TMP3, 0, CHAR1, 0); |
2514 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR2, 0); |
2515 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); |
2516 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
2517 | ||
2518 | label = LABEL(); | label = LABEL(); |
2519 | OP1(SLJIT_MOVU_UB, CHAR1, 0, SLJIT_MEM1(TMP1), 1); | OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1)); |
2520 | OP1(SLJIT_MOVU_UB, CHAR2, 0, SLJIT_MEM1(STR_PTR), 1); | OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
2521 | jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0); | jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0); |
2522 | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); |
2523 | JUMPTO(SLJIT_C_NOT_ZERO, label); | JUMPTO(SLJIT_C_NOT_ZERO, label); |
2524 | ||
2525 | JUMPHERE(jump); | JUMPHERE(jump); |
2526 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
2527 | OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0); | OP1(SLJIT_MOV, CHAR1, 0, TMP3, 0); |
2528 | OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
2529 | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); | sljit_emit_fast_return(compiler, RETURN_ADDR, 0); |
# | Line 2231 OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0); | Line 2544 OP1(SLJIT_MOV, TMP3, 0, LCC_TABLE, 0); |
2544 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, CHAR1, 0); |
2545 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, CHAR2, 0); |
2546 | OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc); | OP1(SLJIT_MOV, LCC_TABLE, 0, SLJIT_IMM, common->lcc); |
2547 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); |
2548 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
2549 | ||
2550 | label = LABEL(); | label = LABEL(); |
2551 | OP1(SLJIT_MOVU_UB, CHAR1, 0, SLJIT_MEM1(TMP1), 1); | OP1(MOVU_UCHAR, CHAR1, 0, SLJIT_MEM1(TMP1), IN_UCHARS(1)); |
2552 | OP1(SLJIT_MOVU_UB, CHAR2, 0, SLJIT_MEM1(STR_PTR), 1); | OP1(MOVU_UCHAR, CHAR2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
2553 | #ifndef COMPILE_PCRE8 | |
2554 | jump = CMP(SLJIT_C_GREATER, CHAR1, 0, SLJIT_IMM, 255); | |
2555 | #endif | |
2556 | OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0); | OP1(SLJIT_MOV_UB, CHAR1, 0, SLJIT_MEM2(LCC_TABLE, CHAR1), 0); |
2557 | #ifndef COMPILE_PCRE8 | |
2558 | JUMPHERE(jump); | |
2559 | jump = CMP(SLJIT_C_GREATER, CHAR2, 0, SLJIT_IMM, 255); | |
2560 | #endif | |
2561 | OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0); | OP1(SLJIT_MOV_UB, CHAR2, 0, SLJIT_MEM2(LCC_TABLE, CHAR2), 0); |
2562 | #ifndef COMPILE_PCRE8 | |
2563 | JUMPHERE(jump); | |
2564 | #endif | |
2565 | jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0); | jump = CMP(SLJIT_C_NOT_EQUAL, CHAR1, 0, CHAR2, 0); |
2566 | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); |
2567 | JUMPTO(SLJIT_C_NOT_ZERO, label); | JUMPTO(SLJIT_C_NOT_ZERO, label); |
2568 | ||
2569 | JUMPHERE(jump); | JUMPHERE(jump); |
2570 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
2571 | OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0); | OP1(SLJIT_MOV, LCC_TABLE, 0, TMP3, 0); |
2572 | OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | OP1(SLJIT_MOV, CHAR1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
2573 | OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); | OP1(SLJIT_MOV, CHAR2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1); |
# | Line 2255 sljit_emit_fast_return(compiler, RETURN_ | Line 2578 sljit_emit_fast_return(compiler, RETURN_ |
2578 | #undef CHAR1 | #undef CHAR1 |
2579 | #undef CHAR2 | #undef CHAR2 |
2580 | ||
2581 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF && defined SUPPORT_UCP |
#ifdef SUPPORT_UCP | ||
2582 | ||
2583 | static uschar * SLJIT_CALL do_utf8caselesscmp(uschar *src1, jit_arguments *args, uschar *end1) | static const pcre_uchar *SLJIT_CALL do_utf_caselesscmp(pcre_uchar *src1, jit_arguments *args, pcre_uchar *end1) |
2584 | { | { |
2585 | /* This function would be ineffective to do in JIT level. */ | /* This function would be ineffective to do in JIT level. */ |
2586 | int c1, c2; | int c1, c2; |
2587 | uschar *src2 = args->ptr; | const pcre_uchar *src2 = args->ptr; |
2588 | uschar *end2 = (uschar*)args->end; | const pcre_uchar *end2 = args->end; |
2589 | ||
2590 | while (src1 < end1) | while (src1 < end1) |
2591 | { | { |
2592 | if (src2 >= end2) | if (src2 >= end2) |
2593 | return 0; | return (pcre_uchar*)1; |
2594 | GETCHARINC(c1, src1); | GETCHARINC(c1, src1); |
2595 | GETCHARINC(c2, src2); | GETCHARINC(c2, src2); |
2596 | if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return 0; | if (c1 != c2 && c1 != UCD_OTHERCASE(c2)) return NULL; |
2597 | } | } |
2598 | return src2; | return src2; |
2599 | } | } |
2600 | ||
2601 | #endif | #endif /* SUPPORT_UTF && SUPPORT_UCP */ |
#endif | ||
2602 | ||
2603 | static uschar *byte_sequence_compare(compiler_common *common, BOOL caseless, uschar *cc, | static pcre_uchar *byte_sequence_compare(compiler_common *common, BOOL caseless, pcre_uchar *cc, |
2604 | compare_context* context, jump_list **fallbacks) | compare_context* context, jump_list **fallbacks) |
2605 | { | { |
2606 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2607 | unsigned int othercasebit = 0; | unsigned int othercasebit = 0; |
2608 | uschar *othercasebyte = NULL; | pcre_uchar *othercasechar = NULL; |
2609 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
2610 | int utf8length; | int utflength; |
2611 | #endif | #endif |
2612 | ||
2613 | if (caseless && char_has_othercase(common, cc)) | if (caseless && char_has_othercase(common, cc)) |
# | Line 2294 if (caseless && char_has_othercase(commo | Line 2615 if (caseless && char_has_othercase(commo |
2615 | othercasebit = char_get_othercase_bit(common, cc); | othercasebit = char_get_othercase_bit(common, cc); |
2616 | SLJIT_ASSERT(othercasebit); | SLJIT_ASSERT(othercasebit); |
2617 | /* Extracting bit difference info. */ | /* Extracting bit difference info. */ |
2618 | othercasebyte = cc + (othercasebit >> 8); | #ifdef COMPILE_PCRE8 |
2619 | othercasechar = cc + (othercasebit >> 8); | |
2620 | othercasebit &= 0xff; | othercasebit &= 0xff; |
2621 | #else | |
2622 | #ifdef COMPILE_PCRE16 | |
2623 | othercasechar = cc + (othercasebit >> 9); | |
2624 | if ((othercasebit & 0x100) != 0) | |
2625 | othercasebit = (othercasebit & 0xff) << 8; | |
2626 | else | |
2627 | othercasebit &= 0xff; | |
2628 | #endif | |
2629 | #endif | |
2630 | } | } |
2631 | ||
2632 | if (context->sourcereg == -1) | if (context->sourcereg == -1) |
2633 | { | { |
2634 | #ifdef COMPILE_PCRE8 | |
2635 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED |
2636 | if (context->length >= 4) | if (context->length >= 4) |
2637 | OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); | OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); |
2638 | else if (context->length >= 2) | else if (context->length >= 2) |
2639 | OP1(SLJIT_MOV_SH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); | OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); |
2640 | else | else |
2641 | #endif | #endif |
2642 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); |
2643 | #else | |
2644 | #ifdef COMPILE_PCRE16 | |
2645 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | |
2646 | if (context->length >= 4) | |
2647 | OP1(SLJIT_MOV_SI, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); | |
2648 | else | |
2649 | #endif | |
2650 | OP1(SLJIT_MOV_UH, TMP1, 0, SLJIT_MEM1(STR_PTR), -context->length); | |
2651 | #endif | |
2652 | #endif /* COMPILE_PCRE8 */ | |
2653 | context->sourcereg = TMP2; | context->sourcereg = TMP2; |
2654 | } | } |
2655 | ||
2656 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
2657 | utf8length = 1; | utflength = 1; |
2658 | if (common->utf8 && *cc >= 0xc0) | if (common->utf && HAS_EXTRALEN(*cc)) |
2659 | utf8length += _pcre_utf8_table4[*cc & 0x3f]; | utflength += GET_EXTRALEN(*cc); |
2660 | ||
2661 | do | do |
2662 | { | { |
2663 | #endif | #endif |
2664 | ||
2665 | context->length--; | context->length -= IN_UCHARS(1); |
2666 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED |
2667 | ||
2668 | /* Unaligned read is supported. */ | /* Unaligned read is supported. */ |
2669 | if (othercasebit != 0 && othercasebyte == cc) | if (othercasebit != 0 && othercasechar == cc) |
2670 | { | { |
2671 | context->c.asbytes[context->byteptr] = *cc | othercasebit; | context->c.asuchars[context->ucharptr] = *cc | othercasebit; |
2672 | context->oc.asbytes[context->byteptr] = othercasebit; | context->oc.asuchars[context->ucharptr] = othercasebit; |
2673 | } | } |
2674 | else | else |
2675 | { | { |
2676 | context->c.asbytes[context->byteptr] = *cc; | context->c.asuchars[context->ucharptr] = *cc; |
2677 | context->oc.asbytes[context->byteptr] = 0; | context->oc.asuchars[context->ucharptr] = 0; |
2678 | } | } |
2679 | context->byteptr++; | context->ucharptr++; |
2680 | ||
2681 | if (context->byteptr >= 4 || context->length == 0 || (context->byteptr == 2 && context->length == 1)) | #ifdef COMPILE_PCRE8 |
2682 | if (context->ucharptr >= 4 || context->length == 0 || (context->ucharptr == 2 && context->length == 1)) | |
2683 | #else | |
2684 | if (context->ucharptr >= 2 || context->length == 0) | |
2685 | #endif | |
2686 | { | { |
2687 | if (context->length >= 4) | if (context->length >= 4) |
2688 | 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); |
2689 | #ifdef COMPILE_PCRE8 | |
2690 | else if (context->length >= 2) | else if (context->length >= 2) |
2691 | OP1(SLJIT_MOV_SH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); | OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); |
2692 | else if (context->length >= 1) | else if (context->length >= 1) |
2693 | 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); |
2694 | #else | |
2695 | else if (context->length >= 2) | |
2696 | OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); | |
2697 | #endif | |
2698 | context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; | context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; |
2699 | ||
2700 | switch(context->byteptr) | switch(context->ucharptr) |
2701 | { | { |
2702 | case 4: | case 4 / sizeof(pcre_uchar): |
2703 | if (context->oc.asint != 0) | if (context->oc.asint != 0) |
2704 | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint); | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asint); |
2705 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asint | context->oc.asint)); |
2706 | break; | break; |
2707 | ||
2708 | case 2: | case 2 / sizeof(pcre_uchar): |
2709 | if (context->oc.asshort != 0) | if (context->oc.asushort != 0) |
2710 | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asshort); | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asushort); |
2711 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asshort | context->oc.asshort)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asushort | context->oc.asushort)); |
2712 | break; | break; |
2713 | ||
2714 | #ifdef COMPILE_PCRE8 | |
2715 | case 1: | case 1: |
2716 | if (context->oc.asbyte != 0) | if (context->oc.asbyte != 0) |
2717 | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte); | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, context->oc.asbyte); |
2718 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, context->c.asbyte | context->oc.asbyte)); |
2719 | break; | break; |
2720 | #endif | |
2721 | ||
2722 | default: | default: |
2723 | SLJIT_ASSERT_STOP(); | SLJIT_ASSERT_STOP(); |
2724 | break; | break; |
2725 | } | } |
2726 | context->byteptr = 0; | context->ucharptr = 0; |
2727 | } | } |
2728 | ||
2729 | #else | #else |
2730 | ||
2731 | /* Unaligned read is unsupported. */ | /* Unaligned read is unsupported. */ |
2732 | #ifdef COMPILE_PCRE8 | |
2733 | if (context->length > 0) | if (context->length > 0) |
2734 | 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); |
2735 | #else | |
2736 | if (context->length > 0) | |
2737 | OP1(SLJIT_MOV_UH, context->sourcereg, 0, SLJIT_MEM1(STR_PTR), -context->length); | |
2738 | #endif | |
2739 | context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; | context->sourcereg = context->sourcereg == TMP1 ? TMP2 : TMP1; |
2740 | ||
2741 | if (othercasebit != 0 && othercasebyte == cc) | if (othercasebit != 0 && othercasechar == cc) |
2742 | { | { |
2743 | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); | OP2(SLJIT_OR, context->sourcereg, 0, context->sourcereg, 0, SLJIT_IMM, othercasebit); |
2744 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, context->sourcereg, 0, SLJIT_IMM, *cc | othercasebit)); |
# | Line 2391 do | Line 2749 do |
2749 | #endif | #endif |
2750 | ||
2751 | cc++; | cc++; |
2752 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
2753 | utf8length--; | utflength--; |
2754 | } | } |
2755 | while (utf8length > 0); | while (utflength > 0); |
2756 | #endif | #endif |
2757 | ||
2758 | return cc; | return cc; |
2759 | } | } |
2760 | ||
2761 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
2762 | ||
2763 | #define SET_TYPE_OFFSET(value) \ | #define SET_TYPE_OFFSET(value) \ |
2764 | if ((value) != typeoffset) \ | if ((value) != typeoffset) \ |
# | Line 2422 return cc; | Line 2780 return cc; |
2780 | } \ | } \ |
2781 | charoffset = (value); | charoffset = (value); |
2782 | ||
2783 | static void compile_xclass_hotpath(compiler_common *common, uschar *cc, jump_list **fallbacks) | static void compile_xclass_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks) |
2784 | { | { |
2785 | DEFINE_COMPILER; | DEFINE_COMPILER; |
2786 | jump_list *found = NULL; | jump_list *found = NULL; |
# | Line 2430 jump_list **list = (*cc & XCL_NOT) == 0 | Line 2788 jump_list **list = (*cc & XCL_NOT) == 0 |
2788 | unsigned int c; | unsigned int c; |
2789 | int compares; | int compares; |
2790 | struct sljit_jump *jump = NULL; | struct sljit_jump *jump = NULL; |
2791 | uschar *ccbegin; | pcre_uchar *ccbegin; |
2792 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
2793 | BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE; | BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE; |
2794 | BOOL charsaved = FALSE; | BOOL charsaved = FALSE; |
2795 | int typereg = TMP1, scriptreg = TMP1, typeoffset; | int typereg = TMP1, scriptreg = TMP1; |
2796 | unsigned int typeoffset; | |
2797 | #endif | #endif |
2798 | int charoffset, invertcmp, numberofcmps; | int invertcmp, numberofcmps; |
2799 | unsigned int charoffset; | |
2800 | ||
2801 | /* Although SUPPORT_UTF8 must be defined, we are not necessary in utf8 mode. */ | /* Although SUPPORT_UTF must be defined, we are not necessary in utf mode. */ |
2802 | check_input_end(common, fallbacks); | fallback_at_str_end(common, fallbacks); |
2803 | read_char(common); | read_char(common); |
2804 | ||
2805 | if ((*cc++ & XCL_MAP) != 0) | if ((*cc++ & XCL_MAP) != 0) |
2806 | { | { |
2807 | OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); | OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); |
2808 | if (common->utf8) | #ifndef COMPILE_PCRE8 |
2809 | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | |
2810 | #elif defined SUPPORT_UTF | |
2811 | if (common->utf) | |
2812 | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | jump = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); |
2813 | #endif | |
2814 | ||
2815 | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); |
2816 | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); |
# | Line 2455 if ((*cc++ & XCL_MAP) != 0) | Line 2819 if ((*cc++ & XCL_MAP) != 0) |
2819 | 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); |
2820 | add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO)); | add_jump(compiler, list, JUMP(SLJIT_C_NOT_ZERO)); |
2821 | ||
2822 | if (common->utf8) | #ifndef COMPILE_PCRE8 |
2823 | JUMPHERE(jump); | |
2824 | #elif defined SUPPORT_UTF | |
2825 | if (common->utf) | |
2826 | JUMPHERE(jump); | JUMPHERE(jump); |
2827 | #endif | |
2828 | OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); | OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); |
2829 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
2830 | charsaved = TRUE; | charsaved = TRUE; |
2831 | #endif | #endif |
2832 | cc += 32; | cc += 32 / sizeof(pcre_uchar); |
2833 | } | } |
2834 | ||
2835 | /* Scanning the necessary info. */ | /* Scanning the necessary info. */ |
# | Line 2473 while (*cc != XCL_END) | Line 2841 while (*cc != XCL_END) |
2841 | if (*cc == XCL_SINGLE) | if (*cc == XCL_SINGLE) |
2842 | { | { |
2843 | cc += 2; | cc += 2; |
2844 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
2845 | if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f]; | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); |
2846 | #endif | #endif |
2847 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
2848 | needschar = TRUE; | needschar = TRUE; |
# | Line 2483 while (*cc != XCL_END) | Line 2851 while (*cc != XCL_END) |
2851 | else if (*cc == XCL_RANGE) | else if (*cc == XCL_RANGE) |
2852 | { | { |
2853 | cc += 2; | cc += 2; |
2854 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
2855 | if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f]; | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); |
2856 | #endif | #endif |
2857 | cc++; | cc++; |
2858 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
2859 | if (common->utf8 && cc[-1] >= 0xc0) cc += _pcre_utf8_table4[cc[-1] & 0x3f]; | if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); |
2860 | #endif | #endif |
2861 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
2862 | needschar = TRUE; | needschar = TRUE; |
# | Line 2558 if (needstype || needsscript) | Line 2926 if (needstype || needsscript) |
2926 | { | { |
2927 | if (scriptreg == TMP1) | if (scriptreg == TMP1) |
2928 | { | { |
2929 | OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, script)); | OP1(SLJIT_MOV, scriptreg, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); |
2930 | OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3); | OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM2(scriptreg, TMP2), 3); |
2931 | } | } |
2932 | else | else |
2933 | { | { |
2934 | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3); | OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3); |
2935 | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_w)_pcre_ucd_records + SLJIT_OFFSETOF(ucd_record, script)); | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_w)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); |
2936 | OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0); | OP1(SLJIT_MOV_UB, scriptreg, 0, SLJIT_MEM1(TMP2), 0); |
2937 | } | } |
2938 | } | } |
# | Line 2588 while (*cc != XCL_END) | Line 2956 while (*cc != XCL_END) |
2956 | if (*cc == XCL_SINGLE) | if (*cc == XCL_SINGLE) |
2957 | { | { |
2958 | cc ++; | cc ++; |
2959 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
2960 | if (common->utf8) | if (common->utf) |
2961 | { | { |
2962 | GETCHARINC(c, cc); | GETCHARINC(c, cc); |
2963 | } | } |
# | Line 2619 while (*cc != XCL_END) | Line 2987 while (*cc != XCL_END) |
2987 | else if (*cc == XCL_RANGE) | else if (*cc == XCL_RANGE) |
2988 | { | { |
2989 | cc ++; | cc ++; |
2990 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
2991 | if (common->utf8) | if (common->utf) |
2992 | { | { |
2993 | GETCHARINC(c, cc); | GETCHARINC(c, cc); |
2994 | } | } |
# | Line 2628 while (*cc != XCL_END) | Line 2996 while (*cc != XCL_END) |
2996 | #endif | #endif |
2997 | c = *cc++; | c = *cc++; |
2998 | SET_CHAR_OFFSET(c); | SET_CHAR_OFFSET(c); |
2999 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
3000 | if (common->utf8) | if (common->utf) |
3001 | { | { |
3002 | GETCHARINC(c, cc); | GETCHARINC(c, cc); |
3003 | } | } |
# | Line 2685 while (*cc != XCL_END) | Line 3053 while (*cc != XCL_END) |
3053 | break; | break; |
3054 | ||
3055 | case PT_GC: | case PT_GC: |
3056 | c = _pcre_ucp_typerange[(int)cc[1] * 2]; | c = PRIV(ucp_typerange)[(int)cc[1] * 2]; |
3057 | SET_TYPE_OFFSET(c); | SET_TYPE_OFFSET(c); |
3058 | jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, _pcre_ucp_typerange[(int)cc[1] * 2 + 1] - c); | jump = CMP(SLJIT_C_LESS_EQUAL ^ invertcmp, typereg, 0, SLJIT_IMM, PRIV(ucp_typerange)[(int)cc[1] * 2 + 1] - c); |
3059 | break; | break; |
3060 | ||
3061 | case PT_PC: | case PT_PC: |
# | Line 2749 if (found != NULL) | Line 3117 if (found != NULL) |
3117 | ||
3118 | #endif | #endif |
3119 | ||
3120 | static uschar *compile_char1_hotpath(compiler_common *common, uschar type, uschar *cc, jump_list **fallbacks) | static pcre_uchar *compile_char1_hotpath(compiler_common *common, pcre_uchar type, pcre_uchar *cc, jump_list **fallbacks) |
3121 | { | { |
3122 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3123 | int length; | int length; |
3124 | unsigned int c, oc, bit; | unsigned int c, oc, bit; |
3125 | compare_context context; | compare_context context; |
3126 | struct sljit_jump *jump[4]; | struct sljit_jump *jump[4]; |
3127 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
3128 | struct sljit_label *label; | struct sljit_label *label; |
3129 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
3130 | uschar propdata[5]; | pcre_uchar propdata[5]; |
3131 | #endif | #endif |
3132 | #endif | #endif |
3133 | ||
# | Line 2785 switch(type) | Line 3153 switch(type) |
3153 | ||
3154 | case OP_NOT_DIGIT: | case OP_NOT_DIGIT: |
3155 | case OP_DIGIT: | case OP_DIGIT: |
3156 | check_input_end(common, fallbacks); | fallback_at_str_end(common, fallbacks); |
3157 | read_char8_type(common); | read_char8_type(common); |
3158 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit); |
3159 | add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); | add_jump(compiler, fallbacks, JUMP(type == OP_DIGIT ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
# | Line 2793 switch(type) | Line 3161 switch(type) |
3161 | ||
3162 | case OP_NOT_WHITESPACE: | case OP_NOT_WHITESPACE: |
3163 | case OP_WHITESPACE: | case OP_WHITESPACE: |
3164 | check_input_end(common, fallbacks); | fallback_at_str_end(common, fallbacks); |
3165 | read_char8_type(common); | read_char8_type(common); |
3166 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space); |
3167 | add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); | add_jump(compiler, fallbacks, JUMP(type == OP_WHITESPACE ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
# | Line 2801 switch(type) | Line 3169 switch(type) |
3169 | ||
3170 | case OP_NOT_WORDCHAR: | case OP_NOT_WORDCHAR: |
3171 | case OP_WORDCHAR: | case OP_WORDCHAR: |
3172 | check_input_end(common, fallbacks); | fallback_at_str_end(common, fallbacks); |
3173 | read_char8_type(common); | read_char8_type(common); |
3174 | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); | OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word); |
3175 | add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); | add_jump(compiler, fallbacks, JUMP(type == OP_WORDCHAR ? SLJIT_C_ZERO : SLJIT_C_NOT_ZERO)); |
3176 | return cc; | return cc; |
3177 | ||
3178 | case OP_ANY: | case OP_ANY: |
3179 | check_input_end(common, fallbacks); | fallback_at_str_end(common, fallbacks); |
3180 | read_char(common); | read_char(common); |
3181 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
3182 | { | { |
3183 | 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); |
3184 | jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
3185 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
3186 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, common->newline & 0xff)); |
3187 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
3188 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
# | Line 2824 switch(type) | Line 3192 switch(type) |
3192 | return cc; | return cc; |
3193 | ||
3194 | case OP_ALLANY: | case OP_ALLANY: |
3195 | check_input_end(common, fallbacks); | fallback_at_str_end(common, fallbacks); |
3196 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
3197 | if (common->utf8) | if (common->utf) |
3198 | { | { |
3199 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
3200 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
3201 | #ifdef COMPILE_PCRE8 | |
3202 | jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); | |
3203 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); | |
3204 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); |
3205 | #else /* COMPILE_PCRE8 */ | |
3206 | #ifdef COMPILE_PCRE16 | |
3207 | jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xd800); | |
3208 | OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00); | |
3209 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800); | |
3210 | COND_VALUE(SLJIT_MOV, TMP1, 0, SLJIT_C_EQUAL); | |
3211 | OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); | |
3212 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | |
3213 | #endif /* COMPILE_PCRE16 */ | |
3214 | #endif /* COMPILE_PCRE8 */ | |
3215 | JUMPHERE(jump[0]); | |
3216 | return cc; | return cc; |
3217 | } | } |
3218 | #endif | #endif |
3219 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
3220 | return cc; | |
3221 | ||
3222 | case OP_ANYBYTE: | |
3223 | fallback_at_str_end(common, fallbacks); | |
3224 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); | |
3225 | return cc; | return cc; |
3226 | ||
3227 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
3228 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
3229 | case OP_NOTPROP: | case OP_NOTPROP: |
3230 | case OP_PROP: | case OP_PROP: |
# | Line 2852 switch(type) | Line 3239 switch(type) |
3239 | #endif | #endif |
3240 | ||
3241 | case OP_ANYNL: | case OP_ANYNL: |
3242 | check_input_end(common, fallbacks); | fallback_at_str_end(common, fallbacks); |
3243 | read_char(common); | read_char(common); |
3244 | 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); |
3245 | jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | jump[1] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
3246 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
3247 | jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); | jump[2] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); |
3248 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
3249 | jump[3] = JUMP(SLJIT_JUMP); | jump[3] = JUMP(SLJIT_JUMP); |
3250 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
3251 | check_newlinechar(common, common->bsr_nltype, fallbacks, FALSE); | check_newlinechar(common, common->bsr_nltype, fallbacks, FALSE); |
# | Line 2869 switch(type) | Line 3256 switch(type) |
3256 | ||
3257 | case OP_NOT_HSPACE: | case OP_NOT_HSPACE: |
3258 | case OP_HSPACE: | case OP_HSPACE: |
3259 | check_input_end(common, fallbacks); | fallback_at_str_end(common, fallbacks); |
3260 | read_char(common); | read_char(common); |
3261 | add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL)); |
3262 | add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); | add_jump(compiler, fallbacks, JUMP(type == OP_NOT_HSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
# | Line 2877 switch(type) | Line 3264 switch(type) |
3264 | ||
3265 | case OP_NOT_VSPACE: | case OP_NOT_VSPACE: |
3266 | case OP_VSPACE: | case OP_VSPACE: |
3267 | check_input_end(common, fallbacks); | fallback_at_str_end(common, fallbacks); |
3268 | read_char(common); | read_char(common); |
3269 | add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL)); |
3270 | add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); | add_jump(compiler, fallbacks, JUMP(type == OP_NOT_VSPACE ? SLJIT_C_NOT_ZERO : SLJIT_C_ZERO)); |
# | Line 2885 switch(type) | Line 3272 switch(type) |
3272 | ||
3273 | #ifdef SUPPORT_UCP | #ifdef SUPPORT_UCP |
3274 | case OP_EXTUNI: | case OP_EXTUNI: |
3275 | check_input_end(common, fallbacks); | fallback_at_str_end(common, fallbacks); |
3276 | read_char(common); | read_char(common); |
3277 | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); |
3278 | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); | OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Mc); |
# | Line 2901 switch(type) | Line 3288 switch(type) |
3288 | ||
3289 | OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); | OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); |
3290 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
3291 | if (common->mode == JIT_PARTIAL_HARD_COMPILE) | |
3292 | { | |
3293 | jump[0] = CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0); | |
3294 | check_partial(common); | |
3295 | JUMPHERE(jump[0]); | |
3296 | } | |
3297 | return cc; | return cc; |
3298 | #endif | #endif |
3299 | ||
# | Line 2908 switch(type) | Line 3301 switch(type) |
3301 | jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); | jump[0] = CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); |
3302 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
3303 | { | { |
3304 | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2); | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
3305 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
3306 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); |
3307 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
3308 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); |
3309 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); |
3310 | } | } |
3311 | else if (common->nltype == NLTYPE_FIXED) | else if (common->nltype == NLTYPE_FIXED) |
3312 | { | { |
3313 | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
3314 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
3315 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, STR_END, 0)); |
3316 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, common->newline)); |
3317 | } | } |
3318 | else | else |
3319 | { | { |
3320 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
3321 | jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); | jump[1] = CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); |
3322 | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2); | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
3323 | 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); |
3324 | jump[2] = JUMP(SLJIT_C_GREATER); | jump[2] = JUMP(SLJIT_C_GREATER); |
3325 | add_jump(compiler, fallbacks, JUMP(SLJIT_C_LESS)); | add_jump(compiler, fallbacks, JUMP(SLJIT_C_LESS)); |
3326 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 1); | /* Equal. */ |
3327 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); | |
3328 | jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); | jump[3] = CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL); |
3329 | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); |
3330 | ||
3331 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
3332 | if (common->nltype == NLTYPE_ANYCRLF) | if (common->nltype == NLTYPE_ANYCRLF) |
3333 | { | { |
3334 | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 1); | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
3335 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, STR_END, 0)); |
3336 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_NL)); |
3337 | } | } |
# | Line 2954 switch(type) | Line 3348 switch(type) |
3348 | JUMPHERE(jump[3]); | JUMPHERE(jump[3]); |
3349 | } | } |
3350 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
3351 | check_partial(common); | |
3352 | return cc; | return cc; |
3353 | ||
3354 | case OP_EOD: | case OP_EOD: |
3355 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, STR_PTR, 0, STR_END, 0)); |
3356 | check_partial(common); | |
3357 | return cc; | return cc; |
3358 | ||
3359 | case OP_CIRC: | case OP_CIRC: |
# | Line 2977 switch(type) | Line 3373 switch(type) |
3373 | jump[0] = JUMP(SLJIT_JUMP); | jump[0] = JUMP(SLJIT_JUMP); |
3374 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
3375 | ||
3376 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, end)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); |
add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP2, 0, STR_PTR, 0)); | ||
3377 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
3378 | { | { |
3379 | OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2); | OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
3380 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, TMP2, 0, TMP1, 0)); |
3381 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -2); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); |
3382 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), -1); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); |
3383 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); |
3384 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); |
3385 | } | } |
# | Line 3006 switch(type) | Line 3400 switch(type) |
3400 | if (!common->endonly) | if (!common->endonly) |
3401 | compile_char1_hotpath(common, OP_EODN, cc, fallbacks); | compile_char1_hotpath(common, OP_EODN, cc, fallbacks); |
3402 | else | else |
3403 | { | |
3404 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, STR_END, 0)); |
3405 | check_partial(common); | |
3406 | } | |
3407 | return cc; | return cc; |
3408 | ||
3409 | case OP_DOLLM: | case OP_DOLLM: |
# | Line 3014 switch(type) | Line 3411 switch(type) |
3411 | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0); |
3412 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, noteol)); |
3413 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
3414 | check_partial(common); | |
3415 | jump[0] = JUMP(SLJIT_JUMP); | jump[0] = JUMP(SLJIT_JUMP); |
3416 | JUMPHERE(jump[1]); | JUMPHERE(jump[1]); |
3417 | ||
3418 | if (common->nltype == NLTYPE_FIXED && common->newline > 255) | if (common->nltype == NLTYPE_FIXED && common->newline > 255) |
3419 | { | { |
3420 | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, 2); | OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); |
3421 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, TMP2, 0, STR_END, 0)); |
3422 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); |
3423 | OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(STR_PTR), 1); | OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); |
3424 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff)); |
3425 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff)); |
3426 | } | } |
# | Line 3037 switch(type) | Line 3435 switch(type) |
3435 | case OP_CHAR: | case OP_CHAR: |
3436 | case OP_CHARI: | case OP_CHARI: |
3437 | length = 1; | length = 1; |
3438 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
3439 | if (common->utf8 && *cc >= 0xc0) length += _pcre_utf8_table4[*cc & 0x3f]; | if (common->utf && HAS_EXTRALEN(*cc)) length += GET_EXTRALEN(*cc); |
3440 | #endif | #endif |
3441 | if (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0) | if (common->mode == JIT_COMPILE && (type == OP_CHAR || !char_has_othercase(common, cc) || char_get_othercase_bit(common, cc) != 0)) |
3442 | { | { |
3443 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, length); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); |
3444 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); |
3445 | ||
3446 | context.length = length; | context.length = IN_UCHARS(length); |
3447 | context.sourcereg = -1; | context.sourcereg = -1; |
3448 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED |
3449 | context.byteptr = 0; | context.ucharptr = 0; |
3450 | #endif | #endif |
3451 | return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks); | return byte_sequence_compare(common, type == OP_CHARI, cc, &context, fallbacks); |
3452 | } | } |
3453 | add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); | fallback_at_str_end(common, fallbacks); |
3454 | read_char(common); | read_char(common); |
3455 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
3456 | if (common->utf8) | if (common->utf) |
3457 | { | { |
3458 | GETCHAR(c, cc); | GETCHAR(c, cc); |
3459 | } | } |
3460 | else | else |
3461 | #endif | #endif |
3462 | c = *cc; | c = *cc; |
3463 | if (type == OP_CHAR || !char_has_othercase(common, cc)) | |
3464 | { | |
3465 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c)); | |
3466 | return cc + length; | |
3467 | } | |
3468 | oc = char_othercase(common, c); | |
3469 | bit = c ^ oc; | |
3470 | if (ispowerof2(bit)) | |
3471 | { | |
3472 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, bit); | |
3473 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c | bit)); | |
3474 | return cc + length; | |
3475 | } | |
3476 | 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); |
3477 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
3478 | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c)); | OP2(SLJIT_SUB | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_othercase(common, c)); |
# | Line 3071 switch(type) | Line 3482 switch(type) |
3482 | ||
3483 | case OP_NOT: | case OP_NOT: |
3484 | case OP_NOTI: | case OP_NOTI: |
3485 | fallback_at_str_end(common, fallbacks); | |
3486 | length = 1; | length = 1; |
3487 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
3488 | if (common->utf8) | if (common->utf) |
3489 | { | { |
3490 | if (*cc >= 0xc0) length += _pcre_utf8_table4[*cc & 0x3f]; | #ifdef COMPILE_PCRE8 |
3491 | c = *cc; | |
3492 | check_input_end(common, fallbacks); | if (c < 128) |
GETCHAR(c, cc); | ||
if (c <= 127) | ||
3493 | { | { |
3494 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); |
OP1(SLJIT_MOV_UB, TMP2, 0, SLJIT_MEM1(TMP1), (sljit_w)_pcre_utf8_char_sizes); | ||
3495 | if (type == OP_NOT || !char_has_othercase(common, cc)) | if (type == OP_NOT || !char_has_othercase(common, cc)) |
3496 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c)); |
3497 | else | else |
3498 | { | { |
3499 | /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */ | /* Since UTF8 code page is fixed, we know that c is in [a-z] or [A-Z] range. */ |
3500 | OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x20); | OP2(SLJIT_OR, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x20); |
3501 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, c | 0x20)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, c | 0x20)); |
3502 | } | } |
3503 | /* Skip the variable-length character. */ | /* Skip the variable-length character. */ |
3504 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); |
3505 | return cc + length; | jump[0] = CMP(SLJIT_C_LESS, TMP1, 0, SLJIT_IMM, 0xc0); |
3506 | OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)PRIV(utf8_table4) - 0xc0); | |
3507 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0); | |
3508 | JUMPHERE(jump[0]); | |
3509 | return cc + 1; | |
3510 | } | } |
3511 | else | else |
3512 | #endif /* COMPILE_PCRE8 */ | |
3513 | { | |
3514 | GETCHARLEN(c, cc, length); | |
3515 | read_char(common); | read_char(common); |
3516 | } | |
3517 | } | } |
3518 | else | else |
3519 | #endif | #endif /* SUPPORT_UTF */ |
3520 | { | { |
3521 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 1); | read_char(common); |
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); | ||
OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(STR_PTR), -1); | ||
3522 | c = *cc; | c = *cc; |
3523 | } | } |
3524 | ||
# | Line 3125 switch(type) | Line 3539 switch(type) |
3539 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_IMM, oc)); |
3540 | } | } |
3541 | } | } |
3542 | return cc + length; | return cc + 1; |
3543 | ||
3544 | case OP_CLASS: | case OP_CLASS: |
3545 | case OP_NCLASS: | case OP_NCLASS: |
3546 | check_input_end(common, fallbacks); | fallback_at_str_end(common, fallbacks); |
3547 | read_char(common); | read_char(common); |
3548 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
3549 | jump[0] = NULL; | jump[0] = NULL; |
3550 | if (common->utf8) | #ifdef COMPILE_PCRE8 |
3551 | /* This check only affects 8 bit mode. In other modes, we | |
3552 | always need to compare the value with 255. */ | |
3553 | if (common->utf) | |
3554 | #endif /* COMPILE_PCRE8 */ | |
3555 | { | { |
3556 | jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); | jump[0] = CMP(SLJIT_C_GREATER, TMP1, 0, SLJIT_IMM, 255); |
3557 | if (type == OP_CLASS) | if (type == OP_CLASS) |
# | Line 3142 switch(type) | Line 3560 switch(type) |
3560 | jump[0] = NULL; | jump[0] = NULL; |
3561 | } | } |
3562 | } | } |
3563 | #endif | #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */ |
3564 | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); | OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); |
3565 | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); | OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); |
3566 | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); | OP1(SLJIT_MOV_UB, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_w)cc); |
3567 | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); | OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0); |
3568 | 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); |
3569 | add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO)); | add_jump(compiler, fallbacks, JUMP(SLJIT_C_ZERO)); |
3570 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 |
3571 | if (jump[0] != NULL) | if (jump[0] != NULL) |
3572 | JUMPHERE(jump[0]); | JUMPHERE(jump[0]); |
3573 | #endif | #endif /* SUPPORT_UTF || !COMPILE_PCRE8 */ |
3574 | return cc + 32; | return cc + 32 / sizeof(pcre_uchar); |
3575 | ||
3576 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 |
3577 | case OP_XCLASS: | case OP_XCLASS: |
3578 | compile_xclass_hotpath(common, cc + LINK_SIZE, fallbacks); | compile_xclass_hotpath(common, cc + LINK_SIZE, fallbacks); |
3579 | return cc + GET(cc, 0) - 1; | return cc + GET(cc, 0) - 1; |
# | Line 3165 switch(type) | Line 3583 switch(type) |
3583 | length = GET(cc, 0); | length = GET(cc, 0); |
3584 | SLJIT_ASSERT(length > 0); | SLJIT_ASSERT(length > 0); |
3585 | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); |
3586 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); | #ifdef SUPPORT_UTF |
3587 | #ifdef SUPPORT_UTF8 | if (common->utf) |
if (common->utf8) | ||
3588 | { | { |
3589 | OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); | |
3590 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, length); |
3591 | label = LABEL(); | label = LABEL(); |
3592 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP1, 0)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, STR_PTR, 0, TMP3, 0)); |
3593 | skip_char_back(common); | skip_char_back(common); |
3594 | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, TMP2, 0, SLJIT_IMM, 1); |
3595 | JUMPTO(SLJIT_C_NOT_ZERO, label); | JUMPTO(SLJIT_C_NOT_ZERO, label); |
return cc + LINK_SIZE; | ||
3596 | } | } |
3597 | else | |
3598 | #endif | #endif |
3599 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, length); | { |
3600 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); |
3601 | OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(length)); | |
3602 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS, STR_PTR, 0, TMP1, 0)); | |
3603 | } | |
3604 | check_start_used_ptr(common); | |
3605 | return cc + LINK_SIZE; | return cc + LINK_SIZE; |
3606 | } | } |
3607 | SLJIT_ASSERT_STOP(); | SLJIT_ASSERT_STOP(); |
3608 | return cc; | return cc; |
3609 | } | } |
3610 | ||
3611 | static SLJIT_INLINE uschar *compile_charn_hotpath(compiler_common *common, uschar *cc, uschar *ccend, jump_list **fallbacks) | static SLJIT_INLINE pcre_uchar *compile_charn_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, jump_list **fallbacks) |
3612 | { | { |
3613 | /* This function consumes at least one input character. */ | /* This function consumes at least one input character. */ |
3614 | /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */ | /* To decrease the number of length checks, we try to concatenate the fixed length character sequences. */ |
3615 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3616 | uschar *ccbegin = cc; | pcre_uchar *ccbegin = cc; |
3617 | compare_context context; | compare_context context; |
3618 | int size; | int size; |
3619 | ||
# | Line 3204 do | Line 3626 do |
3626 | if (*cc == OP_CHAR) | if (*cc == OP_CHAR) |
3627 | { | { |
3628 | size = 1; | size = 1; |
3629 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
3630 | if (common->utf8 && cc[1] >= 0xc0) | if (common->utf && HAS_EXTRALEN(cc[1])) |
3631 | size += _pcre_utf8_table4[cc[1] & 0x3f]; | size += GET_EXTRALEN(cc[1]); |
3632 | #endif | #endif |
3633 | } | } |
3634 | else if (*cc == OP_CHARI) | else if (*cc == OP_CHARI) |
3635 | { | { |
3636 | size = 1; | size = 1; |
3637 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
3638 | if (common->utf8) | if (common->utf) |
3639 | { | { |
3640 | if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) | if (char_has_othercase(common, cc + 1) && char_get_othercase_bit(common, cc + 1) == 0) |
3641 | size = 0; | size = 0; |
3642 | else if (cc[1] >= 0xc0) | else if (HAS_EXTRALEN(cc[1])) |
3643 | size += _pcre_utf8_table4[cc[1] & 0x3f]; | size += GET_EXTRALEN(cc[1]); |
3644 | } | } |
3645 | else | else |
3646 | #endif | #endif |
# | Line 3229 do | Line 3651 do |
3651 | size = 0; | size = 0; |
3652 | ||
3653 | cc += 1 + size; | cc += 1 + size; |
3654 | context.length += size; | context.length += IN_UCHARS(size); |
3655 | } | } |
3656 | while (size > 0 && context.length <= 128); | while (size > 0 && context.length <= 128); |
3657 | ||
# | Line 3242 if (context.length > 0) | Line 3664 if (context.length > 0) |
3664 | ||
3665 | context.sourcereg = -1; | context.sourcereg = -1; |
3666 | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED | #if defined SLJIT_UNALIGNED && SLJIT_UNALIGNED |
3667 | context.byteptr = 0; | context.ucharptr = 0; |
3668 | #endif | #endif |
3669 | do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, fallbacks); while (context.length > 0); | do cc = byte_sequence_compare(common, *cc == OP_CHARI, cc + 1, &context, fallbacks); while (context.length > 0); |
3670 | return cc; | return cc; |
# | Line 3252 if (context.length > 0) | Line 3674 if (context.length > 0) |
3674 | return compile_char1_hotpath(common, *cc, cc + 1, fallbacks); | return compile_char1_hotpath(common, *cc, cc + 1, fallbacks); |
3675 | } | } |
3676 | ||
3677 | static struct sljit_jump *compile_ref_checks(compiler_common *common, uschar *cc, jump_list **fallbacks) | static struct sljit_jump *compile_ref_checks(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks) |
3678 | { | { |
3679 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3680 | int offset = GET2(cc, 1) << 1; | int offset = GET2(cc, 1) << 1; |
# | Line 3262 if (!common->jscript_compat) | Line 3684 if (!common->jscript_compat) |
3684 | { | { |
3685 | if (fallbacks == NULL) | if (fallbacks == NULL) |
3686 | { | { |
3687 | /* OVECTOR(1) contains the "string begin - 1" constant. */ | |
3688 | 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)); |
3689 | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); | COND_VALUE(SLJIT_MOV, TMP2, 0, SLJIT_C_EQUAL); |
3690 | 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)); |
# | Line 3274 return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT | Line 3697 return CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT |
3697 | } | } |
3698 | ||
3699 | /* Forward definitions. */ | /* Forward definitions. */ |
3700 | static void compile_hotpath(compiler_common *, uschar *, uschar *, fallback_common *); | static void compile_hotpath(compiler_common *, pcre_uchar *, pcre_uchar *, fallback_common *); |
3701 | static void compile_fallbackpath(compiler_common *, struct fallback_common *); | static void compile_fallbackpath(compiler_common *, struct fallback_common *); |
3702 | ||
3703 | #define PUSH_FALLBACK(size, ccstart, error) \ | #define PUSH_FALLBACK(size, ccstart, error) \ |
# | Line 3303 static void compile_fallbackpath(compile | Line 3726 static void compile_fallbackpath(compile |
3726 | } \ | } \ |
3727 | while (0) | while (0) |
3728 | ||
3729 | #define FALLBACK_AS(type) ((type*)fallback) | #define FALLBACK_AS(type) ((type *)fallback) |
3730 | ||
3731 | static uschar *compile_ref_hotpath(compiler_common *common, uschar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail) | static pcre_uchar *compile_ref_hotpath(compiler_common *common, pcre_uchar *cc, jump_list **fallbacks, BOOL withchecks, BOOL emptyfail) |
3732 | { | { |
3733 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3734 | int offset = GET2(cc, 1) << 1; | int offset = GET2(cc, 1) << 1; |
3735 | struct sljit_jump *jump = NULL; | struct sljit_jump *jump = NULL; |
3736 | struct sljit_jump *partial; | |
3737 | struct sljit_jump *nopartial; | |
3738 | ||
3739 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset)); |
3740 | /* OVECTOR(1) contains the "string begin - 1" constant. */ | |
3741 | if (withchecks && !common->jscript_compat) | if (withchecks && !common->jscript_compat) |
3742 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); |
3743 | ||
3744 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF && defined SUPPORT_UCP |
3745 | #ifdef SUPPORT_UCP | if (common->utf && *cc == OP_REFI) |
if (common->utf8 && *cc == OP_REFI) | ||
3746 | { | { |
3747 | SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3); | SLJIT_ASSERT(TMP1 == SLJIT_TEMPORARY_REG1 && STACK_TOP == SLJIT_TEMPORARY_REG2 && TMP2 == SLJIT_TEMPORARY_REG3); |
3748 | 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)); |
# | Line 3328 if (common->utf8 && *cc == OP_REFI) | Line 3753 if (common->utf8 && *cc == OP_REFI) |
3753 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, STACK_TOP, 0); |
3754 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, ARGUMENTS, 0); |
3755 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, ptr), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_TEMPORARY_REG2), SLJIT_OFFSETOF(jit_arguments, ptr), STR_PTR, 0); |
3756 | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf8caselesscmp)); | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_utf_caselesscmp)); |
3757 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0); |
3758 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); | if (common->mode == JIT_COMPILE) |
3759 | add_jump(compiler, fallbacks, CMP(SLJIT_C_LESS_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1)); | |
3760 | else | |
3761 | { | |
3762 | add_jump(compiler, fallbacks, CMP(SLJIT_C_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0)); | |
3763 | nopartial = CMP(SLJIT_C_NOT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 1); | |
3764 | check_partial(common); | |
3765 | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); | |
3766 | JUMPHERE(nopartial); | |
3767 | } | |
3768 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0); |
3769 | } | } |
3770 | else | else |
3771 | #endif | #endif /* SUPPORT_UTF && SUPPORT_UCP */ |
#endif | ||
3772 | { | { |
3773 | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0); | OP2(SLJIT_SUB | SLJIT_SET_E, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset + 1), TMP1, 0); |
3774 | if (withchecks) | if (withchecks) |
3775 | jump = JUMP(SLJIT_C_ZERO); | jump = JUMP(SLJIT_C_ZERO); |
3776 | ||
3777 | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); | OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); |
3778 | partial = CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0); | |
3779 | if (common->mode == JIT_COMPILE) | |
3780 | add_jump(compiler, fallbacks, partial); | |
3781 | ||
add_jump(compiler, fallbacks, CMP(SLJIT_C_GREATER, STR_PTR, 0, STR_END, 0)); | ||
3782 | add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); | add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); |
3783 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); |
3784 | ||
3785 | if (common->mode != JIT_COMPILE) | |
3786 | { | |
3787 | nopartial = JUMP(SLJIT_JUMP); | |
3788 | JUMPHERE(partial); | |
3789 | /* TMP2 -= STR_END - STR_PTR */ | |
3790 | OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, STR_PTR, 0); | |
3791 | OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, STR_END, 0); | |
3792 | partial = CMP(SLJIT_C_EQUAL, TMP2, 0, SLJIT_IMM, 0); | |
3793 | OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); | |
3794 | add_jump(compiler, *cc == OP_REF ? &common->casefulcmp : &common->caselesscmp, JUMP(SLJIT_FAST_CALL)); | |
3795 | add_jump(compiler, fallbacks, CMP(SLJIT_C_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0)); | |
3796 | JUMPHERE(partial); | |
3797 | check_partial(common); | |
3798 | add_jump(compiler, fallbacks, JUMP(SLJIT_JUMP)); | |
3799 | JUMPHERE(nopartial); | |
3800 | } | |
3801 | } | } |
3802 | ||
3803 | if (jump != NULL) | if (jump != NULL) |
# | Line 3354 if (jump != NULL) | Line 3807 if (jump != NULL) |
3807 | else | else |
3808 | JUMPHERE(jump); | JUMPHERE(jump); |
3809 | } | } |
3810 | return cc + 3; | return cc + 1 + IMM2_SIZE; |
3811 | } | } |
3812 | ||
3813 | static SLJIT_INLINE uschar *compile_ref_iterator_hotpath(compiler_common *common, uschar *cc, fallback_common *parent) | static SLJIT_INLINE pcre_uchar *compile_ref_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) |
3814 | { | { |
3815 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3816 | fallback_common *fallback; | fallback_common *fallback; |
3817 | uschar type; | pcre_uchar type; |
3818 | struct sljit_label *label; | struct sljit_label *label; |
3819 | struct sljit_jump *zerolength; | struct sljit_jump *zerolength; |
3820 | struct sljit_jump *jump = NULL; | struct sljit_jump *jump = NULL; |
3821 | uschar *ccbegin = cc; | pcre_uchar *ccbegin = cc; |
3822 | int min = 0, max = 0; | int min = 0, max = 0; |
3823 | BOOL minimize; | BOOL minimize; |
3824 | ||
3825 | PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL); | PUSH_FALLBACK(sizeof(iterator_fallback), cc, NULL); |
3826 | ||
3827 | type = cc[3]; | type = cc[1 + IMM2_SIZE]; |
3828 | minimize = (type & 0x1) != 0; | minimize = (type & 0x1) != 0; |
3829 | switch(type) | switch(type) |
3830 | { | { |
# | Line 3379 switch(type) | Line 3832 switch(type) |
3832 | case OP_CRMINSTAR: | case OP_CRMINSTAR: |
3833 | min = 0; | min = 0; |
3834 | max = 0; | max = 0; |
3835 | cc += 4; | cc += 1 + IMM2_SIZE + 1; |
3836 | break; | break; |
3837 | case OP_CRPLUS: | case OP_CRPLUS: |
3838 | case OP_CRMINPLUS: | case OP_CRMINPLUS: |
3839 | min = 1; | min = 1; |
3840 | max = 0; | max = 0; |
3841 | cc += 4; | cc += 1 + IMM2_SIZE + 1; |
3842 | break; | break; |
3843 | case OP_CRQUERY: | case OP_CRQUERY: |
3844 | case OP_CRMINQUERY: | case OP_CRMINQUERY: |
3845 | min = 0; | min = 0; |
3846 | max = 1; | max = 1; |
3847 | cc += 4; | cc += 1 + IMM2_SIZE + 1; |
3848 | break; | break; |
3849 | case OP_CRRANGE: | case OP_CRRANGE: |
3850 | case OP_CRMINRANGE: | case OP_CRMINRANGE: |
3851 | min = GET2(cc, 3 + 1); | min = GET2(cc, 1 + IMM2_SIZE + 1); |
3852 | max = GET2(cc, 3 + 3); | max = GET2(cc, 1 + IMM2_SIZE + 1 + IMM2_SIZE); |
3853 | cc += 8; | cc += 1 + IMM2_SIZE + 1 + 2 * IMM2_SIZE; |
3854 | break; | break; |
3855 | default: | default: |
3856 | SLJIT_ASSERT_STOP(); | SLJIT_ASSERT_STOP(); |
# | Line 3501 decrease_call_count(common); | Line 3954 decrease_call_count(common); |
3954 | return cc; | return cc; |
3955 | } | } |
3956 | ||
3957 | static SLJIT_INLINE uschar *compile_recurse_hotpath(compiler_common *common, uschar *cc, fallback_common *parent) | static SLJIT_INLINE pcre_uchar *compile_recurse_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) |
3958 | { | { |
3959 | DEFINE_COMPILER; | DEFINE_COMPILER; |
3960 | fallback_common *fallback; | fallback_common *fallback; |
# | Line 3547 add_jump(compiler, &fallback->topfallbac | Line 4000 add_jump(compiler, &fallback->topfallbac |
4000 | return cc + 1 + LINK_SIZE; | return cc + 1 + LINK_SIZE; |
4001 | } | } |
4002 | ||
4003 | static uschar *compile_assert_hotpath(compiler_common *common, uschar *cc, assert_fallback *fallback, BOOL conditional) | static pcre_uchar *compile_assert_hotpath(compiler_common *common, pcre_uchar *cc, assert_fallback *fallback, BOOL conditional) |
4004 | { | { |
4005 | DEFINE_COMPILER; | DEFINE_COMPILER; |
4006 | int framesize; | int framesize; |
4007 | int localptr; | int localptr; |
4008 | fallback_common altfallback; | fallback_common altfallback; |
4009 | uschar *ccbegin; | pcre_uchar *ccbegin; |
4010 | uschar opcode; | pcre_uchar opcode; |
4011 | uschar bra = OP_BRA; | pcre_uchar bra = OP_BRA; |
4012 | jump_list *tmp = NULL; | jump_list *tmp = NULL; |
4013 | jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks; | jump_list **target = (conditional) ? &fallback->condfailed : &fallback->common.topfallbacks; |
4014 | jump_list **found; | jump_list **found; |
# | Line 3571 if (*cc == OP_BRAZERO || *cc == OP_BRAMI | Line 4024 if (*cc == OP_BRAZERO || *cc == OP_BRAMI |
4024 | bra = *cc; | bra = *cc; |
4025 | cc++; | cc++; |
4026 | } | } |
4027 | localptr = PRIV(cc); | localptr = PRIV_DATA(cc); |
4028 | SLJIT_ASSERT(localptr != 0); | SLJIT_ASSERT(localptr != 0); |
4029 | framesize = get_framesize(common, cc, FALSE); | framesize = get_framesize(common, cc, FALSE); |
4030 | fallback->framesize = framesize; | fallback->framesize = framesize; |
# | Line 3630 while (1) | Line 4083 while (1) |
4083 | if (common->accept != NULL) | if (common->accept != NULL) |
4084 | set_jumps(common->accept, common->acceptlabel); | set_jumps(common->accept, common->acceptlabel); |
4085 | ||
4086 | /* Reset stack. */ | |
4087 | if (framesize < 0) | if (framesize < 0) |
4088 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
4089 | else { | |
4090 | if ((opcode != OP_ASSERT_NOT && opcode != OP_ASSERTBACK_NOT) || conditional) | |
4091 | { | |
4092 | /* We don't need to keep the STR_PTR, only the previous localptr. */ | |
4093 | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w)); | |
4094 | } | |
4095 | else | |
4096 | { | |
4097 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | |
4098 | add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | |
4099 | } | |
4100 | } | |
4101 | ||
4102 | if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) | if (opcode == OP_ASSERT_NOT || opcode == OP_ASSERTBACK_NOT) |
4103 | { | { |
4104 | /* 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. */ |
4105 | if (conditional) | if (conditional) |
4106 | { | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); |
if (framesize < 0) | ||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); | ||
else | ||
{ | ||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | ||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), (framesize + 1) * sizeof(sljit_w)); | ||
} | ||
} | ||
4107 | else if (bra == OP_BRAZERO) | else if (bra == OP_BRAZERO) |
4108 | { | { |
4109 | if (framesize < 0) | if (framesize < 0) |
4110 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); |
4111 | else | else |
4112 | { | { |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | ||
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | ||
4113 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); |
4114 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_w)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (framesize + 1) * sizeof(sljit_w)); |
4115 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); |
# | Line 3661 while (1) | Line 4117 while (1) |
4117 | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); | OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, sizeof(sljit_w)); |
4118 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
4119 | } | } |
4120 | else if (bra == OP_BRAMINZERO) | else if (framesize >= 0) |
4121 | { | { |
4122 | if (framesize >= 0) | /* For OP_BRA and OP_BRAMINZERO. */ |
4123 | { | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); |
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | ||
add_jump(compiler, &common->revertframes, JUMP(SLJIT_FAST_CALL)); | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), framesize * sizeof(sljit_w)); | ||
} | ||
4124 | } | } |
4125 | } | } |
4126 | add_jump(compiler, found, JUMP(SLJIT_JUMP)); | add_jump(compiler, found, JUMP(SLJIT_JUMP)); |
# | Line 3695 if (opcode == OP_ASSERT || opcode == OP_ | Line 4147 if (opcode == OP_ASSERT || opcode == OP_ |
4147 | /* Assert is failed. */ | /* Assert is failed. */ |
4148 | if (conditional || bra == OP_BRAZERO) | if (conditional || bra == OP_BRAZERO) |
4149 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
4150 | ||
4151 | if (framesize < 0) | if (framesize < 0) |
4152 | { | { |
4153 | /* The topmost item should be 0. */ | /* The topmost item should be 0. */ |
# | Line 3706 if (opcode == OP_ASSERT || opcode == OP_ | Line 4159 if (opcode == OP_ASSERT || opcode == OP_ |
4159 | else | else |
4160 | { | { |
4161 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); |
if (framesize > 0) | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); | ||
4162 | /* The topmost item should be 0. */ | /* The topmost item should be 0. */ |
4163 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
4164 | { | { |
# | Line 3717 if (opcode == OP_ASSERT || opcode == OP_ | Line 4168 if (opcode == OP_ASSERT || opcode == OP_ |
4168 | else | else |
4169 | free_stack(common, framesize + 2); | free_stack(common, framesize + 2); |
4170 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); |
if (framesize > 0) | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0); | ||
4171 | } | } |
4172 | jump = JUMP(SLJIT_JUMP); | jump = JUMP(SLJIT_JUMP); |
4173 | if (bra != OP_BRAZERO) | if (bra != OP_BRAZERO) |
# | Line 3741 if (opcode == OP_ASSERT || opcode == OP_ | Line 4190 if (opcode == OP_ASSERT || opcode == OP_ |
4190 | } | } |
4191 | else | else |
4192 | { | { |
4193 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | if (bra == OP_BRA) |
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(TMP1), (framesize + 1) * sizeof(sljit_w)); | ||
if (bra == OP_BRAZERO) | ||
4194 | { | { |
4195 | allocate_stack(common, 1); | /* We don't need to keep the STR_PTR, only the previous localptr. */ |
4196 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 1) * sizeof(sljit_w)); |
4197 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); | |
4198 | } | } |
4199 | else if (bra == OP_BRAMINZERO) | else |
4200 | { | { |
4201 | allocate_stack(common, 1); | /* We don't need to keep the STR_PTR, only the previous localptr. */ |
4202 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (framesize + 2) * sizeof(sljit_w)); |
4203 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | |
4204 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0); | |
4205 | } | } |
4206 | } | } |
4207 | ||
# | Line 3788 else | Line 4238 else |
4238 | { | { |
4239 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); |
4240 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(1)); |
if (framesize > 0) | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(2)); | ||
4241 | /* The topmost item should be 0. */ | /* The topmost item should be 0. */ |
4242 | if (bra != OP_BRA) | if (bra != OP_BRA) |
4243 | { | { |
# | Line 3799 else | Line 4247 else |
4247 | else | else |
4248 | free_stack(common, framesize + 2); | free_stack(common, framesize + 2); |
4249 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, TMP1, 0); |
if (framesize > 0) | ||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS_HEAD, TMP2, 0); | ||
4250 | } | } |
4251 | ||
4252 | if (bra == OP_BRAZERO) | if (bra == OP_BRAZERO) |
# | Line 3824 common->accept = save_accept; | Line 4270 common->accept = save_accept; |
4270 | return cc + 1 + LINK_SIZE; | return cc + 1 + LINK_SIZE; |
4271 | } | } |
4272 | ||
4273 | static sljit_w SLJIT_CALL do_searchovector(sljit_w refno, sljit_w* locals, pcre_uchar *name_table) | |
4274 | { | |
4275 | int condition = FALSE; | |
4276 | pcre_uchar *slotA = name_table; | |
4277 | pcre_uchar *slotB; | |
4278 | sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)]; | |
4279 | sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)]; | |
4280 | sljit_w no_capture; | |
4281 | int i; | |
4282 | ||
4283 | locals += OVECTOR_START / sizeof(sljit_w); | |
4284 | no_capture = locals[1]; | |
4285 | ||
4286 | for (i = 0; i < name_count; i++) | |
4287 | { | |
4288 | if (GET2(slotA, 0) == refno) break; | |
4289 | slotA += name_entry_size; | |
4290 | } | |
4291 | ||
4292 | if (i < name_count) | |
4293 | { | |
4294 | /* Found a name for the number - there can be only one; duplicate names | |
4295 | for different numbers are allowed, but not vice versa. First scan down | |
4296 | for duplicates. */ | |
4297 | ||
4298 | slotB = slotA; | |
4299 | while (slotB > name_table) | |
4300 | { | |
4301 | slotB -= name_entry_size; | |
4302 | if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) | |
4303 | { | |
4304 | condition = locals[GET2(slotB, 0) << 1] != no_capture; | |
4305 | if (condition) break; | |
4306 | } | |
4307 | else break; | |
4308 | } | |
4309 | ||
4310 | /* Scan up for duplicates */ | |
4311 | if (!condition) | |
4312 | { | |
4313 | slotB = slotA; | |
4314 | for (i++; i < name_count; i++) | |
4315 | { | |
4316 | slotB += name_entry_size; | |
4317 | if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) | |
4318 | { | |
4319 | condition = locals[GET2(slotB, 0) << 1] != no_capture; | |
4320 | if (condition) break; | |
4321 | } | |
4322 | else break; | |
4323 | } | |
4324 | } | |
4325 | } | |
4326 | return condition; | |
4327 | } | |
4328 | ||
4329 | static sljit_w SLJIT_CALL do_searchgroups(sljit_w recno, sljit_w* locals, pcre_uchar *name_table) | |
4330 | { | |
4331 | int condition = FALSE; | |
4332 | pcre_uchar *slotA = name_table; | |
4333 | pcre_uchar *slotB; | |
4334 | sljit_w name_count = locals[LOCALS0 / sizeof(sljit_w)]; | |
4335 | sljit_w name_entry_size = locals[LOCALS1 / sizeof(sljit_w)]; | |
4336 | sljit_w group_num = locals[POSSESSIVE0 / sizeof(sljit_w)]; | |
4337 | int i; | |
4338 | ||
4339 | for (i = 0; i < name_count; i++) | |
4340 | { | |
4341 | if (GET2(slotA, 0) == recno) break; | |
4342 | slotA += name_entry_size; | |
4343 | } | |
4344 | ||
4345 | if (i < name_count) | |
4346 | { | |
4347 | /* Found a name for the number - there can be only one; duplicate | |
4348 | names for different numbers are allowed, but not vice versa. First | |
4349 | scan down for duplicates. */ | |
4350 | ||
4351 | slotB = slotA; | |
4352 | while (slotB > name_table) | |
4353 | { | |
4354 | slotB -= name_entry_size; | |
4355 | if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) | |
4356 | { | |
4357 | condition = GET2(slotB, 0) == group_num; | |
4358 | if (condition) break; | |
4359 | } | |
4360 | else break; | |
4361 | } | |
4362 | ||
4363 | /* Scan up for duplicates */ | |
4364 | if (!condition) | |
4365 | { | |
4366 | slotB = slotA; | |
4367 | for (i++; i < name_count; i++) | |
4368 | { | |
4369 | slotB += name_entry_size; | |
4370 | if (STRCMP_UC_UC(slotA + IMM2_SIZE, slotB + IMM2_SIZE) == 0) | |
4371 | { | |
4372 | condition = GET2(slotB, 0) == group_num; | |
4373 | if (condition) break; | |
4374 | } | |
4375 | else break; | |
4376 | } | |
4377 | } | |
4378 | } | |
4379 | return condition; | |
4380 | } | |
4381 | ||
4382 | /* | /* |
4383 | Handling bracketed expressions is probably the most complex part. | Handling bracketed expressions is probably the most complex part. |
4384 | ||
# | Line 3871 return cc + 1 + LINK_SIZE; | Line 4426 return cc + 1 + LINK_SIZE; |
4426 | M - Any values pushed by the current alternative. Can be empty, or anything. | M - Any values pushed by the current alternative. Can be empty, or anything. |
4427 | ||
4428 | The next list shows the possible content of a bracket: | The next list shows the possible content of a bracket: |
4429 | (|) OP_*BRA | OP_ALT ... M A | (|) OP_*BRA | OP_ALT ... M A |
4430 | (?()|) OP_*COND | OP_ALT M A | (?()|) OP_*COND | OP_ALT M A |
4431 | (?>|) OP_ONCE | OP_ALT ... [stack trace] M A | (?>|) OP_ONCE | OP_ALT ... [stack trace] M A |
4432 | Or nothing, if trace is unnecessary | (?>|) OP_ONCE_NC | OP_ALT ... [stack trace] M A |
4433 | Or nothing, if trace is unnecessary | |
4434 | */ | */ |
4435 | ||
4436 | static uschar *compile_bracket_hotpath(compiler_common *common, uschar *cc, fallback_common *parent) | static pcre_uchar *compile_bracket_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) |
4437 | { | { |
4438 | DEFINE_COMPILER; | DEFINE_COMPILER; |
4439 | fallback_common *fallback; | fallback_common *fallback; |
4440 | uschar opcode; | pcre_uchar opcode; |
4441 | int localptr = 0; | int localptr = 0; |
4442 | int offset = 0; | int offset = 0; |
4443 | int stacksize; | int stacksize; |
4444 | uschar *ccbegin; | pcre_uchar *ccbegin; |
4445 | uschar *hotpath; | pcre_uchar *hotpath; |
4446 | uschar bra = OP_BRA; | pcre_uchar bra = OP_BRA; |
4447 | uschar ket; | pcre_uchar ket; |
4448 | assert_fallback *assert; | assert_fallback *assert; |
4449 | BOOL has_alternatives; | BOOL has_alternatives; |
4450 | struct sljit_jump *jump; | struct sljit_jump *jump; |
# | Line 3907 if (*cc == OP_BRAZERO || *cc == OP_BRAMI | Line 4463 if (*cc == OP_BRAZERO || *cc == OP_BRAMI |
4463 | ||
4464 | opcode = *cc; | opcode = *cc; |
4465 | ccbegin = cc; | ccbegin = cc; |
4466 | hotpath = ccbegin + 1 + LINK_SIZE; | |
4467 | ||
4468 | if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF) | if ((opcode == OP_COND || opcode == OP_SCOND) && cc[1 + LINK_SIZE] == OP_DEF) |
4469 | { | { |
4470 | /* Drop this bracket_fallback. */ | /* Drop this bracket_fallback. */ |
# | Line 3918 ket = *(bracketend(cc) - 1 - LINK_SIZE); | Line 4476 ket = *(bracketend(cc) - 1 - LINK_SIZE); |
4476 | SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN); | SLJIT_ASSERT(ket == OP_KET || ket == OP_KETRMAX || ket == OP_KETRMIN); |
4477 | SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX))); | SLJIT_ASSERT(!((bra == OP_BRAZERO && ket == OP_KETRMIN) || (bra == OP_BRAMINZERO && ket == OP_KETRMAX))); |
4478 | cc += GET(cc, 1); | cc += GET(cc, 1); |
4479 | has_alternatives = *cc == OP_ALT || opcode == OP_COND || opcode == OP_SCOND; | |
4480 | has_alternatives = *cc == OP_ALT; | |
4481 | if (SLJIT_UNLIKELY(opcode == OP_COND) || SLJIT_UNLIKELY(opcode == OP_SCOND)) | |
4482 | { | |
4483 | has_alternatives = (*hotpath == OP_RREF) ? FALSE : TRUE; | |
4484 | if (*hotpath == OP_NRREF) | |
4485 | { | |
4486 | stacksize = GET2(hotpath, 1); | |
4487 | if (common->currententry == NULL || stacksize == RREF_ANY) | |
4488 | has_alternatives = FALSE; | |
4489 | else if (common->currententry->start == 0) | |
4490 | has_alternatives = stacksize != 0; | |
4491 | else | |
4492 | has_alternatives = stacksize != GET2(common->start, common->currententry->start + 1 + LINK_SIZE); | |
4493 | } | |
4494 | } | |
4495 | ||
4496 | if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) | if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN)) |
4497 | opcode = OP_SCOND; | opcode = OP_SCOND; |
4498 | if (SLJIT_UNLIKELY(opcode == OP_ONCE_NC)) | |
4499 | opcode = OP_ONCE; | |
4500 | ||
4501 | if (opcode == OP_CBRA || opcode == OP_SCBRA) | if (opcode == OP_CBRA || opcode == OP_SCBRA) |
4502 | { | { |
# | Line 3929 if (opcode == OP_CBRA || opcode == OP_SC | Line 4505 if (opcode == OP_CBRA || opcode == OP_SC |
4505 | localptr = OVECTOR_PRIV(offset); | localptr = OVECTOR_PRIV(offset); |
4506 | offset <<= 1; | offset <<= 1; |
4507 | FALLBACK_AS(bracket_fallback)->localptr = localptr; | FALLBACK_AS(bracket_fallback)->localptr = localptr; |
4508 | hotpath += IMM2_SIZE; | |
4509 | } | } |
4510 | else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND) | else if (opcode == OP_ONCE || opcode == OP_SBRA || opcode == OP_SCOND) |
4511 | { | { |
4512 | /* Other brackets simply allocate the next entry. */ | /* Other brackets simply allocate the next entry. */ |
4513 | localptr = PRIV(ccbegin); | localptr = PRIV_DATA(ccbegin); |
4514 | SLJIT_ASSERT(localptr != 0); | SLJIT_ASSERT(localptr != 0); |
4515 | FALLBACK_AS(bracket_fallback)->localptr = localptr; | FALLBACK_AS(bracket_fallback)->localptr = localptr; |
4516 | if (opcode == OP_ONCE) | if (opcode == OP_ONCE) |
# | Line 4085 else if (has_alternatives) | Line 4662 else if (has_alternatives) |
4662 | } | } |
4663 | ||
4664 | /* Generating code for the first alternative. */ | /* Generating code for the first alternative. */ |
hotpath = ccbegin + 1 + LINK_SIZE; | ||
if (offset != 0) | ||
hotpath += 2; | ||
4665 | if (opcode == OP_COND || opcode == OP_SCOND) | if (opcode == OP_COND || opcode == OP_SCOND) |
4666 | { | { |
4667 | if (*hotpath == OP_CREF) | if (*hotpath == OP_CREF) |
4668 | { | { |
4669 | SLJIT_ASSERT(has_alternatives); | |
4670 | add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), | add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), |
4671 | CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR((GET2(hotpath, 1) << 1)), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); | CMP(SLJIT_C_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(GET2(hotpath, 1) << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1))); |
4672 | hotpath += 3; | hotpath += 1 + IMM2_SIZE; |
4673 | } | |
4674 | else if (*hotpath == OP_NCREF) | |
4675 | { | |
4676 | SLJIT_ASSERT(has_alternatives); | |
4677 | stacksize = GET2(hotpath, 1); | |
4678 | jump = CMP(SLJIT_C_NOT_EQUAL, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(stacksize << 1), SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(1)); | |
4679 | ||
4680 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); | |
4681 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); | |
4682 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); | |
4683 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize); | |
4684 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0); | |
4685 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); | |
4686 | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchovector)); | |
4687 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | |
4688 | add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); | |
4689 | ||
4690 | JUMPHERE(jump); | |
4691 | hotpath += 1 + IMM2_SIZE; | |
4692 | } | |
4693 | else if (*hotpath == OP_RREF || *hotpath == OP_NRREF) | |
4694 | { | |
4695 | /* Never has other case. */ | |
4696 | FALLBACK_AS(bracket_fallback)->u.condfailed = NULL; | |
4697 | ||
4698 | stacksize = GET2(hotpath, 1); | |
4699 | if (common->currententry == NULL) | |
4700 | stacksize = 0; | |
4701 | else if (stacksize == RREF_ANY) | |
4702 | stacksize = 1; | |
4703 | else if (common->currententry->start == 0) | |
4704 | stacksize = stacksize == 0; | |
4705 | else | |
4706 | stacksize = stacksize == GET2(common->start, common->currententry->start + 1 + LINK_SIZE); | |
4707 | ||
4708 | if (*hotpath == OP_RREF || stacksize || common->currententry == NULL) | |
4709 | { | |
4710 | SLJIT_ASSERT(!has_alternatives); | |
4711 | if (stacksize != 0) | |
4712 | hotpath += 1 + IMM2_SIZE; | |
4713 | else | |
4714 | { | |
4715 | if (*cc == OP_ALT) | |
4716 | { | |
4717 | hotpath = cc + 1 + LINK_SIZE; | |
4718 | cc += GET(cc, 1); | |
4719 | } | |
4720 | else | |
4721 | hotpath = cc; | |
4722 | } | |
4723 | } | |
4724 | else | |
4725 | { | |
4726 | SLJIT_ASSERT(has_alternatives); | |
4727 | ||
4728 | stacksize = GET2(hotpath, 1); | |
4729 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1, STACK_TOP, 0); | |
4730 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS0, SLJIT_IMM, common->name_count); | |
4731 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), LOCALS1, SLJIT_IMM, common->name_entry_size); | |
4732 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE0, SLJIT_IMM, GET2(common->start, common->currententry->start + 1 + LINK_SIZE)); | |
4733 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, stacksize); | |
4734 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG2, 0, SLJIT_LOCALS_REG, 0); | |
4735 | OP1(SLJIT_MOV, SLJIT_TEMPORARY_REG3, 0, SLJIT_IMM, common->name_table); | |
4736 | sljit_emit_ijump(compiler, SLJIT_CALL3, SLJIT_IMM, SLJIT_FUNC_OFFSET(do_searchgroups)); | |
4737 | OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), POSSESSIVE1); | |
4738 | add_jump(compiler, &(FALLBACK_AS(bracket_fallback)->u.condfailed), CMP(SLJIT_C_EQUAL, SLJIT_TEMPORARY_REG1, 0, SLJIT_IMM, 0)); | |
4739 | hotpath += 1 + IMM2_SIZE; | |
4740 | } | |
4741 | } | } |
4742 | else | else |
4743 | { | { |
4744 | SLJIT_ASSERT(*hotpath >= OP_ASSERT && *hotpath <= OP_ASSERTBACK_NOT); | SLJIT_ASSERT(has_alternatives && *hotpath >= OP_ASSERT && *hotpath <= OP_ASSERTBACK_NOT); |
4745 | /* Similar code as PUSH_FALLBACK macro. */ | /* Similar code as PUSH_FALLBACK macro. */ |
4746 | assert = sljit_alloc_memory(compiler, sizeof(assert_fallback)); | assert = sljit_alloc_memory(compiler, sizeof(assert_fallback)); |
4747 | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) | if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) |
# | Line 4128 if (opcode == OP_ONCE) | Line 4771 if (opcode == OP_ONCE) |
4771 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_MEM1(STACK_TOP), 0); |
4772 | } | } |
4773 | } | } |
4774 | else if (ket == OP_KETRMAX) | else |
4775 | { | { |
4776 | /* TMP2 which is set here used by OP_KETRMAX below. */ | stacksize = (ket == OP_KETRMIN || ket == OP_KETRMAX || has_alternatives) ? 2 : 1; |
4777 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, (FALLBACK_AS(bracket_fallback)->u.framesize + stacksize) * sizeof(sljit_w)); |
4778 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), (FALLBACK_AS(bracket_fallback)->u.framesize + 1) * sizeof(sljit_w)); | if (ket == OP_KETRMAX) |
4779 | { | |
4780 | /* TMP2 which is set here used by OP_KETRMAX below. */ | |
4781 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0)); | |
4782 | } | |
4783 | } | } |
4784 | } | } |
4785 | ||
# | Line 4197 if (bra == OP_BRAZERO) | Line 4844 if (bra == OP_BRAZERO) |
4844 | if (bra == OP_BRAMINZERO) | if (bra == OP_BRAMINZERO) |
4845 | { | { |
4846 | /* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */ | /* This is a fallback path! (From the viewpoint of OP_BRAMINZERO) */ |
4847 | JUMPTO(SLJIT_JUMP, ((braminzero_fallback*)parent)->hotpath); | JUMPTO(SLJIT_JUMP, ((braminzero_fallback *)parent)->hotpath); |
4848 | if (braminzerojump != NULL) | if (braminzerojump != NULL) |
4849 | { | { |
4850 | JUMPHERE(braminzerojump); | JUMPHERE(braminzerojump); |
# | Line 4225 cc += 1 + LINK_SIZE; | Line 4872 cc += 1 + LINK_SIZE; |
4872 | return cc; | return cc; |
4873 | } | } |
4874 | ||
4875 | static uschar *compile_bracketpos_hotpath(compiler_common *common, uschar *cc, fallback_common *parent) | static pcre_uchar *compile_bracketpos_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) |
4876 | { | { |
4877 | DEFINE_COMPILER; | DEFINE_COMPILER; |
4878 | fallback_common *fallback; | fallback_common *fallback; |
4879 | uschar opcode; | pcre_uchar opcode; |
4880 | int localptr; | int localptr; |
4881 | int cbraprivptr = 0; | int cbraprivptr = 0; |
4882 | int framesize; | int framesize; |
4883 | int stacksize; | int stacksize; |
4884 | int offset = 0; | int offset = 0; |
4885 | BOOL zero = FALSE; | BOOL zero = FALSE; |
4886 | uschar *ccbegin = NULL; | pcre_uchar *ccbegin = NULL; |
4887 | int stack; | int stack; |
4888 | struct sljit_label *loop = NULL; | struct sljit_label *loop = NULL; |
4889 | struct jump_list *emptymatch = NULL; | struct jump_list *emptymatch = NULL; |
# | Line 4249 if (*cc == OP_BRAPOSZERO) | Line 4896 if (*cc == OP_BRAPOSZERO) |
4896 | } | } |
4897 | ||
4898 | opcode = *cc; | opcode = *cc; |
4899 | localptr = PRIV(cc); | localptr = PRIV_DATA(cc); |
4900 | SLJIT_ASSERT(localptr != 0); | SLJIT_ASSERT(localptr != 0); |
4901 | FALLBACK_AS(bracketpos_fallback)->localptr = localptr; | FALLBACK_AS(bracketpos_fallback)->localptr = localptr; |
4902 | switch(opcode) | switch(opcode) |
# | Line 4264 switch(opcode) | Line 4911 switch(opcode) |
4911 | offset = GET2(cc, 1 + LINK_SIZE); | offset = GET2(cc, 1 + LINK_SIZE); |
4912 | cbraprivptr = OVECTOR_PRIV(offset); | cbraprivptr = OVECTOR_PRIV(offset); |
4913 | offset <<= 1; | offset <<= 1; |
4914 | ccbegin = cc + 1 + LINK_SIZE + 2; | ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE; |
4915 | break; | break; |
4916 | ||
4917 | default: | default: |
# | Line 4366 while (*cc != OP_KETRPOS) | Line 5013 while (*cc != OP_KETRPOS) |
5013 | { | { |
5014 | if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) | if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) |
5015 | { | { |
5016 | OP2(SLJIT_ADD, STACK_TOP, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr, SLJIT_IMM, stacksize * sizeof(sljit_w)); | |
5017 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); |
if (!zero) | ||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | ||
5018 | 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); |
5019 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr, STR_PTR, 0); |
5020 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); |
# | Line 4376 while (*cc != OP_KETRPOS) | Line 5022 while (*cc != OP_KETRPOS) |
5022 | else | else |
5023 | { | { |
5024 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
5025 | OP2(SLJIT_ADD, STACK_TOP, 0, TMP2, 0, SLJIT_IMM, stacksize * sizeof(sljit_w)); | |
5026 | if (opcode == OP_SBRAPOS) | if (opcode == OP_SBRAPOS) |
5027 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w)); |
5028 | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w), STR_PTR, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_w), STR_PTR, 0); |
# | Line 4384 while (*cc != OP_KETRPOS) | Line 5031 while (*cc != OP_KETRPOS) |
5031 | if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) | if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) |
5032 | add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0)); | add_jump(compiler, &emptymatch, CMP(SLJIT_C_EQUAL, TMP1, 0, STR_PTR, 0)); |
5033 | ||
/* TMP2 must be set above. */ | ||
5034 | if (!zero) | if (!zero) |
5035 | { | { |
5036 | if (framesize < 0) | if (framesize < 0) |
5037 | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize - 1), SLJIT_IMM, 0); |
5038 | else | else |
5039 | OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (stacksize - 1) * sizeof(sljit_w), SLJIT_IMM, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0); |
5040 | } | } |
5041 | } | } |
5042 | JUMPTO(SLJIT_JUMP, loop); | JUMPTO(SLJIT_JUMP, loop); |
# | Line 4412 while (*cc != OP_KETRPOS) | Line 5058 while (*cc != OP_KETRPOS) |
5058 | { | { |
5059 | if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) | if (opcode == OP_CBRAPOS || opcode == OP_SCBRAPOS) |
5060 | { | { |
5061 | /* Last alternative. */ | |
5062 | if (*cc == OP_KETRPOS) | if (*cc == OP_KETRPOS) |
5063 | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); | OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), localptr); |
5064 | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); | OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), cbraprivptr); |
# | Line 4443 decrease_call_count(common); | Line 5090 decrease_call_count(common); |
5090 | return cc + 1 + LINK_SIZE; | return cc + 1 + LINK_SIZE; |
5091 | } | } |
5092 | ||
5093 | static SLJIT_INLINE uschar *get_iterator_parameters(compiler_common *common, uschar *cc, uschar *opcode, uschar *type, int *arg1, int *arg2, uschar **end) | static SLJIT_INLINE pcre_uchar *get_iterator_parameters(compiler_common *common, pcre_uchar *cc, pcre_uchar *opcode, pcre_uchar *type, int *arg1, int *arg2, pcre_uchar **end) |
5094 | { | { |
5095 | int class_len; | int class_len; |
5096 | ||
# | Line 4482 else | Line 5129 else |
5129 | SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS); | SLJIT_ASSERT(*opcode >= OP_CLASS || *opcode <= OP_XCLASS); |
5130 | *type = *opcode; | *type = *opcode; |
5131 | cc++; | cc++; |
5132 | class_len = (*type < OP_XCLASS) ? 33 : GET(cc, 0); | class_len = (*type < OP_XCLASS) ? (int)(1 + (32 / sizeof(pcre_uchar))) : GET(cc, 0); |
5133 | *opcode = cc[class_len - 1]; | *opcode = cc[class_len - 1]; |
5134 | if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY) | if (*opcode >= OP_CRSTAR && *opcode <= OP_CRMINQUERY) |
5135 | { | { |
# | Line 4493 else | Line 5140 else |
5140 | else | else |
5141 | { | { |
5142 | SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE); | SLJIT_ASSERT(*opcode == OP_CRRANGE || *opcode == OP_CRMINRANGE); |
5143 | *arg1 = GET2(cc, (class_len + 2)); | *arg1 = GET2(cc, (class_len + IMM2_SIZE)); |
5144 | *arg2 = GET2(cc, class_len); | *arg2 = GET2(cc, class_len); |
5145 | ||
5146 | if (*arg2 == 0) | if (*arg2 == 0) |
# | Line 4505 else | Line 5152 else |
5152 | *opcode = OP_EXACT; | *opcode = OP_EXACT; |
5153 | ||
5154 | if (end != NULL) | if (end != NULL) |
5155 | *end = cc + class_len + 4; | *end = cc + class_len + 2 * IMM2_SIZE; |
5156 | } | } |
5157 | return cc; | return cc; |
5158 | } | } |
# | Line 4513 else | Line 5160 else |
5160 | if (*opcode == OP_UPTO || *opcode == OP_MINUPTO || *opcode == OP_EXACT || *opcode == OP_POSUPTO) | if (*opcode == OP_UPTO || *opcode == OP_MINUPTO || *opcode == OP_EXACT || *opcode == OP_POSUPTO) |
5161 | { | { |
5162 | *arg1 = GET2(cc, 0); | *arg1 = GET2(cc, 0); |
5163 | cc += 2; | cc += IMM2_SIZE; |
5164 | } | } |
5165 | ||
5166 | if (*type == 0) | if (*type == 0) |
# | Line 4528 if (*type == 0) | Line 5175 if (*type == 0) |
5175 | if (end != NULL) | if (end != NULL) |
5176 | { | { |
5177 | *end = cc + 1; | *end = cc + 1; |
5178 | #ifdef SUPPORT_UTF8 | #ifdef SUPPORT_UTF |
5179 | if (common->utf8 && *cc >= 0xc0) *end += _pcre_utf8_table4[*cc & 0x3f]; | if (common->utf && HAS_EXTRALEN(*cc)) *end += GET_EXTRALEN(*cc); |
5180 | #endif | #endif |
5181 | } | } |
5182 | return cc; | return cc; |
5183 | } | } |
5184 | ||
5185 | static uschar *compile_iterator_hotpath(compiler_common *common, uschar *cc, fallback_common *parent) | static pcre_uchar *compile_iterator_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) |
5186 | { | { |
5187 | DEFINE_COMPILER; | DEFINE_COMPILER; |
5188 | fallback_common *fallback; | fallback_common *fallback; |
5189 | uschar opcode; | pcre_uchar opcode; |
5190 | uschar type; | pcre_uchar type; |
5191 | int arg1 = -1, arg2 = -1; | int arg1 = -1, arg2 = -1; |
5192 | uschar* end; | pcre_uchar* end; |
5193 | jump_list *nomatch = NULL; | jump_list *nomatch = NULL; |
5194 | struct sljit_jump *jump = NULL; | struct sljit_jump *jump = NULL; |
5195 | struct sljit_label *label; | struct sljit_label *label; |
# | Line 4704 decrease_call_count(common); | Line 5351 decrease_call_count(common); |
5351 | return end; | return end; |
5352 | } | } |
5353 | ||
5354 | static SLJIT_INLINE uschar *compile_fail_accept_hotpath(compiler_common *common, uschar *cc, fallback_common *parent) | static SLJIT_INLINE pcre_uchar *compile_fail_accept_hotpath(compiler_common *common, pcre_uchar *cc, fallback_common *parent) |
5355 | { | { |
5356 | DEFINE_COMPILER; | DEFINE_COMPILER; |
5357 | fallback_common *fallback; | fallback_common *fallback; |
# | Line 4748 add_jump(compiler, &fallback->topfallbac | Line 5395 add_jump(compiler, &fallback->topfallbac |
5395 | return cc + 1; | return cc + 1; |
5396 | } | } |
5397 | ||
5398 | static SLJIT_INLINE uschar *compile_close_hotpath(compiler_common *common, uschar *cc) | static SLJIT_INLINE pcre_uchar *compile_close_hotpath(compiler_common *common, pcre_uchar *cc) |
5399 | { | { |
5400 | DEFINE_COMPILER; | DEFINE_COMPILER; |
5401 | int offset = GET2(cc, 1); | int offset = GET2(cc, 1); |
5402 | ||
5403 | /* Data will be discarded anyway... */ | /* Data will be discarded anyway... */ |
5404 | if (common->currententry != NULL) | if (common->currententry != NULL) |
5405 | return cc + 3; | return cc + 1 + IMM2_SIZE; |
5406 | ||
5407 | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset)); | OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR_PRIV(offset)); |
5408 | offset <<= 1; | offset <<= 1; |
5409 | 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); |
5410 | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); | OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_LOCALS_REG), OVECTOR(offset), TMP1, 0); |
5411 | return cc + 3; | return cc + 1 + IMM2_SIZE; |
5412 | } | } |
5413 | ||
5414 | static void compile_hotpath(compiler_common *common, uschar *cc, uschar *ccend, fallback_common *parent) | static void compile_hotpath(compiler_common *common, pcre_uchar *cc, pcre_uchar *ccend, fallback_common *parent) |
5415 | { | { |
5416 | DEFINE_COMPILER; | DEFINE_COMPILER; |
5417 | fallback_common *fallback; | fallback_common *fallback; |
# | Line 4785 while (cc < ccend) | Line 5432 while (cc < ccend) |
5432 | case OP_WORDCHAR: | case OP_WORDCHAR: |
5433 | case OP_ANY: | case OP_ANY: |
5434 | case OP_ALLANY: | case OP_ALLANY: |
5435 | case OP_ANYBYTE: | |
5436 | case OP_NOTPROP: | case OP_NOTPROP: |
5437 | case OP_PROP: | case OP_PROP: |
5438 | case OP_ANYNL: | case OP_ANYNL: |
# | Line 4816 while (cc < ccend) | Line 5464 while (cc < ccend) |
5464 | ||
5465 | case OP_CHAR: | case OP_CHAR: |
5466 | case OP_CHARI: | case OP_CHARI: |
5467 | cc = compile_charn_hotpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | if (common->mode == JIT_COMPILE) |
5468 | cc = compile_charn_hotpath(common, cc, ccend, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | |
5469 | else | |
5470 | cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | |
5471 | break; | break; |
5472 | ||
5473 | case OP_STAR: | case OP_STAR: |
# | Line 4889 while (cc < ccend) | Line 5540 while (cc < ccend) |
5540 | ||
5541 | case OP_CLASS: | case OP_CLASS: |
5542 | case OP_NCLASS: | case OP_NCLASS: |
5543 | if (cc[33] >= OP_CRSTAR && cc[33] <= OP_CRMINRANGE) | if (cc[1 + (32 / sizeof(pcre_uchar))] >= OP_CRSTAR && cc[1 + (32 / sizeof(pcre_uchar))] <= OP_CRMINRANGE) |
5544 | cc = compile_iterator_hotpath(common, cc, parent); | cc = compile_iterator_hotpath(common, cc, parent); |
5545 | else | else |
5546 | cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); | cc = compile_char1_hotpath(common, *cc, cc + 1, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks); |
5547 | break; | break; |
5548 | ||
5549 | #ifdef SUPPORT_UTF8 | #if defined SUPPORT_UTF || defined COMPILE_PCRE16 |
5550 | case OP_XCLASS: | case OP_XCLASS: |
5551 | if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE) | if (*(cc + GET(cc, 1)) >= OP_CRSTAR && *(cc + GET(cc, 1)) <= OP_CRMINRANGE) |
5552 | cc = compile_iterator_hotpath(common, cc, parent); | cc = compile_iterator_hotpath(common, cc, parent); |
# | Line 4906 while (cc < ccend) | Line 5557 while (cc < ccend) |
5557 | ||
5558 | case OP_REF: | case OP_REF: |
5559 | case OP_REFI: | case OP_REFI: |
5560 | if (cc[3] >= OP_CRSTAR && cc[3] <= OP_CRMINRANGE) | if (cc[1 + IMM2_SIZE] >= OP_CRSTAR && cc[1 + IMM2_SIZE] <= OP_CRMINRANGE) |
5561 | cc = compile_ref_iterator_hotpath(common, cc, parent); | cc = compile_ref_iterator_hotpath(common, cc, parent); |
5562 | else | else |
5563 | cc = compile_ref_hotpath(common, cc, parent->top != NULL ? &parent->top->nextfallbacks : &parent->topfallbacks, TRUE, FALSE); | cc = compile_ref_hotpath(common, cc, parent->top != NULL ? &parent->top->next |