Revert "Update to PCRE2 10.35"

This reverts commit b419f96c62.

This breaks the GCC build with -fcf-protection (default on Ubuntu
at least).
This commit is contained in:
Nikita Popov 2020-06-30 18:24:48 +02:00
parent af4ff75c98
commit e2a407c2fe
39 changed files with 3388 additions and 4722 deletions

View file

@ -5,7 +5,7 @@
/* This is the public header file for the PCRE library, second API, to be
#included by applications that call PCRE2 functions.
Copyright (c) 2016-2020 University of Cambridge
Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE2_MAJOR 10
#define PCRE2_MINOR 35
#define PCRE2_MINOR 34
#define PCRE2_PRERELEASE
#define PCRE2_DATE 2020-05-09
#define PCRE2_DATE 2019-11-21
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE2, the appropriate
@ -181,9 +181,6 @@ pcre2_jit_match() ignores the latter since it bypasses all sanity checks). */
#define PCRE2_SUBSTITUTE_OVERFLOW_LENGTH 0x00001000u /* pcre2_substitute() only */
#define PCRE2_NO_JIT 0x00002000u /* Not for pcre2_dfa_match() */
#define PCRE2_COPY_MATCHED_SUBJECT 0x00004000u
#define PCRE2_SUBSTITUTE_LITERAL 0x00008000u /* pcre2_substitute() only */
#define PCRE2_SUBSTITUTE_MATCHED 0x00010000u /* pcre2_substitute() only */
#define PCRE2_SUBSTITUTE_REPLACEMENT_ONLY 0x00020000u /* pcre2_substitute() only */
/* Options for pcre2_pattern_convert(). */
@ -448,7 +445,6 @@ released, the numbers must not be changed. */
#define PCRE2_CONFIG_HEAPLIMIT 12
#define PCRE2_CONFIG_NEVER_BACKSLASH_C 13
#define PCRE2_CONFIG_COMPILED_WIDTHS 14
#define PCRE2_CONFIG_TABLES_LENGTH 15
/* Types for code units in patterns and subject strings. */

View file

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2016-2020 University of Cambridge
New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -292,7 +292,6 @@ possessification, and if so, fills a list with its properties.
Arguments:
code points to start of expression
utf TRUE if in UTF mode
ucp TRUE if in UCP mode
fcc points to the case-flipping table
list points to output list
list[0] will be filled with the opcode
@ -305,7 +304,7 @@ Returns: points to the start of the next opcode if *code is accepted
*/
static PCRE2_SPTR
get_chr_property_list(PCRE2_SPTR code, BOOL utf, BOOL ucp, const uint8_t *fcc,
get_chr_property_list(PCRE2_SPTR code, BOOL utf, const uint8_t *fcc,
uint32_t *list)
{
PCRE2_UCHAR c = *code;
@ -317,8 +316,7 @@ uint32_t chr;
uint32_t *clist_dest;
const uint32_t *clist_src;
#else
(void)utf; /* Suppress "unused parameter" compiler warnings */
(void)ucp;
(void)utf; /* Suppress "unused parameter" compiler warning */
#endif
list[0] = c;
@ -398,7 +396,7 @@ switch(c)
list[2] = chr;
#ifdef SUPPORT_UNICODE
if (chr < 128 || (chr < 256 && !utf && !ucp))
if (chr < 128 || (chr < 256 && !utf))
list[3] = fcc[chr];
else
list[3] = UCD_OTHERCASE(chr);
@ -505,7 +503,6 @@ which case the base cannot be possessified.
Arguments:
code points to the byte code
utf TRUE in UTF mode
ucp TRUE in UCP mode
cb compile data block
base_list the data list of the base opcode
base_end the end of the base opcode
@ -515,7 +512,7 @@ Returns: TRUE if the auto-possessification is possible
*/
static BOOL
compare_opcodes(PCRE2_SPTR code, BOOL utf, BOOL ucp, const compile_block *cb,
compare_opcodes(PCRE2_SPTR code, BOOL utf, const compile_block *cb,
const uint32_t *base_list, PCRE2_SPTR base_end, int *rec_limit)
{
PCRE2_UCHAR c;
@ -654,7 +651,7 @@ for(;;)
while (*next_code == OP_ALT)
{
if (!compare_opcodes(code, utf, ucp, cb, base_list, base_end, rec_limit))
if (!compare_opcodes(code, utf, cb, base_list, base_end, rec_limit))
return FALSE;
code = next_code + 1 + LINK_SIZE;
next_code += GET(next_code, 1);
@ -675,8 +672,7 @@ for(;;)
/* The bracket content will be checked by the OP_BRA/OP_CBRA case above. */
next_code += 1 + LINK_SIZE;
if (!compare_opcodes(next_code, utf, ucp, cb, base_list, base_end,
rec_limit))
if (!compare_opcodes(next_code, utf, cb, base_list, base_end, rec_limit))
return FALSE;
code += PRIV(OP_lengths)[c];
@ -692,7 +688,7 @@ for(;;)
/* We now have the next appropriate opcode to compare with the base. Check
for a supported opcode, and load its properties. */
code = get_chr_property_list(code, utf, ucp, cb->fcc, list);
code = get_chr_property_list(code, utf, cb->fcc, list);
if (code == NULL) return FALSE; /* Unsupported */
/* If either opcode is a small character list, set pointers for comparing
@ -1104,6 +1100,7 @@ leaving the remainder of the pattern unpossessified.
Arguments:
code points to start of the byte code
utf TRUE in UTF mode
cb compile data block
Returns: 0 for success
@ -1111,15 +1108,13 @@ Returns: 0 for success
*/
int
PRIV(auto_possessify)(PCRE2_UCHAR *code, const compile_block *cb)
PRIV(auto_possessify)(PCRE2_UCHAR *code, BOOL utf, const compile_block *cb)
{
PCRE2_UCHAR c;
PCRE2_SPTR end;
PCRE2_UCHAR *repeat_opcode;
uint32_t list[8];
int rec_limit = 1000; /* Was 10,000 but clang+ASAN uses a lot of stack. */
BOOL utf = (cb->external_options & PCRE2_UTF) != 0;
BOOL ucp = (cb->external_options & PCRE2_UCP) != 0;
for (;;)
{
@ -1131,11 +1126,10 @@ for (;;)
{
c -= get_repeat_base(c) - OP_STAR;
end = (c <= OP_MINUPTO) ?
get_chr_property_list(code, utf, ucp, cb->fcc, list) : NULL;
get_chr_property_list(code, utf, cb->fcc, list) : NULL;
list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO;
if (end != NULL && compare_opcodes(end, utf, ucp, cb, list, end,
&rec_limit))
if (end != NULL && compare_opcodes(end, utf, cb, list, end, &rec_limit))
{
switch(c)
{
@ -1187,11 +1181,11 @@ for (;;)
if (c >= OP_CRSTAR && c <= OP_CRMINRANGE)
{
/* end must not be NULL. */
end = get_chr_property_list(code, utf, ucp, cb->fcc, list);
end = get_chr_property_list(code, utf, cb->fcc, list);
list[1] = (c & 1) == 0;
if (compare_opcodes(end, utf, ucp, cb, list, end, &rec_limit))
if (compare_opcodes(end, utf, cb, list, end, &rec_limit))
{
switch (c)
{

View file

@ -2,21 +2,17 @@
* Perl-Compatible Regular Expressions *
*************************************************/
/* This file was automatically written by the pcre2_dftables auxiliary
/* This file was automatically written by the dftables auxiliary
program. It contains character tables that are used when no external
tables are passed to PCRE2 by the application that calls it. The tables
are used only for characters whose code values are less than 256. */
/* This set of tables was written in the C locale. */
/* The pcre2_ftables program (which is distributed with PCRE2) can be used
to build alternative versions of this file. This is necessary if you are
/*The dftables program (which is distributed with PCRE2) can be used to
build alternative versions of this file. This is necessary if you are
running in an EBCDIC environment, or if you want to default to a different
encoding, for example ISO-8859-1. When pcre2_dftables is run, it creates
these tables in the "C" locale by default. This happens automatically if
PCRE2 is configured with --enable-rebuild-chartables. However, you can run
pcre2_dftables manually with the -L option to build tables using the LC_ALL
locale. */
encoding, for example ISO-8859-1. When dftables is run, it creates these
tables in the current locale. This happens automatically if PCRE2 is
configured with --enable-rebuild-chartables. */
/* The following #include is present because without it gcc 4.x may remove
the array definition from the final binary if PCRE2 is built into a static
@ -106,54 +102,54 @@ const uint8_t PRIV(default_tables)[] = {
/* This table contains bit maps for various character classes. Each map is 32
bytes long and the bits run from the least significant end of each byte. The
classes that have their own maps are: space, xdigit, digit, upper, lower, word,
graph, print, punct, and cntrl. Other classes are built from combinations. */
graph print, punct, and cntrl. Other classes are built from combinations. */
0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00, /* space */
0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, /* xdigit */
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, /* digit */
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* upper */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* lower */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, /* word */
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, /* graph */
0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, /* print */
0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc, /* punct */
0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,
0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, /* cntrl */
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

View file

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2016-2020 University of Cambridge
New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -1202,7 +1202,7 @@ in the decoded tables. */
if ((code->flags & PCRE2_DEREF_TABLES) != 0)
{
ref_count = (PCRE2_SIZE *)(code->tables + TABLES_LENGTH);
ref_count = (PCRE2_SIZE *)(code->tables + tables_length);
(*ref_count)++;
}
@ -1232,15 +1232,15 @@ if (newcode == NULL) return NULL;
memcpy(newcode, code, code->blocksize);
newcode->executable_jit = NULL;
newtables = code->memctl.malloc(TABLES_LENGTH + sizeof(PCRE2_SIZE),
newtables = code->memctl.malloc(tables_length + sizeof(PCRE2_SIZE),
code->memctl.memory_data);
if (newtables == NULL)
{
code->memctl.free((void *)newcode, code->memctl.memory_data);
return NULL;
}
memcpy(newtables, code->tables, TABLES_LENGTH);
ref_count = (PCRE2_SIZE *)(newtables + TABLES_LENGTH);
memcpy(newtables, code->tables, tables_length);
ref_count = (PCRE2_SIZE *)(newtables + tables_length);
*ref_count = 1;
newcode->tables = newtables;
@ -1270,7 +1270,7 @@ if (code != NULL)
be freed when there are no more references to them. The *ref_count should
always be > 0. */
ref_count = (PCRE2_SIZE *)(code->tables + TABLES_LENGTH);
ref_count = (PCRE2_SIZE *)(code->tables + tables_length);
if (*ref_count > 0)
{
(*ref_count)--;
@ -3653,7 +3653,7 @@ while (ptr < ptrend)
if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
/* If ( is not followed by ? it is either a capture or a special verb or an
alpha assertion or a positive non-atomic lookahead. */
alpha assertion. */
if (*ptr != CHAR_QUESTION_MARK)
{
@ -3685,10 +3685,10 @@ while (ptr < ptrend)
break;
/* Handle "alpha assertions" such as (*pla:...). Most of these are
synonyms for the historical symbolic assertions, but the script run and
non-atomic lookaround ones are new. They are distinguished by starting
with a lower case letter. Checking both ends of the alphabet makes this
work in all character codes. */
synonyms for the historical symbolic assertions, but the script run ones
are new. They are distinguished by starting with a lower case letter.
Checking both ends of the alphabet makes this work in all character
codes. */
else if (CHMAX_255(c) && (cb->ctypes[c] & ctype_lcletter) != 0)
{
@ -3747,7 +3747,9 @@ while (ptr < ptrend)
goto POSITIVE_LOOK_AHEAD;
case META_LOOKAHEAD_NA:
goto POSITIVE_NONATOMIC_LOOK_AHEAD;
*parsed_pattern++ = meta;
ptr++;
goto POST_ASSERTION;
case META_LOOKAHEADNOT:
goto NEGATIVE_LOOK_AHEAD;
@ -4436,12 +4438,6 @@ while (ptr < ptrend)
ptr++;
goto POST_ASSERTION;
case CHAR_ASTERISK:
POSITIVE_NONATOMIC_LOOK_AHEAD: /* Come from (?* */
*parsed_pattern++ = META_LOOKAHEAD_NA;
ptr++;
goto POST_ASSERTION;
case CHAR_EXCLAMATION_MARK:
NEGATIVE_LOOK_AHEAD: /* Come from (*nla: */
*parsed_pattern++ = META_LOOKAHEADNOT;
@ -4451,21 +4447,18 @@ while (ptr < ptrend)
/* ---- Lookbehind assertions ---- */
/* (?< followed by = or ! or * is a lookbehind assertion. Otherwise (?<
is the start of the name of a capturing group. */
/* (?< followed by = or ! is a lookbehind assertion. Otherwise (?< is the
start of the name of a capturing group. */
case CHAR_LESS_THAN_SIGN:
if (ptrend - ptr <= 1 ||
(ptr[1] != CHAR_EQUALS_SIGN &&
ptr[1] != CHAR_EXCLAMATION_MARK &&
ptr[1] != CHAR_ASTERISK))
(ptr[1] != CHAR_EQUALS_SIGN && ptr[1] != CHAR_EXCLAMATION_MARK))
{
terminator = CHAR_GREATER_THAN_SIGN;
goto DEFINE_NAME;
}
*parsed_pattern++ = (ptr[1] == CHAR_EQUALS_SIGN)?
META_LOOKBEHIND : (ptr[1] == CHAR_EXCLAMATION_MARK)?
META_LOOKBEHINDNOT : META_LOOKBEHIND_NA;
META_LOOKBEHIND : META_LOOKBEHINDNOT;
POST_LOOKBEHIND: /* Come from (*plb: (*naplb: and (*nlb: */
*has_lookbehind = TRUE;
@ -4640,6 +4633,8 @@ while (ptr < ptrend)
*parsed_pattern++ = META_KET;
}
if (top_nest == (nest_save *)(cb->start_workspace)) top_nest = NULL;
else top_nest--;
}
@ -4904,7 +4899,7 @@ range. */
if ((options & PCRE2_CASELESS) != 0)
{
#ifdef SUPPORT_UNICODE
if ((options & (PCRE2_UTF|PCRE2_UCP)) != 0)
if ((options & PCRE2_UTF) != 0)
{
int rc;
uint32_t oc, od;
@ -5319,8 +5314,7 @@ dynamically as we process the pattern. */
#ifdef SUPPORT_UNICODE
BOOL utf = (options & PCRE2_UTF) != 0;
BOOL ucp = (options & PCRE2_UCP) != 0;
#else /* No Unicode support */
#else /* No UTF support */
BOOL utf = FALSE;
#endif
@ -5565,12 +5559,12 @@ for (;; pptr++)
zerofirstcu = firstcu;
zerofirstcuflags = firstcuflags;
/* For caseless UTF or UCP mode, check whether this character has more
than one other case. If so, generate a special OP_NOTPROP item instead of
/* For caseless UTF mode, check whether this character has more than
one other case. If so, generate a special OP_NOTPROP item instead of
OP_NOTI. */
#ifdef SUPPORT_UNICODE
if ((utf||ucp) && (options & PCRE2_CASELESS) != 0 &&
if (utf && (options & PCRE2_CASELESS) != 0 &&
(d = UCD_CASESET(c)) != 0)
{
*code++ = OP_NOTPROP;
@ -5603,7 +5597,7 @@ for (;; pptr++)
uint32_t d;
#ifdef SUPPORT_UNICODE
if ((utf || ucp) && c > 127) d = UCD_OTHERCASE(c); else
if (utf && c > 127) d = UCD_OTHERCASE(c); else
#endif
{
#if PCRE2_CODE_UNIT_WIDTH != 8
@ -6677,11 +6671,23 @@ for (;; pptr++)
}
/* For a back reference, update the back reference map and the
maximum back reference. */
maximum back reference. Then, for each group, we must check to
see if it is recursive, that is, it is inside the group that it
references. A flag is set so that the group can be made atomic.
*/
cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;
if (groupnumber > cb->top_backref)
cb->top_backref = groupnumber;
for (oc = cb->open_caps; oc != NULL; oc = oc->next)
{
if (oc->number == groupnumber)
{
oc->flag = TRUE;
break;
}
}
}
}
@ -7075,18 +7081,15 @@ for (;; pptr++)
previous[GET(previous, 1)] != OP_ALT)
goto END_REPEAT;
/* Perl allows all assertions to be quantified, and when they contain
capturing parentheses and/or are optional there are potential uses for
this feature. PCRE2 used to force the maximum quantifier to 1 on the
invalid grounds that further repetition was never useful. This was
always a bit pointless, since an assertion could be wrapped with a
repeated group to achieve the effect. General repetition is now
permitted, but if the maximum is unlimited it is set to one more than
the minimum. */
/* There is no sense in actually repeating assertions. The only
potential use of repetition is in cases when the assertion is optional.
Therefore, if the minimum is greater than zero, just ignore the repeat.
If the maximum is not zero or one, set it to 1. */
if (op_previous < OP_ONCE) /* Assertion */
{
if (repeat_max == REPEAT_UNLIMITED) repeat_max = repeat_min + 1;
if (repeat_min > 0) goto END_REPEAT;
if (repeat_max > 1) repeat_max = 1;
}
/* The case of a zero minimum is special because of the need to stick
@ -7679,6 +7682,19 @@ for (;; pptr++)
cb->backref_map |= (meta_arg < 32)? (1u << meta_arg) : 1;
if (meta_arg > cb->top_backref) cb->top_backref = meta_arg;
/* Check to see if this back reference is recursive, that it, it
is inside the group that it references. A flag is set so that the
group can be made atomic. */
for (oc = cb->open_caps; oc != NULL; oc = oc->next)
{
if (oc->number == meta_arg)
{
oc->flag = TRUE;
break;
}
}
break;
@ -7824,12 +7840,11 @@ for (;; pptr++)
NORMAL_CHAR_SET: /* Character is already in meta */
matched_char = TRUE;
/* For caseless UTF or UCP mode, check whether this character has more than
one other case. If so, generate a special OP_PROP item instead of OP_CHARI.
*/
/* For caseless UTF mode, check whether this character has more than one
other case. If so, generate a special OP_PROP item instead of OP_CHARI. */
#ifdef SUPPORT_UNICODE
if ((utf||ucp) && (options & PCRE2_CASELESS) != 0)
if (utf && (options & PCRE2_CASELESS) != 0)
{
uint32_t caseset = UCD_CASESET(meta);
if (caseset != 0)
@ -8038,6 +8053,7 @@ if (*code == OP_CBRA)
capnumber = GET2(code, 1 + LINK_SIZE);
capitem.number = capnumber;
capitem.next = cb->open_caps;
capitem.flag = FALSE;
capitem.assert_depth = cb->assert_depth;
cb->open_caps = &capitem;
}
@ -8166,9 +8182,26 @@ for (;;)
PUT(code, 1, (int)(code - start_bracket));
code += 1 + LINK_SIZE;
/* If it was a capturing subpattern, remove the block from the chain. */
/* If it was a capturing subpattern, check to see if it contained any
recursive back references. If so, we must wrap it in atomic brackets. In
any event, remove the block from the chain. */
if (capnumber > 0) cb->open_caps = cb->open_caps->next;
if (capnumber > 0)
{
if (cb->open_caps->flag)
{
(void)memmove(start_bracket + 1 + LINK_SIZE, start_bracket,
CU2BYTES(code - start_bracket));
*start_bracket = OP_ONCE;
code += 1 + LINK_SIZE;
PUT(start_bracket, 1, (int)(code - start_bracket));
*code = OP_KET;
PUT(code, 1, (int)(code - start_bracket));
code += 1 + LINK_SIZE;
length += 2 + 2*LINK_SIZE;
}
cb->open_caps = cb->open_caps->next;
}
/* Set values to pass back */
@ -8803,10 +8836,9 @@ memset(slot + IMM2_SIZE + length, 0,
/* This function is called to skip parts of the parsed pattern when finding the
length of a lookbehind branch. It is called after (*ACCEPT) and (*FAIL) to find
the end of the branch, it is called to skip over an internal lookaround or
(DEFINE) group, and it is also called to skip to the end of a class, during
which it will never encounter nested groups (but there's no need to have
special code for that).
the end of the branch, it is called to skip over an internal lookaround, and it
is also called to skip to the end of a class, during which it will never
encounter nested groups (but there's no need to have special code for that).
When called to find the end of a branch or group, pptr must point to the first
meta code inside the branch, not the branch-starting code. In other cases it
@ -9284,21 +9316,14 @@ for (;; pptr++)
itemlength = grouplength;
break;
/* A (DEFINE) group is never obeyed inline and so it does not contribute to
the length of this branch. Skip from the following item to the next
unpaired ket. */
case META_COND_DEFINE:
pptr = parsed_skip(pptr + 1, PSKIP_KET);
break;
/* Check other nested groups - advance past the initial data for each type
and then seek a fixed length with get_grouplength(). */
/* Check nested groups - advance past the initial data for each type and
then seek a fixed length with get_grouplength(). */
case META_COND_NAME:
case META_COND_NUMBER:
case META_COND_RNAME:
case META_COND_RNUMBER:
case META_COND_DEFINE:
pptr += 2 + SIZEOFFSET;
goto CHECK_GROUP;
@ -9555,10 +9580,6 @@ for (; *pptr != META_END; pptr++)
break;
case META_COND_DEFINE:
pptr += SIZEOFFSET;
nestlevel++;
break;
case META_COND_NAME:
case META_COND_NUMBER:
case META_COND_RNAME:
@ -9639,7 +9660,6 @@ pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE patlen, uint32_t options,
int *errorptr, PCRE2_SIZE *erroroffset, pcre2_compile_context *ccontext)
{
BOOL utf; /* Set TRUE for UTF mode */
BOOL ucp; /* Set TRUE for UCP mode */
BOOL has_lookbehind = FALSE; /* Set TRUE if a lookbehind is found */
BOOL zero_terminated; /* Set TRUE for zero-terminated pattern */
pcre2_real_code *re = NULL; /* What we will return */
@ -9927,8 +9947,8 @@ if (utf)
/* Check UCP lockout. */
ucp = (cb.external_options & PCRE2_UCP) != 0;
if (ucp && (cb.external_options & PCRE2_NEVER_UCP) != 0)
if ((cb.external_options & (PCRE2_UCP|PCRE2_NEVER_UCP)) ==
(PCRE2_UCP|PCRE2_NEVER_UCP))
{
errorcode = ERR75;
goto HAD_EARLY_ERROR;
@ -10304,7 +10324,7 @@ function call. */
if (errorcode == 0 && (re->overall_options & PCRE2_NO_AUTO_POSSESS) == 0)
{
PCRE2_UCHAR *temp = (PCRE2_UCHAR *)codestart;
if (PRIV(auto_possessify)(temp, &cb) != 0) errorcode = ERR80;
if (PRIV(auto_possessify)(temp, utf, &cb) != 0) errorcode = ERR80;
}
/* Failed to compile, or error while post-processing. */
@ -10352,25 +10372,21 @@ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
if ((firstcuflags & REQ_CASELESS) != 0)
{
if (firstcu < 128 || (!utf && !ucp && firstcu < 255))
if (firstcu < 128 || (!utf && firstcu < 255))
{
if (cb.fcc[firstcu] != firstcu) re->flags |= PCRE2_FIRSTCASELESS;
}
/* The first code unit is > 128 in UTF or UCP mode, or > 255 otherwise.
In 8-bit UTF mode, codepoints in the range 128-255 are introductory code
points and cannot have another case, but if UCP is set they may do. */
/* The first code unit is > 128 in UTF mode, or > 255 otherwise. In
8-bit UTF mode, codepoints in the range 128-255 are introductory code
points and cannot have another case. In 16-bit and 32-bit modes, we can
check wide characters when UTF (and therefore UCP) is supported. */
#ifdef SUPPORT_UNICODE
#if PCRE2_CODE_UNIT_WIDTH == 8
else if (ucp && !utf && UCD_OTHERCASE(firstcu) != firstcu)
re->flags |= PCRE2_FIRSTCASELESS;
#else
else if ((utf || ucp) && firstcu <= MAX_UTF_CODE_POINT &&
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
else if (firstcu <= MAX_UTF_CODE_POINT &&
UCD_OTHERCASE(firstcu) != firstcu)
re->flags |= PCRE2_FIRSTCASELESS;
#endif
#endif /* SUPPORT_UNICODE */
}
}
@ -10419,20 +10435,14 @@ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
if ((reqcuflags & REQ_CASELESS) != 0)
{
if (reqcu < 128 || (!utf && !ucp && reqcu < 255))
if (reqcu < 128 || (!utf && reqcu < 255))
{
if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS;
}
#ifdef SUPPORT_UNICODE
#if PCRE2_CODE_UNIT_WIDTH == 8
else if (ucp && !utf && UCD_OTHERCASE(reqcu) != reqcu)
re->flags |= PCRE2_LASTCASELESS;
#else
else if ((utf || ucp) && reqcu <= MAX_UTF_CODE_POINT &&
UCD_OTHERCASE(reqcu) != reqcu)
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
else if (reqcu <= MAX_UTF_CODE_POINT && UCD_OTHERCASE(reqcu) != reqcu)
re->flags |= PCRE2_LASTCASELESS;
#endif
#endif /* SUPPORT_UNICODE */
}
}
}

View file

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2016-2020 University of Cambridge
New API code Copyright (c) 2016-2017 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -43,8 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
#endif
/* Save the configured link size, which is in bytes. In 16-bit and 32-bit modes
its value gets changed by pcre2_intmodedep.h (included by pcre2_internal.h) to
be in code units. */
its value gets changed by pcre2_internal.h to be in code units. */
static int configured_link_size = LINK_SIZE;
@ -95,7 +94,6 @@ if (where == NULL) /* Requests a length */
case PCRE2_CONFIG_NEWLINE:
case PCRE2_CONFIG_PARENSLIMIT:
case PCRE2_CONFIG_STACKRECURSE: /* Obsolete */
case PCRE2_CONFIG_TABLES_LENGTH:
case PCRE2_CONFIG_UNICODE:
return sizeof(uint32_t);
@ -193,10 +191,6 @@ switch (what)
*((uint32_t *)where) = 0;
break;
case PCRE2_CONFIG_TABLES_LENGTH:
*((uint32_t *)where) = TABLES_LENGTH;
break;
case PCRE2_CONFIG_UNICODE_VERSION:
{
#if defined SUPPORT_UNICODE

View file

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2016-2020 University of Cambridge
New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -548,7 +548,6 @@ PCRE2_SPTR start_code = mb->start_code;
#ifdef SUPPORT_UNICODE
BOOL utf = (mb->poptions & PCRE2_UTF) != 0;
BOOL utf_or_ucp = utf || (mb->poptions & PCRE2_UCP) != 0;
#else
BOOL utf = FALSE;
#endif
@ -2191,7 +2190,7 @@ for (;;)
if (clen == 0) break;
#ifdef SUPPORT_UNICODE
if (utf_or_ucp)
if (utf)
{
if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else
{
@ -2205,7 +2204,7 @@ for (;;)
}
else
#endif /* SUPPORT_UNICODE */
/* Not UTF or UCP mode */
/* Not UTF mode */
{
if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d))
{ ADD_NEW(state_offset + 2, 0); }
@ -2340,7 +2339,7 @@ for (;;)
{
uint32_t otherd;
#ifdef SUPPORT_UNICODE
if (utf_or_ucp && d >= 128)
if (utf && d >= 128)
otherd = UCD_OTHERCASE(d);
else
#endif /* SUPPORT_UNICODE */
@ -2375,7 +2374,7 @@ for (;;)
if (caseless)
{
#ifdef SUPPORT_UNICODE
if (utf_or_ucp && d >= 128)
if (utf && d >= 128)
otherd = UCD_OTHERCASE(d);
else
#endif /* SUPPORT_UNICODE */
@ -2418,7 +2417,7 @@ for (;;)
if (caseless)
{
#ifdef SUPPORT_UNICODE
if (utf_or_ucp && d >= 128)
if (utf && d >= 128)
otherd = UCD_OTHERCASE(d);
else
#endif /* SUPPORT_UNICODE */
@ -2459,7 +2458,7 @@ for (;;)
if (caseless)
{
#ifdef SUPPORT_UNICODE
if (utf_or_ucp && d >= 128)
if (utf && d >= 128)
otherd = UCD_OTHERCASE(d);
else
#endif /* SUPPORT_UNICODE */
@ -2492,7 +2491,7 @@ for (;;)
if (caseless)
{
#ifdef SUPPORT_UNICODE
if (utf_or_ucp && d >= 128)
if (utf && d >= 128)
otherd = UCD_OTHERCASE(d);
else
#endif /* SUPPORT_UNICODE */
@ -2532,7 +2531,7 @@ for (;;)
if (caseless)
{
#ifdef SUPPORT_UNICODE
if (utf_or_ucp && d >= 128)
if (utf && d >= 128)
otherd = UCD_OTHERCASE(d);
else
#endif /* SUPPORT_UNICODE */
@ -3527,15 +3526,10 @@ if ((re->flags & PCRE2_FIRSTSET) != 0)
if ((re->flags & PCRE2_FIRSTCASELESS) != 0)
{
first_cu2 = TABLE_GET(first_cu, mb->tables + fcc_offset, first_cu);
#ifdef SUPPORT_UNICODE
#if PCRE2_CODE_UNIT_WIDTH == 8
if (first_cu > 127 && !utf && (re->overall_options & PCRE2_UCP) != 0)
first_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(first_cu);
#else
if (first_cu > 127 && (utf || (re->overall_options & PCRE2_UCP) != 0))
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
if (utf && first_cu > 127)
first_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(first_cu);
#endif
#endif /* SUPPORT_UNICODE */
}
}
else
@ -3551,15 +3545,9 @@ if ((re->flags & PCRE2_LASTSET) != 0)
if ((re->flags & PCRE2_LASTCASELESS) != 0)
{
req_cu2 = TABLE_GET(req_cu, mb->tables + fcc_offset, req_cu);
#ifdef SUPPORT_UNICODE
#if PCRE2_CODE_UNIT_WIDTH == 8
if (req_cu > 127 && !utf && (re->overall_options & PCRE2_UCP) != 0)
req_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(req_cu);
#else
if (req_cu > 127 && (utf || (re->overall_options & PCRE2_UCP) != 0))
req_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(req_cu);
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
if (utf && req_cu > 127) req_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(req_cu);
#endif
#endif /* SUPPORT_UNICODE */
}
}

View file

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2016-2020 University of Cambridge
New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -76,17 +76,6 @@ typedef int BOOL;
#include <valgrind/memcheck.h>
#endif
/* -ftrivial-auto-var-init support supports initializing all local variables
to avoid some classes of bug, but this can cause an unacceptable slowdown
for large on-stack arrays in hot functions. This macro lets us annotate
such arrays. */
#ifdef HAVE_ATTRIBUTE_UNINITIALIZED
#define PCRE2_KEEP_UNINITIALIZED __attribute__((uninitialized))
#else
#define PCRE2_KEEP_UNINITIALIZED
#endif
/* Older versions of MSVC lack snprintf(). This define allows for
warning/error-free compilation and testing with MSVC compilers back to at least
MSVC 10/2010. Except for VC6 (which is missing some fundamentals and fails). */
@ -590,7 +579,7 @@ total length of the tables. */
#define fcc_offset 256 /* Flip case */
#define cbits_offset 512 /* Character classes */
#define ctypes_offset (cbits_offset + cbit_length) /* Character types */
#define TABLES_LENGTH (ctypes_offset + 256)
#define tables_length (ctypes_offset + 256)
/* -------------------- Character and string names ------------------------ */
@ -1770,11 +1759,13 @@ typedef struct pcre2_memctl {
/* Structure for building a chain of open capturing subpatterns during
compiling, so that instructions to close them can be compiled when (*ACCEPT) is
encountered. */
encountered. This is also used to identify subpatterns that contain recursive
back references to themselves, so that they can be made atomic. */
typedef struct open_capitem {
struct open_capitem *next; /* Chain link */
uint16_t number; /* Capture number */
uint16_t flag; /* Set TRUE if recursive back ref */
uint16_t assert_depth; /* Assertion depth when opened */
} open_capitem;
@ -1963,7 +1954,7 @@ is available. */
#define _pcre2_was_newline PCRE2_SUFFIX(_pcre2_was_newline_)
#define _pcre2_xclass PCRE2_SUFFIX(_pcre2_xclass_)
extern int _pcre2_auto_possessify(PCRE2_UCHAR *,
extern int _pcre2_auto_possessify(PCRE2_UCHAR *, BOOL,
const compile_block *);
extern int _pcre2_check_escape(PCRE2_SPTR *, PCRE2_SPTR, uint32_t *,
int *, uint32_t, uint32_t, BOOL, compile_block *);

File diff suppressed because it is too large Load diff

View file

@ -145,11 +145,6 @@ maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
jit_stack = PRIV(memctl_malloc)(sizeof(pcre2_real_jit_stack), (pcre2_memctl *)gcontext);
if (jit_stack == NULL) return NULL;
jit_stack->stack = sljit_allocate_stack(startsize, maxsize, &jit_stack->memctl);
if (jit_stack->stack == NULL)
{
jit_stack->memctl.free(jit_stack, jit_stack->memctl.memory_data);
return NULL;
}
return jit_stack;
#endif

View file

@ -344,136 +344,6 @@ if (common->utf && offset > 0)
#endif
}
#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2))
static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2)
{
DEFINE_COMPILER;
struct sljit_label *start;
struct sljit_jump *quit;
jump_list *not_found = NULL;
sse2_compare_type compare_type = sse2_compare_match1;
sljit_u8 instruction[8];
sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1);
sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR);
sljit_s32 data_ind = 0;
sljit_s32 tmp_ind = 1;
sljit_s32 cmp1_ind = 2;
sljit_s32 cmp2_ind = 3;
sljit_u32 bit = 0;
int i;
if (char1 != char2)
{
bit = char1 ^ char2;
compare_type = sse2_compare_match1i;
if (!is_powerof2(bit))
{
bit = 0;
compare_type = sse2_compare_match2;
}
}
add_jump(compiler, &not_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));
OP1(SLJIT_MOV, TMP2, 0, TMP1, 0);
OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
/* First part (unaligned start) */
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
SLJIT_ASSERT(tmp1_reg_ind < 8);
/* MOVD xmm, r/m32 */
instruction[0] = 0x66;
instruction[1] = 0x0f;
instruction[2] = 0x6e;
instruction[3] = 0xc0 | (cmp1_ind << 3) | tmp1_reg_ind;
sljit_emit_op_custom(compiler, instruction, 4);
if (char1 != char2)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
/* MOVD xmm, r/m32 */
instruction[3] = 0xc0 | (cmp2_ind << 3) | tmp1_reg_ind;
sljit_emit_op_custom(compiler, instruction, 4);
}
OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);
/* PSHUFD xmm1, xmm2/m128, imm8 */
/* instruction[0] = 0x66; */
/* instruction[1] = 0x0f; */
instruction[2] = 0x70;
instruction[3] = 0xc0 | (cmp1_ind << 3) | cmp1_ind;
instruction[4] = 0;
sljit_emit_op_custom(compiler, instruction, 5);
if (char1 != char2)
{
/* PSHUFD xmm1, xmm2/m128, imm8 */
instruction[3] = 0xc0 | (cmp2_ind << 3) | cmp2_ind;
sljit_emit_op_custom(compiler, instruction, 5);
}
OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);
for (i = 0; i < 4; i++)
fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
/* PMOVMSKB reg, xmm */
/* instruction[0] = 0x66; */
/* instruction[1] = 0x0f; */
instruction[2] = 0xd7;
instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;
sljit_emit_op_custom(compiler, instruction, 4);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
/* Second part (aligned) */
start = LABEL();
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
add_jump(compiler, &not_found, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0);
for (i = 0; i < 4; i++)
fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
/* PMOVMSKB reg, xmm */
/* instruction[0] = 0x66; */
/* instruction[1] = 0x0f; */
instruction[2] = 0xd7;
instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind;
sljit_emit_op_custom(compiler, instruction, 4);
CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);
JUMPHERE(quit);
/* BSF r32, r/m32 */
instruction[0] = 0x0f;
instruction[1] = 0xbc;
instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind;
sljit_emit_op_custom(compiler, instruction, 3);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, STR_PTR, 0);
add_jump(compiler, &not_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));
OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0);
return not_found;
}
#ifndef _WIN64
static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void)

View file

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2016-2020 University of Cambridge
New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -41,11 +41,10 @@ POSSIBILITY OF SUCH DAMAGE.
/* This module contains the external function pcre2_maketables(), which builds
character tables for PCRE2 in the current locale. The file is compiled on its
own as part of the PCRE2 library. It is also included in the compilation of
pcre2_dftables.c as a freestanding program, in which case the macro
PCRE2_DFTABLES is defined. */
own as part of the PCRE2 library. However, it is also included in the
compilation of dftables.c, in which case the macro DFTABLES is defined. */
#ifndef PCRE2_DFTABLES /* Compiling the library */
#ifndef DFTABLES
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
@ -62,29 +61,28 @@ PCRE2_DFTABLES is defined. */
a pointer to them. They are build using the ctype functions, and consequently
their contents will depend upon the current locale setting. When compiled as
part of the library, the store is obtained via a general context malloc, if
supplied, but when PCRE2_DFTABLES is defined (when compiling the pcre2_dftables
freestanding auxiliary program) malloc() is used, and the function has a
different name so as not to clash with the prototype in pcre2.h.
supplied, but when DFTABLES is defined (when compiling the dftables auxiliary
program) malloc() is used, and the function has a different name so as not to
clash with the prototype in pcre2.h.
Arguments: none when PCRE2_DFTABLES is defined
Arguments: none when DFTABLES is defined
else a PCRE2 general context or NULL
Returns: pointer to the contiguous block of data
else NULL if memory allocation failed
*/
#ifdef PCRE2_DFTABLES /* Included in freestanding pcre2_dftables program */
#ifdef DFTABLES /* Included in freestanding dftables.c program */
static const uint8_t *maketables(void)
{
uint8_t *yield = (uint8_t *)malloc(TABLES_LENGTH);
uint8_t *yield = (uint8_t *)malloc(tables_length);
#else /* Not PCRE2_DFTABLES, that is, compiling the library */
#else /* Not DFTABLES, compiling the library */
PCRE2_EXP_DEFN const uint8_t * PCRE2_CALL_CONVENTION
pcre2_maketables(pcre2_general_context *gcontext)
{
uint8_t *yield = (uint8_t *)((gcontext != NULL)?
gcontext->memctl.malloc(TABLES_LENGTH, gcontext->memctl.memory_data) :
malloc(TABLES_LENGTH));
#endif /* PCRE2_DFTABLES */
gcontext->memctl.malloc(tables_length, gcontext->memctl.memory_data) :
malloc(tables_length));
#endif /* DFTABLES */
int i;
uint8_t *p;
@ -105,8 +103,8 @@ exclusive ones - in some locales things may be different.
Note that the table for "space" includes everything "isspace" gives, including
VT in the default locale. This makes it work for the POSIX class [:space:].
From PCRE1 release 8.34 and for all PCRE2 releases it is also correct for Perl
space, because Perl added VT at release 5.18.
From release 8.34 is is also correct for Perl space, because Perl added VT at
release 5.18.
Note also that it is possible for a character to be alnum or alpha without
being lower or upper, such as "male and female ordinals" (\xAA and \xBA) in the
@ -122,7 +120,7 @@ for (i = 0; i < 256; i++)
if (isalnum(i)) p[cbit_word + i/8] |= 1u << (i&7);
if (i == '_') p[cbit_word + i/8] |= 1u << (i&7);
if (isspace(i)) p[cbit_space + i/8] |= 1u << (i&7);
if (isxdigit(i)) p[cbit_xdigit + i/8] |= 1u << (i&7);
if (isxdigit(i))p[cbit_xdigit + i/8] |= 1u << (i&7);
if (isgraph(i)) p[cbit_graph + i/8] |= 1u << (i&7);
if (isprint(i)) p[cbit_print + i/8] |= 1u << (i&7);
if (ispunct(i)) p[cbit_punct + i/8] |= 1u << (i&7);
@ -132,8 +130,8 @@ p += cbit_length;
/* Finally, the character type table. In this, we used to exclude VT from the
white space chars, because Perl didn't recognize it as such for \s and for
comments within regexes. However, Perl changed at release 5.18, so PCRE1
changed at release 8.34 and it's always been this way for PCRE2. */
comments within regexes. However, Perl changed at release 5.18, so PCRE changed
at release 8.34. */
for (i = 0; i < 256; i++)
{
@ -149,7 +147,7 @@ for (i = 0; i < 256; i++)
return yield;
}
#ifndef PCRE2_DFTABLES /* Compiling the library */
#ifndef DFTABLES
PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
pcre2_maketables_free(pcre2_general_context *gcontext, const uint8_t *tables)
{

View file

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2015-2020 University of Cambridge
New API code Copyright (c) 2015-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -381,12 +381,8 @@ length = Fovector[offset+1] - Fovector[offset];
if (caseless)
{
#if defined SUPPORT_UNICODE
BOOL utf = (mb->poptions & PCRE2_UTF) != 0;
if (utf || (mb->poptions & PCRE2_UCP) != 0)
if ((mb->poptions & PCRE2_UTF) != 0)
{
PCRE2_SPTR endptr = p + length;
/* Match characters up to the end of the reference. NOTE: the number of
code units matched may differ, because in UTF-8 there are some characters
whose upper and lower case codes have different numbers of bytes. For
@ -394,25 +390,16 @@ if (caseless)
bytes in UTF-8); a sequence of 3 of the former uses 6 bytes, as does a
sequence of two of the latter. It is important, therefore, to check the
length along the reference, not along the subject (earlier code did this
wrong). UCP without uses Unicode properties but without UTF encoding. */
wrong). */
PCRE2_SPTR endptr = p + length;
while (p < endptr)
{
uint32_t c, d;
const ucd_record *ur;
if (eptr >= mb->end_subject) return 1; /* Partial match */
if (utf)
{
GETCHARINC(c, eptr);
GETCHARINC(d, p);
}
else
{
c = *eptr++;
d = *p++;
}
ur = GET_UCD(d);
if (c != d && c != (uint32_t)((int)d + ur->other_case))
{
@ -428,7 +415,7 @@ if (caseless)
else
#endif
/* Not in UTF or UCP mode */
/* Not in UTF mode */
{
for (; length > 0; length--)
{
@ -445,8 +432,7 @@ if (caseless)
}
/* In the caseful case, we can just compare the code units, whether or not we
are in UTF and/or UCP mode. When partial matching, we have to do this unit by
unit. */
are in UTF mode. When partial matching, we have to do this unit-by-unit. */
else
{
@ -588,7 +574,7 @@ match(PCRE2_SPTR start_eptr, PCRE2_SPTR start_ecode, PCRE2_SIZE *ovector,
heapframe *F; /* Current frame pointer */
heapframe *N = NULL; /* Temporary frame pointers */
heapframe *P = NULL;
heapframe *assert_accept_frame = NULL; /* For passing back a frame with captures */
heapframe *assert_accept_frame; /* For passing back the frame with captures */
PCRE2_SIZE frame_copy_size; /* Amount to copy when creating a new frame */
/* Local variables that do not need to be preserved over calls to RRMATCH(). */
@ -612,13 +598,12 @@ BOOL condition; /* Used in conditional groups */
BOOL cur_is_word; /* Used in "word" tests */
BOOL prev_is_word; /* Used in "word" tests */
/* UTF and UCP flags */
/* UTF flag */
#ifdef SUPPORT_UNICODE
BOOL utf = (mb->poptions & PCRE2_UTF) != 0;
BOOL ucp = (mb->poptions & PCRE2_UCP) != 0;
#else
BOOL utf = FALSE; /* Required for convenience even when no Unicode support */
BOOL utf = FALSE;
#endif
/* This is the length of the last part of a backtracking frame that must be
@ -943,7 +928,6 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
else
#endif
/* Not UTF mode */
{
if (mb->end_subject - Feptr < 1)
@ -1003,30 +987,10 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (dc != fc && dc != UCD_OTHERCASE(fc)) RRETURN(MATCH_NOMATCH);
}
}
/* If UCP is set without UTF we must do the same as above, but with one
character per code unit. */
else if (ucp)
{
uint32_t cc = UCHAR21(Feptr);
fc = Fecode[1];
if (fc < 128)
{
if (mb->lcc[fc] != TABLE_GET(cc, mb->lcc, cc)) RRETURN(MATCH_NOMATCH);
}
else
{
if (cc != fc && cc != UCD_OTHERCASE(fc)) RRETURN(MATCH_NOMATCH);
}
Feptr++;
Fecode += 2;
}
else
#endif /* SUPPORT_UNICODE */
/* Not UTF or UCP mode; use the table for characters < 256. */
/* Not UTF mode; use the table for characters < 256. */
{
if (TABLE_GET(Fecode[1], mb->lcc, Fecode[1])
!= TABLE_GET(*Feptr, mb->lcc, *Feptr)) RRETURN(MATCH_NOMATCH);
@ -1046,7 +1010,6 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
#ifdef SUPPORT_UNICODE
if (utf)
{
@ -1063,42 +1026,15 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (ch > 127)
ch = UCD_OTHERCASE(ch);
else
ch = (mb->fcc)[ch];
ch = TABLE_GET(ch, mb->fcc, ch);
if (ch == fc) RRETURN(MATCH_NOMATCH);
}
}
/* UCP without UTF is as above, but with one character per code unit. */
else if (ucp)
{
uint32_t ch;
fc = UCHAR21INC(Feptr);
ch = Fecode[1];
Fecode += 2;
if (ch == fc)
{
RRETURN(MATCH_NOMATCH); /* Caseful match */
}
else if (Fop == OP_NOTI) /* If caseless */
{
if (ch > 127)
ch = UCD_OTHERCASE(ch);
else
ch = (mb->fcc)[ch];
if (ch == fc) RRETURN(MATCH_NOMATCH);
}
}
else
#endif /* SUPPORT_UNICODE */
/* Neither UTF nor UCP is set */
{
uint32_t ch = Fecode[1];
fc = UCHAR21INC(Feptr);
fc = *Feptr++;
if (ch == fc || (Fop == OP_NOTI && TABLE_GET(ch, mb->fcc, ch) == fc))
RRETURN(MATCH_NOMATCH);
Fecode += 2;
@ -1308,7 +1244,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
#endif /* SUPPORT_UNICODE */
/* When not in UTF mode, load a single-code-unit character. Then proceed as
above, using Unicode casing if either UTF or UCP is set. */
above. */
Lc = *Fecode++;
@ -1317,15 +1253,11 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (Fop >= OP_STARI)
{
#if PCRE2_CODE_UNIT_WIDTH == 8
#ifdef SUPPORT_UNICODE
if (ucp && !utf && Lc > 127) Loc = UCD_OTHERCASE(Lc);
else
#endif /* SUPPORT_UNICODE */
/* Lc will be < 128 in UTF-8 mode. */
/* Lc must be < 128 in UTF-8 mode. */
Loc = mb->fcc[Lc];
#else /* 16-bit & 32-bit */
#ifdef SUPPORT_UNICODE
if ((utf || ucp) && Lc > 127) Loc = UCD_OTHERCASE(Lc);
if (utf && Lc > 127) Loc = UCD_OTHERCASE(Lc);
else
#endif /* SUPPORT_UNICODE */
Loc = TABLE_GET(Lc, mb->fcc, Lc);
@ -1558,7 +1490,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (Fop >= OP_NOTSTARI) /* Caseless */
{
#ifdef SUPPORT_UNICODE
if ((utf || ucp) && Lc > 127)
if (utf && Lc > 127)
Loc = UCD_OTHERCASE(Lc);
else
#endif /* SUPPORT_UNICODE */
@ -6113,6 +6045,7 @@ BOOL firstline;
BOOL has_first_cu = FALSE;
BOOL has_req_cu = FALSE;
BOOL startline;
BOOL utf;
#if PCRE2_CODE_UNIT_WIDTH == 8
BOOL memchr_not_found_first_cu = FALSE;
@ -6136,19 +6069,13 @@ PCRE2_SPTR match_partial;
BOOL use_jit;
#endif
/* This flag is needed even when Unicode is not supported for convenience
(it is used by the IS_NEWLINE macro). */
BOOL utf = FALSE;
#ifdef SUPPORT_UNICODE
BOOL ucp = FALSE;
BOOL allow_invalid;
uint32_t fragment_options = 0;
#ifdef SUPPORT_JIT
BOOL jit_checked_utf = FALSE;
#endif
#endif /* SUPPORT_UNICODE */
#endif
PCRE2_SIZE frame_size;
@ -6164,8 +6091,7 @@ proves to be too small, it is replaced by a larger one on the heap. To get a
vector of the size required that is aligned for pointers, allocate it as a
vector of pointers. */
PCRE2_SPTR stack_frames_vector[START_FRAMES_SIZE/sizeof(PCRE2_SPTR)]
PCRE2_KEEP_UNINITIALIZED;
PCRE2_SPTR stack_frames_vector[START_FRAMES_SIZE/sizeof(PCRE2_SPTR)];
mb->stack_frames = (heapframe *)stack_frames_vector;
/* A length equal to PCRE2_ZERO_TERMINATED implies a zero-terminated
@ -6221,13 +6147,12 @@ use_jit = (re->executable_jit != NULL &&
(options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0);
#endif
/* Initialize UTF/UCP parameters. */
/* Initialize UTF parameters. */
#ifdef SUPPORT_UNICODE
utf = (re->overall_options & PCRE2_UTF) != 0;
#ifdef SUPPORT_UNICODE
allow_invalid = (re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0;
ucp = (re->overall_options & PCRE2_UCP) != 0;
#endif /* SUPPORT_UNICODE */
#endif
/* Convert the partial matching flags into an integer. */
@ -6664,13 +6589,9 @@ if ((re->flags & PCRE2_FIRSTSET) != 0)
if ((re->flags & PCRE2_FIRSTCASELESS) != 0)
{
first_cu2 = TABLE_GET(first_cu, mb->fcc, first_cu);
#ifdef SUPPORT_UNICODE
#if PCRE2_CODE_UNIT_WIDTH == 8
if (first_cu > 127 && ucp && !utf) first_cu2 = UCD_OTHERCASE(first_cu);
#else
if (first_cu > 127 && (utf || ucp)) first_cu2 = UCD_OTHERCASE(first_cu);
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
if (utf && first_cu > 127) first_cu2 = UCD_OTHERCASE(first_cu);
#endif
#endif /* SUPPORT_UNICODE */
}
}
else
@ -6686,13 +6607,9 @@ if ((re->flags & PCRE2_LASTSET) != 0)
if ((re->flags & PCRE2_LASTCASELESS) != 0)
{
req_cu2 = TABLE_GET(req_cu, mb->fcc, req_cu);
#ifdef SUPPORT_UNICODE
#if PCRE2_CODE_UNIT_WIDTH == 8
if (req_cu > 127 && ucp && !utf) req_cu2 = UCD_OTHERCASE(req_cu);
#else
if (req_cu > 127 && (utf || ucp)) req_cu2 = UCD_OTHERCASE(req_cu);
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8
if (utf && req_cu > 127) req_cu2 = UCD_OTHERCASE(req_cu);
#endif
#endif /* SUPPORT_UNICODE */
}
}
@ -6839,16 +6756,15 @@ for(;;)
#endif
}
/* If we can't find the required first code unit, having reached the
true end of the subject, break the bumpalong loop, to force a match
failure, except when doing partial matching, when we let the next cycle
run at the end of the subject. To see why, consider the pattern
/(?<=abc)def/, which partially matches "abc", even though the string
does not contain the starting character "d". If we have not reached the
true end of the subject (PCRE2_FIRSTLINE caused end_subject to be
temporarily modified) we also let the cycle run, because the matching
string is legitimately allowed to start with the first code unit of a
newline. */
/* If we can't find the required code unit, having reached the true end
of the subject, break the bumpalong loop, to force a match failure,
except when doing partial matching, when we let the next cycle run at
the end of the subject. To see why, consider the pattern /(?<=abc)def/,
which partially matches "abc", even though the string does not contain
the starting character "d". If we have not reached the true end of the
subject (PCRE2_FIRSTLINE caused end_subject to be temporarily modified)
we also let the cycle run, because the matching string is legitimately
allowed to start with the first code unit of a newline. */
if (mb->partial == 0 && start_match >= mb->end_subject)
{

View file

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2016-2020 University of Cambridge
New API code Copyright (c) 2016-2018 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -90,7 +90,7 @@ if (codes == NULL || serialized_bytes == NULL || serialized_size == NULL)
if (number_of_codes <= 0) return PCRE2_ERROR_BADDATA;
/* Compute total size. */
total_size = sizeof(pcre2_serialized_data) + TABLES_LENGTH;
total_size = sizeof(pcre2_serialized_data) + tables_length;
tables = NULL;
for (i = 0; i < number_of_codes; i++)
@ -121,8 +121,8 @@ data->number_of_codes = number_of_codes;
/* Copy all compiled code data. */
dst_bytes = bytes + sizeof(pcre2_serialized_data);
memcpy(dst_bytes, tables, TABLES_LENGTH);
dst_bytes += TABLES_LENGTH;
memcpy(dst_bytes, tables, tables_length);
dst_bytes += tables_length;
for (i = 0; i < number_of_codes; i++)
{
@ -189,12 +189,12 @@ src_bytes = bytes + sizeof(pcre2_serialized_data);
/* Decode tables. The reference count for the tables is stored immediately
following them. */
tables = memctl->malloc(TABLES_LENGTH + sizeof(PCRE2_SIZE), memctl->memory_data);
tables = memctl->malloc(tables_length + sizeof(PCRE2_SIZE), memctl->memory_data);
if (tables == NULL) return PCRE2_ERROR_NOMEMORY;
memcpy(tables, src_bytes, TABLES_LENGTH);
*(PCRE2_SIZE *)(tables + TABLES_LENGTH) = number_of_codes;
src_bytes += TABLES_LENGTH;
memcpy(tables, src_bytes, tables_length);
*(PCRE2_SIZE *)(tables + tables_length) = number_of_codes;
src_bytes += tables_length;
/* Decode the byte stream. We must not try to read the size from the compiled
code block in the stream, because it might be unaligned, which causes errors on

View file

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2016-2020 University of Cambridge
New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -58,7 +58,7 @@ collecting data (e.g. minimum matching length). */
/* Returns from set_start_bits() */
enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE, SSB_UNKNOWN, SSB_TOODEEP };
enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE, SSB_UNKNOWN };
/*************************************************
@ -772,19 +772,15 @@ Arguments:
p points to the first code unit of the character
caseless TRUE if caseless
utf TRUE for UTF mode
ucp TRUE for UCP mode
Returns: pointer after the character
*/
static PCRE2_SPTR
set_table_bit(pcre2_real_code *re, PCRE2_SPTR p, BOOL caseless, BOOL utf,
BOOL ucp)
set_table_bit(pcre2_real_code *re, PCRE2_SPTR p, BOOL caseless, BOOL utf)
{
uint32_t c = *p++; /* First code unit */
(void)utf; /* Stop compiler warnings when UTF not supported */
(void)ucp;
(void)utf; /* Stop compiler warning when UTF not supported */
/* In 16-bit and 32-bit modes, code units greater than 0xff set the bit for
0xff. */
@ -814,26 +810,22 @@ if (utf)
if (caseless)
{
#ifdef SUPPORT_UNICODE
if (utf || ucp)
{
c = UCD_OTHERCASE(c);
#if PCRE2_CODE_UNIT_WIDTH == 8
if (utf)
{
#if PCRE2_CODE_UNIT_WIDTH == 8
PCRE2_UCHAR buff[6];
c = UCD_OTHERCASE(c);
(void)PRIV(ord2utf)(c, buff);
SET_BIT(buff[0]);
}
else if (c < 256) SET_BIT(c);
#else /* 16-bit or 32-bit mode */
c = UCD_OTHERCASE(c);
if (c > 0xff) SET_BIT(0xff); else SET_BIT(c);
#endif
}
else
#endif /* SUPPORT_UNICODE */
/* Not UTF or UCP */
/* Not UTF */
if (MAX_255(c)) SET_BIT(re->tables[fcc_offset + c]);
}
@ -932,26 +924,19 @@ The SSB_CONTINUE return is useful for parenthesized groups in patterns such as
must continue at the outer level to find at least one mandatory code unit. At
the outermost level, this function fails unless the result is SSB_DONE.
We restrict recursion (for nested groups) to 1000 to avoid stack overflow
issues.
Arguments:
re points to the compiled regex block
code points to an expression
utf TRUE if in UTF mode
ucp TRUE if in UCP mode
depthptr pointer to recurse depth
Returns: SSB_FAIL => Failed to find any starting code units
SSB_DONE => Found mandatory starting code units
SSB_CONTINUE => Found optional starting code units
SSB_UNKNOWN => Hit an unrecognized opcode
SSB_TOODEEP => Recursion is too deep
*/
static int
set_start_bits(pcre2_real_code *re, PCRE2_SPTR code, BOOL utf, BOOL ucp,
int *depthptr)
set_start_bits(pcre2_real_code *re, PCRE2_SPTR code, BOOL utf)
{
uint32_t c;
int yield = SSB_DONE;
@ -962,9 +947,6 @@ int table_limit = utf? 16:32;
int table_limit = 32;
#endif
*depthptr += 1;
if (*depthptr > 1000) return SSB_TOODEEP;
do
{
BOOL try_next = TRUE;
@ -1121,17 +1103,13 @@ do
case OP_SCRIPT_RUN:
case OP_ASSERT:
case OP_ASSERT_NA:
rc = set_start_bits(re, tcode, utf, ucp, depthptr);
if (rc == SSB_DONE)
{
try_next = FALSE;
}
else if (rc == SSB_CONTINUE)
rc = set_start_bits(re, tcode, utf);
if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
if (rc == SSB_DONE) try_next = FALSE; else
{
do tcode += GET(tcode, 1); while (*tcode == OP_ALT);
tcode += 1 + LINK_SIZE;
}
else return rc; /* FAIL, UNKNOWN, or TOODEEP */
break;
/* If we hit ALT or KET, it means we haven't found anything mandatory in
@ -1177,8 +1155,8 @@ do
case OP_BRAZERO:
case OP_BRAMINZERO:
case OP_BRAPOSZERO:
rc = set_start_bits(re, ++tcode, utf, ucp, depthptr);
if (rc == SSB_FAIL || rc == SSB_UNKNOWN || rc == SSB_TOODEEP) return rc;
rc = set_start_bits(re, ++tcode, utf);
if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc;
do tcode += GET(tcode,1); while (*tcode == OP_ALT);
tcode += 1 + LINK_SIZE;
break;
@ -1199,7 +1177,7 @@ do
case OP_QUERY:
case OP_MINQUERY:
case OP_POSQUERY:
tcode = set_table_bit(re, tcode + 1, FALSE, utf, ucp);
tcode = set_table_bit(re, tcode + 1, FALSE, utf);
break;
case OP_STARI:
@ -1208,7 +1186,7 @@ do
case OP_QUERYI:
case OP_MINQUERYI:
case OP_POSQUERYI:
tcode = set_table_bit(re, tcode + 1, TRUE, utf, ucp);
tcode = set_table_bit(re, tcode + 1, TRUE, utf);
break;
/* Single-char upto sets the bit and tries the next */
@ -1216,13 +1194,13 @@ do
case OP_UPTO:
case OP_MINUPTO:
case OP_POSUPTO:
tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, FALSE, utf, ucp);
tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, FALSE, utf);
break;
case OP_UPTOI:
case OP_MINUPTOI:
case OP_POSUPTOI:
tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, TRUE, utf, ucp);
tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, TRUE, utf);
break;
/* At least one single char sets the bit and stops */
@ -1234,7 +1212,7 @@ do
case OP_PLUS:
case OP_MINPLUS:
case OP_POSPLUS:
(void)set_table_bit(re, tcode + 1, FALSE, utf, ucp);
(void)set_table_bit(re, tcode + 1, FALSE, utf);
try_next = FALSE;
break;
@ -1245,7 +1223,7 @@ do
case OP_PLUSI:
case OP_MINPLUSI:
case OP_POSPLUSI:
(void)set_table_bit(re, tcode + 1, TRUE, utf, ucp);
(void)set_table_bit(re, tcode + 1, TRUE, utf);
try_next = FALSE;
break;
@ -1674,7 +1652,6 @@ PRIV(study)(pcre2_real_code *re)
int count = 0;
PCRE2_UCHAR *code;
BOOL utf = (re->overall_options & PCRE2_UTF) != 0;
BOOL ucp = (re->overall_options & PCRE2_UCP) != 0;
/* Find start of compiled code */
@ -1687,8 +1664,7 @@ code units. */
if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0)
{
int depth = 0;
int rc = set_start_bits(re, code, utf, ucp, &depth);
int rc = set_start_bits(re, code, utf);
if (rc == SSB_UNKNOWN) return 1;
/* If a list of starting code units was set up, scan the list to see if only
@ -1736,27 +1712,27 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0)
}
/* c contains the code unit value, in the range 0-255. In 8-bit UTF
mode, only values < 128 can be used. In all the other cases, c is a
character value. */
mode, only values < 128 can be used. */
#if PCRE2_CODE_UNIT_WIDTH == 8
if (utf && c > 127) goto DONE;
if (c > 127) goto DONE;
#endif
if (a < 0) a = c; /* First one found, save in a */
if (a < 0) a = c; /* First one found */
else if (b < 0) /* Second one found */
{
int d = TABLE_GET((unsigned int)c, re->tables + fcc_offset, c);
#ifdef SUPPORT_UNICODE
if (utf || ucp)
{
#if PCRE2_CODE_UNIT_WIDTH == 8
if (utf && UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */
#else /* 16-bit or 32-bit */
if (UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */
if (c > 127) d = UCD_OTHERCASE(c);
}
if (utf && c > 127) d = UCD_OTHERCASE(c);
#endif /* Code width */
#endif /* SUPPORT_UNICODE */
if (d != a) goto DONE; /* Not the other case of a */
b = c; /* Save second in b */
if (d != a) goto DONE; /* Not other case of a */
b = c;
}
else goto DONE; /* More than two characters found */
}

View file

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2016-2020 University of Cambridge
New API code Copyright (c) 2016-2019 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -49,9 +49,8 @@ POSSIBILITY OF SUCH DAMAGE.
#define SUBSTITUTE_OPTIONS \
(PCRE2_SUBSTITUTE_EXTENDED|PCRE2_SUBSTITUTE_GLOBAL| \
PCRE2_SUBSTITUTE_LITERAL|PCRE2_SUBSTITUTE_MATCHED| \
PCRE2_SUBSTITUTE_OVERFLOW_LENGTH|PCRE2_SUBSTITUTE_REPLACEMENT_ONLY| \
PCRE2_SUBSTITUTE_UNKNOWN_UNSET|PCRE2_SUBSTITUTE_UNSET_EMPTY)
PCRE2_SUBSTITUTE_OVERFLOW_LENGTH|PCRE2_SUBSTITUTE_UNKNOWN_UNSET| \
PCRE2_SUBSTITUTE_UNSET_EMPTY)
@ -195,7 +194,6 @@ overflow, either give an error immediately, or keep on, accumulating the
length. */
#define CHECKMEMCPY(from,length) \
{ \
if (!overflowed && lengthleft < length) \
{ \
if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \
@ -211,7 +209,6 @@ length. */
memcpy(buffer + buff_offset, from, CU2BYTES(length)); \
buff_offset += length; \
lengthleft -= length; \
} \
}
/* Here's the function */
@ -229,14 +226,11 @@ int forcecasereset = 0;
uint32_t ovector_count;
uint32_t goptions = 0;
uint32_t suboptions;
pcre2_match_data *internal_match_data = NULL;
BOOL escaped_literal = FALSE;
BOOL match_data_created = FALSE;
BOOL literal = FALSE;
BOOL overflowed = FALSE;
BOOL use_existing_match;
BOOL replacement_only;
#ifdef SUPPORT_UNICODE
BOOL utf = (code->overall_options & PCRE2_UTF) != 0;
BOOL ucp = (code->overall_options & PCRE2_UCP) != 0;
#endif
PCRE2_UCHAR temp[6];
PCRE2_SPTR ptr;
@ -260,48 +254,17 @@ PCRE2_UNSET, so as not to imply an offset in the replacement. */
if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0)
return PCRE2_ERROR_BADOPTION;
/* Check for using a match that has already happened. Note that the subject
pointer in the match data may be NULL after a no-match. */
use_existing_match = ((options & PCRE2_SUBSTITUTE_MATCHED) != 0);
replacement_only = ((options & PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) != 0);
/* If starting from an existing match, there must be an externally provided
match data block. We create an internal match_data block in two cases: (a) an
external one is not supplied (and we are not starting from an existing match);
(b) an existing match is to be used for the first substitution. In the latter
case, we copy the existing match into the internal block. This ensures that no
changes are made to the existing match data block. */
/* If no match data block is provided, create one. */
if (match_data == NULL)
{
pcre2_general_context *gcontext;
if (use_existing_match) return PCRE2_ERROR_NULL;
gcontext = (mcontext == NULL)?
(pcre2_general_context *)code :
(pcre2_general_context *)mcontext;
match_data = internal_match_data =
pcre2_match_data_create_from_pattern(code, gcontext);
if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY;
}
else if (use_existing_match)
{
pcre2_general_context *gcontext = (mcontext == NULL)?
(pcre2_general_context *)code :
(pcre2_general_context *)mcontext;
int pairs = (code->top_bracket + 1 < match_data->oveccount)?
code->top_bracket + 1 : match_data->oveccount;
internal_match_data = pcre2_match_data_create(match_data->oveccount,
gcontext);
if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY;
memcpy(internal_match_data, match_data, offsetof(pcre2_match_data, ovector)
+ 2*pairs*sizeof(PCRE2_SIZE));
match_data = internal_match_data;
match_data = pcre2_match_data_create_from_pattern(code, gcontext);
if (match_data == NULL) return PCRE2_ERROR_NOMEMORY;
match_data_created = TRUE;
}
/* Remember ovector details */
ovector = pcre2_get_ovector_pointer(match_data);
ovector_count = pcre2_get_ovector_count(match_data);
@ -323,7 +286,7 @@ repend = replacement + rlength;
#ifdef SUPPORT_UNICODE
if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)
{
rc = PRIV(valid_utf)(replacement, rlength, &(match_data->startchar));
rc = PRIV(valid_utf)(replacement, rlength, &(match_data->rightchar));
if (rc != 0)
{
match_data->leftchar = 0;
@ -337,7 +300,7 @@ if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)
suboptions = options & SUBSTITUTE_OPTIONS;
options &= ~SUBSTITUTE_OPTIONS;
/* Error if the start match offset is greater than the length of the subject. */
/* Copy up to the start offset */
if (start_offset > length)
{
@ -345,13 +308,9 @@ if (start_offset > length)
rc = PCRE2_ERROR_BADOFFSET;
goto EXIT;
}
CHECKMEMCPY(subject, start_offset);
/* Copy up to the start offset, unless only the replacement is required. */
if (!replacement_only) CHECKMEMCPY(subject, start_offset);
/* Loop for global substituting. If PCRE2_SUBSTITUTE_MATCHED is set, the first
match is taken from the match_data that was passed in. */
/* Loop for global substituting. */
subs = 0;
do
@ -359,12 +318,7 @@ do
PCRE2_SPTR ptrstack[PTR_STACK_SIZE];
uint32_t ptrstackptr = 0;
if (use_existing_match)
{
rc = match_data->rc;
use_existing_match = FALSE;
}
else rc = pcre2_match(code, subject, length, start_offset, options|goptions,
rc = pcre2_match(code, subject, length, start_offset, options|goptions,
match_data, mcontext);
#ifdef SUPPORT_UNICODE
@ -410,11 +364,11 @@ do
#endif
}
/* Copy what we have advanced past (unless not required), reset the special
global options, and continue to the next match. */
/* Copy what we have advanced past, reset the special global options, and
continue to the next match. */
fraglength = start_offset - save_start;
if (!replacement_only) CHECKMEMCPY(subject + save_start, fraglength);
CHECKMEMCPY(subject + save_start, fraglength);
goptions = 0;
continue;
}
@ -458,30 +412,21 @@ do
}
subs++;
/* Copy the text leading up to the match (unless not required), and remember
where the insert begins and how many ovector pairs are set. */
/* Copy the text leading up to the match, and remember where the insert
begins and how many ovector pairs are set. */
if (rc == 0) rc = ovector_count;
fraglength = ovector[0] - start_offset;
if (!replacement_only) CHECKMEMCPY(subject + start_offset, fraglength);
CHECKMEMCPY(subject + start_offset, fraglength);
scb.output_offsets[0] = buff_offset;
scb.oveccount = rc;
/* Process the replacement string. If the entire replacement is literal, just
copy it with length check. */
/* Process the replacement string. Literal mode is set by \Q, but only in
extended mode when backslashes are being interpreted. In extended mode we
must handle nested substrings that are to be reprocessed. */
ptr = replacement;
if ((suboptions & PCRE2_SUBSTITUTE_LITERAL) != 0)
{
CHECKMEMCPY(ptr, rlength);
}
/* Within a non-literal replacement, which must be scanned character by
character, local literal mode can be set by \Q, but only in extended mode
when backslashes are being interpreted. In extended mode we must handle
nested substrings that are to be reprocessed. */
else for (;;)
for (;;)
{
uint32_t ch;
unsigned int chlen;
@ -498,11 +443,11 @@ do
/* Handle the next character */
if (escaped_literal)
if (literal)
{
if (ptr[0] == CHAR_BACKSLASH && ptr < repend - 1 && ptr[1] == CHAR_E)
{
escaped_literal = FALSE;
literal = FALSE;
ptr += 2;
continue;
}
@ -759,7 +704,7 @@ do
if (forcecase != 0)
{
#ifdef SUPPORT_UNICODE
if (utf || ucp)
if (utf)
{
uint32_t type = UCD_CHARTYPE(ch);
if (PRIV(ucp_gentype)[type] == ucp_L &&
@ -839,7 +784,7 @@ do
continue;
case ESC_Q:
escaped_literal = TRUE;
literal = TRUE;
continue;
case 0: /* Data character */
@ -861,7 +806,7 @@ do
if (forcecase != 0)
{
#ifdef SUPPORT_UNICODE
if (utf || ucp)
if (utf)
{
uint32_t type = UCD_CHARTYPE(ch);
if (PRIV(ucp_gentype)[type] == ucp_L &&
@ -910,7 +855,7 @@ do
buff_offset -= newlength;
lengthleft += newlength;
if (!replacement_only) CHECKMEMCPY(subject + ovector[0], oldlength);
CHECKMEMCPY(subject + ovector[0], oldlength);
/* A negative return means do not do any more. */
@ -919,9 +864,8 @@ do
}
/* Save the details of this match. See above for how this data is used. If we
matched an empty string, do the magic for global matches. Update the start
offset to point to the rest of the subject string. If we re-used an existing
match for the first match, switch to the internal match data block. */
matched an empty string, do the magic for global matches. Finally, update the
start offset to point to the rest of the subject string. */
ovecsave[0] = ovector[0];
ovecsave[1] = ovector[1];
@ -932,17 +876,12 @@ do
start_offset = ovector[1];
} while ((suboptions & PCRE2_SUBSTITUTE_GLOBAL) != 0); /* Repeat "do" loop */
/* Copy the rest of the subject unless not required, and terminate the output
with a binary zero. */
if (!replacement_only)
{
fraglength = length - start_offset;
CHECKMEMCPY(subject + start_offset, fraglength);
}
/* Copy the rest of the subject. */
fraglength = length - start_offset;
CHECKMEMCPY(subject + start_offset, fraglength);
temp[0] = 0;
CHECKMEMCPY(temp, 1);
CHECKMEMCPY(temp , 1);
/* If overflowed is set it means the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set,
and matching has carried on after a full buffer, in order to compute the length
@ -964,7 +903,7 @@ else
}
EXIT:
if (internal_match_data != NULL) pcre2_match_data_free(internal_match_data);
if (match_data_created) pcre2_match_data_free(match_data);
else match_data->rc = rc;
return rc;

View file

@ -265,7 +265,6 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Chakma0 STR_C STR_h STR_a STR_k STR_m STR_a "\0"
#define STRING_Cham0 STR_C STR_h STR_a STR_m "\0"
#define STRING_Cherokee0 STR_C STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0"
#define STRING_Chorasmian0 STR_C STR_h STR_o STR_r STR_a STR_s STR_m STR_i STR_a STR_n "\0"
#define STRING_Cn0 STR_C STR_n "\0"
#define STRING_Co0 STR_C STR_o "\0"
#define STRING_Common0 STR_C STR_o STR_m STR_m STR_o STR_n "\0"
@ -276,7 +275,6 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Cyrillic0 STR_C STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0"
#define STRING_Deseret0 STR_D STR_e STR_s STR_e STR_r STR_e STR_t "\0"
#define STRING_Devanagari0 STR_D STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0"
#define STRING_Dives_Akuru0 STR_D STR_i STR_v STR_e STR_s STR_UNDERSCORE STR_A STR_k STR_u STR_r STR_u "\0"
#define STRING_Dogra0 STR_D STR_o STR_g STR_r STR_a "\0"
#define STRING_Duployan0 STR_D STR_u STR_p STR_l STR_o STR_y STR_a STR_n "\0"
#define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
@ -308,7 +306,6 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Katakana0 STR_K STR_a STR_t STR_a STR_k STR_a STR_n STR_a "\0"
#define STRING_Kayah_Li0 STR_K STR_a STR_y STR_a STR_h STR_UNDERSCORE STR_L STR_i "\0"
#define STRING_Kharoshthi0 STR_K STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0"
#define STRING_Khitan_Small_Script0 STR_K STR_h STR_i STR_t STR_a STR_n STR_UNDERSCORE STR_S STR_m STR_a STR_l STR_l STR_UNDERSCORE STR_S STR_c STR_r STR_i STR_p STR_t "\0"
#define STRING_Khmer0 STR_K STR_h STR_m STR_e STR_r "\0"
#define STRING_Khojki0 STR_K STR_h STR_o STR_j STR_k STR_i "\0"
#define STRING_Khudawadi0 STR_K STR_h STR_u STR_d STR_a STR_w STR_a STR_d STR_i "\0"
@ -432,7 +429,6 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Xsp0 STR_X STR_s STR_p "\0"
#define STRING_Xuc0 STR_X STR_u STR_c "\0"
#define STRING_Xwd0 STR_X STR_w STR_d "\0"
#define STRING_Yezidi0 STR_Y STR_e STR_z STR_i STR_d STR_i "\0"
#define STRING_Yi0 STR_Y STR_i "\0"
#define STRING_Z0 STR_Z "\0"
#define STRING_Zanabazar_Square0 STR_Z STR_a STR_n STR_a STR_b STR_a STR_z STR_a STR_r STR_UNDERSCORE STR_S STR_q STR_u STR_a STR_r STR_e "\0"
@ -468,7 +464,6 @@ const char PRIV(utt_names)[] =
STRING_Chakma0
STRING_Cham0
STRING_Cherokee0
STRING_Chorasmian0
STRING_Cn0
STRING_Co0
STRING_Common0
@ -479,7 +474,6 @@ const char PRIV(utt_names)[] =
STRING_Cyrillic0
STRING_Deseret0
STRING_Devanagari0
STRING_Dives_Akuru0
STRING_Dogra0
STRING_Duployan0
STRING_Egyptian_Hieroglyphs0
@ -511,7 +505,6 @@ const char PRIV(utt_names)[] =
STRING_Katakana0
STRING_Kayah_Li0
STRING_Kharoshthi0
STRING_Khitan_Small_Script0
STRING_Khmer0
STRING_Khojki0
STRING_Khudawadi0
@ -635,7 +628,6 @@ const char PRIV(utt_names)[] =
STRING_Xsp0
STRING_Xuc0
STRING_Xwd0
STRING_Yezidi0
STRING_Yi0
STRING_Z0
STRING_Zanabazar_Square0
@ -671,180 +663,176 @@ const ucp_type_table PRIV(utt)[] = {
{ 203, PT_SC, ucp_Chakma },
{ 210, PT_SC, ucp_Cham },
{ 215, PT_SC, ucp_Cherokee },
{ 224, PT_SC, ucp_Chorasmian },
{ 235, PT_PC, ucp_Cn },
{ 238, PT_PC, ucp_Co },
{ 241, PT_SC, ucp_Common },
{ 248, PT_SC, ucp_Coptic },
{ 255, PT_PC, ucp_Cs },
{ 258, PT_SC, ucp_Cuneiform },
{ 268, PT_SC, ucp_Cypriot },
{ 276, PT_SC, ucp_Cyrillic },
{ 285, PT_SC, ucp_Deseret },
{ 293, PT_SC, ucp_Devanagari },
{ 304, PT_SC, ucp_Dives_Akuru },
{ 316, PT_SC, ucp_Dogra },
{ 322, PT_SC, ucp_Duployan },
{ 331, PT_SC, ucp_Egyptian_Hieroglyphs },
{ 352, PT_SC, ucp_Elbasan },
{ 360, PT_SC, ucp_Elymaic },
{ 368, PT_SC, ucp_Ethiopic },
{ 377, PT_SC, ucp_Georgian },
{ 386, PT_SC, ucp_Glagolitic },
{ 397, PT_SC, ucp_Gothic },
{ 404, PT_SC, ucp_Grantha },
{ 412, PT_SC, ucp_Greek },
{ 418, PT_SC, ucp_Gujarati },
{ 427, PT_SC, ucp_Gunjala_Gondi },
{ 441, PT_SC, ucp_Gurmukhi },
{ 450, PT_SC, ucp_Han },
{ 454, PT_SC, ucp_Hangul },
{ 461, PT_SC, ucp_Hanifi_Rohingya },
{ 477, PT_SC, ucp_Hanunoo },
{ 485, PT_SC, ucp_Hatran },
{ 492, PT_SC, ucp_Hebrew },
{ 499, PT_SC, ucp_Hiragana },
{ 508, PT_SC, ucp_Imperial_Aramaic },
{ 525, PT_SC, ucp_Inherited },
{ 535, PT_SC, ucp_Inscriptional_Pahlavi },
{ 557, PT_SC, ucp_Inscriptional_Parthian },
{ 580, PT_SC, ucp_Javanese },
{ 589, PT_SC, ucp_Kaithi },
{ 596, PT_SC, ucp_Kannada },
{ 604, PT_SC, ucp_Katakana },
{ 613, PT_SC, ucp_Kayah_Li },
{ 622, PT_SC, ucp_Kharoshthi },
{ 633, PT_SC, ucp_Khitan_Small_Script },
{ 653, PT_SC, ucp_Khmer },
{ 659, PT_SC, ucp_Khojki },
{ 666, PT_SC, ucp_Khudawadi },
{ 676, PT_GC, ucp_L },
{ 678, PT_LAMP, 0 },
{ 681, PT_SC, ucp_Lao },
{ 685, PT_SC, ucp_Latin },
{ 691, PT_SC, ucp_Lepcha },
{ 698, PT_SC, ucp_Limbu },
{ 704, PT_SC, ucp_Linear_A },
{ 713, PT_SC, ucp_Linear_B },
{ 722, PT_SC, ucp_Lisu },
{ 727, PT_PC, ucp_Ll },
{ 730, PT_PC, ucp_Lm },
{ 733, PT_PC, ucp_Lo },
{ 736, PT_PC, ucp_Lt },
{ 739, PT_PC, ucp_Lu },
{ 742, PT_SC, ucp_Lycian },
{ 749, PT_SC, ucp_Lydian },
{ 756, PT_GC, ucp_M },
{ 758, PT_SC, ucp_Mahajani },
{ 767, PT_SC, ucp_Makasar },
{ 775, PT_SC, ucp_Malayalam },
{ 785, PT_SC, ucp_Mandaic },
{ 793, PT_SC, ucp_Manichaean },
{ 804, PT_SC, ucp_Marchen },
{ 812, PT_SC, ucp_Masaram_Gondi },
{ 826, PT_PC, ucp_Mc },
{ 829, PT_PC, ucp_Me },
{ 832, PT_SC, ucp_Medefaidrin },
{ 844, PT_SC, ucp_Meetei_Mayek },
{ 857, PT_SC, ucp_Mende_Kikakui },
{ 871, PT_SC, ucp_Meroitic_Cursive },
{ 888, PT_SC, ucp_Meroitic_Hieroglyphs },
{ 909, PT_SC, ucp_Miao },
{ 914, PT_PC, ucp_Mn },
{ 917, PT_SC, ucp_Modi },
{ 922, PT_SC, ucp_Mongolian },
{ 932, PT_SC, ucp_Mro },
{ 936, PT_SC, ucp_Multani },
{ 944, PT_SC, ucp_Myanmar },
{ 952, PT_GC, ucp_N },
{ 954, PT_SC, ucp_Nabataean },
{ 964, PT_SC, ucp_Nandinagari },
{ 976, PT_PC, ucp_Nd },
{ 979, PT_SC, ucp_New_Tai_Lue },
{ 991, PT_SC, ucp_Newa },
{ 996, PT_SC, ucp_Nko },
{ 1000, PT_PC, ucp_Nl },
{ 1003, PT_PC, ucp_No },
{ 1006, PT_SC, ucp_Nushu },
{ 1012, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
{ 1035, PT_SC, ucp_Ogham },
{ 1041, PT_SC, ucp_Ol_Chiki },
{ 1050, PT_SC, ucp_Old_Hungarian },
{ 1064, PT_SC, ucp_Old_Italic },
{ 1075, PT_SC, ucp_Old_North_Arabian },
{ 1093, PT_SC, ucp_Old_Permic },
{ 1104, PT_SC, ucp_Old_Persian },
{ 1116, PT_SC, ucp_Old_Sogdian },
{ 1128, PT_SC, ucp_Old_South_Arabian },
{ 1146, PT_SC, ucp_Old_Turkic },
{ 1157, PT_SC, ucp_Oriya },
{ 1163, PT_SC, ucp_Osage },
{ 1169, PT_SC, ucp_Osmanya },
{ 1177, PT_GC, ucp_P },
{ 1179, PT_SC, ucp_Pahawh_Hmong },
{ 1192, PT_SC, ucp_Palmyrene },
{ 1202, PT_SC, ucp_Pau_Cin_Hau },
{ 1214, PT_PC, ucp_Pc },
{ 1217, PT_PC, ucp_Pd },
{ 1220, PT_PC, ucp_Pe },
{ 1223, PT_PC, ucp_Pf },
{ 1226, PT_SC, ucp_Phags_Pa },
{ 1235, PT_SC, ucp_Phoenician },
{ 1246, PT_PC, ucp_Pi },
{ 1249, PT_PC, ucp_Po },
{ 1252, PT_PC, ucp_Ps },
{ 1255, PT_SC, ucp_Psalter_Pahlavi },
{ 1271, PT_SC, ucp_Rejang },
{ 1278, PT_SC, ucp_Runic },
{ 1284, PT_GC, ucp_S },
{ 1286, PT_SC, ucp_Samaritan },
{ 1296, PT_SC, ucp_Saurashtra },
{ 1307, PT_PC, ucp_Sc },
{ 1310, PT_SC, ucp_Sharada },
{ 1318, PT_SC, ucp_Shavian },
{ 1326, PT_SC, ucp_Siddham },
{ 1334, PT_SC, ucp_SignWriting },
{ 1346, PT_SC, ucp_Sinhala },
{ 1354, PT_PC, ucp_Sk },
{ 1357, PT_PC, ucp_Sm },
{ 1360, PT_PC, ucp_So },
{ 1363, PT_SC, ucp_Sogdian },
{ 1371, PT_SC, ucp_Sora_Sompeng },
{ 1384, PT_SC, ucp_Soyombo },
{ 1392, PT_SC, ucp_Sundanese },
{ 1402, PT_SC, ucp_Syloti_Nagri },
{ 1415, PT_SC, ucp_Syriac },
{ 1422, PT_SC, ucp_Tagalog },
{ 1430, PT_SC, ucp_Tagbanwa },
{ 1439, PT_SC, ucp_Tai_Le },
{ 1446, PT_SC, ucp_Tai_Tham },
{ 1455, PT_SC, ucp_Tai_Viet },
{ 1464, PT_SC, ucp_Takri },
{ 1470, PT_SC, ucp_Tamil },
{ 1476, PT_SC, ucp_Tangut },
{ 1483, PT_SC, ucp_Telugu },
{ 1490, PT_SC, ucp_Thaana },
{ 1497, PT_SC, ucp_Thai },
{ 1502, PT_SC, ucp_Tibetan },
{ 1510, PT_SC, ucp_Tifinagh },
{ 1519, PT_SC, ucp_Tirhuta },
{ 1527, PT_SC, ucp_Ugaritic },
{ 1536, PT_SC, ucp_Unknown },
{ 1544, PT_SC, ucp_Vai },
{ 1548, PT_SC, ucp_Wancho },
{ 1555, PT_SC, ucp_Warang_Citi },
{ 1567, PT_ALNUM, 0 },
{ 1571, PT_PXSPACE, 0 },
{ 1575, PT_SPACE, 0 },
{ 1579, PT_UCNC, 0 },
{ 1583, PT_WORD, 0 },
{ 1587, PT_SC, ucp_Yezidi },
{ 1594, PT_SC, ucp_Yi },
{ 1597, PT_GC, ucp_Z },
{ 1599, PT_SC, ucp_Zanabazar_Square },
{ 1616, PT_PC, ucp_Zl },
{ 1619, PT_PC, ucp_Zp },
{ 1622, PT_PC, ucp_Zs }
{ 224, PT_PC, ucp_Cn },
{ 227, PT_PC, ucp_Co },
{ 230, PT_SC, ucp_Common },
{ 237, PT_SC, ucp_Coptic },
{ 244, PT_PC, ucp_Cs },
{ 247, PT_SC, ucp_Cuneiform },
{ 257, PT_SC, ucp_Cypriot },
{ 265, PT_SC, ucp_Cyrillic },
{ 274, PT_SC, ucp_Deseret },
{ 282, PT_SC, ucp_Devanagari },
{ 293, PT_SC, ucp_Dogra },
{ 299, PT_SC, ucp_Duployan },
{ 308, PT_SC, ucp_Egyptian_Hieroglyphs },
{ 329, PT_SC, ucp_Elbasan },
{ 337, PT_SC, ucp_Elymaic },
{ 345, PT_SC, ucp_Ethiopic },
{ 354, PT_SC, ucp_Georgian },
{ 363, PT_SC, ucp_Glagolitic },
{ 374, PT_SC, ucp_Gothic },
{ 381, PT_SC, ucp_Grantha },
{ 389, PT_SC, ucp_Greek },
{ 395, PT_SC, ucp_Gujarati },
{ 404, PT_SC, ucp_Gunjala_Gondi },
{ 418, PT_SC, ucp_Gurmukhi },
{ 427, PT_SC, ucp_Han },
{ 431, PT_SC, ucp_Hangul },
{ 438, PT_SC, ucp_Hanifi_Rohingya },
{ 454, PT_SC, ucp_Hanunoo },
{ 462, PT_SC, ucp_Hatran },
{ 469, PT_SC, ucp_Hebrew },
{ 476, PT_SC, ucp_Hiragana },
{ 485, PT_SC, ucp_Imperial_Aramaic },
{ 502, PT_SC, ucp_Inherited },
{ 512, PT_SC, ucp_Inscriptional_Pahlavi },
{ 534, PT_SC, ucp_Inscriptional_Parthian },
{ 557, PT_SC, ucp_Javanese },
{ 566, PT_SC, ucp_Kaithi },
{ 573, PT_SC, ucp_Kannada },
{ 581, PT_SC, ucp_Katakana },
{ 590, PT_SC, ucp_Kayah_Li },
{ 599, PT_SC, ucp_Kharoshthi },
{ 610, PT_SC, ucp_Khmer },
{ 616, PT_SC, ucp_Khojki },
{ 623, PT_SC, ucp_Khudawadi },
{ 633, PT_GC, ucp_L },
{ 635, PT_LAMP, 0 },
{ 638, PT_SC, ucp_Lao },
{ 642, PT_SC, ucp_Latin },
{ 648, PT_SC, ucp_Lepcha },
{ 655, PT_SC, ucp_Limbu },
{ 661, PT_SC, ucp_Linear_A },
{ 670, PT_SC, ucp_Linear_B },
{ 679, PT_SC, ucp_Lisu },
{ 684, PT_PC, ucp_Ll },
{ 687, PT_PC, ucp_Lm },
{ 690, PT_PC, ucp_Lo },
{ 693, PT_PC, ucp_Lt },
{ 696, PT_PC, ucp_Lu },
{ 699, PT_SC, ucp_Lycian },
{ 706, PT_SC, ucp_Lydian },
{ 713, PT_GC, ucp_M },
{ 715, PT_SC, ucp_Mahajani },
{ 724, PT_SC, ucp_Makasar },
{ 732, PT_SC, ucp_Malayalam },
{ 742, PT_SC, ucp_Mandaic },
{ 750, PT_SC, ucp_Manichaean },
{ 761, PT_SC, ucp_Marchen },
{ 769, PT_SC, ucp_Masaram_Gondi },
{ 783, PT_PC, ucp_Mc },
{ 786, PT_PC, ucp_Me },
{ 789, PT_SC, ucp_Medefaidrin },
{ 801, PT_SC, ucp_Meetei_Mayek },
{ 814, PT_SC, ucp_Mende_Kikakui },
{ 828, PT_SC, ucp_Meroitic_Cursive },
{ 845, PT_SC, ucp_Meroitic_Hieroglyphs },
{ 866, PT_SC, ucp_Miao },
{ 871, PT_PC, ucp_Mn },
{ 874, PT_SC, ucp_Modi },
{ 879, PT_SC, ucp_Mongolian },
{ 889, PT_SC, ucp_Mro },
{ 893, PT_SC, ucp_Multani },
{ 901, PT_SC, ucp_Myanmar },
{ 909, PT_GC, ucp_N },
{ 911, PT_SC, ucp_Nabataean },
{ 921, PT_SC, ucp_Nandinagari },
{ 933, PT_PC, ucp_Nd },
{ 936, PT_SC, ucp_New_Tai_Lue },
{ 948, PT_SC, ucp_Newa },
{ 953, PT_SC, ucp_Nko },
{ 957, PT_PC, ucp_Nl },
{ 960, PT_PC, ucp_No },
{ 963, PT_SC, ucp_Nushu },
{ 969, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
{ 992, PT_SC, ucp_Ogham },
{ 998, PT_SC, ucp_Ol_Chiki },
{ 1007, PT_SC, ucp_Old_Hungarian },
{ 1021, PT_SC, ucp_Old_Italic },
{ 1032, PT_SC, ucp_Old_North_Arabian },
{ 1050, PT_SC, ucp_Old_Permic },
{ 1061, PT_SC, ucp_Old_Persian },
{ 1073, PT_SC, ucp_Old_Sogdian },
{ 1085, PT_SC, ucp_Old_South_Arabian },
{ 1103, PT_SC, ucp_Old_Turkic },
{ 1114, PT_SC, ucp_Oriya },
{ 1120, PT_SC, ucp_Osage },
{ 1126, PT_SC, ucp_Osmanya },
{ 1134, PT_GC, ucp_P },
{ 1136, PT_SC, ucp_Pahawh_Hmong },
{ 1149, PT_SC, ucp_Palmyrene },
{ 1159, PT_SC, ucp_Pau_Cin_Hau },
{ 1171, PT_PC, ucp_Pc },
{ 1174, PT_PC, ucp_Pd },
{ 1177, PT_PC, ucp_Pe },
{ 1180, PT_PC, ucp_Pf },
{ 1183, PT_SC, ucp_Phags_Pa },
{ 1192, PT_SC, ucp_Phoenician },
{ 1203, PT_PC, ucp_Pi },
{ 1206, PT_PC, ucp_Po },
{ 1209, PT_PC, ucp_Ps },
{ 1212, PT_SC, ucp_Psalter_Pahlavi },
{ 1228, PT_SC, ucp_Rejang },
{ 1235, PT_SC, ucp_Runic },
{ 1241, PT_GC, ucp_S },
{ 1243, PT_SC, ucp_Samaritan },
{ 1253, PT_SC, ucp_Saurashtra },
{ 1264, PT_PC, ucp_Sc },
{ 1267, PT_SC, ucp_Sharada },
{ 1275, PT_SC, ucp_Shavian },
{ 1283, PT_SC, ucp_Siddham },
{ 1291, PT_SC, ucp_SignWriting },
{ 1303, PT_SC, ucp_Sinhala },
{ 1311, PT_PC, ucp_Sk },
{ 1314, PT_PC, ucp_Sm },
{ 1317, PT_PC, ucp_So },
{ 1320, PT_SC, ucp_Sogdian },
{ 1328, PT_SC, ucp_Sora_Sompeng },
{ 1341, PT_SC, ucp_Soyombo },
{ 1349, PT_SC, ucp_Sundanese },
{ 1359, PT_SC, ucp_Syloti_Nagri },
{ 1372, PT_SC, ucp_Syriac },
{ 1379, PT_SC, ucp_Tagalog },
{ 1387, PT_SC, ucp_Tagbanwa },
{ 1396, PT_SC, ucp_Tai_Le },
{ 1403, PT_SC, ucp_Tai_Tham },
{ 1412, PT_SC, ucp_Tai_Viet },
{ 1421, PT_SC, ucp_Takri },
{ 1427, PT_SC, ucp_Tamil },
{ 1433, PT_SC, ucp_Tangut },
{ 1440, PT_SC, ucp_Telugu },
{ 1447, PT_SC, ucp_Thaana },
{ 1454, PT_SC, ucp_Thai },
{ 1459, PT_SC, ucp_Tibetan },
{ 1467, PT_SC, ucp_Tifinagh },
{ 1476, PT_SC, ucp_Tirhuta },
{ 1484, PT_SC, ucp_Ugaritic },
{ 1493, PT_SC, ucp_Unknown },
{ 1501, PT_SC, ucp_Vai },
{ 1505, PT_SC, ucp_Wancho },
{ 1512, PT_SC, ucp_Warang_Citi },
{ 1524, PT_ALNUM, 0 },
{ 1528, PT_PXSPACE, 0 },
{ 1532, PT_SPACE, 0 },
{ 1536, PT_UCNC, 0 },
{ 1540, PT_WORD, 0 },
{ 1544, PT_SC, ucp_Yi },
{ 1547, PT_GC, ucp_Z },
{ 1549, PT_SC, ucp_Zanabazar_Square },
{ 1566, PT_PC, ucp_Zl },
{ 1569, PT_PC, ucp_Zp },
{ 1572, PT_PC, ucp_Zs }
};
const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);

File diff suppressed because it is too large Load diff

View file

@ -286,12 +286,7 @@ enum {
ucp_Elymaic,
ucp_Nandinagari,
ucp_Nyiakeng_Puachue_Hmong,
ucp_Wancho,
/* New for Unicode 13.0.0 */
ucp_Chorasmian,
ucp_Dives_Akuru,
ucp_Khitan_Small_Script,
ucp_Yezidi
ucp_Wancho
};
#endif /* PCRE2_UCP_H_IDEMPOTENT_GUARD */

View file

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2016-2020 University of Cambridge
New API code Copyright (c) 2016-2017 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -347,7 +347,7 @@ for (p = string; length > 0; p++)
length--;
if ((*p & 0xfc00) != 0xdc00)
{
*erroroffset = p - string - 1;
*erroroffset = p - string;
return PCRE2_ERROR_UTF16_ERR2;
}
}

View file

@ -27,10 +27,6 @@
#ifndef _SLJIT_CONFIG_H_
#define _SLJIT_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
/* --------------------------------------------------------------------- */
/* Custom defines */
/* --------------------------------------------------------------------- */
@ -69,19 +65,12 @@ extern "C" {
#define SLJIT_UTIL_GLOBAL_LOCK 1
#endif
/* Implements a stack like data structure (by using mmap / VirtualAlloc */
/* or a custom allocator). */
/* Implements a stack like data structure (by using mmap / VirtualAlloc). */
#ifndef SLJIT_UTIL_STACK
/* Enabled by default */
#define SLJIT_UTIL_STACK 1
#endif
/* Uses user provided allocator to allocate the stack (see SLJIT_UTIL_STACK) */
#ifndef SLJIT_UTIL_SIMPLE_STACK_ALLOCATION
/* Disabled by default */
#define SLJIT_UTIL_SIMPLE_STACK_ALLOCATION 0
#endif
/* Single threaded application. Does not require any locks. */
#ifndef SLJIT_SINGLE_THREADED
/* Disabled by default. */
@ -155,8 +144,4 @@ extern "C" {
/* For further configurations, see the beginning of sljitConfigInternal.h */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View file

@ -27,20 +27,6 @@
#ifndef _SLJIT_CONFIG_INTERNAL_H_
#define _SLJIT_CONFIG_INTERNAL_H_
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_DEBUG && SLJIT_DEBUG && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)))
#include <stdio.h>
#endif
#if (defined SLJIT_DEBUG && SLJIT_DEBUG \
&& (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) || !defined(SLJIT_HALT_PROCESS)))
#include <stdlib.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
SLJIT defines the following architecture dependent types and macros:
@ -205,24 +191,6 @@ extern "C" {
#define SLJIT_CONFIG_SPARC 1
#endif
/***********************************************************/
/* Intel Control-flow Enforcement Technology (CET) spport. */
/***********************************************************/
#ifdef SLJIT_CONFIG_X86
#if defined(__CET__)
#define SLJIT_CONFIG_X86_CET 1
#endif
#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)
#if defined(__GNUC__)
#if !defined (__SHSTK__)
#error "-mshstk is needed to compile with -fcf-protection"
#endif
#include <x86intrin.h>
#endif
#endif
#endif
/**********************************/
/* External function definitions. */
/**********************************/
@ -297,7 +265,6 @@ extern "C" {
/* Type of public API functions. */
/*********************************/
#ifndef SLJIT_API_FUNC_ATTRIBUTE
#if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC)
/* Static ABI functions. For all-in-one programs. */
@ -311,7 +278,6 @@ extern "C" {
#else
#define SLJIT_API_FUNC_ATTRIBUTE
#endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */
#endif /* defined SLJIT_API_FUNC_ATTRIBUTE */
/****************************/
/* Instruction cache flush. */
@ -321,7 +287,7 @@ extern "C" {
#if __has_builtin(__builtin___clear_cache)
#define SLJIT_CACHE_FLUSH(from, to) \
__builtin___clear_cache((char*)(from), (char*)(to))
__builtin___clear_cache((char*)from, (char*)to)
#endif /* __has_builtin(__builtin___clear_cache) */
#endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */
@ -352,7 +318,7 @@ extern "C" {
#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
#define SLJIT_CACHE_FLUSH(from, to) \
__builtin___clear_cache((char*)(from), (char*)(to))
__builtin___clear_cache((char*)from, (char*)to)
#elif defined __ANDROID__
@ -485,25 +451,6 @@ typedef double sljit_f64;
#define SLJIT_BIG_ENDIAN 1
#endif
#ifndef SLJIT_MIPS_REV
/* Auto detecting mips revision. */
#if (defined __mips_isa_rev) && (__mips_isa_rev >= 6)
#define SLJIT_MIPS_REV 6
#elif (defined __mips_isa_rev && __mips_isa_rev >= 1) \
|| (defined __clang__ && defined _MIPS_ARCH_OCTEON) \
|| (defined __clang__ && defined _MIPS_ARCH_P5600)
/* clang either forgets to define (clang-7) __mips_isa_rev at all
* or sets it to zero (clang-8,-9) for -march=octeon (MIPS64 R2+)
* and -march=p5600 (MIPS32 R5).
* It also sets the __mips macro to 64 or 32 for -mipsN when N <= 5
* (should be set to N exactly) so we cannot rely on this too.
*/
#define SLJIT_MIPS_REV 1
#endif
#endif /* !SLJIT_MIPS_REV */
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
#define SLJIT_BIG_ENDIAN 1
@ -732,16 +679,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
/* Debug and verbose related macros. */
/*************************************/
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
#include <stdio.h>
#endif
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
#if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)
/* SLJIT_HALT_PROCESS must halt the process. */
#ifndef SLJIT_HALT_PROCESS
#include <stdlib.h>
#define SLJIT_HALT_PROCESS() \
abort();
#endif /* !SLJIT_HALT_PROCESS */
#include <stdio.h>
#endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */
/* Feel free to redefine these two macros. */
@ -787,8 +742,4 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#endif /* !SLJIT_COMPILE_ASSERT */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View file

@ -106,10 +106,10 @@ static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
static SLJIT_INLINE int get_map_jit_flag()
{
/* On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a version
of macOS where it's OK to have more than one JIT block.
On non-macOS systems, returns MAP_JIT if it is defined. */
#if TARGET_OS_OSX
/* On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a version
of macOS where it's OK to have more than one JIT block. On non-macOS systems, returns
MAP_JIT if it is defined. */
static int map_jit_flag = -1;
/* The following code is thread safe because multiple initialization
@ -124,19 +124,12 @@ static SLJIT_INLINE int get_map_jit_flag()
/* Kernel version for 10.14.0 (Mojave) */
if (atoi(name.release) >= 18) {
/* Only use MAP_JIT if a hardened runtime is used, because MAP_JIT is incompatible with fork(). */
/* mirroring page size detection from sljit_allocate_stack */
long page_size = sysconf(_SC_PAGESIZE);
/* Should never happen */
if (page_size < 0)
page_size = 4096;
void *ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
void *ptr = mmap(NULL, getpagesize(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (ptr == MAP_FAILED) {
map_jit_flag = MAP_JIT;
} else {
munmap(ptr, page_size);
munmap(ptr, getpagesize());
}
}
}

View file

@ -926,8 +926,7 @@ static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, s
static const char* op0_names[] = {
(char*)"breakpoint", (char*)"nop", (char*)"lmul.uw", (char*)"lmul.sw",
(char*)"divmod.u", (char*)"divmod.s", (char*)"div.u", (char*)"div.s",
(char*)"endbr", (char*)"skip_frames_before_return"
(char*)"divmod.u", (char*)"divmod.s", (char*)"div.u", (char*)"div.s"
};
static const char* op1_names[] = {
@ -944,12 +943,6 @@ static const char* op2_names[] = {
(char*)"shl", (char*)"lshr", (char*)"ashr",
};
static const char* op_src_names[] = {
(char*)"fast_return", (char*)"skip_frames_before_fast_return",
(char*)"prefetch_l1", (char*)"prefetch_l2",
(char*)"prefetch_l3", (char*)"prefetch_once",
};
static const char* fop1_names[] = {
(char*)"mov", (char*)"conv", (char*)"conv", (char*)"conv",
(char*)"conv", (char*)"conv", (char*)"cmp", (char*)"neg",
@ -1159,21 +1152,37 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_c
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
FUNCTION_CHECK_SRC(src, srcw);
CHECK_ARGUMENT(src != SLJIT_IMM);
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " fast_return ");
sljit_verbose_param(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW)
|| ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW)
|| (op >= SLJIT_ENDBR && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN));
CHECK_ARGUMENT(GET_OPCODE(op) < SLJIT_LMUL_UW || GET_OPCODE(op) >= SLJIT_ENDBR || compiler->scratches >= 2);
if ((GET_OPCODE(op) >= SLJIT_LMUL_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN)
|| ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW));
CHECK_ARGUMENT(op < SLJIT_LMUL_UW || compiler->scratches >= 2);
if (op >= SLJIT_LMUL_UW)
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose))
{
fprintf(compiler->verbose, " %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]);
if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) {
if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW) {
fprintf(compiler->verbose, (op & SLJIT_I32_OP) ? "32" : "w");
}
fprintf(compiler->verbose, "\n");
@ -1215,7 +1224,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
break;
}
FUNCTION_CHECK_DST(dst, dstw, HAS_FLAGS(op));
FUNCTION_CHECK_DST(dst, dstw, 1);
FUNCTION_CHECK_SRC(src, srcw);
if (GET_OPCODE(op) >= SLJIT_NOT) {
@ -1295,7 +1304,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler
break;
}
FUNCTION_CHECK_DST(dst, dstw, HAS_FLAGS(op));
FUNCTION_CHECK_DST(dst, dstw, 1);
FUNCTION_CHECK_SRC(src1, src1w);
FUNCTION_CHECK_SRC(src2, src2w);
compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
@ -1316,33 +1325,6 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(op >= SLJIT_FAST_RETURN && op <= SLJIT_PREFETCH_ONCE);
FUNCTION_CHECK_SRC(src, srcw);
if (op == SLJIT_FAST_RETURN || op == SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN)
{
CHECK_ARGUMENT(src != SLJIT_IMM);
compiler->last_flags = 0;
}
else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE)
{
CHECK_ARGUMENT(src & SLJIT_MEM);
}
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s ", op_src_names[op - SLJIT_OP_SRC_BASE]);
sljit_verbose_param(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 reg)
{
SLJIT_UNUSED_ARG(reg);
@ -2034,7 +2016,7 @@ static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *comp
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|| ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1))
|| ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1))
static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 dst_reg,
@ -2399,6 +2381,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
SLJIT_UNUSED_ARG(compiler);
@ -2438,17 +2429,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(op);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
SLJIT_UNREACHABLE();
return SLJIT_ERR_UNSUPPORTED;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
{
SLJIT_UNREACHABLE();
@ -2569,13 +2549,6 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
SLJIT_UNREACHABLE();
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label)
{
SLJIT_UNUSED_ARG(put_label);
SLJIT_UNUSED_ARG(label);
SLJIT_UNREACHABLE();
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
{
SLJIT_UNUSED_ARG(compiler);

View file

@ -80,10 +80,6 @@ of sljitConfigInternal.h */
#include "sljitConfigInternal.h"
#ifdef __cplusplus
extern "C" {
#endif
/* --------------------------------------------------------------------- */
/* Error codes */
/* --------------------------------------------------------------------- */
@ -158,10 +154,10 @@ extern "C" {
*/
/* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1
or sljit_emit_op2 operations the result is discarded. Some status
flags must be set when the destination is SLJIT_UNUSED, because the
operation would have no effect otherwise. Other SLJIT operations do
not support SLJIT_UNUSED as a destination operand. */
or sljit_emit_op2 operations the result is discarded. If no status
flags are set, no instructions are emitted for these operations. Data
prefetch is a special exception, see SLJIT_MOV operation. Other SLJIT
operations do not support SLJIT_UNUSED as a destination operand. */
#define SLJIT_UNUSED 0
/* Scratch registers. */
@ -571,14 +567,10 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
#define SLJIT_HAS_FPU 0
/* [Limitation] Some registers are virtual registers. */
#define SLJIT_HAS_VIRTUAL_REGISTERS 1
/* [Emulated] Has zero register (setting a memory location to zero is efficient). */
#define SLJIT_HAS_ZERO_REGISTER 2
/* [Emulated] Count leading zero is supported. */
#define SLJIT_HAS_CLZ 3
#define SLJIT_HAS_CLZ 2
/* [Emulated] Conditional move is supported. */
#define SLJIT_HAS_CMOV 4
/* [Emulated] Conditional move is supported. */
#define SLJIT_HAS_PREFETCH 5
#define SLJIT_HAS_CMOV 3
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
/* [Not emulated] SSE2 support is available on x86. */
@ -666,10 +658,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
sljit_s32 src, sljit_sw srcw);
/* Generating entry and exit points for fast call functions (see SLJIT_FAST_CALL).
Both sljit_emit_fast_enter and SLJIT_FAST_RETURN operations preserve the
Both sljit_emit_fast_enter and sljit_emit_fast_return functions preserve the
values of all registers and stack frame. The return address is stored in the
dst argument of sljit_emit_fast_enter, and this return address can be passed
to SLJIT_FAST_RETURN to continue the execution after the fast call.
to sljit_emit_fast_return to continue the execution after the fast call.
Fast calls are cheap operations (usually only a single call instruction is
emitted) but they do not preserve any registers. However the callee function
@ -677,15 +669,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
efficiently exploited by various optimizations. Registers can be saved
manually by the callee function if needed.
Although returning to different address by SLJIT_FAST_RETURN is possible,
Although returning to different address by sljit_emit_fast_return is possible,
this address usually cannot be predicted by the return address predictor of
modern CPUs which may reduce performance. Furthermore certain security
enhancement technologies such as Intel Control-flow Enforcement Technology
(CET) may disallow returning to a different address.
modern CPUs which may reduce performance. Furthermore using sljit_emit_ijump
to return is also inefficient since return address prediction is usually
triggered by a specific form of ijump.
Flags: - (does not modify flags). */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw);
/*
Source and destination operands for arithmetical instructions
@ -894,14 +887,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
the behaviour is undefined. */
#define SLJIT_DIV_SW (SLJIT_OP0_BASE + 7)
#define SLJIT_DIV_S32 (SLJIT_DIV_SW | SLJIT_I32_OP)
/* Flags: - (does not modify flags)
ENDBR32 instruction for x86-32 and ENDBR64 instruction for x86-64
when Intel Control-flow Enforcement Technology (CET) is enabled.
No instruction for other architectures. */
#define SLJIT_ENDBR (SLJIT_OP0_BASE + 8)
/* Flags: - (may destroy flags)
Skip stack frames before return. */
#define SLJIT_SKIP_FRAMES_BEFORE_RETURN (SLJIT_OP0_BASE + 9)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op);
@ -919,6 +904,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
U32 - unsigned int (32 bit) data transfer
S32 - signed int (32 bit) data transfer
P - pointer (sljit_p) data transfer
If the destination of a MOV instruction is SLJIT_UNUSED and the source
operand is a memory address the compiler emits a prefetch instruction
if this instruction is supported by the current CPU. Higher data sizes
bring the data closer to the core: a MOV with word size loads the data
into a higher level cache than a byte size. Otherwise the type does not
affect the prefetch instruction. Furthermore a prefetch instruction
never fails, so it can be used to prefetch a data from an address and
check whether that address is NULL afterwards.
*/
/* Flags: - (does not modify flags) */
@ -1023,46 +1017,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w);
/* Starting index of opcodes for sljit_emit_op2. */
#define SLJIT_OP_SRC_BASE 128
/* Note: src cannot be an immedate value
Flags: - (does not modify flags) */
#define SLJIT_FAST_RETURN (SLJIT_OP_SRC_BASE + 0)
/* Skip stack frames before fast return.
Note: src cannot be an immedate value
Flags: may destroy flags. */
#define SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN (SLJIT_OP_SRC_BASE + 1)
/* Prefetch value into the level 1 data cache
Note: if the target CPU does not support data prefetch,
no instructions are emitted.
Note: this instruction never fails, even if the memory address is invalid.
Flags: - (does not modify flags) */
#define SLJIT_PREFETCH_L1 (SLJIT_OP_SRC_BASE + 2)
/* Prefetch value into the level 2 data cache
Note: same as SLJIT_PREFETCH_L1 if the target CPU
does not support this instruction form.
Note: this instruction never fails, even if the memory address is invalid.
Flags: - (does not modify flags) */
#define SLJIT_PREFETCH_L2 (SLJIT_OP_SRC_BASE + 3)
/* Prefetch value into the level 3 data cache
Note: same as SLJIT_PREFETCH_L2 if the target CPU
does not support this instruction form.
Note: this instruction never fails, even if the memory address is invalid.
Flags: - (does not modify flags) */
#define SLJIT_PREFETCH_L3 (SLJIT_OP_SRC_BASE + 4)
/* Prefetch a value which is only used once (and can be discarded afterwards)
Note: same as SLJIT_PREFETCH_L1 if the target CPU
does not support this instruction form.
Note: this instruction never fails, even if the memory address is invalid.
Flags: - (does not modify flags) */
#define SLJIT_PREFETCH_ONCE (SLJIT_OP_SRC_BASE + 5)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw);
/* Starting index of opcodes for sljit_emit_fop1. */
#define SLJIT_FOP1_BASE 160
#define SLJIT_FOP1_BASE 128
/* Flags: - (does not modify flags) */
#define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0)
@ -1101,7 +1057,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
sljit_s32 src, sljit_sw srcw);
/* Starting index of opcodes for sljit_emit_fop2. */
#define SLJIT_FOP2_BASE 192
#define SLJIT_FOP2_BASE 160
/* Flags: - (does not modify flags) */
#define SLJIT_ADD_F64 (SLJIT_FOP2_BASE + 0)
@ -1205,7 +1161,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
/* Unconditional jump types. */
#define SLJIT_JUMP 24
/* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */
/* Fast calling method. See sljit_emit_fast_enter / sljit_emit_fast_return. */
#define SLJIT_FAST_CALL 25
/* Called function must be declared with the SLJIT_FUNC attribute. */
#define SLJIT_CALL 26
@ -1534,8 +1490,4 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler,
sljit_s32 current_flags);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _SLJIT_LIR_H_ */

View file

@ -666,8 +666,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = code_ptr - code;
label = label->next;
next_addr = compute_next_addr(label, jump, const_, put_label);
}
}
}
@ -872,9 +870,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
case SLJIT_HAS_CLZ:
case SLJIT_HAS_CMOV:
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
case SLJIT_HAS_PREFETCH:
#endif
return 1;
default:
@ -1681,9 +1676,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
| (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
}
return SLJIT_SUCCESS;
case SLJIT_ENDBR:
case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
return SLJIT_SUCCESS;
}
return SLJIT_SUCCESS;
@ -1698,6 +1690,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);
#endif
return SLJIT_SUCCESS;
}
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
case SLJIT_MOV_U32:
@ -1779,40 +1779,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
switch (op) {
case SLJIT_FAST_RETURN:
SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src)));
else
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1));
return push_inst(compiler, BX | RM(TMP_REG2));
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
return SLJIT_SUCCESS;
case SLJIT_PREFETCH_L1:
case SLJIT_PREFETCH_L2:
case SLJIT_PREFETCH_L3:
case SLJIT_PREFETCH_ONCE:
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
SLJIT_ASSERT(src & SLJIT_MEM);
return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1);
#else /* !SLJIT_CONFIG_ARM_V7 */
return SLJIT_SUCCESS;
#endif /* SLJIT_CONFIG_ARM_V7 */
}
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
{
CHECK_REG_INDEX(check_sljit_get_register_index(reg));
@ -2075,6 +2041,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src)));
else
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1));
return push_inst(compiler, BX | RM(TMP_REG2));
}
/* --------------------------------------------------------------------- */
/* Conditional instructions */
/* --------------------------------------------------------------------- */
@ -2633,11 +2615,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
}
else {
if (is_type1_transfer) {
if (memw > 4095 || memw < -4095)
if (memw > 4095 && memw < -4095)
return SLJIT_ERR_UNSUPPORTED;
}
else {
if (memw > 255 || memw < -255)
if (memw > 255 && memw < -255)
return SLJIT_ERR_UNSUPPORTED;
}
}

View file

@ -396,7 +396,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
case SLJIT_HAS_CLZ:
case SLJIT_HAS_CMOV:
case SLJIT_HAS_PREFETCH:
return 1;
default:
@ -1155,9 +1154,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
case SLJIT_DIV_UW:
case SLJIT_DIV_SW:
return push_inst(compiler, ((op == SLJIT_DIV_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1));
case SLJIT_ENDBR:
case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
return SLJIT_SUCCESS;
}
return SLJIT_SUCCESS;
@ -1175,6 +1171,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) {
SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4);
if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8)
dst = 5;
else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16)
dst = 3;
else
dst = 1;
/* Signed word sized load is the prefetch instruction. */
return emit_op_mem(compiler, WORD_SIZE | SIGNED, dst, src, srcw, TMP_REG1);
}
return SLJIT_SUCCESS;
}
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
op = GET_OPCODE(op);
@ -1314,46 +1327,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
switch (op) {
case SLJIT_FAST_RETURN:
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src)));
else
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1));
return push_inst(compiler, RET | RN(TMP_LR));
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
return SLJIT_SUCCESS;
case SLJIT_PREFETCH_L1:
case SLJIT_PREFETCH_L2:
case SLJIT_PREFETCH_L3:
case SLJIT_PREFETCH_ONCE:
SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4);
/* The reg_map[op] should provide the appropriate constant. */
if (op == SLJIT_PREFETCH_L1)
op = 1;
else if (op == SLJIT_PREFETCH_L2)
op = 3;
else if (op == SLJIT_PREFETCH_L3)
op = 5;
else
op = 2;
/* Signed word sized load is the prefetch instruction. */
return emit_op_mem(compiler, WORD_SIZE | SIGNED, op, src, srcw, TMP_REG1);
}
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
{
CHECK_REG_INDEX(check_sljit_get_register_index(reg));
@ -1605,6 +1578,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw, TMP_REG1);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src)));
else
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1));
return push_inst(compiler, RET | RN(TMP_LR));
}
/* --------------------------------------------------------------------- */
/* Conditional instructions */
/* --------------------------------------------------------------------- */
@ -1878,7 +1865,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
CHECK_ERROR();
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))
if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -256))
return SLJIT_ERR_UNSUPPORTED;
if (type & SLJIT_MEM_SUPP)
@ -1928,7 +1915,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw));
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256))
if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -256))
return SLJIT_ERR_UNSUPPORTED;
if (type & SLJIT_MEM_SUPP)

View file

@ -480,7 +480,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
case SLJIT_HAS_CLZ:
case SLJIT_HAS_CMOV:
case SLJIT_HAS_PREFETCH:
return 1;
default:
@ -1329,9 +1328,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
}
return SLJIT_SUCCESS;
#endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */
case SLJIT_ENDBR:
case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
return SLJIT_SUCCESS;
}
return SLJIT_SUCCESS;
@ -1349,6 +1345,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
/* Since TMP_PC has index 15, IS_2_LO_REGS and IS_3_LO_REGS checks always fail. */
if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1);
return SLJIT_SUCCESS;
}
dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
op = GET_OPCODE(op);
@ -1472,35 +1475,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG2);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
switch (op) {
case SLJIT_FAST_RETURN:
SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
if (FAST_IS_REG(src))
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));
else
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));
return push_inst16(compiler, BX | RN3(TMP_REG2));
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
return SLJIT_SUCCESS;
case SLJIT_PREFETCH_L1:
case SLJIT_PREFETCH_L2:
case SLJIT_PREFETCH_L3:
case SLJIT_PREFETCH_ONCE:
return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1);
}
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
{
CHECK_REG_INDEX(check_sljit_get_register_index(reg));
@ -1754,6 +1728,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
if (FAST_IS_REG(src))
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));
else
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));
return push_inst16(compiler, BX | RN3(TMP_REG2));
}
/* --------------------------------------------------------------------- */
/* Conditional instructions */
/* --------------------------------------------------------------------- */
@ -2274,7 +2264,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
CHECK_ERROR();
CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw));
if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255))
if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -255))
return SLJIT_ERR_UNSUPPORTED;
if (type & SLJIT_MEM_SUPP)

View file

@ -86,12 +86,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_S8) {
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
#else /* SLJIT_MIPS_REV < 1 */
#else
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
#endif /* SLJIT_MIPS_REV >= 1 */
#endif
}
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
}
@ -105,12 +105,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_S16) {
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
#else /* SLJIT_MIPS_REV < 1 */
#else
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
#endif /* SLJIT_MIPS_REV >= 1 */
#endif
}
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
}
@ -129,12 +129,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
if (!(flags & UNUSED_DEST))
FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
#else /* SLJIT_MIPS_REV < 1 */
#else
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
@ -149,7 +149,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst)));
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
#endif /* SLJIT_MIPS_REV >= 1 */
#endif
return SLJIT_SUCCESS;
case SLJIT_ADD:
@ -368,22 +368,21 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
SLJIT_ASSERT(!(flags & SRC2_IMM));
if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) || (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
#else /* SLJIT_MIPS_REV < 1 */
#else /* !SLJIT_MIPS_R1 && !SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
return push_inst(compiler, MFLO | D(dst), DR(dst));
#endif /* SLJIT_MIPS_REV >= 1 */
#endif /* SLJIT_MIPS_R1 || SLJIT_MIPS_R6 */
}
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
FAIL_IF(push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)));
FAIL_IF(push_inst(compiler, MUH | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
#else /* SLJIT_MIPS_REV < 6 */
#else /* !SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS));
FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);

View file

@ -220,12 +220,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
if (!(flags & UNUSED_DEST))
FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst)));
#else /* SLJIT_MIPS_REV < 1 */
#else
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
@ -240,7 +240,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
#endif /* SLJIT_MIPS_REV >= 1 */
#endif
return SLJIT_SUCCESS;
case SLJIT_ADD:
@ -459,27 +459,26 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
SLJIT_ASSERT(!(flags & SRC2_IMM));
if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) {
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));
#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#elif (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
if (op & SLJIT_I32_OP)
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
return push_inst(compiler, MFLO | D(dst), DR(dst));
#else /* SLJIT_MIPS_REV < 1 */
#else /* !SLJIT_MIPS_R6 && !SLJIT_MIPS_R1 */
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
return push_inst(compiler, MFLO | D(dst), DR(dst));
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
}
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)));
FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
#else /* SLJIT_MIPS_REV < 6 */
#else /* !SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS));
FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG));
FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst)));
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG));
return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG);

View file

@ -25,16 +25,15 @@
*/
/* Latest MIPS architecture. */
/* Automatically detect SLJIT_MIPS_R1 */
#ifndef __mips_hard_float
/* Disable automatic detection, covers both -msoft-float and -mno-float */
#undef SLJIT_IS_FPU_AVAILABLE
#define SLJIT_IS_FPU_AVAILABLE 0
#if (defined __mips_isa_rev) && (__mips_isa_rev >= 6)
#define SLJIT_MIPS_R6 1
#endif
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
{
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
return "MIPS32-R6" SLJIT_CPUINFO;
@ -42,7 +41,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
return "MIPS64-R6" SLJIT_CPUINFO;
#endif /* SLJIT_CONFIG_MIPS_32 */
#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#elif (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
return "MIPS32-R1" SLJIT_CPUINFO;
@ -50,9 +49,9 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
return "MIPS64-R1" SLJIT_CPUINFO;
#endif /* SLJIT_CONFIG_MIPS_32 */
#else /* SLJIT_MIPS_REV < 1 */
#else /* SLJIT_MIPS_R1 */
return "MIPS III" SLJIT_CPUINFO;
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
}
/* Length of an instruction word
@ -118,11 +117,11 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define FR(dr) (freg_map[dr])
#define HI(opcode) ((opcode) << 26)
#define LO(opcode) (opcode)
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
/* CMP.cond.fmt */
/* S = (20 << 21) D = (21 << 21) */
#define CMP_FMT_S (20 << 21)
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
/* S = (16 << 21) D = (17 << 21) */
#define FMT_S (16 << 21)
#define FMT_D (17 << 21)
@ -135,13 +134,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define ANDI (HI(12))
#define B (HI(4))
#define BAL (HI(1) | (17 << 16))
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#define BC1EQZ (HI(17) | (9 << 21) | FT(TMP_FREG3))
#define BC1NEZ (HI(17) | (13 << 21) | FT(TMP_FREG3))
#else /* SLJIT_MIPS_REV < 6 */
#else /* !SLJIT_MIPS_R6 */
#define BC1F (HI(17) | (8 << 21))
#define BC1T (HI(17) | (8 << 21) | (1 << 16))
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
#define BEQ (HI(4))
#define BGEZ (HI(1) | (1 << 16))
#define BGTZ (HI(7))
@ -150,23 +149,23 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define BNE (HI(5))
#define BREAK (HI(0) | LO(13))
#define CFC1 (HI(17) | (2 << 21))
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3))
#define C_ULE_S (HI(17) | CMP_FMT_S | LO(7))
#define C_ULT_S (HI(17) | CMP_FMT_S | LO(5))
#define C_UN_S (HI(17) | CMP_FMT_S | LO(1))
#define C_FD (FD(TMP_FREG3))
#else /* SLJIT_MIPS_REV < 6 */
#else /* !SLJIT_MIPS_R6 */
#define C_UEQ_S (HI(17) | FMT_S | LO(51))
#define C_ULE_S (HI(17) | FMT_S | LO(55))
#define C_ULT_S (HI(17) | FMT_S | LO(53))
#define C_UN_S (HI(17) | FMT_S | LO(49))
#define C_FD (0)
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
#define CVT_S_S (HI(17) | FMT_S | LO(32))
#define DADDIU (HI(25))
#define DADDU (HI(0) | LO(45))
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#define DDIV (HI(0) | (2 << 6) | LO(30))
#define DDIVU (HI(0) | (2 << 6) | LO(31))
#define DMOD (HI(0) | (3 << 6) | LO(30))
@ -177,14 +176,14 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define DMUHU (HI(0) | (3 << 6) | LO(29))
#define DMUL (HI(0) | (2 << 6) | LO(28))
#define DMULU (HI(0) | (2 << 6) | LO(29))
#else /* SLJIT_MIPS_REV < 6 */
#else /* !SLJIT_MIPS_R6 */
#define DDIV (HI(0) | LO(30))
#define DDIVU (HI(0) | LO(31))
#define DIV (HI(0) | LO(26))
#define DIVU (HI(0) | LO(27))
#define DMULT (HI(0) | LO(28))
#define DMULTU (HI(0) | LO(29))
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
#define DIV_S (HI(17) | FMT_S | LO(3))
#define DSLL (HI(0) | LO(56))
#define DSLL32 (HI(0) | LO(60))
@ -199,33 +198,33 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define J (HI(2))
#define JAL (HI(3))
#define JALR (HI(0) | LO(9))
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#define JR (HI(0) | LO(9))
#else /* SLJIT_MIPS_REV < 6 */
#else /* !SLJIT_MIPS_R6 */
#define JR (HI(0) | LO(8))
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
#define LD (HI(55))
#define LUI (HI(15))
#define LW (HI(35))
#define MFC1 (HI(17))
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#define MOD (HI(0) | (3 << 6) | LO(26))
#define MODU (HI(0) | (3 << 6) | LO(27))
#else /* SLJIT_MIPS_REV < 6 */
#if !(defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#define MFHI (HI(0) | LO(16))
#define MFLO (HI(0) | LO(18))
#endif /* SLJIT_MIPS_REV >= 6 */
#else /* SLJIT_MIPS_R6 */
#define MOD (HI(0) | (3 << 6) | LO(26))
#define MODU (HI(0) | (3 << 6) | LO(27))
#endif /* !SLJIT_MIPS_R6 */
#define MOV_S (HI(17) | FMT_S | LO(6))
#define MTC1 (HI(17) | (4 << 21))
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#define MUH (HI(0) | (3 << 6) | LO(24))
#define MUHU (HI(0) | (3 << 6) | LO(25))
#define MUL (HI(0) | (2 << 6) | LO(24))
#define MULU (HI(0) | (2 << 6) | LO(25))
#else /* SLJIT_MIPS_REV < 6 */
#else /* !SLJIT_MIPS_R6 */
#define MULT (HI(0) | LO(24))
#define MULTU (HI(0) | LO(25))
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
#define MUL_S (HI(17) | FMT_S | LO(2))
#define NEG_S (HI(17) | FMT_S | LO(7))
#define NOP (HI(0) | LO(0))
@ -252,23 +251,23 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define XOR (HI(0) | LO(38))
#define XORI (HI(14))
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) || (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#define CLZ (HI(28) | LO(32))
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#define DCLZ (LO(18))
#else /* SLJIT_MIPS_REV < 6 */
#else /* !SLJIT_MIPS_R6 */
#define DCLZ (HI(28) | LO(36))
#define MOVF (HI(0) | (0 << 16) | LO(1))
#define MOVN (HI(0) | LO(11))
#define MOVT (HI(0) | (1 << 16) | LO(1))
#define MOVZ (HI(0) | LO(10))
#define MUL (HI(28) | LO(2))
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
#define PREF (HI(51))
#define PREFX (HI(19) | LO(15))
#define SEB (HI(31) | (16 << 6) | LO(32))
#define SEH (HI(31) | (24 << 6) | LO(32))
#endif /* SLJIT_MIPS_REV >= 1 */
#endif
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#define ADDU_W ADDU
@ -304,10 +303,10 @@ static SLJIT_INLINE sljit_ins invert_branch(sljit_s32 flags)
{
if (flags & IS_BIT26_COND)
return (1 << 26);
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
if (flags & IS_BIT23_COND)
return (1 << 23);
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
return (1 << 16);
}
@ -684,15 +683,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
#else
#error "FIR check is not implemented for this architecture"
#endif
case SLJIT_HAS_ZERO_REGISTER:
return 1;
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
case SLJIT_HAS_CLZ:
case SLJIT_HAS_CMOV:
case SLJIT_HAS_PREFETCH:
return 1;
#endif /* SLJIT_MIPS_REV >= 1 */
#endif
default:
return fir;
@ -1234,7 +1230,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
return push_inst(compiler, NOP, UNMOVABLE_INS);
case SLJIT_LMUL_UW:
case SLJIT_LMUL_SW:
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1)));
@ -1244,7 +1240,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
#endif /* SLJIT_CONFIG_MIPS_64 */
FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
#else /* SLJIT_MIPS_REV < 6 */
#else /* !SLJIT_MIPS_R6 */
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
#else /* !SLJIT_CONFIG_MIPS_64 */
@ -1252,13 +1248,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
#endif /* SLJIT_CONFIG_MIPS_64 */
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
case SLJIT_DIVMOD_UW:
case SLJIT_DIVMOD_SW:
case SLJIT_DIV_UW:
case SLJIT_DIV_SW:
SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
if (int_op) {
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3)));
@ -1274,11 +1270,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
#endif /* SLJIT_CONFIG_MIPS_64 */
FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0)));
return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1));
#else /* SLJIT_MIPS_REV < 6 */
#if !(defined SLJIT_MIPS_REV)
#else /* !SLJIT_MIPS_R6 */
#if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif /* !SLJIT_MIPS_REV */
#endif /* !SLJIT_MIPS_R1 */
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
if (int_op)
FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS));
@ -1289,16 +1285,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
#endif /* SLJIT_CONFIG_MIPS_64 */
FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0)));
return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1));
#endif /* SLJIT_MIPS_REV >= 6 */
case SLJIT_ENDBR:
case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
return SLJIT_SUCCESS;
#endif /* SLJIT_MIPS_R6 */
}
return SLJIT_SUCCESS;
}
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
sljit_s32 src, sljit_sw srcw)
{
@ -1319,7 +1312,7 @@ static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS);
}
#endif /* SLJIT_MIPS_REV >= 1 */
#endif
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
@ -1336,6 +1329,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
return emit_prefetch(compiler, src, srcw);
#endif
return SLJIT_SUCCESS;
}
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT)
flags |= INT_DATA | SIGNED_DATA;
@ -1462,38 +1463,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
#endif
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
switch (op) {
case SLJIT_FAST_RETURN:
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
else
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
return push_inst(compiler, NOP, UNMOVABLE_INS);
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
return SLJIT_SUCCESS;
case SLJIT_PREFETCH_L1:
case SLJIT_PREFETCH_L2:
case SLJIT_PREFETCH_L3:
case SLJIT_PREFETCH_ONCE:
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
return emit_prefetch(compiler, src, srcw);
#else /* SLJIT_MIPS_REV < 1 */
return SLJIT_SUCCESS;
#endif /* SLJIT_MIPS_REV >= 1 */
}
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
{
CHECK_REG_INDEX(check_sljit_get_register_index(reg));
@ -1763,12 +1732,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
ADJUST_LOCAL_OFFSET(dst, dstw);
if (FAST_IS_REG(dst))
return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);
return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst));
/* Memory. */
FAIL_IF(emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw));
compiler->delay_slot = UNMOVABLE_INS;
return SLJIT_SUCCESS;
return emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
else
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
return push_inst(compiler, NOP, UNMOVABLE_INS);
}
/* --------------------------------------------------------------------- */
@ -1808,7 +1790,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
flags = IS_BIT26_COND; \
delay_check = src;
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
#define BR_T() \
inst = BC1NEZ; \
@ -1819,7 +1801,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
flags = IS_BIT23_COND; \
delay_check = FCSR_FCC;
#else /* SLJIT_MIPS_REV < 6 */
#else /* !SLJIT_MIPS_R6 */
#define BR_T() \
inst = BC1T | JUMP_LENGTH; \
@ -1830,7 +1812,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
flags = IS_BIT16_COND; \
delay_check = FCSR_FCC;
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
{
@ -2141,11 +2123,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
case SLJIT_GREATER_EQUAL_F64:
case SLJIT_UNORDERED_F64:
case SLJIT_ORDERED_F64:
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6)
FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar));
#else /* SLJIT_MIPS_REV < 6 */
#else /* !SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar));
#endif /* SLJIT_MIPS_REV >= 6 */
#endif /* SLJIT_MIPS_R6 */
FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar));
FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar));
src_ar = dst_ar;
@ -2185,14 +2167,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
sljit_s32 dst_reg,
sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
sljit_ins ins;
#endif /* SLJIT_MIPS_REV >= 1 */
#endif
CHECK_ERROR();
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
@ -2249,9 +2231,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg));
#else /* SLJIT_MIPS_REV < 1 */
#else
return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
#endif /* SLJIT_MIPS_REV >= 1 */
#endif
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)

View file

@ -626,10 +626,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
return 1;
#endif
/* A saved register is set to a zero value. */
case SLJIT_HAS_ZERO_REGISTER:
case SLJIT_HAS_CLZ:
case SLJIT_HAS_PREFETCH:
return 1;
default:
@ -1161,9 +1158,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
#else
return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1));
#endif
case SLJIT_ENDBR:
case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
return SLJIT_SUCCESS;
}
return SLJIT_SUCCESS;
@ -1209,6 +1203,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
return emit_prefetch(compiler, src, srcw);
return SLJIT_SUCCESS;
}
op = GET_OPCODE(op);
if ((src & SLJIT_IMM) && srcw == 0)
src = TMP_ZERO;
@ -1535,35 +1536,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
switch (op) {
case SLJIT_FAST_RETURN:
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, MTLR | S(src)));
else {
FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
}
return push_inst(compiler, BLR);
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
return SLJIT_SUCCESS;
case SLJIT_PREFETCH_L1:
case SLJIT_PREFETCH_L2:
case SLJIT_PREFETCH_L3:
case SLJIT_PREFETCH_ONCE:
return emit_prefetch(compiler, src, srcw);
}
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
{
CHECK_REG_INDEX(check_sljit_get_register_index(reg));
@ -1882,6 +1854,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, MTLR | S(src)));
else {
FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw));
FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2)));
}
return push_inst(compiler, BLR);
}
/* --------------------------------------------------------------------- */
/* Conditional instructions */
/* --------------------------------------------------------------------- */

View file

@ -451,9 +451,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
return 1;
#endif
case SLJIT_HAS_ZERO_REGISTER:
return 1;
#if (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64)
case SLJIT_HAS_CMOV:
return 1;
@ -875,9 +872,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
#else
#error "Implementation required"
#endif
case SLJIT_ENDBR:
case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
return SLJIT_SUCCESS;
}
return SLJIT_SUCCESS;
@ -894,6 +888,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
return SLJIT_SUCCESS;
op = GET_OPCODE(op);
switch (op) {
case SLJIT_MOV:
@ -974,33 +971,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
switch (op) {
case SLJIT_FAST_RETURN:
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK)));
else
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw));
FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS));
return push_inst(compiler, NOP, UNMOVABLE_INS);
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
case SLJIT_PREFETCH_L1:
case SLJIT_PREFETCH_L2:
case SLJIT_PREFETCH_L3:
case SLJIT_PREFETCH_ONCE:
return SLJIT_SUCCESS;
}
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
{
CHECK_REG_INDEX(check_sljit_get_register_index(reg));
@ -1245,12 +1215,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
ADJUST_LOCAL_OFFSET(dst, dstw);
if (FAST_IS_REG(dst))
return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), UNMOVABLE_INS);
return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), DR(dst));
/* Memory. */
FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw));
compiler->delay_slot = UNMOVABLE_INS;
return SLJIT_SUCCESS;
return emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK)));
else
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw));
FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS));
return push_inst(compiler, NOP, UNMOVABLE_INS);
}
/* --------------------------------------------------------------------- */

View file

@ -1564,6 +1564,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
return emit_op_mem(compiler, WORD_DATA, RA, dst, dstw);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
if (FAST_IS_REG(src))
FAIL_IF(ADD(RA, reg_map[src], ZERO));
else if (src & SLJIT_MEM)
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RA, src, srcw));
else if (src & SLJIT_IMM)
FAIL_IF(load_immediate(compiler, RA, srcw));
return JR(RA);
}
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
{
sljit_s32 overflow_ra = 0;
@ -2166,9 +2184,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
case SLJIT_DIV_UW:
case SLJIT_DIV_SW:
SLJIT_UNREACHABLE();
case SLJIT_ENDBR:
case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
return SLJIT_SUCCESS;
}
return SLJIT_SUCCESS;
@ -2278,29 +2293,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
switch (op) {
case SLJIT_FAST_RETURN:
if (FAST_IS_REG(src))
FAIL_IF(ADD(RA, reg_map[src], ZERO));
else
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RA, src, srcw));
return JR(RA);
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
return SLJIT_SUCCESS;
}
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_compiler *compiler)
{
struct sljit_label *label;

View file

@ -76,9 +76,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
/* Emit ENDBR32 at function entry if needed. */
FAIL_IF(emit_endbranch(compiler));
args = get_arg_count(arg_types);
compiler->args = args;
@ -310,11 +307,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
#endif
size = 2 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) +
size = 2 + (compiler->scratches > 7 ? (compiler->scratches - 7) : 0) +
(compiler->saveds <= 3 ? compiler->saveds : 3);
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
if (compiler->args > 2)
size += 2;
#else
if (compiler->args > 0)
size += 2;
#endif
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
FAIL_IF(!inst);
@ -367,8 +367,6 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
&& (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
&& (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
/* We don't support (%ebp). */
SLJIT_ASSERT(!(b & SLJIT_MEM) || immb || reg_map[b & REG_MASK] != 5);
size &= 0xf;
inst_size = size;
@ -865,10 +863,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
return SLJIT_SUCCESS;
}
static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
{
sljit_u8 *inst;
CHECK_ERROR();
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
CHECK_EXTRA_REGS(src, srcw, (void)0);
if (FAST_IS_REG(src)) {
@ -892,37 +894,3 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src
RET();
return SLJIT_SUCCESS;
}
static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)
{
sljit_s32 size, saved_size;
sljit_s32 has_f64_aligment;
/* Don't adjust shadow stack if it isn't enabled. */
if (!cpu_has_shadow_stack ())
return SLJIT_SUCCESS;
SLJIT_ASSERT(compiler->args >= 0);
SLJIT_ASSERT(compiler->local_size > 0);
#if !defined(__APPLE__)
has_f64_aligment = compiler->options & SLJIT_F64_ALIGNMENT;
#else
has_f64_aligment = 0;
#endif
size = compiler->local_size;
saved_size = (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) + (compiler->saveds <= 3 ? compiler->saveds : 3)) * sizeof(sljit_uw);
if (has_f64_aligment) {
/* mov TMP_REG1, [esp + local_size]. */
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), size);
/* mov TMP_REG1, [TMP_REG1+ saved_size]. */
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), saved_size);
/* Move return address to [esp]. */
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, TMP_REG1, 0);
size = 0;
} else
size += saved_size;
return adjust_shadow_stack(compiler, SLJIT_UNUSED, 0, SLJIT_SP, size);
}

View file

@ -135,9 +135,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
/* Emit ENDBR64 at function entry if needed. */
FAIL_IF(emit_endbranch(compiler));
compiler->mode32 = 0;
#ifdef _WIN64
@ -799,10 +796,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
return SLJIT_SUCCESS;
}
static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw)
{
sljit_u8 *inst;
CHECK_ERROR();
CHECK(check_sljit_emit_fast_return(compiler, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
if (FAST_IS_REG(src)) {
if (reg_map[src] < 8) {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1);
@ -897,22 +898,3 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign,
return SLJIT_SUCCESS;
}
static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)
{
sljit_s32 tmp, size;
/* Don't adjust shadow stack if it isn't enabled. */
if (!cpu_has_shadow_stack ())
return SLJIT_SUCCESS;
size = compiler->local_size;
tmp = compiler->scratches;
if (tmp >= SLJIT_FIRST_SAVED_REG)
size += (tmp - SLJIT_FIRST_SAVED_REG + 1) * sizeof(sljit_uw);
tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
if (SLJIT_S0 >= tmp)
size += (SLJIT_S0 - tmp + 1) * sizeof(sljit_uw);
return adjust_shadow_stack(compiler, SLJIT_UNUSED, 0, SLJIT_SP, size);
}

View file

@ -657,9 +657,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
get_cpu_features();
return cpu_has_cmov;
case SLJIT_HAS_PREFETCH:
return 1;
case SLJIT_HAS_SSE2:
#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
if (cpu_has_sse2 == -1)
@ -705,171 +702,6 @@ static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler,
static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler,
sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw);
static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w);
static SLJIT_INLINE sljit_s32 emit_endbranch(struct sljit_compiler *compiler)
{
#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)
/* Emit endbr32/endbr64 when CET is enabled. */
sljit_u8 *inst;
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!inst);
INC_SIZE(4);
*inst++ = 0xf3;
*inst++ = 0x0f;
*inst++ = 0x1e;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
*inst = 0xfb;
#else
*inst = 0xfa;
#endif
#else
SLJIT_UNUSED_ARG(compiler);
#endif
return SLJIT_SUCCESS;
}
static SLJIT_INLINE sljit_s32 emit_rdssp(struct sljit_compiler *compiler, sljit_s32 reg)
{
#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)
sljit_u8 *inst;
sljit_s32 size;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
size = 5;
#else
size = 4;
#endif
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
FAIL_IF(!inst);
INC_SIZE(size);
*inst++ = 0xf3;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
*inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B);
#endif
*inst++ = 0x0f;
*inst++ = 0x1e;
*inst = (0x3 << 6) | (0x1 << 3) | (reg_map[reg] & 0x7);
#else
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(reg);
#endif
return SLJIT_SUCCESS;
}
static SLJIT_INLINE sljit_s32 emit_incssp(struct sljit_compiler *compiler, sljit_s32 reg)
{
#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)
sljit_u8 *inst;
sljit_s32 size;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
size = 5;
#else
size = 4;
#endif
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
FAIL_IF(!inst);
INC_SIZE(size);
*inst++ = 0xf3;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
*inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B);
#endif
*inst++ = 0x0f;
*inst++ = 0xae;
*inst = (0x3 << 6) | (0x5 << 3) | (reg_map[reg] & 0x7);
#else
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(reg);
#endif
return SLJIT_SUCCESS;
}
static SLJIT_INLINE sljit_s32 cpu_has_shadow_stack(void)
{
#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)
return _get_ssp() != 0;
#else
return 0;
#endif
}
static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compiler,
sljit_s32 src, sljit_sw srcw, sljit_s32 base, sljit_sw disp)
{
#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)
sljit_u8 *inst;
sljit_s32 size_before_rdssp_inst = compiler->size;
/* Generate "RDSSP TMP_REG1". */
FAIL_IF(emit_rdssp(compiler, TMP_REG1));
/* Load return address on shadow stack into TMP_REG1. */
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
SLJIT_ASSERT(reg_map[TMP_REG1] == 5);
/* Hand code unsupported "mov 0x0(%ebp),%ebp". */
inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);
FAIL_IF(!inst);
INC_SIZE(3);
*inst++ = 0x8b;
*inst++ = 0x6d;
*inst = 0;
#else /* !SLJIT_CONFIG_X86_32 */
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), 0);
#endif /* SLJIT_CONFIG_X86_32 */
if (src == SLJIT_UNUSED) {
/* Return address is on stack. */
src = SLJIT_MEM1(base);
srcw = disp;
}
/* Compare return address against TMP_REG1. */
FAIL_IF(emit_cmp_binary (compiler, TMP_REG1, 0, src, srcw));
/* Generate JZ to skip shadow stack ajdustment when shadow
stack matches normal stack. */
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
INC_SIZE(2);
*inst++ = get_jump_code(SLJIT_EQUAL) - 0x10;
sljit_uw size_jz_after_cmp_inst = compiler->size;
sljit_u8 *jz_after_cmp_inst = inst;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
/* REX_W is not necessary. */
compiler->mode32 = 1;
#endif
/* Load 1 into TMP_REG1. */
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1);
/* Generate "INCSSP TMP_REG1". */
FAIL_IF(emit_incssp(compiler, TMP_REG1));
/* Jump back to "RDSSP TMP_REG1" to check shadow stack again. */
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
INC_SIZE(2);
*inst++ = JMP_i8;
*inst = size_before_rdssp_inst - compiler->size;
*jz_after_cmp_inst = compiler->size - size_jz_after_cmp_inst;
#else /* SLJIT_CONFIG_X86_CET */
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
SLJIT_UNUSED_ARG(base);
SLJIT_UNUSED_ARG(disp);
#endif /* SLJIT_CONFIG_X86_CET */
return SLJIT_SUCCESS;
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#include "sljitNativeX86_32.c"
#else
@ -1073,10 +905,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0);
#endif
break;
case SLJIT_ENDBR:
return emit_endbranch(compiler);
case SLJIT_SKIP_FRAMES_BEFORE_RETURN:
return skip_frames_before_return(compiler);
}
return SLJIT_SUCCESS;
@ -1246,12 +1074,12 @@ static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op,
*inst++ = GROUP_0F;
*inst++ = PREFETCH;
if (op == SLJIT_PREFETCH_L1)
*inst |= (1 << 3);
else if (op == SLJIT_PREFETCH_L2)
*inst |= (2 << 3);
else if (op == SLJIT_PREFETCH_L3)
if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8)
*inst |= (3 << 3);
else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16)
*inst |= (2 << 3);
else
*inst |= (1 << 3);
return SLJIT_SUCCESS;
}
@ -1456,6 +1284,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
compiler->mode32 = op_flags & SLJIT_I32_OP;
#endif
if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) {
if (op <= SLJIT_MOV_P && (src & SLJIT_MEM))
return emit_prefetch(compiler, op, src, srcw);
return SLJIT_SUCCESS;
}
op = GET_OPCODE(op);
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {
@ -2316,10 +2150,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
if (!HAS_FLAGS(op)) {
if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED)
return compiler->error;
if (SLOW_IS_REG(dst) && src2 == dst) {
FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), dst, 0, dst, 0, src1, src1w));
return emit_unary(compiler, NEG_rm, dst, 0, dst, 0);
}
}
if (dst == SLJIT_UNUSED)
@ -2356,33 +2186,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_src(compiler, op, src, srcw));
ADJUST_LOCAL_OFFSET(src, srcw);
CHECK_EXTRA_REGS(src, srcw, (void)0);
switch (op) {
case SLJIT_FAST_RETURN:
return emit_fast_return(compiler, src, srcw);
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
/* Don't adjust shadow stack if it isn't enabled. */
if (!cpu_has_shadow_stack ())
return SLJIT_SUCCESS;
return adjust_shadow_stack(compiler, src, srcw, SLJIT_UNUSED, 0);
case SLJIT_PREFETCH_L1:
case SLJIT_PREFETCH_L2:
case SLJIT_PREFETCH_L3:
case SLJIT_PREFETCH_ONCE:
return emit_prefetch(compiler, op, src, srcw);
}
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
{
CHECK_REG_INDEX(check_sljit_get_register_index(reg));

View file

@ -70,6 +70,7 @@
struct chunk_header {
void *executable;
int fd;
};
/*
@ -95,20 +96,8 @@ struct chunk_header {
#endif
#endif
#if !(defined(__NetBSD__) && defined(MAP_REMAPDUP))
int mkostemp(char *template, int flags);
#ifdef __NetBSD__
/*
* this is a workaround for NetBSD < 8 that lacks a system provided
* secure_getenv function.
* ideally this should never be used, as the standard allocator is
* a preferred option for those systems and should be used instead.
*/
#define secure_getenv(name) issetugid() ? NULL : getenv(name)
#else
char *secure_getenv(const char *name);
#endif
static SLJIT_INLINE int create_tempfile(void)
{
@ -119,13 +108,6 @@ static SLJIT_INLINE int create_tempfile(void)
char *dir;
size_t len;
#ifdef HAVE_MEMFD_CREATE
/* this is a GNU extension, make sure to use -D_GNU_SOURCE */
fd = memfd_create("sljit", MFD_CLOEXEC);
if (fd != -1)
return fd;
#endif
#ifdef P_tmpdir
len = (P_tmpdir != NULL) ? strlen(P_tmpdir) : 0;
@ -143,7 +125,6 @@ static SLJIT_INLINE int create_tempfile(void)
#endif
dir = secure_getenv("TMPDIR");
if (dir) {
len = strlen(dir);
if (len > 0 && len < sizeof(tmp_name)) {
@ -208,50 +189,23 @@ static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size)
retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);
if (retval->executable == MAP_FAILED) {
munmap((void *)retval, size);
munmap(retval, size);
close(fd);
return NULL;
}
close(fd);
retval->fd = fd;
return retval;
}
#else
static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size)
{
struct chunk_header *retval;
void *maprx;
retval = (struct chunk_header *)mmap(NULL, size,
PROT_MPROTECT(PROT_EXEC|PROT_WRITE|PROT_READ),
MAP_ANON, -1, 0);
if (retval == MAP_FAILED)
return NULL;
maprx = mremap(retval, size, NULL, size, MAP_REMAPDUP);
if (maprx == MAP_FAILED) {
munmap((void *)retval, size);
return NULL;
}
if (mprotect(retval, size, PROT_READ | PROT_WRITE) == -1 ||
mprotect(maprx, size, PROT_READ | PROT_EXEC) == -1) {
munmap(maprx, size);
munmap((void *)retval, size);
return NULL;
}
retval->executable = maprx;
return retval;
}
#endif /* NetBSD >= 8 */
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
{
struct chunk_header *header = ((struct chunk_header *)chunk) - 1;
int fd = header->fd;
munmap(header->executable, size);
munmap((void *)header, size);
munmap(header, size);
close(fd);
}
/* --------------------------------------------------------------------- */
@ -431,9 +385,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
if (total_size - free_block->size > (allocated_size * 3 / 2)) {
total_size -= free_block->size;
sljit_remove_free_block(free_block);
free_chunk(free_block, free_block->size +
sizeof(struct chunk_header) +
sizeof(struct block_header));
free_chunk(free_block, free_block->size + sizeof(struct block_header));
}
}
@ -454,9 +406,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) {
total_size -= free_block->size;
sljit_remove_free_block(free_block);
free_chunk(free_block, free_block->size +
sizeof(struct chunk_header) +
sizeof(struct block_header));
free_chunk(free_block, free_block->size + sizeof(struct block_header));
}
free_block = next_free_block;
}

View file

@ -152,23 +152,15 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void)
#ifdef _WIN32
#include "windows.h"
#else /* !_WIN32 */
#else
/* Provides mmap function. */
#include <sys/types.h>
#include <sys/mman.h>
#ifndef MAP_ANON
#ifdef MAP_ANONYMOUS
#define MAP_ANON MAP_ANONYMOUS
#endif /* MAP_ANONYMOUS */
#endif /* !MAP_ANON */
#ifndef MADV_DONTNEED
#ifdef POSIX_MADV_DONTNEED
#define MADV_DONTNEED POSIX_MADV_DONTNEED
#endif /* POSIX_MADV_DONTNEED */
#endif /* !MADV_DONTNEED */
#endif
#endif
/* For detecting the page size. */
#include <unistd.h>
@ -206,85 +198,35 @@ static SLJIT_INLINE sljit_s32 open_dev_zero(void)
#endif /* SLJIT_SINGLE_THREADED */
#endif /* !MAP_ANON */
#endif
#endif /* _WIN32 */
#endif
#endif /* SLJIT_UTIL_STACK || SLJIT_EXECUTABLE_ALLOCATOR */
#endif /* SLJIT_EXECUTABLE_ALLOCATOR || SLJIT_UTIL_GLOBAL_LOCK */
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
#if (defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)
/* Planning to make it even more clever in the future. */
static sljit_sw sljit_page_align = 0;
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)
{
struct sljit_stack *stack;
void *ptr;
#ifdef _WIN32
SYSTEM_INFO si;
#endif
SLJIT_UNUSED_ARG(allocator_data);
if (start_size > max_size || start_size < 1)
return NULL;
stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
if (stack == NULL)
return NULL;
ptr = SLJIT_MALLOC(max_size, allocator_data);
if (ptr == NULL) {
SLJIT_FREE(stack, allocator_data);
return NULL;
}
stack->min_start = (sljit_u8 *)ptr;
stack->end = stack->min_start + max_size;
stack->start = stack->end - start_size;
stack->top = stack->end;
return stack;
}
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
{
SLJIT_UNUSED_ARG(allocator_data);
SLJIT_FREE((void*)stack->min_start, allocator_data);
SLJIT_FREE(stack, allocator_data);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)
{
if ((new_start < stack->min_start) || (new_start >= stack->end))
return NULL;
stack->start = new_start;
return new_start;
}
#else /* !SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */
#ifdef _WIN32
SLJIT_INLINE static sljit_sw get_page_alignment(void) {
SYSTEM_INFO si;
static sljit_sw sljit_page_align;
if (!sljit_page_align) {
GetSystemInfo(&si);
sljit_page_align = si.dwPageSize - 1;
}
return sljit_page_align;
}
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
{
SLJIT_UNUSED_ARG(allocator_data);
VirtualFree((void*)stack->min_start, 0, MEM_RELEASE);
SLJIT_FREE(stack, allocator_data);
}
#else /* ! defined _WIN32 */
SLJIT_INLINE static sljit_sw get_page_alignment(void) {
static sljit_sw sljit_page_align;
#else
if (!sljit_page_align) {
sljit_page_align = sysconf(_SC_PAGESIZE);
/* Should never happen. */
@ -292,36 +234,14 @@ SLJIT_INLINE static sljit_sw get_page_alignment(void) {
sljit_page_align = 4096;
sljit_page_align--;
}
return sljit_page_align;
}
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
{
SLJIT_UNUSED_ARG(allocator_data);
munmap((void*)stack->min_start, stack->end - stack->min_start);
SLJIT_FREE(stack, allocator_data);
}
#endif /* defined _WIN32 */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data)
{
struct sljit_stack *stack;
void *ptr;
sljit_sw page_align;
SLJIT_UNUSED_ARG(allocator_data);
if (start_size > max_size || start_size < 1)
return NULL;
#endif
stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data);
if (stack == NULL)
if (!stack)
return NULL;
/* Align max_size. */
page_align = get_page_alignment();
max_size = (max_size + page_align) & ~page_align;
max_size = (max_size + sljit_page_align) & ~sljit_page_align;
#ifdef _WIN32
ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE);
@ -338,18 +258,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(slj
sljit_free_stack(stack, allocator_data);
return NULL;
}
#else /* !_WIN32 */
#else
#ifdef MAP_ANON
ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
#else /* !MAP_ANON */
#else
if (dev_zero < 0) {
if (open_dev_zero() != 0) {
if (open_dev_zero()) {
SLJIT_FREE(stack, allocator_data);
return NULL;
}
}
ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
#endif /* MAP_ANON */
#endif
if (ptr == MAP_FAILED) {
SLJIT_FREE(stack, allocator_data);
return NULL;
@ -357,28 +277,35 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(slj
stack->min_start = (sljit_u8 *)ptr;
stack->end = stack->min_start + max_size;
stack->start = stack->end - start_size;
#endif /* _WIN32 */
#endif
stack->top = stack->end;
return stack;
}
#undef PAGE_ALIGN
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
{
SLJIT_UNUSED_ARG(allocator_data);
#ifdef _WIN32
VirtualFree((void*)stack->min_start, 0, MEM_RELEASE);
#else
munmap((void*)stack->min_start, stack->end - stack->min_start);
#endif
SLJIT_FREE(stack, allocator_data);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)
{
#if defined _WIN32 || defined(MADV_DONTNEED)
sljit_uw aligned_old_start;
sljit_uw aligned_new_start;
sljit_sw page_align;
#endif
if ((new_start < stack->min_start) || (new_start >= stack->end))
return NULL;
#ifdef _WIN32
page_align = get_page_alignment();
aligned_new_start = (sljit_uw)new_start & ~page_align;
aligned_old_start = ((sljit_uw)stack->start) & ~page_align;
aligned_new_start = (sljit_uw)new_start & ~sljit_page_align;
aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align;
if (aligned_new_start != aligned_old_start) {
if (aligned_new_start < aligned_old_start) {
if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE))
@ -389,22 +316,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_st
return NULL;
}
}
#elif defined(MADV_DONTNEED)
#else
if (stack->start < new_start) {
page_align = get_page_alignment();
aligned_new_start = (sljit_uw)new_start & ~page_align;
aligned_old_start = ((sljit_uw)stack->start) & ~page_align;
aligned_new_start = (sljit_uw)new_start & ~sljit_page_align;
aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align;
/* If madvise is available, we release the unnecessary space. */
#if defined(MADV_DONTNEED)
if (aligned_new_start > aligned_old_start)
madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED);
#elif defined(POSIX_MADV_DONTNEED)
if (aligned_new_start > aligned_old_start)
posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED);
#endif
}
#endif /* _WIN32 */
#endif
stack->start = new_start;
return new_start;
}
#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */
#endif /* SLJIT_UTIL_STACK */
#endif