feat: modules moved and engine moved to submodule

This commit is contained in:
Jan van der Weide 2025-04-12 18:40:44 +02:00
parent dfb5e645cd
commit c33d2130cc
5136 changed files with 225275 additions and 64485 deletions

View file

@ -52,15 +52,24 @@ sure both macros are undefined; an emulation function will then be used. */
LF does in an ASCII/Unicode environment. */
/* #undef EBCDIC_NL25 */
/* Define to 1 if you have the <assert.h> header file. */
/* #undef HAVE_ASSERT_H */
/* Define this if your compiler supports __attribute__((uninitialized)) */
/* #undef HAVE_ATTRIBUTE_UNINITIALIZED */
/* Define to 1 if you have the 'bcopy' function. */
/* Define to 1 if you have the `bcopy' function. */
/* #undef HAVE_BCOPY */
/* Define this if your compiler provides __assume() */
/* #undef HAVE_BUILTIN_ASSUME */
/* Define this if your compiler provides __builtin_mul_overflow() */
/* #undef HAVE_BUILTIN_MUL_OVERFLOW */
/* Define this if your compiler provides __builtin_unreachable() */
/* #undef HAVE_BUILTIN_UNREACHABLE */
/* Define to 1 if you have the <bzlib.h> header file. */
/* #undef HAVE_BZLIB_H */
@ -82,16 +91,16 @@ sure both macros are undefined; an emulation function will then be used. */
/* Define to 1 if you have the <limits.h> header file. */
/* #undef HAVE_LIMITS_H */
/* Define to 1 if you have the 'memfd_create' function. */
/* Define to 1 if you have the `memfd_create' function. */
/* #undef HAVE_MEMFD_CREATE */
/* Define to 1 if you have the 'memmove' function. */
/* Define to 1 if you have the `memmove' function. */
/* #undef HAVE_MEMMOVE */
/* Define to 1 if you have the <minix/config.h> header file. */
/* #undef HAVE_MINIX_CONFIG_H */
/* Define to 1 if you have the 'mkostemp' function. */
/* Define to 1 if you have the `mkostemp' function. */
/* #undef HAVE_MKOSTEMP */
/* Define if you have POSIX threads libraries and header files. */
@ -112,7 +121,7 @@ sure both macros are undefined; an emulation function will then be used. */
/* Define to 1 if you have the `realpath' function. */
/* #undef HAVE_REALPATH */
/* Define to 1 if you have the 'secure_getenv' function. */
/* Define to 1 if you have the `secure_getenv' function. */
/* #undef HAVE_SECURE_GETENV */
/* Define to 1 if you have the <stdint.h> header file. */
@ -124,7 +133,7 @@ sure both macros are undefined; an emulation function will then be used. */
/* Define to 1 if you have the <stdlib.h> header file. */
/* #undef HAVE_STDLIB_H */
/* Define to 1 if you have the 'strerror' function. */
/* Define to 1 if you have the `strerror' function. */
/* #undef HAVE_STRERROR */
/* Define to 1 if you have the <strings.h> header file. */
@ -145,7 +154,8 @@ sure both macros are undefined; an emulation function will then be used. */
/* Define to 1 if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */
/* Define to 1 if the compiler supports simple visibility declarations. */
/* Define to 1 if the compiler supports GCC compatible visibility
declarations. */
/* #undef HAVE_VISIBILITY */
/* Define to 1 if you have the <wchar.h> header file. */
@ -215,7 +225,7 @@ sure both macros are undefined; an emulation function will then be used. */
Care must be taken if it is increased, because it guards against integer
overflow caused by enormously large patterns. */
#ifndef MAX_NAME_SIZE
#define MAX_NAME_SIZE 32
#define MAX_NAME_SIZE 128
#endif
/* The value of MAX_VARLOOKBEHIND specifies the default maximum length, in
@ -245,7 +255,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_NAME "PCRE2"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "PCRE2 10.43"
#define PACKAGE_STRING "PCRE2 10.45"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre2"
@ -254,7 +264,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "10.43"
#define PACKAGE_VERSION "10.45"
/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
parentheses (of any kind) in a pattern. This limits the amount of system
@ -311,7 +321,7 @@ sure both macros are undefined; an emulation function will then be used. */
unless SUPPORT_JIT is also defined. */
/* #undef SLJIT_PROT_EXECUTABLE_ALLOCATOR */
/* Define to 1 if all of the C89 standard headers exist (not just the ones
/* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
/* #undef STDC_HEADERS */
@ -366,7 +376,7 @@ sure both macros are undefined; an emulation function will then be used. */
/* Define to any value for valgrind support to find invalid memory reads. */
/* #undef SUPPORT_VALGRIND */
/* Enable extensions on AIX, Interix, z/OS. */
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
@ -427,15 +437,11 @@ sure both macros are undefined; an emulation function will then be used. */
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
# define __STDC_WANT_IEC_60559_DFP_EXT__ 1
#endif
/* Enable extensions specified by C23 Annex F. */
#ifndef __STDC_WANT_IEC_60559_EXT__
# define __STDC_WANT_IEC_60559_EXT__ 1
#endif
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
# define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1
#endif
/* Enable extensions specified by C23 Annex H and ISO/IEC TS 18661-3:2015. */
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
#endif
@ -458,26 +464,20 @@ sure both macros are undefined; an emulation function will then be used. */
#endif
/* Version number of package */
#define VERSION "10.43"
#define VERSION "10.45"
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define to 1 on platforms where this makes off_t a 64-bit type. */
/* Define for large files, on AIX-style hosts. */
/* #undef _LARGE_FILES */
/* Number of bits in time_t, on hosts where this is settable. */
/* #undef _TIME_BITS */
/* Define to 1 on platforms where this makes time_t a 64-bit type. */
/* #undef __MINGW_USE_VC2005_COMPAT */
/* Define to empty if 'const' does not conform to ANSI C. */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to the type of a signed integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
/* #undef int64_t */
/* Define as 'unsigned int' if <stddef.h> doesn't define. */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */

View file

@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE2_MAJOR 10
#define PCRE2_MINOR 43
#define PCRE2_MINOR 45
#define PCRE2_PRERELEASE
#define PCRE2_DATE 2024-02-16
#define PCRE2_DATE 2025-02-05
/* 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
@ -143,6 +143,7 @@ D is inspected during pcre2_dfa_match() execution
#define PCRE2_EXTENDED_MORE 0x01000000u /* C */
#define PCRE2_LITERAL 0x02000000u /* C */
#define PCRE2_MATCH_INVALID_UTF 0x04000000u /* J M D */
#define PCRE2_ALT_EXTENDED_CLASS 0x08000000u /* C */
/* An additional compile options word is available in the compile context. */
@ -159,6 +160,10 @@ D is inspected during pcre2_dfa_match() execution
#define PCRE2_EXTRA_ASCII_BSW 0x00000400u /* C */
#define PCRE2_EXTRA_ASCII_POSIX 0x00000800u /* C */
#define PCRE2_EXTRA_ASCII_DIGIT 0x00001000u /* C */
#define PCRE2_EXTRA_PYTHON_OCTAL 0x00002000u /* C */
#define PCRE2_EXTRA_NO_BS0 0x00004000u /* C */
#define PCRE2_EXTRA_NEVER_CALLOUT 0x00008000u /* C */
#define PCRE2_EXTRA_TURKISH_CASING 0x00010000u /* C */
/* These are for pcre2_jit_compile(). */
@ -166,6 +171,7 @@ D is inspected during pcre2_dfa_match() execution
#define PCRE2_JIT_PARTIAL_SOFT 0x00000002u
#define PCRE2_JIT_PARTIAL_HARD 0x00000004u
#define PCRE2_JIT_INVALID_UTF 0x00000100u
#define PCRE2_JIT_TEST_ALLOC 0x00000200u
/* These are for pcre2_match(), pcre2_dfa_match(), pcre2_jit_match(), and
pcre2_substitute(). Some are allowed only for one of the functions, and in
@ -318,9 +324,25 @@ pcre2_pattern_convert(). */
#define PCRE2_ERROR_ALPHA_ASSERTION_UNKNOWN 195
#define PCRE2_ERROR_SCRIPT_RUN_NOT_AVAILABLE 196
#define PCRE2_ERROR_TOO_MANY_CAPTURES 197
#define PCRE2_ERROR_CONDITION_ATOMIC_ASSERTION_EXPECTED 198
#define PCRE2_ERROR_MISSING_OCTAL_DIGIT 198
#define PCRE2_ERROR_BACKSLASH_K_IN_LOOKAROUND 199
#define PCRE2_ERROR_MAX_VAR_LOOKBEHIND_EXCEEDED 200
#define PCRE2_ERROR_PATTERN_COMPILED_SIZE_TOO_BIG 201
#define PCRE2_ERROR_OVERSIZE_PYTHON_OCTAL 202
#define PCRE2_ERROR_CALLOUT_CALLER_DISABLED 203
#define PCRE2_ERROR_EXTRA_CASING_REQUIRES_UNICODE 204
#define PCRE2_ERROR_TURKISH_CASING_REQUIRES_UTF 205
#define PCRE2_ERROR_EXTRA_CASING_INCOMPATIBLE 206
#define PCRE2_ERROR_ECLASS_NEST_TOO_DEEP 207
#define PCRE2_ERROR_ECLASS_INVALID_OPERATOR 208
#define PCRE2_ERROR_ECLASS_UNEXPECTED_OPERATOR 209
#define PCRE2_ERROR_ECLASS_EXPECTED_OPERAND 210
#define PCRE2_ERROR_ECLASS_MIXED_OPERATORS 211
#define PCRE2_ERROR_ECLASS_HINT_SQUARE_BRACKET 212
#define PCRE2_ERROR_PERL_ECLASS_UNEXPECTED_EXPR 213
#define PCRE2_ERROR_PERL_ECLASS_EMPTY_EXPR 214
#define PCRE2_ERROR_PERL_ECLASS_MISSING_CLOSE 215
#define PCRE2_ERROR_PERL_ECLASS_UNEXPECTED_CHAR 216
/* "Expected" matching error codes: no match and partial match. */
@ -407,6 +429,9 @@ released, the numbers must not be changed. */
#define PCRE2_ERROR_INTERNAL_DUPMATCH (-65)
#define PCRE2_ERROR_DFA_UINVALID_UTF (-66)
#define PCRE2_ERROR_INVALIDOFFSET (-67)
#define PCRE2_ERROR_JIT_UNSUPPORTED (-68)
#define PCRE2_ERROR_REPLACECASE (-69)
#define PCRE2_ERROR_TOOLARGEREPLACE (-70)
/* Request types for pcre2_pattern_info() */
@ -460,6 +485,30 @@ released, the numbers must not be changed. */
#define PCRE2_CONFIG_COMPILED_WIDTHS 14
#define PCRE2_CONFIG_TABLES_LENGTH 15
/* Optimization directives for pcre2_set_optimize().
For binary compatibility, only add to this list; do not renumber. */
#define PCRE2_OPTIMIZATION_NONE 0
#define PCRE2_OPTIMIZATION_FULL 1
#define PCRE2_AUTO_POSSESS 64
#define PCRE2_AUTO_POSSESS_OFF 65
#define PCRE2_DOTSTAR_ANCHOR 66
#define PCRE2_DOTSTAR_ANCHOR_OFF 67
#define PCRE2_START_OPTIMIZE 68
#define PCRE2_START_OPTIMIZE_OFF 69
/* Types used in pcre2_set_substitute_case_callout().
PCRE2_SUBSTITUTE_CASE_LOWER and PCRE2_SUBSTITUTE_CASE_UPPER are passed to the
callout to indicate that the case of the entire callout input should be
case-transformed. PCRE2_SUBSTITUTE_CASE_TITLE_FIRST is passed to indicate that
only the first character or glyph should be transformed to Unicode titlecase,
and the rest to lowercase. */
#define PCRE2_SUBSTITUTE_CASE_LOWER 1
#define PCRE2_SUBSTITUTE_CASE_UPPER 2
#define PCRE2_SUBSTITUTE_CASE_TITLE_FIRST 3
/* Types for code units in patterns and subject strings. */
@ -603,6 +652,8 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_compile_extra_options(pcre2_compile_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_max_pattern_length(pcre2_compile_context *, PCRE2_SIZE); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_max_pattern_compiled_length(pcre2_compile_context *, PCRE2_SIZE); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_max_varlookbehind(pcre2_compile_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
@ -611,7 +662,9 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_parens_nest_limit(pcre2_compile_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_compile_recursion_guard(pcre2_compile_context *, \
int (*)(uint32_t, void *), void *);
int (*)(uint32_t, void *), void *); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_optimize(pcre2_compile_context *, uint32_t);
#define PCRE2_MATCH_CONTEXT_FUNCTIONS \
PCRE2_EXP_DECL pcre2_match_context *PCRE2_CALL_CONVENTION \
@ -626,6 +679,11 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_substitute_callout(pcre2_match_context *, \
int (*)(pcre2_substitute_callout_block *, void *), void *); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_substitute_case_callout(pcre2_match_context *, \
PCRE2_SIZE (*)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *, PCRE2_SIZE, int, \
void *), \
void *); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_depth_limit(pcre2_match_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
@ -738,6 +796,7 @@ PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_substring_list_get(pcre2_match_data *, PCRE2_UCHAR ***, PCRE2_SIZE **);
/* Functions for serializing / deserializing compiled patterns. */
#define PCRE2_SERIALIZE_FUNCTIONS \
@ -901,10 +960,13 @@ pcre2_compile are called by application code. */
#define pcre2_set_match_limit PCRE2_SUFFIX(pcre2_set_match_limit_)
#define pcre2_set_max_varlookbehind PCRE2_SUFFIX(pcre2_set_max_varlookbehind_)
#define pcre2_set_max_pattern_length PCRE2_SUFFIX(pcre2_set_max_pattern_length_)
#define pcre2_set_max_pattern_compiled_length PCRE2_SUFFIX(pcre2_set_max_pattern_compiled_length_)
#define pcre2_set_newline PCRE2_SUFFIX(pcre2_set_newline_)
#define pcre2_set_parens_nest_limit PCRE2_SUFFIX(pcre2_set_parens_nest_limit_)
#define pcre2_set_offset_limit PCRE2_SUFFIX(pcre2_set_offset_limit_)
#define pcre2_set_optimize PCRE2_SUFFIX(pcre2_set_optimize_)
#define pcre2_set_substitute_callout PCRE2_SUFFIX(pcre2_set_substitute_callout_)
#define pcre2_set_substitute_case_callout PCRE2_SUFFIX(pcre2_set_substitute_case_callout_)
#define pcre2_substitute PCRE2_SUFFIX(pcre2_substitute_)
#define pcre2_substring_copy_byname PCRE2_SUFFIX(pcre2_substring_copy_byname_)
#define pcre2_substring_copy_bynumber PCRE2_SUFFIX(pcre2_substring_copy_bynumber_)

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-2022 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -49,6 +49,10 @@ repeats into possessive repeats where possible. */
#include "pcre2_internal.h"
/* This macro represents the max size of list[] and that is used to keep
track of UCD info in several places, it should be kept on sync with the
value used by GenerateUcd.py */
#define MAX_LIST 8
/*************************************************
* Tables for auto-possessification *
@ -64,7 +68,7 @@ The Unicode property types (\P and \p) have to be present to fill out the table
because of what their opcode values are, but the table values should always be
zero because property types are handled separately in the code. The last four
columns apply to items that cannot be repeated, so there is no need to have
rows for them. Note that OP_DIGIT etc. are generated only when PCRE_UCP is
rows for them. Note that OP_DIGIT etc. are generated only when PCRE2_UCP is
*not* set. When it is set, \d etc. are converted into OP_(NOT_)PROP codes. */
#define APTROWS (LAST_AUTOTAB_LEFT_OP - FIRST_AUTOTAB_OP + 1)
@ -123,21 +127,21 @@ opcode is used to select the column. The values are as follows:
*/
static const uint8_t propposstab[PT_TABSIZE][PT_TABSIZE] = {
/* ANY LAMP GC PC SC SCX ALNUM SPACE PXSPACE WORD CLIST UCNC BIDICL BOOL */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_ANY */
{ 0, 3, 0, 0, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_LAMP */
{ 0, 0, 2, 4, 0, 0, 9, 10, 10, 11, 0, 0, 0, 0 }, /* PT_GC */
{ 0, 0, 5, 2, 0, 0, 15, 16, 16, 17, 0, 0, 0, 0 }, /* PT_PC */
{ 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SC */
{ 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SCX */
{ 0, 3, 6, 12, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_ALNUM */
{ 0, 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_SPACE */
{ 0, 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_PXSPACE */
{ 0, 0, 8, 14, 0, 0, 0, 1, 1, 3, 0, 0, 0, 0 }, /* PT_WORD */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, /* PT_UCNC */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_BIDICL */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* PT_BOOL */
/* LAMP GC PC SC SCX ALNUM SPACE PXSPACE WORD CLIST UCNC BIDICL BOOL */
{ 3, 0, 0, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_LAMP */
{ 0, 2, 4, 0, 0, 9, 10, 10, 11, 0, 0, 0, 0 }, /* PT_GC */
{ 0, 5, 2, 0, 0, 15, 16, 16, 17, 0, 0, 0, 0 }, /* PT_PC */
{ 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SC */
{ 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SCX */
{ 3, 6, 12, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_ALNUM */
{ 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_SPACE */
{ 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_PXSPACE */
{ 0, 8, 14, 0, 0, 0, 1, 1, 3, 0, 0, 0, 0 }, /* PT_WORD */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, /* PT_UCNC */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_BIDICL */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* PT_BOOL */
/* PT_ANY does not need a record. */
};
/* This table is used to check whether auto-possessification is possible
@ -199,7 +203,7 @@ static BOOL
check_char_prop(uint32_t c, unsigned int ptype, unsigned int pdata,
BOOL negated)
{
BOOL ok;
BOOL ok, rc;
const uint32_t *p;
const ucd_record *prop = GET_UCD(c);
@ -240,12 +244,13 @@ switch(ptype)
{
HSPACE_CASES:
VSPACE_CASES:
return negated;
rc = negated;
break;
default:
return (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated;
rc = (PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == negated;
}
break; /* Control never reaches here */
return rc;
case PT_WORD:
return (PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
@ -259,7 +264,8 @@ switch(ptype)
if (c < *p) return !negated;
if (c == *p++) return negated;
}
break; /* Control never reaches here */
PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */
break;
/* Haven't yet thought these through. */
@ -328,6 +334,7 @@ get_chr_property_list(PCRE2_SPTR code, BOOL utf, BOOL ucp, const uint8_t *fcc,
PCRE2_UCHAR c = *code;
PCRE2_UCHAR base;
PCRE2_SPTR end;
PCRE2_SPTR class_end;
uint32_t chr;
#ifdef SUPPORT_UNICODE
@ -450,10 +457,12 @@ switch(c)
code += 2;
do {
if (clist_dest >= list + 8)
if (clist_dest >= list + MAX_LIST)
{
/* Early return if there is not enough space. This should never
happen, since all clists are shorter than 5 character now. */
/* Early return if there is not enough space. GenerateUcd.py
generated a list with more than 5 characters and something
must be done about that going forward. */
PCRE2_DEBUG_UNREACHABLE(); /* Remove if it ever triggers */
list[2] = code[0];
list[3] = code[1];
return code;
@ -473,11 +482,13 @@ switch(c)
case OP_CLASS:
#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
if (c == OP_XCLASS)
case OP_ECLASS:
if (c == OP_XCLASS || c == OP_ECLASS)
end = code + GET(code, 0) - 1;
else
#endif
end = code + 32 / sizeof(PCRE2_UCHAR);
class_end = end;
switch(*end)
{
@ -505,6 +516,7 @@ switch(c)
break;
}
list[2] = (uint32_t)(end - code);
list[3] = (uint32_t)(end - class_end);
return end;
}
@ -537,7 +549,7 @@ compare_opcodes(PCRE2_SPTR code, BOOL utf, BOOL ucp, const compile_block *cb,
const uint32_t *base_list, PCRE2_SPTR base_end, int *rec_limit)
{
PCRE2_UCHAR c;
uint32_t list[8];
uint32_t list[MAX_LIST];
const uint32_t *chr_ptr;
const uint32_t *ochr_ptr;
const uint32_t *list_ptr;
@ -581,7 +593,7 @@ for(;;)
continue;
}
/* At the end of a branch, skip to the end of the group. */
/* At the end of a branch, skip to the end of the group and process it. */
if (c == OP_ALT)
{
@ -638,19 +650,29 @@ for(;;)
return FALSE;
break;
/* Atomic sub-patterns and assertions can always auto-possessify their
last iterator except for variable length lookbehinds. However, if the
group was entered as a result of checking a previous iterator, this is
not possible. */
/* Atomic sub-patterns and forward assertions can always auto-possessify
their last iterator. However, if the group was entered as a result of
checking a previous iterator, this is not possible. */
case OP_ASSERT:
case OP_ASSERT_NOT:
case OP_ONCE:
return !entered_a_group;
/* Fixed-length lookbehinds can be treated the same way, but variable
length lookbehinds must not auto-possessify their last iterator. Note
that in order to identify a variable length lookbehind we must check
through all branches, because some may be of fixed length. */
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
return (bracode[1+LINK_SIZE] == OP_VREVERSE)? FALSE : !entered_a_group;
do
{
if (bracode[1+LINK_SIZE] == OP_VREVERSE) return FALSE; /* Variable */
bracode += GET(bracode, 1);
}
while (*bracode == OP_ALT);
return !entered_a_group; /* Not variable length */
/* Non-atomic assertions - don't possessify last iterator. This needs
more thought. */
@ -748,12 +770,12 @@ for(;;)
if (base_list[0] == OP_CLASS)
#endif
{
set1 = (uint8_t *)(base_end - base_list[2]);
set1 = (const uint8_t *)(base_end - base_list[2]);
list_ptr = list;
}
else
{
set1 = (uint8_t *)(code - list[2]);
set1 = (const uint8_t *)(code - list[2]);
list_ptr = base_list;
}
@ -762,13 +784,14 @@ for(;;)
{
case OP_CLASS:
case OP_NCLASS:
set2 = (uint8_t *)
set2 = (const uint8_t *)
((list_ptr == list ? code : base_end) - list_ptr[2]);
break;
#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
xclass_flags = (list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE;
xclass_flags = (list_ptr == list ? code : base_end) -
list_ptr[2] + LINK_SIZE;
if ((*xclass_flags & XCL_HASPROP) != 0) return FALSE;
if ((*xclass_flags & XCL_MAP) == 0)
{
@ -777,7 +800,7 @@ for(;;)
/* Might be an empty repeat. */
continue;
}
set2 = (uint8_t *)(xclass_flags + 1);
set2 = (const uint8_t *)(xclass_flags + 1);
break;
#endif
@ -785,21 +808,21 @@ for(;;)
invert_bits = TRUE;
/* Fall through */
case OP_DIGIT:
set2 = (uint8_t *)(cb->cbits + cbit_digit);
set2 = (const uint8_t *)(cb->cbits + cbit_digit);
break;
case OP_NOT_WHITESPACE:
invert_bits = TRUE;
/* Fall through */
case OP_WHITESPACE:
set2 = (uint8_t *)(cb->cbits + cbit_space);
set2 = (const uint8_t *)(cb->cbits + cbit_space);
break;
case OP_NOT_WORDCHAR:
invert_bits = TRUE;
/* Fall through */
case OP_WORDCHAR:
set2 = (uint8_t *)(cb->cbits + cbit_word);
set2 = (const uint8_t *)(cb->cbits + cbit_word);
break;
default:
@ -1084,7 +1107,7 @@ for(;;)
case OP_CLASS:
if (chr > 255) break;
class_bitset = (uint8_t *)
class_bitset = (const uint8_t *)
((list_ptr == list ? code : base_end) - list_ptr[2]);
if ((class_bitset[chr >> 3] & (1u << (chr & 7))) != 0) return FALSE;
break;
@ -1092,9 +1115,18 @@ for(;;)
#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
if (PRIV(xclass)(chr, (list_ptr == list ? code : base_end) -
list_ptr[2] + LINK_SIZE, utf)) return FALSE;
list_ptr[2] + LINK_SIZE, (const uint8_t*)cb->start_code, utf))
return FALSE;
break;
#endif
case OP_ECLASS:
if (PRIV(eclass)(chr,
(list_ptr == list ? code : base_end) - list_ptr[2] + LINK_SIZE,
(list_ptr == list ? code : base_end) - list_ptr[3],
(const uint8_t*)cb->start_code, utf))
return FALSE;
break;
#endif /* SUPPORT_WIDE_CHARS */
default:
return FALSE;
@ -1109,8 +1141,8 @@ for(;;)
if (list[1] == 0) return TRUE;
}
/* Control never reaches here. There used to be a fail-save return FALSE; here,
but some compilers complain about an unreachable statement. */
PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */
return FALSE; /* Avoid compiler warnings */
}
@ -1140,7 +1172,7 @@ PRIV(auto_possessify)(PCRE2_UCHAR *code, const compile_block *cb)
PCRE2_UCHAR c;
PCRE2_SPTR end;
PCRE2_UCHAR *repeat_opcode;
uint32_t list[8];
uint32_t list[MAX_LIST];
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;
@ -1149,7 +1181,11 @@ for (;;)
{
c = *code;
if (c >= OP_TABLE_LENGTH) return -1; /* Something gone wrong */
if (c >= OP_TABLE_LENGTH)
{
PCRE2_DEBUG_UNREACHABLE();
return -1; /* Something gone wrong */
}
if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)
{
@ -1198,10 +1234,14 @@ for (;;)
}
c = *code;
}
else if (c == OP_CLASS || c == OP_NCLASS || c == OP_XCLASS)
else if (c == OP_CLASS || c == OP_NCLASS
#ifdef SUPPORT_WIDE_CHARS
|| c == OP_XCLASS || c == OP_ECLASS
#endif
)
{
#ifdef SUPPORT_WIDE_CHARS
if (c == OP_XCLASS)
if (c == OP_XCLASS || c == OP_ECLASS)
repeat_opcode = code + GET(code, 1);
else
#endif
@ -1211,7 +1251,7 @@ for (;;)
if (c >= OP_CRSTAR && c <= OP_CRMINRANGE)
{
/* The return from get_chr_property_list() will never be NULL when
*code (aka c) is one of the three class opcodes. However, gcc with
*code (aka c) is one of the four class opcodes. However, gcc with
-fanalyzer notes that a NULL return is possible, and grumbles. Hence we
put in a check. */
@ -1279,6 +1319,7 @@ for (;;)
#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
case OP_ECLASS:
code += GET(code, 1);
break;
#endif

View file

@ -74,9 +74,7 @@ if (__builtin_mul_overflow(a, b, &m)) return TRUE;
#else
INT64_OR_DOUBLE m;
#ifdef PCRE2_DEBUG
if (a < 0 || b < 0) abort();
#endif
PCRE2_ASSERT(a >= 0 && b >= 0);
m = (INT64_OR_DOUBLE)a * (INT64_OR_DOUBLE)b;
@ -93,4 +91,4 @@ if (m > PCRE2_SIZE_MAX) return TRUE;
return FALSE;
}
/* End of pcre_chkdint.c */
/* End of pcre2_chkdint.c */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,280 @@
/*************************************************
* Perl-Compatible Regular Expressions *
*************************************************/
/* PCRE2 is a library of functions to support regular expressions whose syntax
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-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of Cambridge nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
#ifndef PCRE2_COMPILE_H_IDEMPOTENT_GUARD
#define PCRE2_COMPILE_H_IDEMPOTENT_GUARD
#include "pcre2_internal.h"
/* Compile time error code numbers. They are given names so that they can more
easily be tracked. When a new number is added, the tables called eint1 and
eint2 in pcre2posix.c may need to be updated, and a new error text must be
added to compile_error_texts in pcre2_error.c. Also, the error codes in
pcre2.h.in must be updated - their values are exactly 100 greater than these
values. */
enum { ERR0 = COMPILE_ERROR_BASE,
ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10,
ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20,
ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, ERR30,
ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40,
ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, ERR50,
ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, ERR60,
ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70,
ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80,
ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90,
ERR91, ERR92, ERR93, ERR94, ERR95, ERR96, ERR97, ERR98, ERR99, ERR100,
ERR101,ERR102,ERR103,ERR104,ERR105,ERR106,ERR107,ERR108,ERR109,ERR110,
ERR111,ERR112,ERR113,ERR114,ERR115,ERR116 };
/* Code values for parsed patterns, which are stored in a vector of 32-bit
unsigned ints. Values less than META_END are literal data values. The coding
for identifying the item is in the top 16-bits, leaving 16 bits for the
additional data that some of them need. The META_CODE, META_DATA, and META_DIFF
macros are used to manipulate parsed pattern elements.
NOTE: When these definitions are changed, the table of extra lengths for each
code (meta_extra_lengths) must be updated to remain in step. */
#define META_END 0x80000000u /* End of pattern */
#define META_ALT 0x80010000u /* alternation */
#define META_ATOMIC 0x80020000u /* atomic group */
#define META_BACKREF 0x80030000u /* Back ref */
#define META_BACKREF_BYNAME 0x80040000u /* \k'name' */
#define META_BIGVALUE 0x80050000u /* Next is a literal > META_END */
#define META_CALLOUT_NUMBER 0x80060000u /* (?C with numerical argument */
#define META_CALLOUT_STRING 0x80070000u /* (?C with string argument */
#define META_CAPTURE 0x80080000u /* Capturing parenthesis */
#define META_CIRCUMFLEX 0x80090000u /* ^ metacharacter */
#define META_CLASS 0x800a0000u /* start non-empty class */
#define META_CLASS_EMPTY 0x800b0000u /* empty class */
#define META_CLASS_EMPTY_NOT 0x800c0000u /* negative empty class */
#define META_CLASS_END 0x800d0000u /* end of non-empty class */
#define META_CLASS_NOT 0x800e0000u /* start non-empty negative class */
#define META_COND_ASSERT 0x800f0000u /* (?(?assertion)... */
#define META_COND_DEFINE 0x80100000u /* (?(DEFINE)... */
#define META_COND_NAME 0x80110000u /* (?(<name>)... */
#define META_COND_NUMBER 0x80120000u /* (?(digits)... */
#define META_COND_RNAME 0x80130000u /* (?(R&name)... */
#define META_COND_RNUMBER 0x80140000u /* (?(Rdigits)... */
#define META_COND_VERSION 0x80150000u /* (?(VERSION<op>x.y)... */
#define META_OFFSET 0x80160000u /* Setting offset for various
META codes (e.g. META_SCS_NAME) */
#define META_SCS 0x80170000u /* (*scan_substring:... */
#define META_SCS_NAME 0x80180000u /* Next <name> of scan_substring */
#define META_SCS_NUMBER 0x80190000u /* Next digits of scan_substring */
#define META_DOLLAR 0x801a0000u /* $ metacharacter */
#define META_DOT 0x801b0000u /* . metacharacter */
#define META_ESCAPE 0x801c0000u /* \d and friends */
#define META_KET 0x801d0000u /* closing parenthesis */
#define META_NOCAPTURE 0x801e0000u /* no capture parens */
#define META_OPTIONS 0x801f0000u /* (?i) and friends */
#define META_POSIX 0x80200000u /* POSIX class item */
#define META_POSIX_NEG 0x80210000u /* negative POSIX class item */
#define META_RANGE_ESCAPED 0x80220000u /* range with at least one escape */
#define META_RANGE_LITERAL 0x80230000u /* range defined literally */
#define META_RECURSE 0x80240000u /* Recursion */
#define META_RECURSE_BYNAME 0x80250000u /* (?&name) */
#define META_SCRIPT_RUN 0x80260000u /* (*script_run:...) */
/* These must be kept together to make it easy to check that an assertion
is present where expected in a conditional group. */
#define META_LOOKAHEAD 0x80270000u /* (?= */
#define META_LOOKAHEADNOT 0x80280000u /* (?! */
#define META_LOOKBEHIND 0x80290000u /* (?<= */
#define META_LOOKBEHINDNOT 0x802a0000u /* (?<! */
/* These cannot be conditions */
#define META_LOOKAHEAD_NA 0x802b0000u /* (*napla: */
#define META_LOOKBEHIND_NA 0x802c0000u /* (*naplb: */
/* These must be kept in this order, with consecutive values, and the _ARG
versions of COMMIT, PRUNE, SKIP, and THEN immediately after their non-argument
versions. */
#define META_MARK 0x802d0000u /* (*MARK) */
#define META_ACCEPT 0x802e0000u /* (*ACCEPT) */
#define META_FAIL 0x802f0000u /* (*FAIL) */
#define META_COMMIT 0x80300000u /* These */
#define META_COMMIT_ARG 0x80310000u /* pairs */
#define META_PRUNE 0x80320000u /* must */
#define META_PRUNE_ARG 0x80330000u /* be */
#define META_SKIP 0x80340000u /* kept */
#define META_SKIP_ARG 0x80350000u /* in */
#define META_THEN 0x80360000u /* this */
#define META_THEN_ARG 0x80370000u /* order */
/* These must be kept in groups of adjacent 3 values, and all together. */
#define META_ASTERISK 0x80380000u /* * */
#define META_ASTERISK_PLUS 0x80390000u /* *+ */
#define META_ASTERISK_QUERY 0x803a0000u /* *? */
#define META_PLUS 0x803b0000u /* + */
#define META_PLUS_PLUS 0x803c0000u /* ++ */
#define META_PLUS_QUERY 0x803d0000u /* +? */
#define META_QUERY 0x803e0000u /* ? */
#define META_QUERY_PLUS 0x803f0000u /* ?+ */
#define META_QUERY_QUERY 0x80400000u /* ?? */
#define META_MINMAX 0x80410000u /* {n,m} repeat */
#define META_MINMAX_PLUS 0x80420000u /* {n,m}+ repeat */
#define META_MINMAX_QUERY 0x80430000u /* {n,m}? repeat */
/* These meta codes must be kept in a group, with the OR/SUB/XOR in
this order, and AND/NOT at the start/end. */
#define META_ECLASS_AND 0x80440000u /* && (or &) in a class */
#define META_ECLASS_OR 0x80450000u /* || (or |, +) in a class */
#define META_ECLASS_SUB 0x80460000u /* -- (or -) in a class */
#define META_ECLASS_XOR 0x80470000u /* ~~ (or ^) in a class */
#define META_ECLASS_NOT 0x80480000u /* ! in a class */
/* Convenience aliases. */
#define META_FIRST_QUANTIFIER META_ASTERISK
#define META_LAST_QUANTIFIER META_MINMAX_QUERY
/* This is a special "meta code" that is used only to distinguish (*asr: from
(*sr: in the table of alphabetic assertions. It is never stored in the parsed
pattern because (*asr: is turned into (*sr:(*atomic: at that stage. There is
therefore no need for it to have a length entry, so use a high value. */
#define META_ATOMIC_SCRIPT_RUN 0x8fff0000u
/* Macros for manipulating elements of the parsed pattern vector. */
#define META_CODE(x) (x & 0xffff0000u)
#define META_DATA(x) (x & 0x0000ffffu)
#define META_DIFF(x,y) ((x-y)>>16)
/* Extended class management flags. */
#define CLASS_IS_ECLASS 0x1
/* Macro for the highest character value. */
#if PCRE2_CODE_UNIT_WIDTH == 8
#define MAX_UCHAR_VALUE 0xffu
#elif PCRE2_CODE_UNIT_WIDTH == 16
#define MAX_UCHAR_VALUE 0xffffu
#else
#define MAX_UCHAR_VALUE 0xffffffffu
#endif
#define GET_MAX_CHAR_VALUE(utf) \
((utf) ? MAX_UTF_CODE_POINT : MAX_UCHAR_VALUE)
/* Macro for setting individual bits in class bitmaps. */
#define SETBIT(a,b) a[(b) >> 3] |= (uint8_t)(1u << ((b) & 0x7))
/* Macro for 8 bit specific checks. */
#if PCRE2_CODE_UNIT_WIDTH == 8
#define SELECT_VALUE8(value8, value) (value8)
#else
#define SELECT_VALUE8(value8, value) (value)
#endif
/* Macro for aligning data. */
#define CLIST_ALIGN_TO(base, align) \
((base + ((size_t)(align) - 1)) & ~((size_t)(align) - 1))
/* Structure for holding information about an OP_ECLASS internal operand.
An "operand" here could be just a single OP_[X]CLASS, or it could be some
complex expression; but it's some sequence of ECL_* codes which pushes one
value to the stack. */
typedef struct {
/* The position of the operand - or NULL if (lengthptr != NULL). */
PCRE2_UCHAR *code_start;
PCRE2_SIZE length;
/* The operand's type if it is a single code (ECL_XCLASS, ECL_ANY, ECL_NONE);
otherwise zero if the operand is not atomic. */
uint8_t op_single_type;
/* Regardless of whether it's a single code or not, we fully constant-fold
the bitmap for code points < 256. */
class_bits_storage bits;
} eclass_op_info;
/* Macros for the definitions below, to prevent name collisions. */
#define _pcre2_posix_class_maps PCRE2_SUFFIX(_pcre2_posix_class_maps)
#define _pcre2_update_classbits PCRE2_SUFFIX(_pcre2_update_classbits_)
#define _pcre2_compile_class_nested PCRE2_SUFFIX(_pcre2_compile_class_nested_)
#define _pcre2_compile_class_not_nested PCRE2_SUFFIX(_pcre2_compile_class_not_nested_)
/* Indices of the POSIX classes in posix_names, posix_name_lengths,
posix_class_maps, and posix_substitutes. They must be kept in sync. */
#define PC_DIGIT 7
#define PC_GRAPH 8
#define PC_PRINT 9
#define PC_PUNCT 10
#define PC_XDIGIT 13
extern const int PRIV(posix_class_maps)[];
/* Set bits in classbits according to the property type */
void PRIV(update_classbits)(uint32_t ptype, uint32_t pdata, BOOL negated,
uint8_t *classbits);
/* Compile the META codes from start_ptr...end_ptr, writing a single OP_CLASS
OP_CLASS, OP_NCLASS, OP_XCLASS, or OP_ALLANY into pcode. */
uint32_t *PRIV(compile_class_not_nested)(uint32_t options, uint32_t xoptions,
uint32_t *start_ptr, PCRE2_UCHAR **pcode, BOOL negate_class, BOOL* has_bitmap,
int *errorcodeptr, compile_block *cb, PCRE2_SIZE *lengthptr);
/* Compile the META codes in pptr into opcodes written to pcode. The pptr must
start at a META_CLASS or META_CLASS_NOT.
The pptr will be left pointing at the matching META_CLASS_END. */
BOOL PRIV(compile_class_nested)(uint32_t options, uint32_t xoptions,
uint32_t **pptr, PCRE2_UCHAR **pcode, int *errorcodeptr,
compile_block *cb, PCRE2_SIZE *lengthptr);
#endif /* PCRE2_COMPILE_H_IDEMPOTENT_GUARD */
/* End of pcre2_compile.h */

File diff suppressed because it is too large Load diff

View file

@ -224,8 +224,8 @@ switch (what)
XSTRING when PCRE2_PRERELEASE is not empty, an unwanted space is inserted.
There are problems using an "obvious" approach like this:
XSTRING(PCRE2_MAJOR) "." XSTRING(PCRE_MINOR)
XSTRING(PCRE2_PRERELEASE) " " XSTRING(PCRE_DATE)
XSTRING(PCRE2_MAJOR) "." XSTRING(PCRE2_MINOR)
XSTRING(PCRE2_PRERELEASE) " " XSTRING(PCRE2_DATE)
because, when PCRE2_PRERELEASE is empty, this leads to an attempted expansion
of STRING(). The C standard states: "If (before argument substitution) any

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-2023 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -130,17 +130,19 @@ return gcontext;
/* A default compile context is set up to save having to initialize at run time
when no context is supplied to the compile function. */
const pcre2_compile_context PRIV(default_compile_context) = {
pcre2_compile_context PRIV(default_compile_context) = {
{ default_malloc, default_free, NULL }, /* Default memory handling */
NULL, /* Stack guard */
NULL, /* Stack guard data */
PRIV(default_tables), /* Character tables */
PCRE2_UNSET, /* Max pattern length */
PCRE2_UNSET, /* Max pattern compiled length */
BSR_DEFAULT, /* Backslash R default */
NEWLINE_DEFAULT, /* Newline convention */
PARENS_NEST_LIMIT, /* As it says */
0, /* Extra options */
MAX_VARLOOKBEHIND /* As it says */
MAX_VARLOOKBEHIND, /* As it says */
PCRE2_OPTIMIZATION_ALL /* All optimizations enabled */
};
/* The create function copies the default into the new memory, but must
@ -162,7 +164,7 @@ return ccontext;
/* A default match context is set up to save having to initialize at run time
when no context is supplied to a match function. */
const pcre2_match_context PRIV(default_match_context) = {
pcre2_match_context PRIV(default_match_context) = {
{ default_malloc, default_free, NULL },
#ifdef SUPPORT_JIT
NULL, /* JIT callback */
@ -172,6 +174,8 @@ const pcre2_match_context PRIV(default_match_context) = {
NULL, /* Callout data */
NULL, /* Substitute callout function */
NULL, /* Substitute callout data */
NULL, /* Substitute case callout function */
NULL, /* Substitute case callout data */
PCRE2_UNSET, /* Offset limit */
HEAP_LIMIT,
MATCH_LIMIT,
@ -196,7 +200,7 @@ return mcontext;
/* A default convert context is set up to save having to initialize at run time
when no context is supplied to the convert function. */
const pcre2_convert_context PRIV(default_convert_context) = {
pcre2_convert_context PRIV(default_convert_context) = {
{ default_malloc, default_free, NULL }, /* Default memory handling */
#ifdef _WIN32
CHAR_BACKSLASH, /* Default path separator */
@ -352,6 +356,13 @@ ccontext->max_pattern_length = length;
return 0;
}
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_max_pattern_compiled_length(pcre2_compile_context *ccontext, PCRE2_SIZE length)
{
ccontext->max_pattern_compiled_length = length;
return 0;
}
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_newline(pcre2_compile_context *ccontext, uint32_t newline)
{
@ -401,6 +412,38 @@ ccontext->stack_guard_data = user_data;
return 0;
}
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_optimize(pcre2_compile_context *ccontext, uint32_t directive)
{
if (ccontext == NULL)
return PCRE2_ERROR_NULL;
switch (directive)
{
case PCRE2_OPTIMIZATION_NONE:
ccontext->optimization_flags = 0;
break;
case PCRE2_OPTIMIZATION_FULL:
ccontext->optimization_flags = PCRE2_OPTIMIZATION_ALL;
break;
default:
if (directive >= PCRE2_AUTO_POSSESS && directive <= PCRE2_START_OPTIMIZE_OFF)
{
/* Even directive numbers starting from 64 switch a bit on;
* Odd directive numbers starting from 65 switch a bit off */
if ((directive & 1) != 0)
ccontext->optimization_flags &= ~(1u << ((directive >> 1) - 32));
else
ccontext->optimization_flags |= 1u << ((directive >> 1) - 32);
return 0;
}
return PCRE2_ERROR_BADOPTION;
}
return 0;
}
/* ------------ Match context ------------ */
@ -416,13 +459,24 @@ return 0;
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_substitute_callout(pcre2_match_context *mcontext,
int (*substitute_callout)(pcre2_substitute_callout_block *, void *),
void *substitute_callout_data)
void *substitute_callout_data)
{
mcontext->substitute_callout = substitute_callout;
mcontext->substitute_callout_data = substitute_callout_data;
return 0;
}
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_substitute_case_callout(pcre2_match_context *mcontext,
PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *,
PCRE2_SIZE, int, void *),
void *substitute_case_callout_data)
{
mcontext->substitute_case_callout = substitute_case_callout;
mcontext->substitute_case_callout_data = substitute_case_callout_data;
return 0;
}
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_heap_limit(pcre2_match_context *mcontext, uint32_t limit)
{

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-2022 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -74,7 +74,7 @@ enum { POSIX_START_REGEX, POSIX_ANCHORED, POSIX_NOT_BRACKET,
#define PUTCHARS(string) \
{ \
for (s = (char *)(string); *s != 0; s++) \
for (const char *s = string; *s != 0; s++) \
{ \
if (p >= endp) return PCRE2_ERROR_NOMEMORY; \
*p++ = *s; \
@ -125,7 +125,6 @@ convert_posix(uint32_t pattype, PCRE2_SPTR pattern, PCRE2_SIZE plength,
BOOL utf, PCRE2_UCHAR *use_buffer, PCRE2_SIZE use_length,
PCRE2_SIZE *bufflenptr, BOOL dummyrun, pcre2_convert_context *ccontext)
{
char *s;
PCRE2_SPTR posix = pattern;
PCRE2_UCHAR *p = use_buffer;
PCRE2_UCHAR *pp = p;
@ -1065,7 +1064,7 @@ pcre2_pattern_convert(PCRE2_SPTR pattern, PCRE2_SIZE plength, uint32_t options,
PCRE2_UCHAR **buffptr, PCRE2_SIZE *bufflenptr,
pcre2_convert_context *ccontext)
{
int i, rc;
int rc;
PCRE2_UCHAR dummy_buffer[DUMMY_BUFFER_SIZE];
PCRE2_UCHAR *use_buffer = dummy_buffer;
PCRE2_SIZE use_length = DUMMY_BUFFER_SIZE;
@ -1119,7 +1118,7 @@ if (buffptr != NULL && *buffptr != NULL)
/* Call an individual converter, either just once (if a buffer was provided or
just the length is needed), or twice (if a memory allocation is required). */
for (i = 0; i < 2; i++)
for (int i = 0; i < 2; i++)
{
PCRE2_UCHAR *allocated;
BOOL dummyrun = buffptr == NULL || *buffptr == NULL;
@ -1138,8 +1137,7 @@ for (i = 0; i < 2; i++)
break;
default:
*bufflenptr = 0; /* Error offset */
return PCRE2_ERROR_INTERNAL;
goto EXIT;
}
if (rc != 0 || /* Error */
@ -1159,8 +1157,12 @@ for (i = 0; i < 2; i++)
use_length = *bufflenptr + 1;
}
/* Control should never get here. */
/* Something went terribly wrong. Trigger an assert and return an error */
PCRE2_DEBUG_UNREACHABLE();
EXIT:
*bufflenptr = 0; /* Error offset */
return PCRE2_ERROR_INTERNAL;
}

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-2023 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -156,6 +156,7 @@ static const uint8_t coptable[] = {
0, /* CLASS */
0, /* NCLASS */
0, /* XCLASS - variable length */
0, /* ECLASS - variable length */
0, /* REF */
0, /* REFI */
0, /* DNREF */
@ -175,6 +176,7 @@ static const uint8_t coptable[] = {
0, /* Assert behind not */
0, /* NA assert */
0, /* NA assert behind */
0, /* Assert scan substring */
0, /* ONCE */
0, /* SCRIPT_RUN */
0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */
@ -188,7 +190,7 @@ static const uint8_t coptable[] = {
0, 0, /* COMMIT, COMMIT_ARG */
0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */
0, 0, 0, /* CLOSE, SKIPZERO, DEFINE */
0, 0 /* \B and \b in UCP mode */
0, 0, /* \B and \b in UCP mode */
};
/* This table identifies those opcodes that inspect a character. It is used to
@ -234,6 +236,7 @@ static const uint8_t poptable[] = {
1, /* CLASS */
1, /* NCLASS */
1, /* XCLASS - variable length */
1, /* ECLASS - variable length */
0, /* REF */
0, /* REFI */
0, /* DNREF */
@ -253,6 +256,7 @@ static const uint8_t poptable[] = {
0, /* Assert behind not */
0, /* NA assert */
0, /* NA assert behind */
0, /* Assert scan substring */
0, /* ONCE */
0, /* SCRIPT_RUN */
0, 0, 0, 0, 0, /* BRA, BRAPOS, CBRA, CBRAPOS, COND */
@ -266,9 +270,13 @@ static const uint8_t poptable[] = {
0, 0, /* COMMIT, COMMIT_ARG */
0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */
0, 0, 0, /* CLOSE, SKIPZERO, DEFINE */
1, 1 /* \B and \b in UCP mode */
1, 1, /* \B and \b in UCP mode */
};
/* Compile-time check that these tables have the correct size. */
STATIC_ASSERT(sizeof(coptable) == OP_TABLE_LENGTH, coptable);
STATIC_ASSERT(sizeof(poptable) == OP_TABLE_LENGTH, poptable);
/* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,
and \w */
@ -695,7 +703,6 @@ for (;;)
int i, j;
int clen, dlen;
uint32_t c, d;
int forced_fail = 0;
BOOL partial_newline = FALSE;
BOOL could_continue = reset_could_continue;
reset_could_continue = FALSE;
@ -841,19 +848,6 @@ for (;;)
switch (codevalue)
{
/* ========================================================================== */
/* These cases are never obeyed. This is a fudge that causes a compile-
time error if the vectors coptable or poptable, which are indexed by
opcode, are not the correct length. It seems to be the only way to do
such a check at compile time, as the sizeof() operator does not work
in the C preprocessor. */
case OP_TABLE_LENGTH:
case OP_TABLE_LENGTH +
((sizeof(coptable) == OP_TABLE_LENGTH) &&
(sizeof(poptable) == OP_TABLE_LENGTH)):
return 0;
/* ========================================================================== */
/* Reached a closing bracket. If not at the end of the pattern, carry
on with the next opcode. For repeating opcodes, also add the repeat
@ -1179,10 +1173,6 @@ for (;;)
const ucd_record * prop = GET_UCD(c);
switch(code[1])
{
case PT_ANY:
OK = TRUE;
break;
case PT_LAMP:
chartype = prop->chartype;
OK = chartype == ucp_Lu || chartype == ucp_Ll ||
@ -1462,10 +1452,6 @@ for (;;)
const ucd_record * prop = GET_UCD(c);
switch(code[2])
{
case PT_ANY:
OK = TRUE;
break;
case PT_LAMP:
chartype = prop->chartype;
OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;
@ -1727,10 +1713,6 @@ for (;;)
const ucd_record * prop = GET_UCD(c);
switch(code[2])
{
case PT_ANY:
OK = TRUE;
break;
case PT_LAMP:
chartype = prop->chartype;
OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;
@ -2017,10 +1999,6 @@ for (;;)
const ucd_record * prop = GET_UCD(c);
switch(code[1 + IMM2_SIZE + 1])
{
case PT_ANY:
OK = TRUE;
break;
case PT_LAMP:
chartype = prop->chartype;
OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;
@ -2663,35 +2641,54 @@ for (;;)
case OP_CLASS:
case OP_NCLASS:
#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
case OP_ECLASS:
#endif
{
BOOL isinclass = FALSE;
int next_state_offset;
PCRE2_SPTR ecode;
#ifdef SUPPORT_WIDE_CHARS
/* An extended class may have a table or a list of single characters,
ranges, or both, and it may be positive or negative. There's a
function that sorts all this out. */
if (codevalue == OP_XCLASS)
{
ecode = code + GET(code, 1);
if (clen > 0)
isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE,
(const uint8_t*)mb->start_code, utf);
}
/* A nested set-based class has internal opcodes for performing
set operations. */
else if (codevalue == OP_ECLASS)
{
ecode = code + GET(code, 1);
if (clen > 0)
isinclass = PRIV(eclass)(c, code + 1 + LINK_SIZE, ecode,
(const uint8_t*)mb->start_code, utf);
}
else
#endif /* SUPPORT_WIDE_CHARS */
/* For a simple class, there is always just a 32-byte table, and we
can set isinclass from it. */
if (codevalue != OP_XCLASS)
{
ecode = code + 1 + (32 / sizeof(PCRE2_UCHAR));
if (clen > 0)
{
isinclass = (c > 255)? (codevalue == OP_NCLASS) :
((((uint8_t *)(code + 1))[c/8] & (1u << (c&7))) != 0);
((((const uint8_t *)(code + 1))[c/8] & (1u << (c&7))) != 0);
}
}
/* An extended class may have a table or a list of single characters,
ranges, or both, and it may be positive or negative. There's a
function that sorts all this out. */
else
{
ecode = code + GET(code, 1);
if (clen > 0) isinclass = PRIV(xclass)(c, code + 1 + LINK_SIZE, utf);
}
/* At this point, isinclass is set for all kinds of class, and ecode
points to the byte after the end of the class. If there is a
quantifier, this is where it will be. */
@ -2784,7 +2781,6 @@ for (;;)
though the other "backtracking verbs" are not supported. */
case OP_FAIL:
forced_fail++; /* Count FAILs for multiple states */
break;
case OP_ASSERT:
@ -3058,7 +3054,7 @@ for (;;)
if (codevalue == OP_BRAPOSZERO)
{
allow_zero = TRUE;
codevalue = *(++code); /* Codevalue will be one of above BRAs */
++code; /* The following opcode will be one of the above BRAs */
}
else allow_zero = FALSE;
@ -3271,18 +3267,12 @@ for (;;)
matches that we are going to find. If partial matching has been requested,
check for appropriate conditions.
The "forced_ fail" variable counts the number of (*F) encountered for the
character. If it is equal to the original active_count (saved in
workspace[1]) it means that (*F) was found on every active state. In this
case we don't want to give a partial match.
The "could_continue" variable is true if a state could have continued but
for the fact that the end of the subject was reached. */
if (new_count <= 0)
{
if (could_continue && /* Some could go on, and */
forced_fail != workspace[1] && /* Not all forced fail & */
( /* either... */
(mb->moptions & PCRE2_PARTIAL_HARD) != 0 /* Hard partial */
|| /* or... */
@ -3438,7 +3428,7 @@ if ((re->flags & PCRE2_MODE_MASK) != PCRE2_CODE_UNIT_WIDTH/8)
/* PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART are match-time flags in the
options variable for this function. Users of PCRE2 who are not calling the
function directly would like to have a way of setting these flags, in the same
way that they can set pcre2_compile() flags like PCRE2_NO_AUTOPOSSESS with
way that they can set pcre2_compile() flags like PCRE2_NO_AUTO_POSSESS with
constructions like (*NO_AUTOPOSSESS). To enable this, (*NOTEMPTY) and
(*NOTEMPTY_ATSTART) set bits in the pattern's "flag" function which can now be
transferred to the options for this function. The bits are guaranteed to be
@ -3528,8 +3518,7 @@ if (mb->match_limit_depth > re->limit_depth)
if (mb->heap_limit > re->limit_heap)
mb->heap_limit = re->limit_heap;
mb->start_code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) +
re->name_count * re->name_entry_size;
mb->start_code = (PCRE2_SPTR)((const uint8_t *)re + re->code_start);
mb->tables = re->tables;
mb->start_subject = subject;
mb->end_subject = end_subject;
@ -3576,7 +3565,9 @@ switch(re->newline_convention)
mb->nltype = NLTYPE_ANYCRLF;
break;
default: return PCRE2_ERROR_INTERNAL;
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
}
/* Check a UTF string for validity if required. For 8-bit and 16-bit strings,
@ -3705,7 +3696,7 @@ for (;;)
these, for testing and for ensuring that all callouts do actually occur.
The optimizations must also be avoided when restarting a DFA match. */
if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 &&
if ((re->optimization_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0 &&
(options & PCRE2_DFA_RESTART) == 0)
{
/* If firstline is TRUE, the start of the match is constrained to the first

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-2023 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -96,7 +96,7 @@ static const unsigned char compile_error_texts[] =
"length of lookbehind assertion is not limited\0"
"a relative value of zero is not allowed\0"
"conditional subpattern contains more than two branches\0"
"assertion expected after (?( or (?(?C)\0"
"atomic assertion expected after (?( or (?(?C)\0"
"digit expected after (?+ or (?-\0"
/* 30 */
"unknown POSIX class name\0"
@ -161,7 +161,7 @@ static const unsigned char compile_error_texts[] =
"using UCP is disabled by the application\0"
"name is too long in (*MARK), (*PRUNE), (*SKIP), or (*THEN)\0"
"character code point value in \\u.... sequence is too large\0"
"digits missing in \\x{} or \\o{} or \\N{U+}\0"
"digits missing after \\x or in \\x{} or \\o{} or \\N{U+}\0"
"syntax error or number too big in (?(VERSION condition\0"
/* 80 */
"internal error: unknown opcode in auto_possessify()\0"
@ -185,10 +185,29 @@ static const unsigned char compile_error_texts[] =
"(*alpha_assertion) not recognized\0"
"script runs require Unicode support, which this version of PCRE2 does not have\0"
"too many capturing groups (maximum 65535)\0"
"atomic assertion expected after (?( or (?(?C)\0"
"octal digit missing after \\0 (PCRE2_EXTRA_NO_BS0 is set)\0"
"\\K is not allowed in lookarounds (but see PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK)\0"
/* 100 */
"branch too long in variable-length lookbehind assertion\0"
"compiled pattern would be longer than the limit set by the application\0"
"octal value given by \\ddd is greater than \\377 (forbidden by PCRE2_EXTRA_PYTHON_OCTAL)\0"
"using callouts is disabled by the application\0"
"PCRE2_EXTRA_TURKISH_CASING require Unicode (UTF or UCP) mode\0"
/* 105 */
"PCRE2_EXTRA_TURKISH_CASING requires UTF in 8-bit mode\0"
"PCRE2_EXTRA_TURKISH_CASING and PCRE2_EXTRA_CASELESS_RESTRICT are not compatible\0"
"extended character class nesting is too deep\0"
"invalid operator in extended character class\0"
"unexpected operator in extended character class (no preceding operand)\0"
/* 110 */
"expected operand after operator in extended character class\0"
"square brackets needed to clarify operator precedence in extended character class\0"
"missing terminating ] for extended character class (note '[' must be escaped under PCRE2_ALT_EXTENDED_CLASS)\0"
"unexpected expression in extended character class (no preceding operator)\0"
"empty expression in extended character class\0"
/* 115 */
"terminating ] with no following closing parenthesis in (?[...]\0"
"unexpected character in (?[...]) extended character class\0"
;
/* Match-time and UTF error texts are in the same format. */
@ -275,6 +294,10 @@ static const unsigned char match_error_texts[] =
"internal error - duplicate substitution match\0"
"PCRE2_MATCH_INVALID_UTF is not supported for DFA matching\0"
"INTERNAL ERROR: invalid substring offset\0"
"feature is not supported by the JIT compiler\0"
"error performing replacement case transformation\0"
/* 70 */
"replacement too large (longer than PCRE2_SIZE)\0"
;
@ -317,7 +340,7 @@ else if (enumber < 0) /* Match or UTF error */
}
else /* Invalid error number */
{
message = (unsigned char *)"\0"; /* Empty message list */
message = (const unsigned char *)"\0"; /* Empty message list */
n = 1;
}

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-2021 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -40,7 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
/* This module contains an internal function that is used to match a Unicode
extended grapheme sequence. It is used by both pcre2_match() and
pcre2_def_match(). However, it is called only when Unicode support is being
pcre2_dfa_match(). However, it is called only when Unicode support is being
compiled. Nevertheless, we provide a dummy function when there is no Unicode
support, because some compilers do not like functionless source files. */
@ -75,7 +75,11 @@ return NULL;
* Match an extended grapheme sequence *
*************************************************/
/*
/* NOTE: The logic contained in this function is replicated in three special-
purpose functions in the pcre2_jit_compile.c module. If the logic below is
changed, they must be kept in step so that the interpreter and the JIT have the
same behaviour.
Arguments:
c the first character
eptr pointer to next character
@ -92,6 +96,7 @@ PCRE2_SPTR
PRIV(extuni)(uint32_t c, PCRE2_SPTR eptr, PCRE2_SPTR start_subject,
PCRE2_SPTR end_subject, BOOL utf, int *xcount)
{
BOOL was_ep_ZWJ = FALSE;
int lgb = UCD_GRAPHBREAK(c);
while (eptr < end_subject)
@ -102,6 +107,12 @@ while (eptr < end_subject)
rgb = UCD_GRAPHBREAK(c);
if ((PRIV(ucp_gbtable)[lgb] & (1u << rgb)) == 0) break;
/* ZWJ followed by Extended Pictographic is allowed only if the ZWJ was
preceded by Extended Pictographic. */
if (lgb == ucp_gbZWJ && rgb == ucp_gbExtended_Pictographic && !was_ep_ZWJ)
break;
/* Not breaking between Regional Indicators is allowed only if there
are an even number of preceding RIs. */
@ -129,12 +140,15 @@ while (eptr < end_subject)
if ((ricount & 1) != 0) break; /* Grapheme break required */
}
/* If Extend or ZWJ follows Extended_Pictographic, do not update lgb; this
allows any number of them before a following Extended_Pictographic. */
/* Set a flag when ZWJ follows Extended Pictographic (with optional Extend in
between; see next statement). */
if ((rgb != ucp_gbExtend && rgb != ucp_gbZWJ) ||
lgb != ucp_gbExtended_Pictographic)
lgb = rgb;
was_ep_ZWJ = (lgb == ucp_gbExtended_Pictographic && rgb == ucp_gbZWJ);
/* If Extend follows Extended_Pictographic, do not update lgb; this allows
any number of them before a following ZWJ. */
if (rgb != ucp_gbExtend || lgb != ucp_gbExtended_Pictographic) lgb = rgb;
eptr += len;
if (xcount != NULL) *xcount += 1;

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-2023 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -76,18 +76,19 @@ for (;;)
if (c == OP_END) return NULL;
/* XCLASS is used for classes that cannot be represented just by a bit map.
This includes negated single high-valued characters. CALLOUT_STR is used for
callouts with string arguments. In both cases the length in the table is
This includes negated single high-valued characters. ECLASS is used for
classes that use set operations internally. CALLOUT_STR is used for
callouts with string arguments. In each case the length in the table is
zero; the actual length is stored in the compiled code. */
if (c == OP_XCLASS) code += GET(code, 1);
else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE);
if (c == OP_XCLASS || c == OP_ECLASS) code += GET(code, 1);
else if (c == OP_CALLOUT_STR) code += GET(code, 1 + 2*LINK_SIZE);
/* Handle lookbehind */
else if (c == OP_REVERSE || c == OP_VREVERSE)
{
if (number < 0) return (PCRE2_UCHAR *)code;
if (number < 0) return code;
code += PRIV(OP_lengths)[c];
}
@ -97,7 +98,7 @@ for (;;)
c == OP_CBRAPOS || c == OP_SCBRAPOS)
{
int n = (int)GET2(code, 1+LINK_SIZE);
if (n == number) return (PCRE2_UCHAR *)code;
if (n == number) return code;
code += PRIV(OP_lengths)[c];
}

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-2023 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -88,6 +88,12 @@ typedef int BOOL;
#define TRUE 1
#endif
/* Helper macro for static (compile-time) assertions. Can be used inside
functions, or at the top-level of a file. */
#define STATIC_ASSERT_JOIN(a,b) a ## b
#define STATIC_ASSERT(cond, msg) \
typedef int STATIC_ASSERT_JOIN(static_assertion_,msg)[(cond)?1:-1]
/* Valgrind (memcheck) support */
#ifdef SUPPORT_VALGRIND
@ -523,29 +529,29 @@ start/end of string field names are. */
three must not be changed, because whichever is set is actually the number of
bytes in a code unit in that mode. */
#define PCRE2_MODE8 0x00000001 /* compiled in 8 bit mode */
#define PCRE2_MODE16 0x00000002 /* compiled in 16 bit mode */
#define PCRE2_MODE32 0x00000004 /* compiled in 32 bit mode */
#define PCRE2_FIRSTSET 0x00000010 /* first_code unit is set */
#define PCRE2_FIRSTCASELESS 0x00000020 /* caseless first code unit */
#define PCRE2_FIRSTMAPSET 0x00000040 /* bitmap of first code units is set */
#define PCRE2_LASTSET 0x00000080 /* last code unit is set */
#define PCRE2_LASTCASELESS 0x00000100 /* caseless last code unit */
#define PCRE2_STARTLINE 0x00000200 /* start after \n for multiline */
#define PCRE2_JCHANGED 0x00000400 /* j option used in pattern */
#define PCRE2_HASCRORLF 0x00000800 /* explicit \r or \n in pattern */
#define PCRE2_HASTHEN 0x00001000 /* pattern contains (*THEN) */
#define PCRE2_MATCH_EMPTY 0x00002000 /* pattern can match empty string */
#define PCRE2_BSR_SET 0x00004000 /* BSR was set in the pattern */
#define PCRE2_NL_SET 0x00008000 /* newline was set in the pattern */
#define PCRE2_NOTEMPTY_SET 0x00010000 /* (*NOTEMPTY) used ) keep */
#define PCRE2_NE_ATST_SET 0x00020000 /* (*NOTEMPTY_ATSTART) used) together */
#define PCRE2_DEREF_TABLES 0x00040000 /* release character tables */
#define PCRE2_NOJIT 0x00080000 /* (*NOJIT) used */
#define PCRE2_HASBKPORX 0x00100000 /* contains \P, \p, or \X */
#define PCRE2_DUPCAPUSED 0x00200000 /* contains (?| */
#define PCRE2_HASBKC 0x00400000 /* contains \C */
#define PCRE2_HASACCEPT 0x00800000 /* contains (*ACCEPT) */
#define PCRE2_MODE8 0x00000001u /* compiled in 8 bit mode */
#define PCRE2_MODE16 0x00000002u /* compiled in 16 bit mode */
#define PCRE2_MODE32 0x00000004u /* compiled in 32 bit mode */
#define PCRE2_FIRSTSET 0x00000010u /* first_code unit is set */
#define PCRE2_FIRSTCASELESS 0x00000020u /* caseless first code unit */
#define PCRE2_FIRSTMAPSET 0x00000040u /* bitmap of first code units is set */
#define PCRE2_LASTSET 0x00000080u /* last code unit is set */
#define PCRE2_LASTCASELESS 0x00000100u /* caseless last code unit */
#define PCRE2_STARTLINE 0x00000200u /* start after \n for multiline */
#define PCRE2_JCHANGED 0x00000400u /* j option used in pattern */
#define PCRE2_HASCRORLF 0x00000800u /* explicit \r or \n in pattern */
#define PCRE2_HASTHEN 0x00001000u /* pattern contains (*THEN) */
#define PCRE2_MATCH_EMPTY 0x00002000u /* pattern can match empty string */
#define PCRE2_BSR_SET 0x00004000u /* BSR was set in the pattern */
#define PCRE2_NL_SET 0x00008000u /* newline was set in the pattern */
#define PCRE2_NOTEMPTY_SET 0x00010000u /* (*NOTEMPTY) used ) keep */
#define PCRE2_NE_ATST_SET 0x00020000u /* (*NOTEMPTY_ATSTART) used) together */
#define PCRE2_DEREF_TABLES 0x00040000u /* release character tables */
#define PCRE2_NOJIT 0x00080000u /* (*NOJIT) used */
#define PCRE2_HASBKPORX 0x00100000u /* contains \P, \p, or \X */
#define PCRE2_DUPCAPUSED 0x00200000u /* contains (?| */
#define PCRE2_HASBKC 0x00400000u /* contains \C */
#define PCRE2_HASACCEPT 0x00800000u /* contains (*ACCEPT) */
#define PCRE2_MODE_MASK (PCRE2_MODE8 | PCRE2_MODE16 | PCRE2_MODE32)
@ -574,6 +580,16 @@ modes. */
#define REQ_CU_MAX 2000
#endif
/* The maximum nesting depth for Unicode character class sets.
Currently fixed. Warning: the interpreter relies on this so it can encode
the operand stack in a uint32_t. A nesting limit of 15 implies (15*2+1)=31
stack operands required, due to the fact that we have two (and only two)
levels of operator precedence. In the UTS#18 syntax, you can write 'x&&y[z]'
and in Perl syntax you can write '(?[ x - y & (z) ])', both of which imply
pushing the match results for x & y to the stack. */
#define ECLASS_NEST_LIMIT 15
/* Offsets for the bitmap tables in the cbits set of tables. Each table
contains a set of bits for a class map. Some classes are built by combining
these tables. */
@ -609,6 +625,13 @@ total length of the tables. */
#define ctypes_offset (cbits_offset + cbit_length) /* Character types */
#define TABLES_LENGTH (ctypes_offset + 256)
/* Private flags used in compile_context.optimization_flags */
#define PCRE2_OPTIM_AUTO_POSSESS 0x00000001u
#define PCRE2_OPTIM_DOTSTAR_ANCHOR 0x00000002u
#define PCRE2_OPTIM_START_OPTIMIZE 0x00000004u
#define PCRE2_OPTIMIZATION_ALL 0x00000007u
/* -------------------- Character and string names ------------------------ */
@ -915,6 +938,7 @@ a positive value. */
#define STRING_naplb0 "naplb\0"
#define STRING_nla0 "nla\0"
#define STRING_nlb0 "nlb\0"
#define STRING_scs0 "scs\0"
#define STRING_sr0 "sr\0"
#define STRING_asr0 "asr\0"
#define STRING_positive_lookahead0 "positive_lookahead\0"
@ -925,6 +949,7 @@ a positive value. */
#define STRING_negative_lookbehind0 "negative_lookbehind\0"
#define STRING_script_run0 "script_run\0"
#define STRING_atomic_script_run "atomic_script_run"
#define STRING_scan_substring0 "scan_substring\0"
#define STRING_alpha0 "alpha\0"
#define STRING_lower0 "lower\0"
@ -965,6 +990,8 @@ a positive value. */
#define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)"
#define STRING_NOTEMPTY_RIGHTPAR "NOTEMPTY)"
#define STRING_NOTEMPTY_ATSTART_RIGHTPAR "NOTEMPTY_ATSTART)"
#define STRING_CASELESS_RESTRICT_RIGHTPAR "CASELESS_RESTRICT)"
#define STRING_TURKISH_CASING_RIGHTPAR "TURKISH_CASING)"
#define STRING_LIMIT_HEAP_EQ "LIMIT_HEAP="
#define STRING_LIMIT_MATCH_EQ "LIMIT_MATCH="
#define STRING_LIMIT_DEPTH_EQ "LIMIT_DEPTH="
@ -1216,6 +1243,7 @@ only. */
#define STRING_naplb0 STR_n STR_a STR_p STR_l STR_b "\0"
#define STRING_nla0 STR_n STR_l STR_a "\0"
#define STRING_nlb0 STR_n STR_l STR_b "\0"
#define STRING_scs0 STR_s STR_c STR_s "\0"
#define STRING_sr0 STR_s STR_r "\0"
#define STRING_asr0 STR_a STR_s STR_r "\0"
#define STRING_positive_lookahead0 STR_p STR_o STR_s STR_i STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_a STR_h STR_e STR_a STR_d "\0"
@ -1226,6 +1254,7 @@ only. */
#define STRING_negative_lookbehind0 STR_n STR_e STR_g STR_a STR_t STR_i STR_v STR_e STR_UNDERSCORE STR_l STR_o STR_o STR_k STR_b STR_e STR_h STR_i STR_n STR_d "\0"
#define STRING_script_run0 STR_s STR_c STR_r STR_i STR_p STR_t STR_UNDERSCORE STR_r STR_u STR_n "\0"
#define STRING_atomic_script_run STR_a STR_t STR_o STR_m STR_i STR_c STR_UNDERSCORE STR_s STR_c STR_r STR_i STR_p STR_t STR_UNDERSCORE STR_r STR_u STR_n
#define STRING_scan_substring0 STR_s STR_c STR_a STR_n STR_UNDERSCORE STR_s STR_u STR_b STR_s STR_t STR_r STR_i STR_n STR_g "\0"
#define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0"
#define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0"
@ -1266,6 +1295,8 @@ only. */
#define STRING_NO_START_OPT_RIGHTPAR STR_N STR_O STR_UNDERSCORE STR_S STR_T STR_A STR_R STR_T STR_UNDERSCORE STR_O STR_P STR_T STR_RIGHT_PARENTHESIS
#define STRING_NOTEMPTY_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_RIGHT_PARENTHESIS
#define STRING_NOTEMPTY_ATSTART_RIGHTPAR STR_N STR_O STR_T STR_E STR_M STR_P STR_T STR_Y STR_UNDERSCORE STR_A STR_T STR_S STR_T STR_A STR_R STR_T STR_RIGHT_PARENTHESIS
#define STRING_CASELESS_RESTRICT_RIGHTPAR STR_C STR_A STR_S STR_E STR_L STR_E STR_S STR_S STR_UNDERSCORE STR_R STR_E STR_S STR_T STR_R STR_I STR_C STR_T STR_RIGHT_PARENTHESIS
#define STRING_TURKISH_CASING_RIGHTPAR STR_T STR_U STR_R STR_K STR_I STR_S STR_H STR_UNDERSCORE STR_C STR_A STR_S STR_I STR_N STR_G STR_RIGHT_PARENTHESIS
#define STRING_LIMIT_HEAP_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_H STR_E STR_A STR_P STR_EQUALS_SIGN
#define STRING_LIMIT_MATCH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_M STR_A STR_T STR_C STR_H STR_EQUALS_SIGN
#define STRING_LIMIT_DEPTH_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_D STR_E STR_P STR_T STR_H STR_EQUALS_SIGN
@ -1290,21 +1321,22 @@ only. */
changed, the autopossessifying table in pcre2_auto_possess.c must be updated to
match. */
#define PT_ANY 0 /* Any property - matches all chars */
#define PT_LAMP 1 /* L& - the union of Lu, Ll, Lt */
#define PT_GC 2 /* Specified general characteristic (e.g. L) */
#define PT_PC 3 /* Specified particular characteristic (e.g. Lu) */
#define PT_SC 4 /* Script only (e.g. Han) */
#define PT_SCX 5 /* Script extensions (includes SC) */
#define PT_ALNUM 6 /* Alphanumeric - the union of L and N */
#define PT_SPACE 7 /* Perl space - general category Z plus 9,10,12,13 */
#define PT_PXSPACE 8 /* POSIX space - Z plus 9,10,11,12,13 */
#define PT_WORD 9 /* Word - L, N, Mn, or Pc */
#define PT_CLIST 10 /* Pseudo-property: match character list */
#define PT_UCNC 11 /* Universal Character nameable character */
#define PT_BIDICL 12 /* Specified bidi class */
#define PT_BOOL 13 /* Boolean property */
#define PT_TABSIZE 14 /* Size of square table for autopossessify tests */
#define PT_LAMP 0 /* L& - the union of Lu, Ll, Lt */
#define PT_GC 1 /* Specified general characteristic (e.g. L) */
#define PT_PC 2 /* Specified particular characteristic (e.g. Lu) */
#define PT_SC 3 /* Script only (e.g. Han) */
#define PT_SCX 4 /* Script extensions (includes SC) */
#define PT_ALNUM 5 /* Alphanumeric - the union of L and N */
#define PT_SPACE 6 /* Perl space - general category Z plus 9,10,12,13 */
#define PT_PXSPACE 7 /* POSIX space - Z plus 9,10,11,12,13 */
#define PT_WORD 8 /* Word - L, N, Mn, or Pc */
#define PT_CLIST 9 /* Pseudo-property: match character list */
#define PT_UCNC 10 /* Universal Character nameable character */
#define PT_BIDICL 11 /* Specified bidi class */
#define PT_BOOL 12 /* Boolean property */
#define PT_ANY 13 /* Must be the last entry!
Any property - matches all chars */
#define PT_TABSIZE PT_ANY /* Size of square table for autopossessify tests */
/* The following special properties are used only in XCLASS items, when POSIX
classes are specified and PCRE2_UCP is set - in other words, for Unicode
@ -1334,6 +1366,94 @@ contain characters with values greater than 255. */
#define XCL_RANGE 2 /* A range (two multibyte chars) follows */
#define XCL_PROP 3 /* Unicode property (2-byte property code follows) */
#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */
/* This value represents the beginning of character lists. The value
is 16 bit long, and stored as a high and low byte pair in 8 bit mode.
The lower 12 bit contains information about character lists (see later). */
#define XCL_LIST (sizeof(PCRE2_UCHAR) == 1 ? 0x10 : 0x1000)
/* When a character class contains many characters/ranges,
they are stored in character lists. There are four character
lists which contain characters/ranges within a given range.
The name, character range and item size for each list:
Low16 [0x100 - 0x7fff] 16 bit items
High16 [0x8000 - 0xffff] 16 bit items
Low32 [0x10000 - 0x7fffffff] 32 bit items
High32 [0x80000000 - 0xffffffff] 32 bit items
The Low32 character list is used only when utf encoding or 32 bit
character width is enabled, and the High32 character is used only
when 32 bit character width is enabled.
Each character list contain items. The lowest bit represents that
an item is the beginning of a range (bit is cleared), or not (bit
is set). The other bits represent the character shifted left by
one, so its highest bit is discarded. Due to the layout of character
lists, the highest bit of a character is always known:
Low16 and Low32: the highest bit is always zero
High16 and High32: the highest bit is always one
The items are ordered in increasing order, so binary search can be
used to find the lower bound of an input character. The lower bound
is the highest item, which value is less or equal than the input
character. If the lower bit of the item is cleard, or the character
stored in the item equals to the input character, the input
character is in the character list. */
/* Character list constants. */
#define XCL_CHAR_LIST_LOW_16_START 0x100
#define XCL_CHAR_LIST_LOW_16_END 0x7fff
#define XCL_CHAR_LIST_LOW_16_ADD 0x0
#define XCL_CHAR_LIST_HIGH_16_START 0x8000
#define XCL_CHAR_LIST_HIGH_16_END 0xffff
#define XCL_CHAR_LIST_HIGH_16_ADD 0x8000
#define XCL_CHAR_LIST_LOW_32_START 0x10000
#define XCL_CHAR_LIST_LOW_32_END 0x7fffffff
#define XCL_CHAR_LIST_LOW_32_ADD 0x0
#define XCL_CHAR_LIST_HIGH_32_START 0x80000000
#define XCL_CHAR_LIST_HIGH_32_END 0xffffffff
#define XCL_CHAR_LIST_HIGH_32_ADD 0x80000000
/* Mask for getting the descriptors of character list ranges.
Each descriptor has XCL_TYPE_BIT_LEN bits, and can be processed
by XCL_BEGIN_WITH_RANGE and XCL_ITEM_COUNT_MASK macros. */
#define XCL_TYPE_MASK 0xfff
#define XCL_TYPE_BIT_LEN 3
/* If this bit is set, the first item of the character list is the
end of a range, which started before the starting character of the
character list. */
#define XCL_BEGIN_WITH_RANGE 0x4
/* Number of items in the character list: 0, 1, or 2. The value 3
represents that the item count is stored at the begining of the
character list. The item count has the same width as the items
in the character list (e.g. 16 bit for Low16 and High16 lists). */
#define XCL_ITEM_COUNT_MASK 0x3
/* Shift and flag for constructing character list items. The XCL_CHAR_END
is set, when the item is not the beginning of a range. The XCL_CHAR_SHIFT
can be used to encode / decode the character value stored in an item. */
#define XCL_CHAR_END 0x1
#define XCL_CHAR_SHIFT 1
/* Flag bits for an extended class (OP_ECLASS), which is used for complex
character matches such as [\p{Greek} && \p{Ll}]. */
#define ECL_MAP 0x01 /* Flag: a 32-byte map is present */
/* Type tags for the items stored in an extended class (OP_ECLASS). These items
follow the OP_ECLASS's flag char and bitmap, and represent a Reverse Polish
Notation list of operands and operators manipulating a stack of bits. */
#define ECL_AND 1 /* Pop two from the stack, AND, and push result. */
#define ECL_OR 2 /* Pop two from the stack, OR, and push result. */
#define ECL_XOR 3 /* Pop two from the stack, XOR, and push result. */
#define ECL_NOT 4 /* Pop one from the stack, NOT, and push result. */
#define ECL_XCLASS 5 /* XCLASS nested within ECLASS; match and push result. */
#define ECL_ANY 6 /* Temporary, only used during compilation. */
#define ECL_NONE 7 /* Temporary, only used during compilation. */
/* These are escaped items that aren't just an encoding of a particular data
value such as \n. They must have non-zero values, as check_escape() returns 0
@ -1555,102 +1675,105 @@ enum {
character > 255 is encountered. */
OP_XCLASS, /* 112 Extended class for handling > 255 chars within the
class. This does both positive and negative. */
OP_REF, /* 113 Match a back reference, casefully */
OP_REFI, /* 114 Match a back reference, caselessly */
OP_DNREF, /* 115 Match a duplicate name backref, casefully */
OP_DNREFI, /* 116 Match a duplicate name backref, caselessly */
OP_RECURSE, /* 117 Match a numbered subpattern (possibly recursive) */
OP_CALLOUT, /* 118 Call out to external function if provided */
OP_CALLOUT_STR, /* 119 Call out with string argument */
OP_ECLASS, /* 113 Really-extended class, for handling logical
expressions computed over characters. */
OP_REF, /* 114 Match a back reference, casefully */
OP_REFI, /* 115 Match a back reference, caselessly */
OP_DNREF, /* 116 Match a duplicate name backref, casefully */
OP_DNREFI, /* 117 Match a duplicate name backref, caselessly */
OP_RECURSE, /* 118 Match a numbered subpattern (possibly recursive) */
OP_CALLOUT, /* 119 Call out to external function if provided */
OP_CALLOUT_STR, /* 120 Call out with string argument */
OP_ALT, /* 120 Start of alternation */
OP_KET, /* 121 End of group that doesn't have an unbounded repeat */
OP_KETRMAX, /* 122 These two must remain together and in this */
OP_KETRMIN, /* 123 order. They are for groups the repeat for ever. */
OP_KETRPOS, /* 124 Possessive unlimited repeat. */
OP_ALT, /* 121 Start of alternation */
OP_KET, /* 122 End of group that doesn't have an unbounded repeat */
OP_KETRMAX, /* 123 These two must remain together and in this */
OP_KETRMIN, /* 124 order. They are for groups the repeat for ever. */
OP_KETRPOS, /* 125 Possessive unlimited repeat. */
/* The assertions must come before BRA, CBRA, ONCE, and COND. */
OP_REVERSE, /* 125 Move pointer back - used in lookbehind assertions */
OP_VREVERSE, /* 126 Move pointer back - variable */
OP_ASSERT, /* 127 Positive lookahead */
OP_ASSERT_NOT, /* 128 Negative lookahead */
OP_ASSERTBACK, /* 129 Positive lookbehind */
OP_ASSERTBACK_NOT, /* 130 Negative lookbehind */
OP_ASSERT_NA, /* 131 Positive non-atomic lookahead */
OP_ASSERTBACK_NA, /* 132 Positive non-atomic lookbehind */
OP_REVERSE, /* 126 Move pointer back - used in lookbehind assertions */
OP_VREVERSE, /* 127 Move pointer back - variable */
OP_ASSERT, /* 128 Positive lookahead */
OP_ASSERT_NOT, /* 129 Negative lookahead */
OP_ASSERTBACK, /* 130 Positive lookbehind */
OP_ASSERTBACK_NOT, /* 131 Negative lookbehind */
OP_ASSERT_NA, /* 132 Positive non-atomic lookahead */
OP_ASSERTBACK_NA, /* 133 Positive non-atomic lookbehind */
OP_ASSERT_SCS, /* 134 Scan substring */
/* ONCE, SCRIPT_RUN, BRA, BRAPOS, CBRA, CBRAPOS, and COND must come
immediately after the assertions, with ONCE first, as there's a test for >=
ONCE for a subpattern that isn't an assertion. The POS versions must
immediately follow the non-POS versions in each case. */
OP_ONCE, /* 133 Atomic group, contains captures */
OP_SCRIPT_RUN, /* 134 Non-capture, but check characters' scripts */
OP_BRA, /* 135 Start of non-capturing bracket */
OP_BRAPOS, /* 136 Ditto, with unlimited, possessive repeat */
OP_CBRA, /* 137 Start of capturing bracket */
OP_CBRAPOS, /* 138 Ditto, with unlimited, possessive repeat */
OP_COND, /* 139 Conditional group */
OP_ONCE, /* 135 Atomic group, contains captures */
OP_SCRIPT_RUN, /* 136 Non-capture, but check characters' scripts */
OP_BRA, /* 137 Start of non-capturing bracket */
OP_BRAPOS, /* 138 Ditto, with unlimited, possessive repeat */
OP_CBRA, /* 139 Start of capturing bracket */
OP_CBRAPOS, /* 140 Ditto, with unlimited, possessive repeat */
OP_COND, /* 141 Conditional group */
/* These five must follow the previous five, in the same order. There's a
check for >= SBRA to distinguish the two sets. */
OP_SBRA, /* 140 Start of non-capturing bracket, check empty */
OP_SBRAPOS, /* 141 Ditto, with unlimited, possessive repeat */
OP_SCBRA, /* 142 Start of capturing bracket, check empty */
OP_SCBRAPOS, /* 143 Ditto, with unlimited, possessive repeat */
OP_SCOND, /* 144 Conditional group, check empty */
OP_SBRA, /* 142 Start of non-capturing bracket, check empty */
OP_SBRAPOS, /* 143 Ditto, with unlimited, possessive repeat */
OP_SCBRA, /* 144 Start of capturing bracket, check empty */
OP_SCBRAPOS, /* 145 Ditto, with unlimited, possessive repeat */
OP_SCOND, /* 146 Conditional group, check empty */
/* The next two pairs must (respectively) be kept together. */
OP_CREF, /* 145 Used to hold a capture number as condition */
OP_DNCREF, /* 146 Used to point to duplicate names as a condition */
OP_RREF, /* 147 Used to hold a recursion number as condition */
OP_DNRREF, /* 148 Used to point to duplicate names as a condition */
OP_FALSE, /* 149 Always false (used by DEFINE and VERSION) */
OP_TRUE, /* 150 Always true (used by VERSION) */
OP_CREF, /* 147 Used to hold a capture number as condition */
OP_DNCREF, /* 148 Used to point to duplicate names as a condition */
OP_RREF, /* 149 Used to hold a recursion number as condition */
OP_DNRREF, /* 150 Used to point to duplicate names as a condition */
OP_FALSE, /* 151 Always false (used by DEFINE and VERSION) */
OP_TRUE, /* 152 Always true (used by VERSION) */
OP_BRAZERO, /* 151 These two must remain together and in this */
OP_BRAMINZERO, /* 152 order. */
OP_BRAPOSZERO, /* 153 */
OP_BRAZERO, /* 153 These two must remain together and in this */
OP_BRAMINZERO, /* 154 order. */
OP_BRAPOSZERO, /* 155 */
/* These are backtracking control verbs */
OP_MARK, /* 154 always has an argument */
OP_PRUNE, /* 155 */
OP_PRUNE_ARG, /* 156 same, but with argument */
OP_SKIP, /* 157 */
OP_SKIP_ARG, /* 158 same, but with argument */
OP_THEN, /* 159 */
OP_THEN_ARG, /* 160 same, but with argument */
OP_COMMIT, /* 161 */
OP_COMMIT_ARG, /* 162 same, but with argument */
OP_MARK, /* 156 always has an argument */
OP_PRUNE, /* 157 */
OP_PRUNE_ARG, /* 158 same, but with argument */
OP_SKIP, /* 159 */
OP_SKIP_ARG, /* 160 same, but with argument */
OP_THEN, /* 161 */
OP_THEN_ARG, /* 162 same, but with argument */
OP_COMMIT, /* 163 */
OP_COMMIT_ARG, /* 164 same, but with argument */
/* These are forced failure and success verbs. FAIL and ACCEPT do accept an
argument, but these cases can be compiled as, for example, (*MARK:X)(*FAIL)
without the need for a special opcode. */
OP_FAIL, /* 163 */
OP_ACCEPT, /* 164 */
OP_ASSERT_ACCEPT, /* 165 Used inside assertions */
OP_CLOSE, /* 166 Used before OP_ACCEPT to close open captures */
OP_FAIL, /* 165 */
OP_ACCEPT, /* 166 */
OP_ASSERT_ACCEPT, /* 167 Used inside assertions */
OP_CLOSE, /* 168 Used before OP_ACCEPT to close open captures */
/* This is used to skip a subpattern with a {0} quantifier */
OP_SKIPZERO, /* 167 */
OP_SKIPZERO, /* 169 */
/* This is used to identify a DEFINE group during compilation so that it can
be checked for having only one branch. It is changed to OP_FALSE before
compilation finishes. */
OP_DEFINE, /* 168 */
OP_DEFINE, /* 170 */
/* These opcodes replace their normal counterparts in UCP mode when
PCRE2_EXTRA_ASCII_BSW is not set. */
OP_NOT_UCP_WORD_BOUNDARY, /* 169 */
OP_UCP_WORD_BOUNDARY, /* 170 */
OP_NOT_UCP_WORD_BOUNDARY, /* 171 */
OP_UCP_WORD_BOUNDARY, /* 172 */
/* This is not an opcode, but is used to check that tables indexed by opcode
are the correct length, in order to catch updating errors - there have been
@ -1693,19 +1816,21 @@ some cases doesn't actually use these names at all). */
"*+","++", "?+", "{", \
"*", "*?", "+", "+?", "?", "??", "{", "{", \
"*+","++", "?+", "{", \
"class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \
"class", "nclass", "xclass", "eclass", \
"Ref", "Refi", "DnRef", "DnRefi", \
"Recurse", "Callout", "CalloutStr", \
"Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \
"Reverse", "VReverse", "Assert", "Assert not", \
"Assert back", "Assert back not", \
"Non-atomic assert", "Non-atomic assert back", \
"Scan substring", \
"Once", \
"Script run", \
"Bra", "BraPos", "CBra", "CBraPos", \
"Cond", \
"SBra", "SBraPos", "SCBra", "SCBraPos", \
"SCond", \
"Cond ref", "Cond dnref", "Cond rec", "Cond dnrec", \
"Capture ref", "Capture dnref", "Cond rec", "Cond dnrec", \
"Cond false", "Cond true", \
"Brazero", "Braminzero", "Braposzero", \
"*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \
@ -1766,10 +1891,11 @@ in UTF-8 mode. The code that uses this table must know about such things. */
1+(32/sizeof(PCRE2_UCHAR)), /* CLASS */ \
1+(32/sizeof(PCRE2_UCHAR)), /* NCLASS */ \
0, /* XCLASS - variable length */ \
0, /* ECLASS - variable length */ \
1+IMM2_SIZE, /* REF */ \
1+IMM2_SIZE, /* REFI */ \
1+IMM2_SIZE+1, /* REFI */ \
1+2*IMM2_SIZE, /* DNREF */ \
1+2*IMM2_SIZE, /* DNREFI */ \
1+2*IMM2_SIZE+1, /* DNREFI */ \
1+LINK_SIZE, /* RECURSE */ \
1+2*LINK_SIZE+1, /* CALLOUT */ \
0, /* CALLOUT_STR - variable length */ \
@ -1786,6 +1912,7 @@ in UTF-8 mode. The code that uses this table must know about such things. */
1+LINK_SIZE, /* Assert behind not */ \
1+LINK_SIZE, /* NA Assert */ \
1+LINK_SIZE, /* NA Assert behind */ \
1+LINK_SIZE, /* Scan substring */ \
1+LINK_SIZE, /* ONCE */ \
1+LINK_SIZE, /* SCRIPT_RUN */ \
1+LINK_SIZE, /* BRA */ \
@ -1815,6 +1942,11 @@ in UTF-8 mode. The code that uses this table must know about such things. */
#define RREF_ANY 0xffff
/* Constants used by OP_REFI and OP_DNREFI to control matching behaviour. */
#define REFI_FLAG_CASELESS_RESTRICT 0x1
#define REFI_FLAG_TURKISH_CASING 0x2
/* ---------- Private structures that are mode-independent. ---------- */
@ -1890,6 +2022,14 @@ typedef struct {
#define UCD_SCRIPTX(ch) UCD_SCRIPTX_PROP(GET_UCD(ch))
#define UCD_BPROPS(ch) UCD_BPROPS_PROP(GET_UCD(ch))
#define UCD_BIDICLASS(ch) UCD_BIDICLASS_PROP(GET_UCD(ch))
#define UCD_ANY_I(ch) \
/* match any of the four characters 'i', 'I', U+0130, U+0131 */ \
(((uint32_t)(ch) | 0x20u) == 0x69u || ((uint32_t)(ch) | 1u) == 0x0131u)
#define UCD_DOTTED_I(ch) \
((uint32_t)(ch) == 0x69u || (uint32_t)(ch) == 0x0130u)
#define UCD_FOLD_I_TURKISH(ch) \
((uint32_t)(ch) == 0x0130u ? 0x69u : \
(uint32_t)(ch) == 0x49u ? 0x0131u : (uint32_t)(ch))
/* The "scriptx" and bprops fields contain offsets into vectors of 32-bit words
that form a bitmap representing a list of scripts or boolean properties. These
@ -1955,6 +2095,9 @@ extern const uint8_t PRIV(utf8_table4)[];
#define _pcre2_vspace_list PCRE2_SUFFIX(_pcre2_vspace_list_)
#define _pcre2_ucd_boolprop_sets PCRE2_SUFFIX(_pcre2_ucd_boolprop_sets_)
#define _pcre2_ucd_caseless_sets PCRE2_SUFFIX(_pcre2_ucd_caseless_sets_)
#define _pcre2_ucd_turkish_dotted_i_caseset PCRE2_SUFFIX(_pcre2_ucd_turkish_dotted_i_caseset_)
#define _pcre2_ucd_nocase_ranges PCRE2_SUFFIX(_pcre2_ucd_nocase_ranges_)
#define _pcre2_ucd_nocase_ranges_size PCRE2_SUFFIX(_pcre2_ucd_nocase_ranges_size_)
#define _pcre2_ucd_digit_sets PCRE2_SUFFIX(_pcre2_ucd_digit_sets_)
#define _pcre2_ucd_script_sets PCRE2_SUFFIX(_pcre2_ucd_script_sets_)
#define _pcre2_ucd_records PCRE2_SUFFIX(_pcre2_ucd_records_)
@ -1971,14 +2114,17 @@ extern const uint8_t PRIV(utf8_table4)[];
extern const uint8_t PRIV(OP_lengths)[];
extern const uint32_t PRIV(callout_end_delims)[];
extern const uint32_t PRIV(callout_start_delims)[];
extern const pcre2_compile_context PRIV(default_compile_context);
extern const pcre2_convert_context PRIV(default_convert_context);
extern const pcre2_match_context PRIV(default_match_context);
extern pcre2_compile_context PRIV(default_compile_context);
extern pcre2_convert_context PRIV(default_convert_context);
extern pcre2_match_context PRIV(default_match_context);
extern const uint8_t PRIV(default_tables)[];
extern const uint32_t PRIV(hspace_list)[];
extern const uint32_t PRIV(vspace_list)[];
extern const uint32_t PRIV(ucd_boolprop_sets)[];
extern const uint32_t PRIV(ucd_caseless_sets)[];
extern const uint32_t PRIV(ucd_turkish_dotted_i_caseset);
extern const uint32_t PRIV(ucd_nocase_ranges)[];
extern const uint32_t PRIV(ucd_nocase_ranges_size);
extern const uint32_t PRIV(ucd_digit_sets)[];
extern const uint32_t PRIV(ucd_script_sets)[];
extern const ucd_record PRIV(ucd_records)[];
@ -2039,11 +2185,12 @@ is available. */
#define _pcre2_valid_utf PCRE2_SUFFIX(_pcre2_valid_utf_)
#define _pcre2_was_newline PCRE2_SUFFIX(_pcre2_was_newline_)
#define _pcre2_xclass PCRE2_SUFFIX(_pcre2_xclass_)
#define _pcre2_eclass PCRE2_SUFFIX(_pcre2_eclass_)
extern int _pcre2_auto_possessify(PCRE2_UCHAR *,
const compile_block *);
extern int _pcre2_check_escape(PCRE2_SPTR *, PCRE2_SPTR, uint32_t *,
int *, uint32_t, uint32_t, BOOL, compile_block *);
int *, uint32_t, uint32_t, uint32_t, BOOL, compile_block *);
extern PCRE2_SPTR _pcre2_extuni(uint32_t, PCRE2_SPTR, PCRE2_SPTR, PCRE2_SPTR,
BOOL, int *);
extern PCRE2_SPTR _pcre2_find_bracket(PCRE2_SPTR, BOOL, int);
@ -2066,7 +2213,9 @@ extern int _pcre2_study(pcre2_real_code *);
extern int _pcre2_valid_utf(PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE *);
extern BOOL _pcre2_was_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR,
uint32_t *, BOOL);
extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, BOOL);
extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, const uint8_t *, BOOL);
extern BOOL _pcre2_eclass(uint32_t, PCRE2_SPTR, PCRE2_SPTR,
const uint8_t *, BOOL);
/* This function is needed only when memmove() is not available. */
@ -2079,6 +2228,8 @@ extern void * _pcre2_memmove(void *, const void *, size_t);
extern BOOL PRIV(ckd_smul)(PCRE2_SIZE *, int, int);
#include "pcre2_util.h"
#endif /* PCRE2_INTERNAL_H_IDEMPOTENT_GUARD */
/* End of pcre2_internal.h */

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-2023 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -47,7 +47,7 @@ to have access to the hidden structures at all supported widths.
Some of the mode-dependent macros are required at different widths for
different parts of the pcre2test code (in particular, the included
pcre_printint.c file). We undefine them here so that they can be re-defined for
pcre2_printint.c file). We undefine them here so that they can be re-defined for
multiple inclusions. Not all of these are used in pcre2test, but it's easier
just to undefine them all. */
@ -435,7 +435,7 @@ UTF-16 mode. */
c = *eptr; \
if ((c & 0xfc00u) == 0xd800u) GETUTF16LEN(c, eptr, len);
/* Get the next UTF-816character, testing for UTF-16 mode, not advancing the
/* Get the next UTF-16 character, testing for UTF-16 mode, not advancing the
pointer, incrementing length if there is a low surrogate. This is called when
we do not know if we are in UTF-16 mode. */
@ -556,6 +556,11 @@ code that uses them is simpler because it assumes this. */
/* The real general context structure. At present it holds only data for custom
memory control. */
/* WARNING: if this is ever changed, code in pcre2_substitute.c will have to be
changed because it builds a general context "by hand" in order to avoid the
malloc() call in pcre2_general_context)_create(). There is also code in
pcre2_match.c that makes the same assumption. */
typedef struct pcre2_real_general_context {
pcre2_memctl memctl;
} pcre2_real_general_context;
@ -568,11 +573,13 @@ typedef struct pcre2_real_compile_context {
void *stack_guard_data;
const uint8_t *tables;
PCRE2_SIZE max_pattern_length;
PCRE2_SIZE max_pattern_compiled_length;
uint16_t bsr_convention;
uint16_t newline_convention;
uint32_t parens_nest_limit;
uint32_t extra_options;
uint32_t max_varlookbehind;
uint32_t optimization_flags;
} pcre2_real_compile_context;
/* The real match context structure. */
@ -583,10 +590,13 @@ typedef struct pcre2_real_match_context {
pcre2_jit_callback jit_callback;
void *jit_callback_data;
#endif
int (*callout)(pcre2_callout_block *, void *);
void *callout_data;
int (*substitute_callout)(pcre2_substitute_callout_block *, void *);
void *substitute_callout_data;
int (*callout)(pcre2_callout_block *, void *);
void *callout_data;
int (*substitute_callout)(pcre2_substitute_callout_block *, void *);
void *substitute_callout_data;
PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *,
PCRE2_SIZE, int, void *);
void *substitute_case_callout_data;
PCRE2_SIZE offset_limit;
uint32_t heap_limit;
uint32_t match_limit;
@ -622,6 +632,7 @@ typedef struct pcre2_real_code {
void *executable_jit; /* Pointer to JIT code */
uint8_t start_bitmap[32]; /* Bitmap for starting code unit < 256 */
CODE_BLOCKSIZE_TYPE blocksize; /* Total (bytes) that was malloc-ed */
CODE_BLOCKSIZE_TYPE code_start; /* Byte code start offset */
uint32_t magic_number; /* Paranoid and endianness check */
uint32_t compile_options; /* Options passed to pcre2_compile() */
uint32_t overall_options; /* Options after processing the pattern */
@ -640,6 +651,7 @@ typedef struct pcre2_real_code {
uint16_t top_backref; /* Highest numbered back reference */
uint16_t name_entry_size; /* Size (code units) of table entries */
uint16_t name_count; /* Number of name entries in the table */
uint32_t optimization_flags; /* Optimizations enabled at compile time */
} pcre2_real_code;
/* The real match data structure. Define ovector as large as it can ever
@ -715,6 +727,23 @@ typedef struct named_group {
uint16_t isdup; /* TRUE if a duplicate */
} named_group;
/* Structure for caching sorted ranges. This improves the performance
of translating META code to byte code. */
typedef struct class_ranges {
struct class_ranges *next; /* Next class ranges */
size_t char_lists_size; /* Total size of encoded char lists */
size_t char_lists_start; /* Start offset of encoded char lists */
uint16_t range_list_size; /* Size of ranges array */
uint16_t char_lists_types; /* The XCL_LIST header of char lists */
/* Followed by the list of ranges (start/end pairs) */
} class_ranges;
typedef union class_bits_storage {
uint8_t classbits[32];
uint32_t classwords[8];
} class_bits_storage;
/* Structure for passing "static" information around between the functions
doing the compiling, so that they are thread-safe. */
@ -724,14 +753,15 @@ typedef struct compile_block {
const uint8_t *fcc; /* Points to case-flipping table */
const uint8_t *cbits; /* Points to character type table */
const uint8_t *ctypes; /* Points to table of type maps */
PCRE2_SPTR start_workspace; /* The start of working space */
PCRE2_SPTR start_code; /* The start of the compiled code */
PCRE2_UCHAR *start_workspace; /* The start of working space */
PCRE2_UCHAR *start_code; /* The start of the compiled code */
PCRE2_SPTR start_pattern; /* The start of the pattern */
PCRE2_SPTR end_pattern; /* The end of the pattern */
PCRE2_UCHAR *name_table; /* The name/number table */
PCRE2_SIZE workspace_size; /* Size of workspace */
PCRE2_SIZE small_ref_offset[10]; /* Offsets for \1 to \9 */
PCRE2_SIZE erroroffset; /* Offset of error in pattern */
class_bits_storage classbits; /* Temporary store for classbits */
uint16_t names_found; /* Number of entries so far */
uint16_t name_entry_size; /* Size of each entry */
uint16_t parens_depth; /* Depth of nested parentheses */
@ -749,9 +779,9 @@ typedef struct compile_block {
uint32_t backref_map; /* Bitmap of low back refs */
uint32_t nltype; /* Newline type */
uint32_t nllen; /* Newline string length */
uint32_t class_range_start; /* Overall class range start */
uint32_t class_range_end; /* Overall class range end */
PCRE2_UCHAR nl[4]; /* Newline string when fixed length */
uint8_t class_op_used[ECLASS_NEST_LIMIT]; /* Operation used for
extended classes */
uint32_t req_varyopt; /* "After variable item" flag for reqbyte */
uint32_t max_varlookbehind; /* Limit for variable lookbehinds */
int max_lookbehind; /* Maximum lookbehind encountered (characters) */
@ -759,6 +789,11 @@ typedef struct compile_block {
BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
BOOL had_recurse; /* Had a pattern recursion or subroutine call */
BOOL dupnames; /* Duplicate names exist */
#ifdef SUPPORT_WIDE_CHARS
class_ranges *cranges; /* First class range. */
class_ranges *next_cranges; /* Next class range. */
size_t char_lists_size; /* Current size of character lists */
#endif
} compile_block;
/* Structure for keeping the properties of the in-memory stack used
@ -792,7 +827,7 @@ typedef struct heapframe {
to RRMATCH(), but which do not need to be copied to new frames. */
PCRE2_SPTR ecode; /* The current position in the pattern */
PCRE2_SPTR temp_sptr[2]; /* Used for short-term PCRE_SPTR values */
PCRE2_SPTR temp_sptr[2]; /* Used for short-term PCRE2_SPTR values */
PCRE2_SIZE length; /* Used for character, string, or code lengths */
PCRE2_SIZE back_frame; /* Amount to subtract on RRETURN */
PCRE2_SIZE temp_size; /* Used for short-term PCRE2_SIZE values */
@ -840,11 +875,10 @@ typedef struct heapframe {
PCRE2_SIZE ovector[131072]; /* Must be last in the structure */
} heapframe;
/* This typedef is a check that the size of the heapframe structure is a
multiple of PCRE2_SIZE. See various comments above. */
/* Assert that the size of the heapframe structure is a multiple of PCRE2_SIZE.
See various comments above. */
typedef char check_heapframe_size[
((sizeof(heapframe) % sizeof(PCRE2_SIZE)) == 0)? (+1):(-1)];
STATIC_ASSERT((sizeof(heapframe) % sizeof(PCRE2_SIZE)) == 0, heapframe_size);
/* Structure for computing the alignment of heapframe. */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -83,7 +83,7 @@ Arguments:
Returns: > 0 => success; value is the number of ovector pairs filled
= 0 => success, but ovector is not big enough
-1 => failed to match (PCRE_ERROR_NOMATCH)
-1 => failed to match (PCRE2_ERROR_NOMATCH)
< -1 => some kind of unexpected problem
*/

View file

@ -141,8 +141,8 @@ if (startsize == 0 || maxsize == 0 || maxsize > SIZE_MAX - STACK_GROWTH_RATE)
return NULL;
if (startsize > maxsize)
startsize = maxsize;
startsize = (startsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1);
startsize = (startsize + STACK_GROWTH_RATE - 1) & (size_t)(~(STACK_GROWTH_RATE - 1));
maxsize = (maxsize + STACK_GROWTH_RATE - 1) & (size_t)(~(STACK_GROWTH_RATE - 1));
jit_stack = PRIV(memctl_malloc)(sizeof(pcre2_real_jit_stack), (pcre2_memctl *)gcontext);
if (jit_stack == NULL) return NULL;

View file

@ -82,7 +82,7 @@ POSSIBILITY OF SUCH DAMAGE.
# endif
# endif
#if (defined(__GNUC__) && __SANITIZE_ADDRESS__) \
#if (defined(__GNUC__) && defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__ ) \
|| (defined(__clang__) \
&& ((__clang_major__ == 3 && __clang_minor__ >= 3) || (__clang_major__ > 3)))
__attribute__((no_sanitize_address))
@ -198,14 +198,14 @@ vect_t data = VLD1Q(*str_ptr);
#if PCRE2_CODE_UNIT_WIDTH != 8
data = VANDQ(data, char_mask);
#endif
#if defined(FFCS)
vect_t eq = VCEQQ(data, vc1);
#elif defined(FFCS_2)
vect_t eq1 = VCEQQ(data, vc1);
vect_t eq2 = VCEQQ(data, vc2);
vect_t eq = VORRQ(eq1, eq2);
vect_t eq = VORRQ(eq1, eq2);
#elif defined(FFCS_MASK)
vect_t eq = VORRQ(data, vmask);
@ -226,7 +226,7 @@ if (p1 < *str_ptr)
}
else
data2 = shift_left_n_lanes(data, offs1 - offs2);
if (compare1_type == compare_match1)
data = VCEQQ(data, cmp1a);
else
@ -281,7 +281,7 @@ while (*str_ptr < str_end)
#elif defined(FFCS_2)
eq1 = VCEQQ(data, vc1);
eq2 = VCEQQ(data, vc2);
eq = VORRQ(eq1, eq2);
eq = VORRQ(eq1, eq2);
#elif defined(FFCS_MASK)
eq = VORRQ(data, vmask);

View file

@ -246,10 +246,10 @@ struct sljit_jump *quit;
struct sljit_jump *partial_quit[2];
vector_compare_type compare_type = vector_compare_match1;
sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);
sljit_s32 data_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0);
sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1);
sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR2);
sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR3);
sljit_s32 data_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);
sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);
sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);
sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);
sljit_u32 bit = 0;
int i;
@ -273,17 +273,17 @@ if (common->mode == PCRE2_JIT_COMPLETE)
/* First part (unaligned start) */
value = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_LANE_ZERO;
sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
if (char1 != char2)
sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR2, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR2, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR1, SLJIT_FR1, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR1, SLJIT_VR1, 0);
if (char1 != char2)
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR2, SLJIT_VR2, 0);
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
restart = LABEL();
@ -294,12 +294,12 @@ OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~value);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, value);
value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);
for (i = 0; i < 4; i++)
fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
@ -318,11 +318,11 @@ if (common->mode == PCRE2_JIT_COMPLETE)
add_jump(compiler, &common->failed_match, partial_quit[1]);
value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);
for (i = 0; i < 4; i++)
fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0);
CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);
JUMPHERE(quit);
@ -380,10 +380,10 @@ struct sljit_jump *quit;
jump_list *not_found = NULL;
vector_compare_type compare_type = vector_compare_match1;
sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);
sljit_s32 data_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0);
sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1);
sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR2);
sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR3);
sljit_s32 data_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);
sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);
sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);
sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);
sljit_u32 bit = 0;
int i;
@ -406,29 +406,29 @@ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
/* First part (unaligned start) */
value = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_LANE_ZERO;
sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR1, 0, SLJIT_IMM, character_to_int32(char1 | bit));
if (char1 != char2)
sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR2, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR2, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2));
OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR1, SLJIT_FR1, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR1, SLJIT_VR1, 0);
if (char1 != char2)
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR2, SLJIT_VR2, 0);
value = (reg_type == SLJIT_SIMD_REG_256) ? 0x1f : 0xf;
OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~value);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, value);
value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);
for (i = 0; i < 4; i++)
fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
@ -445,12 +445,12 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, value);
add_jump(compiler, &not_found, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);
for (i = 0; i < 4; i++)
fast_forward_char_pair_sse2_compare(compiler, compare_type, reg_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0);
CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);
JUMPHERE(quit);
@ -488,14 +488,14 @@ sljit_u32 bit1 = 0;
sljit_u32 bit2 = 0;
sljit_u32 diff = IN_UCHARS(offs1 - offs2);
sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);
sljit_s32 data1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR0);
sljit_s32 data2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR1);
sljit_s32 cmp1a_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR2);
sljit_s32 cmp2a_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR3);
sljit_s32 cmp1b_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR4);
sljit_s32 cmp2b_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR5);
sljit_s32 tmp1_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_FR6);
sljit_s32 tmp2_ind = sljit_get_register_index(SLJIT_FLOAT_REGISTER, SLJIT_TMP_FR0);
sljit_s32 data1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);
sljit_s32 data2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);
sljit_s32 cmp1a_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);
sljit_s32 cmp2a_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);
sljit_s32 cmp1b_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR4);
sljit_s32 cmp2b_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR5);
sljit_s32 tmp1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR6);
sljit_s32 tmp2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_TMP_DEST_VREG);
struct sljit_label *start;
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
struct sljit_label *restart;
@ -541,10 +541,10 @@ else
}
value = SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32 | SLJIT_SIMD_LANE_ZERO;
sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR2, 0, TMP1, 0);
sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR2, 0, TMP1, 0);
if (char1a != char1b)
sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR4, 0, TMP2, 0);
sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR4, 0, TMP2, 0);
if (char2a == char2b)
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char2a));
@ -566,18 +566,18 @@ else
}
}
sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR3, 0, TMP1, 0);
sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR3, 0, TMP1, 0);
if (char2a != char2b)
sljit_emit_simd_lane_mov(compiler, value, SLJIT_FR5, 0, TMP2, 0);
sljit_emit_simd_lane_mov(compiler, value, SLJIT_VR5, 0, TMP2, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR2, SLJIT_FR2, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR2, SLJIT_VR2, 0);
if (char1a != char1b)
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR4, SLJIT_FR4, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR4, SLJIT_VR4, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR3, SLJIT_FR3, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR3, SLJIT_VR3, 0);
if (char2a != char2b)
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_FR5, SLJIT_FR5, 0);
sljit_emit_simd_lane_replicate(compiler, reg_type | SLJIT_SIMD_ELEM_32, SLJIT_VR5, SLJIT_VR5, 0);
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
restart = LABEL();
@ -589,11 +589,11 @@ value = (reg_type == SLJIT_SIMD_REG_256) ? ~0x1f : ~0xf;
OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, value);
value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);
jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_PTR, 0);
sljit_emit_simd_mov(compiler, reg_type, SLJIT_FR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff);
sljit_emit_simd_mov(compiler, reg_type, SLJIT_VR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff);
jump[1] = JUMP(SLJIT_JUMP);
JUMPHERE(jump[0]);
@ -668,8 +668,8 @@ for (i = 0; i < 4; i++)
fast_forward_char_pair_sse2_compare(compiler, compare1_type, reg_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);
}
sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_FR0, SLJIT_FR0, SLJIT_FR1);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);
sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_VR0, SLJIT_VR0, SLJIT_VR1, 0);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0);
/* Ignore matches before the first STR_PTR. */
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0);
@ -687,8 +687,8 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, value);
add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
value = (reg_type == SLJIT_SIMD_REG_256) ? SLJIT_SIMD_MEM_ALIGNED_256 : SLJIT_SIMD_MEM_ALIGNED_128;
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_FR0, SLJIT_MEM1(STR_PTR), 0);
sljit_emit_simd_mov(compiler, reg_type, SLJIT_FR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff);
sljit_emit_simd_mov(compiler, reg_type | value, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);
sljit_emit_simd_mov(compiler, reg_type, SLJIT_VR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff);
for (i = 0; i < 4; i++)
{
@ -696,8 +696,8 @@ for (i = 0; i < 4; i++)
fast_forward_char_pair_sse2_compare(compiler, compare2_type, reg_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp1_ind);
}
sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_FR0, SLJIT_FR0, SLJIT_FR1);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_FR0, TMP1, 0);
sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_VR0, SLJIT_VR0, SLJIT_VR1, 0);
sljit_emit_simd_sign(compiler, SLJIT_SIMD_STORE | reg_type | SLJIT_SIMD_ELEM_8, SLJIT_VR0, TMP1, 0);
CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);
@ -843,12 +843,13 @@ DEFINE_COMPILER;
int_char ic;
struct sljit_jump *partial_quit, *quit;
/* Save temporary registers. */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS1, TMP3, 0);
SLJIT_ASSERT(common->locals_size >= 2 * (int)sizeof(sljit_sw));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, STR_PTR, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, TMP3, 0);
/* Prepare function arguments */
OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);
GET_LOCAL_BASE(SLJIT_R1, 0, LOCALS0);
GET_LOCAL_BASE(SLJIT_R1, 0, LOCAL0);
OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, offset);
if (char1 == char2)
@ -910,8 +911,8 @@ else
}
}
/* Restore registers. */
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1);
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0);
OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1);
/* Check return value. */
partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
@ -1038,7 +1039,7 @@ SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));
SLJIT_ASSERT(compiler->scratches == 5);
/* Save temporary register STR_PTR. */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, STR_PTR, 0);
/* Prepare arguments for the function call. */
if (common->match_end_ptr == 0)
@ -1052,7 +1053,7 @@ else
SELECT(SLJIT_LESS, SLJIT_R0, STR_END, 0, SLJIT_R0);
}
GET_LOCAL_BASE(SLJIT_R1, 0, LOCALS0);
GET_LOCAL_BASE(SLJIT_R1, 0, LOCAL0);
OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_IMM, offs1);
OP1(SLJIT_MOV_S32, SLJIT_R3, 0, SLJIT_IMM, offs2);
ic.c.c1 = char1a;
@ -1093,7 +1094,7 @@ if (diff == 1) {
}
/* Restore STR_PTR register. */
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0);
/* Check return value. */
partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
@ -2176,7 +2177,7 @@ struct sljit_label *restart;
struct sljit_jump *jump[2];
SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);
SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));
SLJIT_ASSERT(diff <= (unsigned)IN_UCHARS(max_fast_forward_char_pair_offset()));
/* Initialize. */
if (common->match_end_ptr != 0)

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-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -155,10 +155,10 @@ return yield;
PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
pcre2_maketables_free(pcre2_general_context *gcontext, const uint8_t *tables)
{
if (gcontext)
gcontext->memctl.free((void *)tables, gcontext->memctl.memory_data);
else
free((void *)tables);
if (gcontext != NULL)
gcontext->memctl.free((void *)tables, gcontext->memctl.memory_data);
else
free((void *)tables);
}
#endif

File diff suppressed because it is too large Load diff

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-2022 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -77,14 +77,16 @@ return yield;
* Create a match data block using pattern data *
*************************************************/
/* If no context is supplied, use the memory allocator from the code. */
/* If no context is supplied, use the memory allocator from the code. This code
assumes that a general context contains nothing other than a memory allocator.
If that ever changes, this code will need fixing. */
PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION
pcre2_match_data_create_from_pattern(const pcre2_code *code,
pcre2_general_context *gcontext)
{
if (gcontext == NULL) gcontext = (pcre2_general_context *)code;
return pcre2_match_data_create(((pcre2_real_code *)code)->top_bracket + 1,
return pcre2_match_data_create(((const pcre2_real_code *)code)->top_bracket + 1,
gcontext);
}

View file

@ -117,4 +117,4 @@ return 1;
}
#endif /* SUPPORT_UNICODE */
/* End of pcre_ord2utf.c */
/* End of pcre2_ord2utf.c */

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-2018 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -64,7 +64,7 @@ Returns: 0 when data returned
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_pattern_info(const pcre2_code *code, uint32_t what, void *where)
{
const pcre2_real_code *re = (pcre2_real_code *)code;
const pcre2_real_code *re = (const pcre2_real_code *)code;
if (where == NULL) /* Requests field length */
{
@ -230,7 +230,8 @@ switch(what)
break;
case PCRE2_INFO_NAMETABLE:
*((PCRE2_SPTR *)where) = (PCRE2_SPTR)((char *)re + sizeof(pcre2_real_code));
*((PCRE2_SPTR *)where) = (PCRE2_SPTR)((const char *)re +
sizeof(pcre2_real_code));
break;
case PCRE2_INFO_NEWLINE:
@ -268,7 +269,7 @@ PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_callout_enumerate(const pcre2_code *code,
int (*callback)(pcre2_callout_enumerate_block *, void *), void *callout_data)
{
pcre2_real_code *re = (pcre2_real_code *)code;
const pcre2_real_code *re = (const pcre2_real_code *)code;
pcre2_callout_enumerate_block cb;
PCRE2_SPTR cc;
#ifdef SUPPORT_UNICODE
@ -291,7 +292,7 @@ if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;
if ((re->flags & (PCRE2_CODE_UNIT_WIDTH/8)) == 0) return PCRE2_ERROR_BADMODE;
cb.version = 0;
cc = (PCRE2_SPTR)((uint8_t *)re + sizeof(pcre2_real_code))
cc = (PCRE2_SPTR)((const uint8_t *)re + sizeof(pcre2_real_code))
+ re->name_count * re->name_entry_size;
while (TRUE)
@ -383,8 +384,9 @@ while (TRUE)
#endif
break;
#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
case OP_ECLASS:
cc += GET(cc, 1);
break;
#endif

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-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -127,25 +127,25 @@ dst_bytes += TABLES_LENGTH;
for (i = 0; i < number_of_codes; i++)
{
re = (const pcre2_real_code *)(codes[i]);
(void)memcpy(dst_bytes, (char *)re, re->blocksize);
/* Certain fields in the compiled code block are re-set during
deserialization. In order to ensure that the serialized data stream is always
the same for the same pattern, set them to zero here. We can't assume the
copy of the pattern is correctly aligned for accessing the fields as part of
(void)memcpy(dst_bytes, (const char *)re, re->blocksize);
/* Certain fields in the compiled code block are re-set during
deserialization. In order to ensure that the serialized data stream is always
the same for the same pattern, set them to zero here. We can't assume the
copy of the pattern is correctly aligned for accessing the fields as part of
a structure. Note the use of sizeof(void *) in the second of these, to
specify the size of a pointer. If sizeof(uint8_t *) is used (tables is a
pointer to uint8_t), gcc gives a warning because the first argument is also a
pointer to uint8_t. Casting the first argument to (void *) can stop this, but
specify the size of a pointer. If sizeof(uint8_t *) is used (tables is a
pointer to uint8_t), gcc gives a warning because the first argument is also a
pointer to uint8_t. Casting the first argument to (void *) can stop this, but
it didn't stop Coverity giving the same complaint. */
(void)memset(dst_bytes + offsetof(pcre2_real_code, memctl), 0,
(void)memset(dst_bytes + offsetof(pcre2_real_code, memctl), 0,
sizeof(pcre2_memctl));
(void)memset(dst_bytes + offsetof(pcre2_real_code, tables), 0,
(void)memset(dst_bytes + offsetof(pcre2_real_code, tables), 0,
sizeof(void *));
(void)memset(dst_bytes + offsetof(pcre2_real_code, executable_jit), 0,
sizeof(void *));
sizeof(void *));
dst_bytes += re->blocksize;
}
@ -232,10 +232,10 @@ for (i = 0; i < number_of_codes; i++)
if (dst_re->magic_number != MAGIC_NUMBER ||
dst_re->name_entry_size > MAX_NAME_SIZE + IMM2_SIZE + 1 ||
dst_re->name_count > MAX_NAME_COUNT)
{
memctl->free(dst_re, memctl->memory_data);
{
memctl->free(dst_re, memctl->memory_data);
return PCRE2_ERROR_BADSERIALIZEDDATA;
}
}
/* At the moment only one table is supported. */

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-2023 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -114,7 +114,7 @@ uint32_t once_fudge = 0;
BOOL had_recurse = FALSE;
BOOL dupcapused = (re->flags & PCRE2_DUPCAPUSED) != 0;
PCRE2_SPTR nextbranch = code + GET(code, 1);
PCRE2_UCHAR *cc = (PCRE2_UCHAR *)code + 1 + LINK_SIZE;
PCRE2_SPTR cc = code + 1 + LINK_SIZE;
recurse_check this_recurse;
/* If this is a "could be empty" group, its minimum length is 0. */
@ -136,12 +136,13 @@ passes 16-bits, reset to that value and skip the rest of the branch. */
for (;;)
{
int d, min, recno;
PCRE2_UCHAR op, *cs, *ce;
PCRE2_UCHAR op;
PCRE2_SPTR cs, ce;
if (branchlength >= UINT16_MAX)
{
branchlength = UINT16_MAX;
cc = (PCRE2_UCHAR *)nextbranch;
cc = nextbranch;
}
op = *cc;
@ -249,6 +250,7 @@ for (;;)
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
case OP_ASSERT_NA:
case OP_ASSERT_SCS:
case OP_ASSERTBACK_NA:
do cc += GET(cc, 1); while (*cc == OP_ALT);
/* Fall through */
@ -417,15 +419,14 @@ for (;;)
case OP_NCLASS:
#ifdef SUPPORT_WIDE_CHARS
case OP_XCLASS:
case OP_ECLASS:
/* The original code caused an unsigned overflow in 64 bit systems,
so now we use a conditional statement. */
if (op == OP_XCLASS)
if (op == OP_XCLASS || op == OP_ECLASS)
cc += GET(cc, 1);
else
cc += PRIV(OP_lengths)[OP_CLASS];
#else
cc += PRIV(OP_lengths)[OP_CLASS];
#endif
cc += PRIV(OP_lengths)[OP_CLASS];
switch (*cc)
{
@ -479,8 +480,8 @@ for (;;)
if (!dupcapused && (re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
{
int count = GET2(cc, 1+IMM2_SIZE);
PCRE2_UCHAR *slot =
(PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) +
PCRE2_SPTR slot =
(PCRE2_SPTR)((const uint8_t *)re + sizeof(pcre2_real_code)) +
GET2(cc, 1) * re->name_entry_size;
d = INT_MAX;
@ -496,13 +497,12 @@ for (;;)
dd = backref_cache[recno];
else
{
ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno);
ce = cs = PRIV(find_bracket)(startcode, utf, recno);
if (cs == NULL) return -2;
do ce += GET(ce, 1); while (*ce == OP_ALT);
dd = 0;
if (!dupcapused ||
(PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)
if (!dupcapused || PRIV(find_bracket)(ce, utf, recno) == NULL)
{
if (cc > cs && cc < ce) /* Simple recursion */
{
@ -539,7 +539,7 @@ for (;;)
}
}
else d = 0;
cc += 1 + 2*IMM2_SIZE;
cc += PRIV(OP_lengths)[*cc];
goto REPEAT_BACK_REFERENCE;
/* Single back reference by number. References by name are converted to by
@ -557,12 +557,11 @@ for (;;)
if ((re->overall_options & PCRE2_MATCH_UNSET_BACKREF) == 0)
{
ce = cs = (PCRE2_UCHAR *)PRIV(find_bracket)(startcode, utf, recno);
ce = cs = PRIV(find_bracket)(startcode, utf, recno);
if (cs == NULL) return -2;
do ce += GET(ce, 1); while (*ce == OP_ALT);
if (!dupcapused ||
(PCRE2_UCHAR *)PRIV(find_bracket)(ce, utf, recno) == NULL)
if (!dupcapused || PRIV(find_bracket)(ce, utf, recno) == NULL)
{
if (cc > cs && cc < ce) /* Simple recursion */
{
@ -593,7 +592,7 @@ for (;;)
backref_cache[0] = recno;
}
cc += 1 + IMM2_SIZE;
cc += PRIV(OP_lengths)[*cc];
/* Handle repeated back references */
@ -643,7 +642,7 @@ for (;;)
pattern contains multiple subpatterns with the same number. */
case OP_RECURSE:
cs = ce = (PCRE2_UCHAR *)startcode + GET(cc, 1);
cs = ce = startcode + GET(cc, 1);
recno = GET2(cs, 1+LINK_SIZE);
if (recno == prev_recurse_recno)
{
@ -755,10 +754,13 @@ for (;;)
new ones get added they are properly considered. */
default:
PCRE2_DEBUG_UNREACHABLE();
return -3;
}
}
/* Control never gets here */
PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */
return -3; /* Avoid compiler warnings */
}
@ -919,6 +921,138 @@ if (table_limit != 32) for (c = 24; c < 32; c++) re->start_bitmap[c] = 0xff;
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
/*************************************************
* Set starting bits for a character list. *
*************************************************/
/* This function sets starting bits for a character list. It enumerates
all characters and character ranges in the character list, and sets
the starting bits accordingly.
Arguments:
code pointer to the code
start_bitmap pointer to the starting bitmap
Returns: nothing
*/
static void
study_char_list(PCRE2_SPTR code, uint8_t *start_bitmap,
const uint8_t *char_lists_end)
{
uint32_t type, list_ind;
uint32_t char_list_add = XCL_CHAR_LIST_LOW_16_ADD;
uint32_t range_start = ~(uint32_t)0, range_end = 0;
const uint8_t *next_char;
PCRE2_UCHAR start_buffer[6], end_buffer[6];
PCRE2_UCHAR start, end;
/* Only needed in 8-bit mode at the moment. */
type = (uint32_t)(code[0] << 8) | code[1];
code += 2;
/* Align characters. */
next_char = char_lists_end - (GET(code, 0) << 1);
type &= XCL_TYPE_MASK;
list_ind = 0;
if ((type & XCL_BEGIN_WITH_RANGE) != 0)
range_start = XCL_CHAR_LIST_LOW_16_START;
while (type > 0)
{
uint32_t item_count = type & XCL_ITEM_COUNT_MASK;
if (item_count == XCL_ITEM_COUNT_MASK)
{
if (list_ind <= 1)
{
item_count = *(const uint16_t*)next_char;
next_char += 2;
}
else
{
item_count = *(const uint32_t*)next_char;
next_char += 4;
}
}
while (item_count > 0)
{
if (list_ind <= 1)
{
range_end = *(const uint16_t*)next_char;
next_char += 2;
}
else
{
range_end = *(const uint32_t*)next_char;
next_char += 4;
}
if ((range_end & XCL_CHAR_END) != 0)
{
range_end = char_list_add + (range_end >> XCL_CHAR_SHIFT);
PRIV(ord2utf)(range_end, end_buffer);
end = end_buffer[0];
if (range_start < range_end)
{
PRIV(ord2utf)(range_start, start_buffer);
for (start = start_buffer[0]; start <= end; start++)
start_bitmap[start / 8] |= (1u << (start & 7));
}
else
start_bitmap[end / 8] |= (1u << (end & 7));
range_start = ~(uint32_t)0;
}
else
range_start = char_list_add + (range_end >> XCL_CHAR_SHIFT);
item_count--;
}
list_ind++;
type >>= XCL_TYPE_BIT_LEN;
if (range_start == ~(uint32_t)0)
{
if ((type & XCL_BEGIN_WITH_RANGE) != 0)
{
/* In 8 bit mode XCL_CHAR_LIST_HIGH_32_START is not possible. */
if (list_ind == 1) range_start = XCL_CHAR_LIST_HIGH_16_START;
else range_start = XCL_CHAR_LIST_LOW_32_START;
}
}
else if ((type & XCL_BEGIN_WITH_RANGE) == 0)
{
PRIV(ord2utf)(range_start, start_buffer);
/* In 8 bit mode XCL_CHAR_LIST_LOW_32_END and
XCL_CHAR_LIST_HIGH_32_END are not possible. */
if (list_ind == 1) range_end = XCL_CHAR_LIST_LOW_16_END;
else range_end = XCL_CHAR_LIST_HIGH_16_END;
PRIV(ord2utf)(range_end, end_buffer);
end = end_buffer[0];
for (start = start_buffer[0]; start <= end; start++)
start_bitmap[start / 8] |= (1u << (start & 7));
range_start = ~(uint32_t)0;
}
/* In 8 bit mode XCL_CHAR_LIST_HIGH_32_ADD is not possible. */
if (list_ind == 1) char_list_add = XCL_CHAR_LIST_HIGH_16_ADD;
else char_list_add = XCL_CHAR_LIST_LOW_32_ADD;
}
}
#endif
/*************************************************
* Create bitmap of starting code units *
*************************************************/
@ -980,7 +1114,7 @@ do
{
int rc;
PCRE2_SPTR ncode;
uint8_t *classmap = NULL;
const uint8_t *classmap = NULL;
#ifdef SUPPORT_WIDE_CHARS
PCRE2_UCHAR xclassflags;
#endif
@ -1134,6 +1268,7 @@ do
case OP_ASSERTBACK_NOT:
case OP_ASSERT_NA:
case OP_ASSERTBACK_NA:
case OP_ASSERT_SCS:
ncode += GET(ncode, 1);
while (*ncode == OP_ALT) ncode += GET(ncode, 1);
ncode += 1 + LINK_SIZE;
@ -1252,12 +1387,14 @@ do
tcode += GET(tcode, 1 + 2*LINK_SIZE);
break;
/* Skip over lookbehind and negative lookahead assertions */
/* Skip over lookbehind, negative lookahead, and scan substring
assertions */
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
case OP_ASSERTBACK_NA:
case OP_ASSERT_SCS:
do tcode += GET(tcode, 1); while (*tcode == OP_ALT);
tcode += 1 + LINK_SIZE;
break;
@ -1578,6 +1715,13 @@ do
tcode += 2;
break;
/* Set-based ECLASS: treat it the same as a "complex" XCLASS; give up. */
#ifdef SUPPORT_WIDE_CHARS
case OP_ECLASS:
return SSB_FAIL;
#endif
/* Extended class: if there are any property checks, or if this is a
negative XCLASS without a map, give up. If there are no property checks,
there must be wide characters on the XCLASS list, because otherwise an
@ -1596,7 +1740,7 @@ do
map pointer if there is one, and fall through. */
classmap = ((xclassflags & XCL_MAP) == 0)? NULL :
(uint8_t *)(tcode + 1 + LINK_SIZE + 1);
(const uint8_t *)(tcode + 1 + LINK_SIZE + 1);
/* In UTF-8 mode, scan the character list and set bits for leading bytes,
then jump to handle the map. */
@ -1608,6 +1752,13 @@ do
PCRE2_SPTR p = tcode + 1 + LINK_SIZE + 1 + ((classmap == NULL)? 0:32);
tcode += GET(tcode, 1);
if (*p >= XCL_LIST)
{
study_char_list(p, re->start_bitmap,
((const uint8_t *)re + re->code_start));
goto HANDLE_CLASSMAP;
}
for (;;) switch (*p++)
{
case XCL_SINGLE:
@ -1629,6 +1780,7 @@ do
goto HANDLE_CLASSMAP;
default:
PCRE2_DEBUG_UNREACHABLE();
return SSB_UNKNOWN; /* Internal error, should not occur */
}
}
@ -1665,7 +1817,7 @@ do
case OP_CLASS:
if (*tcode == OP_XCLASS) tcode += GET(tcode, 1); else
{
classmap = (uint8_t *)(++tcode);
classmap = (const uint8_t *)(++tcode);
tcode += 32 / sizeof(PCRE2_UCHAR);
}
@ -1768,8 +1920,7 @@ BOOL ucp = (re->overall_options & PCRE2_UCP) != 0;
/* Find start of compiled code */
code = (PCRE2_UCHAR *)((uint8_t *)re + sizeof(pcre2_real_code)) +
re->name_entry_size * re->name_count;
code = (PCRE2_UCHAR *)((uint8_t *)re + re->code_start);
/* For a pattern that has a first code unit, or a multiline pattern that
matches only at "line start", there is no point in seeking a list of starting
@ -1779,7 +1930,11 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0)
{
int depth = 0;
int rc = set_start_bits(re, code, utf, ucp, &depth);
if (rc == SSB_UNKNOWN) return 1;
if (rc == SSB_UNKNOWN)
{
PCRE2_DEBUG_UNREACHABLE();
return 1;
}
/* If a list of starting code units was set up, scan the list to see if only
one or two were listed. Having only one listed is rare because usually a
@ -1852,25 +2007,22 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0)
}
}
/* Replace the start code unit bits with a first code unit, but only if it
is not the same as a required later code unit. This is because a search for
a required code unit starts after an explicit first code unit, but at a
code unit found from the bitmap. Patterns such as /a*a/ don't work
if both the start unit and required unit are the same. */
/* Replace the start code unit bits with a first code unit. If it is the
same as a required later code unit, then clear the required later code
unit. This is because a search for a required code unit starts after an
explicit first code unit, but at a code unit found from the bitmap.
Patterns such as /a*a/ don't work if both the start unit and required
unit are the same. */
if (a >= 0 &&
(
(re->flags & PCRE2_LASTSET) == 0 ||
(
re->last_codeunit != (uint32_t)a &&
(b < 0 || re->last_codeunit != (uint32_t)b)
)
))
{
if (a >= 0) {
if ((re->flags & PCRE2_LASTSET) && (re->last_codeunit == (uint32_t)a || (b >= 0 && re->last_codeunit == (uint32_t)b))) {
re->flags &= ~(PCRE2_LASTSET | PCRE2_LASTCASELESS);
re->last_codeunit = 0;
}
re->first_codeunit = a;
flags = PCRE2_FIRSTSET;
if (b >= 0) flags |= PCRE2_FIRSTCASELESS;
}
}
DONE:
re->flags |= flags;
@ -1898,9 +2050,11 @@ if ((re->flags & (PCRE2_MATCH_EMPTY|PCRE2_HASACCEPT)) == 0 &&
break; /* Leave minlength unchanged (will be zero) */
case -2:
PCRE2_DEBUG_UNREACHABLE();
return 2; /* missing capturing bracket */
case -3:
PCRE2_DEBUG_UNREACHABLE();
return 3; /* unrecognized opcode */
default:

File diff suppressed because it is too large Load diff

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-2023 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -486,7 +486,7 @@ pcre2_substring_nametable_scan(const pcre2_code *code, PCRE2_SPTR stringname,
uint16_t bot = 0;
uint16_t top = code->name_count;
uint16_t entrysize = code->name_entry_size;
PCRE2_SPTR nametable = (PCRE2_SPTR)((char *)code + sizeof(pcre2_real_code));
PCRE2_SPTR nametable = (PCRE2_SPTR)((const char *)code + sizeof(pcre2_real_code));
while (top > bot)
{

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-2021 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -171,9 +171,9 @@ are implementing).
6. Do not break after Prepend characters.
7. Do not break within emoji modifier sequences or emoji zwj sequences. That
is, do not break between characters with the Extended_Pictographic property.
Extend and ZWJ characters are allowed between the characters; this cannot be
represented in this table, the code has to deal with it.
is, do not break between characters with the Extended_Pictographic property
if a ZWJ intervenes. Extend characters are allowed between the characters;
this cannot be represented in this table, the code has to deal with it.
8. Do not break within emoji flag sequences. That is, do not break between
regional indicator (RI) symbols if there are an odd number of RI characters
@ -203,8 +203,8 @@ const uint32_t PRIV(ucp_gbtable)[] = {
ESZ|(1u<<ucp_gbT), /* 10 LVT */
(1u<<ucp_gbRegional_Indicator), /* 11 Regional Indicator */
ESZ, /* 12 Other */
ESZ, /* 13 ZWJ */
ESZ|(1u<<ucp_gbExtended_Pictographic) /* 14 Extended Pictographic */
ESZ|(1u<<ucp_gbExtended_Pictographic), /* 13 ZWJ */
ESZ /* 14 Extended Pictographic */
};
#undef ESZ

File diff suppressed because it is too large Load diff

View file

@ -132,13 +132,18 @@ enum {
ucp_Hex_Digit,
ucp_IDS_Binary_Operator,
ucp_IDS_Trinary_Operator,
ucp_IDS_Unary_Operator,
ucp_ID_Compat_Math_Continue,
ucp_ID_Compat_Math_Start,
ucp_ID_Continue,
ucp_ID_Start,
ucp_Ideographic,
ucp_InCB,
ucp_Join_Control,
ucp_Logical_Order_Exception,
ucp_Lowercase,
ucp_Math,
ucp_Modifier_Combining_Mark,
ucp_Noncharacter_Code_Point,
ucp_Pattern_Syntax,
ucp_Pattern_White_Space,
@ -219,6 +224,8 @@ enum {
ucp_Latin,
ucp_Greek,
ucp_Cyrillic,
ucp_Armenian,
ucp_Hebrew,
ucp_Arabic,
ucp_Syriac,
ucp_Thaana,
@ -232,15 +239,21 @@ enum {
ucp_Kannada,
ucp_Malayalam,
ucp_Sinhala,
ucp_Thai,
ucp_Tibetan,
ucp_Myanmar,
ucp_Georgian,
ucp_Hangul,
ucp_Ethiopic,
ucp_Cherokee,
ucp_Runic,
ucp_Mongolian,
ucp_Hiragana,
ucp_Katakana,
ucp_Bopomofo,
ucp_Han,
ucp_Yi,
ucp_Gothic,
ucp_Tagalog,
ucp_Hanunoo,
ucp_Buhid,
@ -248,21 +261,33 @@ enum {
ucp_Limbu,
ucp_Tai_Le,
ucp_Linear_B,
ucp_Shavian,
ucp_Cypriot,
ucp_Buginese,
ucp_Coptic,
ucp_Glagolitic,
ucp_Tifinagh,
ucp_Syloti_Nagri,
ucp_Phags_Pa,
ucp_Nko,
ucp_Kayah_Li,
ucp_Lycian,
ucp_Carian,
ucp_Lydian,
ucp_Avestan,
ucp_Samaritan,
ucp_Lisu,
ucp_Javanese,
ucp_Old_Turkic,
ucp_Kaithi,
ucp_Mandaic,
ucp_Chakma,
ucp_Meroitic_Hieroglyphs,
ucp_Sharada,
ucp_Takri,
ucp_Caucasian_Albanian,
ucp_Duployan,
ucp_Elbasan,
ucp_Grantha,
ucp_Khojki,
ucp_Linear_A,
@ -274,7 +299,10 @@ enum {
ucp_Khudawadi,
ucp_Tirhuta,
ucp_Multani,
ucp_Old_Hungarian,
ucp_Adlam,
ucp_Osage,
ucp_Tangut,
ucp_Masaram_Gondi,
ucp_Dogra,
ucp_Gunjala_Gondi,
@ -284,31 +312,28 @@ enum {
ucp_Yezidi,
ucp_Cypro_Minoan,
ucp_Old_Uyghur,
ucp_Toto,
ucp_Garay,
ucp_Gurung_Khema,
ucp_Ol_Onal,
ucp_Sunuwar,
ucp_Todhri,
ucp_Tulu_Tigalari,
/* Scripts which has no characters in other scripts. */
ucp_Unknown,
ucp_Common,
ucp_Armenian,
ucp_Hebrew,
ucp_Thai,
ucp_Lao,
ucp_Tibetan,
ucp_Ethiopic,
ucp_Cherokee,
ucp_Canadian_Aboriginal,
ucp_Ogham,
ucp_Runic,
ucp_Khmer,
ucp_Old_Italic,
ucp_Gothic,
ucp_Deseret,
ucp_Inherited,
ucp_Ugaritic,
ucp_Shavian,
ucp_Osmanya,
ucp_Braille,
ucp_New_Tai_Lue,
ucp_Tifinagh,
ucp_Old_Persian,
ucp_Kharoshthi,
ucp_Balinese,
@ -320,32 +345,22 @@ enum {
ucp_Vai,
ucp_Saurashtra,
ucp_Rejang,
ucp_Lycian,
ucp_Carian,
ucp_Lydian,
ucp_Cham,
ucp_Tai_Tham,
ucp_Tai_Viet,
ucp_Avestan,
ucp_Egyptian_Hieroglyphs,
ucp_Samaritan,
ucp_Lisu,
ucp_Bamum,
ucp_Meetei_Mayek,
ucp_Imperial_Aramaic,
ucp_Old_South_Arabian,
ucp_Inscriptional_Parthian,
ucp_Inscriptional_Pahlavi,
ucp_Old_Turkic,
ucp_Batak,
ucp_Brahmi,
ucp_Meroitic_Cursive,
ucp_Meroitic_Hieroglyphs,
ucp_Miao,
ucp_Sora_Sompeng,
ucp_Caucasian_Albanian,
ucp_Bassa_Vah,
ucp_Elbasan,
ucp_Pahawh_Hmong,
ucp_Mende_Kikakui,
ucp_Mro,
@ -358,13 +373,10 @@ enum {
ucp_Ahom,
ucp_Anatolian_Hieroglyphs,
ucp_Hatran,
ucp_Old_Hungarian,
ucp_SignWriting,
ucp_Bhaiksuki,
ucp_Marchen,
ucp_Newa,
ucp_Osage,
ucp_Tangut,
ucp_Nushu,
ucp_Soyombo,
ucp_Zanabazar_Square,
@ -378,10 +390,10 @@ enum {
ucp_Dives_Akuru,
ucp_Khitan_Small_Script,
ucp_Tangsa,
ucp_Toto,
ucp_Vithkuqi,
ucp_Kawi,
ucp_Nag_Mundari,
ucp_Kirat_Rai,
/* This must be last */
ucp_Script_Count
@ -389,7 +401,7 @@ enum {
/* Size of entries in ucd_script_sets[] */
#define ucd_script_sets_item_size 3
#define ucd_script_sets_item_size 4
#endif /* PCRE2_UCP_H_IDEMPOTENT_GUARD */

View file

@ -199,6 +199,8 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_extendedpictographic0 STR_e STR_x STR_t STR_e STR_n STR_d STR_e STR_d STR_p STR_i STR_c STR_t STR_o STR_g STR_r STR_a STR_p STR_h STR_i STR_c "\0"
#define STRING_extender0 STR_e STR_x STR_t STR_e STR_n STR_d STR_e STR_r "\0"
#define STRING_extpict0 STR_e STR_x STR_t STR_p STR_i STR_c STR_t "\0"
#define STRING_gara0 STR_g STR_a STR_r STR_a "\0"
#define STRING_garay0 STR_g STR_a STR_r STR_a STR_y "\0"
#define STRING_geor0 STR_g STR_e STR_o STR_r "\0"
#define STRING_georgian0 STR_g STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0"
#define STRING_glag0 STR_g STR_l STR_a STR_g "\0"
@ -219,9 +221,11 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_grlink0 STR_g STR_r STR_l STR_i STR_n STR_k "\0"
#define STRING_gujarati0 STR_g STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0"
#define STRING_gujr0 STR_g STR_u STR_j STR_r "\0"
#define STRING_gukh0 STR_g STR_u STR_k STR_h "\0"
#define STRING_gunjalagondi0 STR_g STR_u STR_n STR_j STR_a STR_l STR_a STR_g STR_o STR_n STR_d STR_i "\0"
#define STRING_gurmukhi0 STR_g STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0"
#define STRING_guru0 STR_g STR_u STR_r STR_u "\0"
#define STRING_gurungkhema0 STR_g STR_u STR_r STR_u STR_n STR_g STR_k STR_h STR_e STR_m STR_a "\0"
#define STRING_han0 STR_h STR_a STR_n "\0"
#define STRING_hang0 STR_h STR_a STR_n STR_g "\0"
#define STRING_hangul0 STR_h STR_a STR_n STR_g STR_u STR_l "\0"
@ -242,6 +246,8 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_hmnp0 STR_h STR_m STR_n STR_p "\0"
#define STRING_hung0 STR_h STR_u STR_n STR_g "\0"
#define STRING_idc0 STR_i STR_d STR_c "\0"
#define STRING_idcompatmathcontinue0 STR_i STR_d STR_c STR_o STR_m STR_p STR_a STR_t STR_m STR_a STR_t STR_h STR_c STR_o STR_n STR_t STR_i STR_n STR_u STR_e "\0"
#define STRING_idcompatmathstart0 STR_i STR_d STR_c STR_o STR_m STR_p STR_a STR_t STR_m STR_a STR_t STR_h STR_s STR_t STR_a STR_r STR_t "\0"
#define STRING_idcontinue0 STR_i STR_d STR_c STR_o STR_n STR_t STR_i STR_n STR_u STR_e "\0"
#define STRING_ideo0 STR_i STR_d STR_e STR_o "\0"
#define STRING_ideographic0 STR_i STR_d STR_e STR_o STR_g STR_r STR_a STR_p STR_h STR_i STR_c "\0"
@ -251,7 +257,10 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_idst0 STR_i STR_d STR_s STR_t "\0"
#define STRING_idstart0 STR_i STR_d STR_s STR_t STR_a STR_r STR_t "\0"
#define STRING_idstrinaryoperator0 STR_i STR_d STR_s STR_t STR_r STR_i STR_n STR_a STR_r STR_y STR_o STR_p STR_e STR_r STR_a STR_t STR_o STR_r "\0"
#define STRING_idsu0 STR_i STR_d STR_s STR_u "\0"
#define STRING_idsunaryoperator0 STR_i STR_d STR_s STR_u STR_n STR_a STR_r STR_y STR_o STR_p STR_e STR_r STR_a STR_t STR_o STR_r "\0"
#define STRING_imperialaramaic0 STR_i STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_a STR_r STR_a STR_m STR_a STR_i STR_c "\0"
#define STRING_incb0 STR_i STR_n STR_c STR_b "\0"
#define STRING_inherited0 STR_i STR_n STR_h STR_e STR_r STR_i STR_t STR_e STR_d "\0"
#define STRING_inscriptionalpahlavi0 STR_i STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_p STR_a STR_h STR_l STR_a STR_v STR_i "\0"
#define STRING_inscriptionalparthian0 STR_i STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_p STR_a STR_r STR_t STR_h STR_i STR_a STR_n "\0"
@ -275,8 +284,10 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_khoj0 STR_k STR_h STR_o STR_j "\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"
#define STRING_kiratrai0 STR_k STR_i STR_r STR_a STR_t STR_r STR_a STR_i "\0"
#define STRING_kits0 STR_k STR_i STR_t STR_s "\0"
#define STRING_knda0 STR_k STR_n STR_d STR_a "\0"
#define STRING_krai0 STR_k STR_r STR_a STR_i "\0"
#define STRING_kthi0 STR_k STR_t STR_h STR_i "\0"
#define STRING_l0 STR_l "\0"
#define STRING_l_AMPERSAND0 STR_l STR_AMPERSAND "\0"
@ -323,6 +334,7 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_masaramgondi0 STR_m STR_a STR_s STR_a STR_r STR_a STR_m STR_g STR_o STR_n STR_d STR_i "\0"
#define STRING_math0 STR_m STR_a STR_t STR_h "\0"
#define STRING_mc0 STR_m STR_c "\0"
#define STRING_mcm0 STR_m STR_c STR_m "\0"
#define STRING_me0 STR_m STR_e "\0"
#define STRING_medefaidrin0 STR_m STR_e STR_d STR_e STR_f STR_a STR_i STR_d STR_r STR_i STR_n "\0"
#define STRING_medf0 STR_m STR_e STR_d STR_f "\0"
@ -337,6 +349,7 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_mlym0 STR_m STR_l STR_y STR_m "\0"
#define STRING_mn0 STR_m STR_n "\0"
#define STRING_modi0 STR_m STR_o STR_d STR_i "\0"
#define STRING_modifiercombiningmark0 STR_m STR_o STR_d STR_i STR_f STR_i STR_e STR_r STR_c STR_o STR_m STR_b STR_i STR_n STR_i STR_n STR_g STR_m STR_a STR_r STR_k "\0"
#define STRING_mong0 STR_m STR_o STR_n STR_g "\0"
#define STRING_mongolian0 STR_m STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0"
#define STRING_mro0 STR_m STR_r STR_o "\0"
@ -379,6 +392,8 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_oldsoutharabian0 STR_o STR_l STR_d STR_s STR_o STR_u STR_t STR_h STR_a STR_r STR_a STR_b STR_i STR_a STR_n "\0"
#define STRING_oldturkic0 STR_o STR_l STR_d STR_t STR_u STR_r STR_k STR_i STR_c "\0"
#define STRING_olduyghur0 STR_o STR_l STR_d STR_u STR_y STR_g STR_h STR_u STR_r "\0"
#define STRING_olonal0 STR_o STR_l STR_o STR_n STR_a STR_l "\0"
#define STRING_onao0 STR_o STR_n STR_a STR_o "\0"
#define STRING_oriya0 STR_o STR_r STR_i STR_y STR_a "\0"
#define STRING_orkh0 STR_o STR_r STR_k STR_h "\0"
#define STRING_orya0 STR_o STR_r STR_y STR_a "\0"
@ -463,6 +478,8 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_sterm0 STR_s STR_t STR_e STR_r STR_m "\0"
#define STRING_sund0 STR_s STR_u STR_n STR_d "\0"
#define STRING_sundanese0 STR_s STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0"
#define STRING_sunu0 STR_s STR_u STR_n STR_u "\0"
#define STRING_sunuwar0 STR_s STR_u STR_n STR_u STR_w STR_a STR_r "\0"
#define STRING_sylo0 STR_s STR_y STR_l STR_o "\0"
#define STRING_sylotinagri0 STR_s STR_y STR_l STR_o STR_t STR_i STR_n STR_a STR_g STR_r STR_i "\0"
#define STRING_syrc0 STR_s STR_y STR_r STR_c "\0"
@ -498,7 +515,11 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_tirh0 STR_t STR_i STR_r STR_h "\0"
#define STRING_tirhuta0 STR_t STR_i STR_r STR_h STR_u STR_t STR_a "\0"
#define STRING_tnsa0 STR_t STR_n STR_s STR_a "\0"
#define STRING_todhri0 STR_t STR_o STR_d STR_h STR_r STR_i "\0"
#define STRING_todr0 STR_t STR_o STR_d STR_r "\0"
#define STRING_toto0 STR_t STR_o STR_t STR_o "\0"
#define STRING_tulutigalari0 STR_t STR_u STR_l STR_u STR_t STR_i STR_g STR_a STR_l STR_a STR_r STR_i "\0"
#define STRING_tutg0 STR_t STR_u STR_t STR_g "\0"
#define STRING_ugar0 STR_u STR_g STR_a STR_r "\0"
#define STRING_ugaritic0 STR_u STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0"
#define STRING_uideo0 STR_u STR_i STR_d STR_e STR_o "\0"
@ -690,6 +711,8 @@ const char PRIV(utt_names)[] =
STRING_extendedpictographic0
STRING_extender0
STRING_extpict0
STRING_gara0
STRING_garay0
STRING_geor0
STRING_georgian0
STRING_glag0
@ -710,9 +733,11 @@ const char PRIV(utt_names)[] =
STRING_grlink0
STRING_gujarati0
STRING_gujr0
STRING_gukh0
STRING_gunjalagondi0
STRING_gurmukhi0
STRING_guru0
STRING_gurungkhema0
STRING_han0
STRING_hang0
STRING_hangul0
@ -733,6 +758,8 @@ const char PRIV(utt_names)[] =
STRING_hmnp0
STRING_hung0
STRING_idc0
STRING_idcompatmathcontinue0
STRING_idcompatmathstart0
STRING_idcontinue0
STRING_ideo0
STRING_ideographic0
@ -742,7 +769,10 @@ const char PRIV(utt_names)[] =
STRING_idst0
STRING_idstart0
STRING_idstrinaryoperator0
STRING_idsu0
STRING_idsunaryoperator0
STRING_imperialaramaic0
STRING_incb0
STRING_inherited0
STRING_inscriptionalpahlavi0
STRING_inscriptionalparthian0
@ -766,8 +796,10 @@ const char PRIV(utt_names)[] =
STRING_khoj0
STRING_khojki0
STRING_khudawadi0
STRING_kiratrai0
STRING_kits0
STRING_knda0
STRING_krai0
STRING_kthi0
STRING_l0
STRING_l_AMPERSAND0
@ -814,6 +846,7 @@ const char PRIV(utt_names)[] =
STRING_masaramgondi0
STRING_math0
STRING_mc0
STRING_mcm0
STRING_me0
STRING_medefaidrin0
STRING_medf0
@ -828,6 +861,7 @@ const char PRIV(utt_names)[] =
STRING_mlym0
STRING_mn0
STRING_modi0
STRING_modifiercombiningmark0
STRING_mong0
STRING_mongolian0
STRING_mro0
@ -870,6 +904,8 @@ const char PRIV(utt_names)[] =
STRING_oldsoutharabian0
STRING_oldturkic0
STRING_olduyghur0
STRING_olonal0
STRING_onao0
STRING_oriya0
STRING_orkh0
STRING_orya0
@ -954,6 +990,8 @@ const char PRIV(utt_names)[] =
STRING_sterm0
STRING_sund0
STRING_sundanese0
STRING_sunu0
STRING_sunuwar0
STRING_sylo0
STRING_sylotinagri0
STRING_syrc0
@ -989,7 +1027,11 @@ const char PRIV(utt_names)[] =
STRING_tirh0
STRING_tirhuta0
STRING_tnsa0
STRING_todhri0
STRING_todr0
STRING_toto0
STRING_tulutigalari0
STRING_tutg0
STRING_ugar0
STRING_ugaritic0
STRING_uideo0
@ -1037,7 +1079,7 @@ const char PRIV(utt_names)[] =
const ucp_type_table PRIV(utt)[] = {
{ 0, PT_SCX, ucp_Adlam },
{ 6, PT_SCX, ucp_Adlam },
{ 11, PT_SC, ucp_Caucasian_Albanian },
{ 11, PT_SCX, ucp_Caucasian_Albanian },
{ 16, PT_BOOL, ucp_ASCII_Hex_Digit },
{ 21, PT_SC, ucp_Ahom },
{ 26, PT_BOOL, ucp_Alphabetic },
@ -1046,13 +1088,13 @@ const ucp_type_table PRIV(utt)[] = {
{ 64, PT_ANY, 0 },
{ 68, PT_SCX, ucp_Arabic },
{ 73, PT_SCX, ucp_Arabic },
{ 80, PT_SC, ucp_Armenian },
{ 80, PT_SCX, ucp_Armenian },
{ 89, PT_SC, ucp_Imperial_Aramaic },
{ 94, PT_SC, ucp_Armenian },
{ 94, PT_SCX, ucp_Armenian },
{ 99, PT_BOOL, ucp_ASCII },
{ 105, PT_BOOL, ucp_ASCII_Hex_Digit },
{ 119, PT_SC, ucp_Avestan },
{ 127, PT_SC, ucp_Avestan },
{ 119, PT_SCX, ucp_Avestan },
{ 127, PT_SCX, ucp_Avestan },
{ 132, PT_SC, ucp_Balinese },
{ 137, PT_SC, ucp_Balinese },
{ 146, PT_SC, ucp_Bamum },
@ -1106,11 +1148,11 @@ const ucp_type_table PRIV(utt)[] = {
{ 480, PT_SCX, ucp_Chakma },
{ 485, PT_SC, ucp_Canadian_Aboriginal },
{ 504, PT_SC, ucp_Canadian_Aboriginal },
{ 509, PT_SC, ucp_Carian },
{ 514, PT_SC, ucp_Carian },
{ 509, PT_SCX, ucp_Carian },
{ 514, PT_SCX, ucp_Carian },
{ 521, PT_BOOL, ucp_Cased },
{ 527, PT_BOOL, ucp_Case_Ignorable },
{ 541, PT_SC, ucp_Caucasian_Albanian },
{ 541, PT_SCX, ucp_Caucasian_Albanian },
{ 559, PT_PC, ucp_Cc },
{ 562, PT_PC, ucp_Cf },
{ 565, PT_SCX, ucp_Chakma },
@ -1120,8 +1162,8 @@ const ucp_type_table PRIV(utt)[] = {
{ 621, PT_BOOL, ucp_Changes_When_Lowercased },
{ 643, PT_BOOL, ucp_Changes_When_Titlecased },
{ 665, PT_BOOL, ucp_Changes_When_Uppercased },
{ 687, PT_SC, ucp_Cherokee },
{ 692, PT_SC, ucp_Cherokee },
{ 687, PT_SCX, ucp_Cherokee },
{ 692, PT_SCX, ucp_Cherokee },
{ 701, PT_SC, ucp_Chorasmian },
{ 712, PT_SC, ucp_Chorasmian },
{ 717, PT_BOOL, ucp_Case_Ignorable },
@ -1164,8 +1206,8 @@ const ucp_type_table PRIV(utt)[] = {
{ 963, PT_BOOL, ucp_Emoji_Component },
{ 969, PT_SC, ucp_Egyptian_Hieroglyphs },
{ 974, PT_SC, ucp_Egyptian_Hieroglyphs },
{ 994, PT_SC, ucp_Elbasan },
{ 999, PT_SC, ucp_Elbasan },
{ 994, PT_SCX, ucp_Elbasan },
{ 999, PT_SCX, ucp_Elbasan },
{ 1007, PT_SC, ucp_Elymaic },
{ 1012, PT_SC, ucp_Elymaic },
{ 1020, PT_BOOL, ucp_Emoji_Modifier },
@ -1175,355 +1217,376 @@ const ucp_type_table PRIV(utt)[] = {
{ 1060, PT_BOOL, ucp_Emoji_Modifier_Base },
{ 1078, PT_BOOL, ucp_Emoji_Presentation },
{ 1096, PT_BOOL, ucp_Emoji_Presentation },
{ 1102, PT_SC, ucp_Ethiopic },
{ 1107, PT_SC, ucp_Ethiopic },
{ 1102, PT_SCX, ucp_Ethiopic },
{ 1107, PT_SCX, ucp_Ethiopic },
{ 1116, PT_BOOL, ucp_Extender },
{ 1120, PT_BOOL, ucp_Extended_Pictographic },
{ 1141, PT_BOOL, ucp_Extender },
{ 1150, PT_BOOL, ucp_Extended_Pictographic },
{ 1158, PT_SCX, ucp_Georgian },
{ 1163, PT_SCX, ucp_Georgian },
{ 1172, PT_SCX, ucp_Glagolitic },
{ 1177, PT_SCX, ucp_Glagolitic },
{ 1188, PT_SCX, ucp_Gunjala_Gondi },
{ 1193, PT_SCX, ucp_Masaram_Gondi },
{ 1198, PT_SC, ucp_Gothic },
{ 1203, PT_SC, ucp_Gothic },
{ 1210, PT_SCX, ucp_Grantha },
{ 1215, PT_SCX, ucp_Grantha },
{ 1223, PT_BOOL, ucp_Grapheme_Base },
{ 1236, PT_BOOL, ucp_Grapheme_Extend },
{ 1251, PT_BOOL, ucp_Grapheme_Link },
{ 1264, PT_BOOL, ucp_Grapheme_Base },
{ 1271, PT_SCX, ucp_Greek },
{ 1277, PT_SCX, ucp_Greek },
{ 1282, PT_BOOL, ucp_Grapheme_Extend },
{ 1288, PT_BOOL, ucp_Grapheme_Link },
{ 1295, PT_SCX, ucp_Gujarati },
{ 1304, PT_SCX, ucp_Gujarati },
{ 1309, PT_SCX, ucp_Gunjala_Gondi },
{ 1322, PT_SCX, ucp_Gurmukhi },
{ 1331, PT_SCX, ucp_Gurmukhi },
{ 1336, PT_SCX, ucp_Han },
{ 1340, PT_SCX, ucp_Hangul },
{ 1345, PT_SCX, ucp_Hangul },
{ 1352, PT_SCX, ucp_Han },
{ 1357, PT_SCX, ucp_Hanifi_Rohingya },
{ 1372, PT_SCX, ucp_Hanunoo },
{ 1377, PT_SCX, ucp_Hanunoo },
{ 1385, PT_SC, ucp_Hatran },
{ 1390, PT_SC, ucp_Hatran },
{ 1397, PT_SC, ucp_Hebrew },
{ 1402, PT_SC, ucp_Hebrew },
{ 1409, PT_BOOL, ucp_Hex_Digit },
{ 1413, PT_BOOL, ucp_Hex_Digit },
{ 1422, PT_SCX, ucp_Hiragana },
{ 1427, PT_SCX, ucp_Hiragana },
{ 1436, PT_SC, ucp_Anatolian_Hieroglyphs },
{ 1441, PT_SC, ucp_Pahawh_Hmong },
{ 1446, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
{ 1451, PT_SC, ucp_Old_Hungarian },
{ 1456, PT_BOOL, ucp_ID_Continue },
{ 1460, PT_BOOL, ucp_ID_Continue },
{ 1471, PT_BOOL, ucp_Ideographic },
{ 1476, PT_BOOL, ucp_Ideographic },
{ 1488, PT_BOOL, ucp_ID_Start },
{ 1492, PT_BOOL, ucp_IDS_Binary_Operator },
{ 1497, PT_BOOL, ucp_IDS_Binary_Operator },
{ 1515, PT_BOOL, ucp_IDS_Trinary_Operator },
{ 1520, PT_BOOL, ucp_ID_Start },
{ 1528, PT_BOOL, ucp_IDS_Trinary_Operator },
{ 1547, PT_SC, ucp_Imperial_Aramaic },
{ 1563, PT_SC, ucp_Inherited },
{ 1573, PT_SC, ucp_Inscriptional_Pahlavi },
{ 1594, PT_SC, ucp_Inscriptional_Parthian },
{ 1616, PT_SC, ucp_Old_Italic },
{ 1621, PT_SCX, ucp_Javanese },
{ 1626, PT_SCX, ucp_Javanese },
{ 1635, PT_BOOL, ucp_Join_Control },
{ 1641, PT_BOOL, ucp_Join_Control },
{ 1653, PT_SCX, ucp_Kaithi },
{ 1660, PT_SCX, ucp_Kayah_Li },
{ 1665, PT_SCX, ucp_Katakana },
{ 1670, PT_SCX, ucp_Kannada },
{ 1678, PT_SCX, ucp_Katakana },
{ 1687, PT_SC, ucp_Kawi },
{ 1692, PT_SCX, ucp_Kayah_Li },
{ 1700, PT_SC, ucp_Kharoshthi },
{ 1705, PT_SC, ucp_Kharoshthi },
{ 1716, PT_SC, ucp_Khitan_Small_Script },
{ 1734, PT_SC, ucp_Khmer },
{ 1740, PT_SC, ucp_Khmer },
{ 1745, PT_SCX, ucp_Khojki },
{ 1750, PT_SCX, ucp_Khojki },
{ 1757, PT_SCX, ucp_Khudawadi },
{ 1767, PT_SC, ucp_Khitan_Small_Script },
{ 1772, PT_SCX, ucp_Kannada },
{ 1777, PT_SCX, ucp_Kaithi },
{ 1782, PT_GC, ucp_L },
{ 1784, PT_LAMP, 0 },
{ 1787, PT_SC, ucp_Tai_Tham },
{ 1792, PT_SC, ucp_Lao },
{ 1796, PT_SC, ucp_Lao },
{ 1801, PT_SCX, ucp_Latin },
{ 1807, PT_SCX, ucp_Latin },
{ 1812, PT_LAMP, 0 },
{ 1815, PT_SC, ucp_Lepcha },
{ 1820, PT_SC, ucp_Lepcha },
{ 1827, PT_SCX, ucp_Limbu },
{ 1832, PT_SCX, ucp_Limbu },
{ 1838, PT_SCX, ucp_Linear_A },
{ 1843, PT_SCX, ucp_Linear_B },
{ 1848, PT_SCX, ucp_Linear_A },
{ 1856, PT_SCX, ucp_Linear_B },
{ 1864, PT_SC, ucp_Lisu },
{ 1869, PT_PC, ucp_Ll },
{ 1872, PT_PC, ucp_Lm },
{ 1875, PT_PC, ucp_Lo },
{ 1878, PT_BOOL, ucp_Logical_Order_Exception },
{ 1882, PT_BOOL, ucp_Logical_Order_Exception },
{ 1904, PT_BOOL, ucp_Lowercase },
{ 1910, PT_BOOL, ucp_Lowercase },
{ 1920, PT_PC, ucp_Lt },
{ 1923, PT_PC, ucp_Lu },
{ 1926, PT_SC, ucp_Lycian },
{ 1931, PT_SC, ucp_Lycian },
{ 1938, PT_SC, ucp_Lydian },
{ 1943, PT_SC, ucp_Lydian },
{ 1950, PT_GC, ucp_M },
{ 1952, PT_SCX, ucp_Mahajani },
{ 1961, PT_SCX, ucp_Mahajani },
{ 1966, PT_SC, ucp_Makasar },
{ 1971, PT_SC, ucp_Makasar },
{ 1979, PT_SCX, ucp_Malayalam },
{ 1989, PT_SCX, ucp_Mandaic },
{ 1994, PT_SCX, ucp_Mandaic },
{ 2002, PT_SCX, ucp_Manichaean },
{ 2007, PT_SCX, ucp_Manichaean },
{ 2018, PT_SC, ucp_Marchen },
{ 2023, PT_SC, ucp_Marchen },
{ 2031, PT_SCX, ucp_Masaram_Gondi },
{ 2044, PT_BOOL, ucp_Math },
{ 2049, PT_PC, ucp_Mc },
{ 2052, PT_PC, ucp_Me },
{ 2055, PT_SC, ucp_Medefaidrin },
{ 2067, PT_SC, ucp_Medefaidrin },
{ 2072, PT_SC, ucp_Meetei_Mayek },
{ 2084, PT_SC, ucp_Mende_Kikakui },
{ 2089, PT_SC, ucp_Mende_Kikakui },
{ 2102, PT_SC, ucp_Meroitic_Cursive },
{ 2107, PT_SC, ucp_Meroitic_Hieroglyphs },
{ 2112, PT_SC, ucp_Meroitic_Cursive },
{ 2128, PT_SC, ucp_Meroitic_Hieroglyphs },
{ 2148, PT_SC, ucp_Miao },
{ 2153, PT_SCX, ucp_Malayalam },
{ 2158, PT_PC, ucp_Mn },
{ 2161, PT_SCX, ucp_Modi },
{ 2166, PT_SCX, ucp_Mongolian },
{ 2171, PT_SCX, ucp_Mongolian },
{ 2181, PT_SC, ucp_Mro },
{ 2185, PT_SC, ucp_Mro },
{ 2190, PT_SC, ucp_Meetei_Mayek },
{ 2195, PT_SCX, ucp_Multani },
{ 2200, PT_SCX, ucp_Multani },
{ 2208, PT_SCX, ucp_Myanmar },
{ 2216, PT_SCX, ucp_Myanmar },
{ 2221, PT_GC, ucp_N },
{ 2223, PT_SC, ucp_Nabataean },
{ 2233, PT_SC, ucp_Nag_Mundari },
{ 2238, PT_SC, ucp_Nag_Mundari },
{ 2249, PT_SCX, ucp_Nandinagari },
{ 2254, PT_SCX, ucp_Nandinagari },
{ 2266, PT_SC, ucp_Old_North_Arabian },
{ 2271, PT_SC, ucp_Nabataean },
{ 2276, PT_BOOL, ucp_Noncharacter_Code_Point },
{ 2282, PT_PC, ucp_Nd },
{ 2285, PT_SC, ucp_Newa },
{ 2290, PT_SC, ucp_New_Tai_Lue },
{ 2300, PT_SCX, ucp_Nko },
{ 2304, PT_SCX, ucp_Nko },
{ 2309, PT_PC, ucp_Nl },
{ 2312, PT_PC, ucp_No },
{ 2315, PT_BOOL, ucp_Noncharacter_Code_Point },
{ 2337, PT_SC, ucp_Nushu },
{ 2342, PT_SC, ucp_Nushu },
{ 2348, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
{ 2369, PT_SC, ucp_Ogham },
{ 2374, PT_SC, ucp_Ogham },
{ 2380, PT_SC, ucp_Ol_Chiki },
{ 2388, PT_SC, ucp_Ol_Chiki },
{ 2393, PT_SC, ucp_Old_Hungarian },
{ 2406, PT_SC, ucp_Old_Italic },
{ 2416, PT_SC, ucp_Old_North_Arabian },
{ 2432, PT_SCX, ucp_Old_Permic },
{ 2442, PT_SC, ucp_Old_Persian },
{ 2453, PT_SC, ucp_Old_Sogdian },
{ 2464, PT_SC, ucp_Old_South_Arabian },
{ 2480, PT_SC, ucp_Old_Turkic },
{ 2490, PT_SCX, ucp_Old_Uyghur },
{ 2500, PT_SCX, ucp_Oriya },
{ 2506, PT_SC, ucp_Old_Turkic },
{ 2511, PT_SCX, ucp_Oriya },
{ 2516, PT_SC, ucp_Osage },
{ 2522, PT_SC, ucp_Osage },
{ 2527, PT_SC, ucp_Osmanya },
{ 2532, PT_SC, ucp_Osmanya },
{ 2540, PT_SCX, ucp_Old_Uyghur },
{ 2545, PT_GC, ucp_P },
{ 2547, PT_SC, ucp_Pahawh_Hmong },
{ 2559, PT_SC, ucp_Palmyrene },
{ 2564, PT_SC, ucp_Palmyrene },
{ 2574, PT_BOOL, ucp_Pattern_Syntax },
{ 2581, PT_BOOL, ucp_Pattern_Syntax },
{ 2595, PT_BOOL, ucp_Pattern_White_Space },
{ 2613, PT_BOOL, ucp_Pattern_White_Space },
{ 2619, PT_SC, ucp_Pau_Cin_Hau },
{ 2624, PT_SC, ucp_Pau_Cin_Hau },
{ 2634, PT_PC, ucp_Pc },
{ 2637, PT_BOOL, ucp_Prepended_Concatenation_Mark },
{ 2641, PT_PC, ucp_Pd },
{ 2644, PT_PC, ucp_Pe },
{ 2647, PT_SCX, ucp_Old_Permic },
{ 2652, PT_PC, ucp_Pf },
{ 2655, PT_SCX, ucp_Phags_Pa },
{ 2660, PT_SCX, ucp_Phags_Pa },
{ 2668, PT_SC, ucp_Inscriptional_Pahlavi },
{ 2673, PT_SCX, ucp_Psalter_Pahlavi },
{ 2678, PT_SC, ucp_Phoenician },
{ 2683, PT_SC, ucp_Phoenician },
{ 2694, PT_PC, ucp_Pi },
{ 2697, PT_SC, ucp_Miao },
{ 2702, PT_PC, ucp_Po },
{ 2705, PT_BOOL, ucp_Prepended_Concatenation_Mark },
{ 2732, PT_SC, ucp_Inscriptional_Parthian },
{ 2737, PT_PC, ucp_Ps },
{ 2740, PT_SCX, ucp_Psalter_Pahlavi },
{ 2755, PT_SCX, ucp_Coptic },
{ 2760, PT_SC, ucp_Inherited },
{ 2765, PT_BOOL, ucp_Quotation_Mark },
{ 2771, PT_BOOL, ucp_Quotation_Mark },
{ 2785, PT_BOOL, ucp_Radical },
{ 2793, PT_BOOL, ucp_Regional_Indicator },
{ 2811, PT_SC, ucp_Rejang },
{ 2818, PT_BOOL, ucp_Regional_Indicator },
{ 2821, PT_SC, ucp_Rejang },
{ 2826, PT_SCX, ucp_Hanifi_Rohingya },
{ 2831, PT_SC, ucp_Runic },
{ 2837, PT_SC, ucp_Runic },
{ 2842, PT_GC, ucp_S },
{ 2844, PT_SC, ucp_Samaritan },
{ 2854, PT_SC, ucp_Samaritan },
{ 2859, PT_SC, ucp_Old_South_Arabian },
{ 2864, PT_SC, ucp_Saurashtra },
{ 2869, PT_SC, ucp_Saurashtra },
{ 2880, PT_PC, ucp_Sc },
{ 2883, PT_BOOL, ucp_Soft_Dotted },
{ 2886, PT_BOOL, ucp_Sentence_Terminal },
{ 2903, PT_SC, ucp_SignWriting },
{ 2908, PT_SCX, ucp_Sharada },
{ 2916, PT_SC, ucp_Shavian },
{ 2924, PT_SC, ucp_Shavian },
{ 2929, PT_SCX, ucp_Sharada },
{ 2934, PT_SC, ucp_Siddham },
{ 2939, PT_SC, ucp_Siddham },
{ 2947, PT_SC, ucp_SignWriting },
{ 2959, PT_SCX, ucp_Khudawadi },
{ 2964, PT_SCX, ucp_Sinhala },
{ 2969, PT_SCX, ucp_Sinhala },
{ 2977, PT_PC, ucp_Sk },
{ 2980, PT_PC, ucp_Sm },
{ 2983, PT_PC, ucp_So },
{ 2986, PT_BOOL, ucp_Soft_Dotted },
{ 2997, PT_SCX, ucp_Sogdian },
{ 3002, PT_SCX, ucp_Sogdian },
{ 3010, PT_SC, ucp_Old_Sogdian },
{ 3015, PT_SC, ucp_Sora_Sompeng },
{ 3020, PT_SC, ucp_Sora_Sompeng },
{ 3032, PT_SC, ucp_Soyombo },
{ 3037, PT_SC, ucp_Soyombo },
{ 3045, PT_BOOL, ucp_White_Space },
{ 3051, PT_BOOL, ucp_Sentence_Terminal },
{ 3057, PT_SC, ucp_Sundanese },
{ 3062, PT_SC, ucp_Sundanese },
{ 3072, PT_SCX, ucp_Syloti_Nagri },
{ 3077, PT_SCX, ucp_Syloti_Nagri },
{ 3089, PT_SCX, ucp_Syriac },
{ 3094, PT_SCX, ucp_Syriac },
{ 3101, PT_SCX, ucp_Tagalog },
{ 3109, PT_SCX, ucp_Tagbanwa },
{ 3114, PT_SCX, ucp_Tagbanwa },
{ 3123, PT_SCX, ucp_Tai_Le },
{ 3129, PT_SC, ucp_Tai_Tham },
{ 3137, PT_SC, ucp_Tai_Viet },
{ 3145, PT_SCX, ucp_Takri },
{ 3150, PT_SCX, ucp_Takri },
{ 3156, PT_SCX, ucp_Tai_Le },
{ 3161, PT_SC, ucp_New_Tai_Lue },
{ 3166, PT_SCX, ucp_Tamil },
{ 3172, PT_SCX, ucp_Tamil },
{ 3177, PT_SC, ucp_Tangut },
{ 3182, PT_SC, ucp_Tangsa },
{ 3189, PT_SC, ucp_Tangut },
{ 3196, PT_SC, ucp_Tai_Viet },
{ 3201, PT_SCX, ucp_Telugu },
{ 3206, PT_SCX, ucp_Telugu },
{ 3213, PT_BOOL, ucp_Terminal_Punctuation },
{ 3218, PT_BOOL, ucp_Terminal_Punctuation },
{ 3238, PT_SC, ucp_Tifinagh },
{ 3243, PT_SCX, ucp_Tagalog },
{ 3248, PT_SCX, ucp_Thaana },
{ 3253, PT_SCX, ucp_Thaana },
{ 3260, PT_SC, ucp_Thai },
{ 3265, PT_SC, ucp_Tibetan },
{ 3273, PT_SC, ucp_Tibetan },
{ 3278, PT_SC, ucp_Tifinagh },
{ 3287, PT_SCX, ucp_Tirhuta },
{ 3292, PT_SCX, ucp_Tirhuta },
{ 3300, PT_SC, ucp_Tangsa },
{ 3305, PT_SC, ucp_Toto },
{ 3310, PT_SC, ucp_Ugaritic },
{ 3315, PT_SC, ucp_Ugaritic },
{ 3324, PT_BOOL, ucp_Unified_Ideograph },
{ 3330, PT_BOOL, ucp_Unified_Ideograph },
{ 3347, PT_SC, ucp_Unknown },
{ 3355, PT_BOOL, ucp_Uppercase },
{ 3361, PT_BOOL, ucp_Uppercase },
{ 3371, PT_SC, ucp_Vai },
{ 3375, PT_SC, ucp_Vai },
{ 3380, PT_BOOL, ucp_Variation_Selector },
{ 3398, PT_SC, ucp_Vithkuqi },
{ 3403, PT_SC, ucp_Vithkuqi },
{ 3412, PT_BOOL, ucp_Variation_Selector },
{ 3415, PT_SC, ucp_Wancho },
{ 3422, PT_SC, ucp_Warang_Citi },
{ 3427, PT_SC, ucp_Warang_Citi },
{ 3438, PT_SC, ucp_Wancho },
{ 3443, PT_BOOL, ucp_White_Space },
{ 3454, PT_BOOL, ucp_White_Space },
{ 3461, PT_ALNUM, 0 },
{ 3465, PT_BOOL, ucp_XID_Continue },
{ 3470, PT_BOOL, ucp_XID_Continue },
{ 3482, PT_BOOL, ucp_XID_Start },
{ 3487, PT_BOOL, ucp_XID_Start },
{ 3496, PT_SC, ucp_Old_Persian },
{ 3501, PT_PXSPACE, 0 },
{ 3505, PT_SPACE, 0 },
{ 3509, PT_SC, ucp_Cuneiform },
{ 3514, PT_UCNC, 0 },
{ 3518, PT_WORD, 0 },
{ 3522, PT_SCX, ucp_Yezidi },
{ 3527, PT_SCX, ucp_Yezidi },
{ 3534, PT_SCX, ucp_Yi },
{ 3537, PT_SCX, ucp_Yi },
{ 3542, PT_GC, ucp_Z },
{ 3544, PT_SC, ucp_Zanabazar_Square },
{ 3560, PT_SC, ucp_Zanabazar_Square },
{ 3565, PT_SC, ucp_Inherited },
{ 3570, PT_PC, ucp_Zl },
{ 3573, PT_PC, ucp_Zp },
{ 3576, PT_PC, ucp_Zs },
{ 3579, PT_SC, ucp_Common },
{ 3584, PT_SC, ucp_Unknown }
{ 1158, PT_SCX, ucp_Garay },
{ 1163, PT_SCX, ucp_Garay },
{ 1169, PT_SCX, ucp_Georgian },
{ 1174, PT_SCX, ucp_Georgian },
{ 1183, PT_SCX, ucp_Glagolitic },
{ 1188, PT_SCX, ucp_Glagolitic },
{ 1199, PT_SCX, ucp_Gunjala_Gondi },
{ 1204, PT_SCX, ucp_Masaram_Gondi },
{ 1209, PT_SCX, ucp_Gothic },
{ 1214, PT_SCX, ucp_Gothic },
{ 1221, PT_SCX, ucp_Grantha },
{ 1226, PT_SCX, ucp_Grantha },
{ 1234, PT_BOOL, ucp_Grapheme_Base },
{ 1247, PT_BOOL, ucp_Grapheme_Extend },
{ 1262, PT_BOOL, ucp_Grapheme_Link },
{ 1275, PT_BOOL, ucp_Grapheme_Base },
{ 1282, PT_SCX, ucp_Greek },
{ 1288, PT_SCX, ucp_Greek },
{ 1293, PT_BOOL, ucp_Grapheme_Extend },
{ 1299, PT_BOOL, ucp_Grapheme_Link },
{ 1306, PT_SCX, ucp_Gujarati },
{ 1315, PT_SCX, ucp_Gujarati },
{ 1320, PT_SCX, ucp_Gurung_Khema },
{ 1325, PT_SCX, ucp_Gunjala_Gondi },
{ 1338, PT_SCX, ucp_Gurmukhi },
{ 1347, PT_SCX, ucp_Gurmukhi },
{ 1352, PT_SCX, ucp_Gurung_Khema },
{ 1364, PT_SCX, ucp_Han },
{ 1368, PT_SCX, ucp_Hangul },
{ 1373, PT_SCX, ucp_Hangul },
{ 1380, PT_SCX, ucp_Han },
{ 1385, PT_SCX, ucp_Hanifi_Rohingya },
{ 1400, PT_SCX, ucp_Hanunoo },
{ 1405, PT_SCX, ucp_Hanunoo },
{ 1413, PT_SC, ucp_Hatran },
{ 1418, PT_SC, ucp_Hatran },
{ 1425, PT_SCX, ucp_Hebrew },
{ 1430, PT_SCX, ucp_Hebrew },
{ 1437, PT_BOOL, ucp_Hex_Digit },
{ 1441, PT_BOOL, ucp_Hex_Digit },
{ 1450, PT_SCX, ucp_Hiragana },
{ 1455, PT_SCX, ucp_Hiragana },
{ 1464, PT_SC, ucp_Anatolian_Hieroglyphs },
{ 1469, PT_SC, ucp_Pahawh_Hmong },
{ 1474, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
{ 1479, PT_SCX, ucp_Old_Hungarian },
{ 1484, PT_BOOL, ucp_ID_Continue },
{ 1488, PT_BOOL, ucp_ID_Compat_Math_Continue },
{ 1509, PT_BOOL, ucp_ID_Compat_Math_Start },
{ 1527, PT_BOOL, ucp_ID_Continue },
{ 1538, PT_BOOL, ucp_Ideographic },
{ 1543, PT_BOOL, ucp_Ideographic },
{ 1555, PT_BOOL, ucp_ID_Start },
{ 1559, PT_BOOL, ucp_IDS_Binary_Operator },
{ 1564, PT_BOOL, ucp_IDS_Binary_Operator },
{ 1582, PT_BOOL, ucp_IDS_Trinary_Operator },
{ 1587, PT_BOOL, ucp_ID_Start },
{ 1595, PT_BOOL, ucp_IDS_Trinary_Operator },
{ 1614, PT_BOOL, ucp_IDS_Unary_Operator },
{ 1619, PT_BOOL, ucp_IDS_Unary_Operator },
{ 1636, PT_SC, ucp_Imperial_Aramaic },
{ 1652, PT_BOOL, ucp_InCB },
{ 1657, PT_SC, ucp_Inherited },
{ 1667, PT_SC, ucp_Inscriptional_Pahlavi },
{ 1688, PT_SC, ucp_Inscriptional_Parthian },
{ 1710, PT_SC, ucp_Old_Italic },
{ 1715, PT_SCX, ucp_Javanese },
{ 1720, PT_SCX, ucp_Javanese },
{ 1729, PT_BOOL, ucp_Join_Control },
{ 1735, PT_BOOL, ucp_Join_Control },
{ 1747, PT_SCX, ucp_Kaithi },
{ 1754, PT_SCX, ucp_Kayah_Li },
{ 1759, PT_SCX, ucp_Katakana },
{ 1764, PT_SCX, ucp_Kannada },
{ 1772, PT_SCX, ucp_Katakana },
{ 1781, PT_SC, ucp_Kawi },
{ 1786, PT_SCX, ucp_Kayah_Li },
{ 1794, PT_SC, ucp_Kharoshthi },
{ 1799, PT_SC, ucp_Kharoshthi },
{ 1810, PT_SC, ucp_Khitan_Small_Script },
{ 1828, PT_SC, ucp_Khmer },
{ 1834, PT_SC, ucp_Khmer },
{ 1839, PT_SCX, ucp_Khojki },
{ 1844, PT_SCX, ucp_Khojki },
{ 1851, PT_SCX, ucp_Khudawadi },
{ 1861, PT_SC, ucp_Kirat_Rai },
{ 1870, PT_SC, ucp_Khitan_Small_Script },
{ 1875, PT_SCX, ucp_Kannada },
{ 1880, PT_SC, ucp_Kirat_Rai },
{ 1885, PT_SCX, ucp_Kaithi },
{ 1890, PT_GC, ucp_L },
{ 1892, PT_LAMP, 0 },
{ 1895, PT_SC, ucp_Tai_Tham },
{ 1900, PT_SC, ucp_Lao },
{ 1904, PT_SC, ucp_Lao },
{ 1909, PT_SCX, ucp_Latin },
{ 1915, PT_SCX, ucp_Latin },
{ 1920, PT_LAMP, 0 },
{ 1923, PT_SC, ucp_Lepcha },
{ 1928, PT_SC, ucp_Lepcha },
{ 1935, PT_SCX, ucp_Limbu },
{ 1940, PT_SCX, ucp_Limbu },
{ 1946, PT_SCX, ucp_Linear_A },
{ 1951, PT_SCX, ucp_Linear_B },
{ 1956, PT_SCX, ucp_Linear_A },
{ 1964, PT_SCX, ucp_Linear_B },
{ 1972, PT_SCX, ucp_Lisu },
{ 1977, PT_PC, ucp_Ll },
{ 1980, PT_PC, ucp_Lm },
{ 1983, PT_PC, ucp_Lo },
{ 1986, PT_BOOL, ucp_Logical_Order_Exception },
{ 1990, PT_BOOL, ucp_Logical_Order_Exception },
{ 2012, PT_BOOL, ucp_Lowercase },
{ 2018, PT_BOOL, ucp_Lowercase },
{ 2028, PT_PC, ucp_Lt },
{ 2031, PT_PC, ucp_Lu },
{ 2034, PT_SCX, ucp_Lycian },
{ 2039, PT_SCX, ucp_Lycian },
{ 2046, PT_SCX, ucp_Lydian },
{ 2051, PT_SCX, ucp_Lydian },
{ 2058, PT_GC, ucp_M },
{ 2060, PT_SCX, ucp_Mahajani },
{ 2069, PT_SCX, ucp_Mahajani },
{ 2074, PT_SC, ucp_Makasar },
{ 2079, PT_SC, ucp_Makasar },
{ 2087, PT_SCX, ucp_Malayalam },
{ 2097, PT_SCX, ucp_Mandaic },
{ 2102, PT_SCX, ucp_Mandaic },
{ 2110, PT_SCX, ucp_Manichaean },
{ 2115, PT_SCX, ucp_Manichaean },
{ 2126, PT_SC, ucp_Marchen },
{ 2131, PT_SC, ucp_Marchen },
{ 2139, PT_SCX, ucp_Masaram_Gondi },
{ 2152, PT_BOOL, ucp_Math },
{ 2157, PT_PC, ucp_Mc },
{ 2160, PT_BOOL, ucp_Modifier_Combining_Mark },
{ 2164, PT_PC, ucp_Me },
{ 2167, PT_SC, ucp_Medefaidrin },
{ 2179, PT_SC, ucp_Medefaidrin },
{ 2184, PT_SC, ucp_Meetei_Mayek },
{ 2196, PT_SC, ucp_Mende_Kikakui },
{ 2201, PT_SC, ucp_Mende_Kikakui },
{ 2214, PT_SC, ucp_Meroitic_Cursive },
{ 2219, PT_SCX, ucp_Meroitic_Hieroglyphs },
{ 2224, PT_SC, ucp_Meroitic_Cursive },
{ 2240, PT_SCX, ucp_Meroitic_Hieroglyphs },
{ 2260, PT_SC, ucp_Miao },
{ 2265, PT_SCX, ucp_Malayalam },
{ 2270, PT_PC, ucp_Mn },
{ 2273, PT_SCX, ucp_Modi },
{ 2278, PT_BOOL, ucp_Modifier_Combining_Mark },
{ 2300, PT_SCX, ucp_Mongolian },
{ 2305, PT_SCX, ucp_Mongolian },
{ 2315, PT_SC, ucp_Mro },
{ 2319, PT_SC, ucp_Mro },
{ 2324, PT_SC, ucp_Meetei_Mayek },
{ 2329, PT_SCX, ucp_Multani },
{ 2334, PT_SCX, ucp_Multani },
{ 2342, PT_SCX, ucp_Myanmar },
{ 2350, PT_SCX, ucp_Myanmar },
{ 2355, PT_GC, ucp_N },
{ 2357, PT_SC, ucp_Nabataean },
{ 2367, PT_SC, ucp_Nag_Mundari },
{ 2372, PT_SC, ucp_Nag_Mundari },
{ 2383, PT_SCX, ucp_Nandinagari },
{ 2388, PT_SCX, ucp_Nandinagari },
{ 2400, PT_SC, ucp_Old_North_Arabian },
{ 2405, PT_SC, ucp_Nabataean },
{ 2410, PT_BOOL, ucp_Noncharacter_Code_Point },
{ 2416, PT_PC, ucp_Nd },
{ 2419, PT_SC, ucp_Newa },
{ 2424, PT_SC, ucp_New_Tai_Lue },
{ 2434, PT_SCX, ucp_Nko },
{ 2438, PT_SCX, ucp_Nko },
{ 2443, PT_PC, ucp_Nl },
{ 2446, PT_PC, ucp_No },
{ 2449, PT_BOOL, ucp_Noncharacter_Code_Point },
{ 2471, PT_SC, ucp_Nushu },
{ 2476, PT_SC, ucp_Nushu },
{ 2482, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
{ 2503, PT_SC, ucp_Ogham },
{ 2508, PT_SC, ucp_Ogham },
{ 2514, PT_SC, ucp_Ol_Chiki },
{ 2522, PT_SC, ucp_Ol_Chiki },
{ 2527, PT_SCX, ucp_Old_Hungarian },
{ 2540, PT_SC, ucp_Old_Italic },
{ 2550, PT_SC, ucp_Old_North_Arabian },
{ 2566, PT_SCX, ucp_Old_Permic },
{ 2576, PT_SC, ucp_Old_Persian },
{ 2587, PT_SC, ucp_Old_Sogdian },
{ 2598, PT_SC, ucp_Old_South_Arabian },
{ 2614, PT_SCX, ucp_Old_Turkic },
{ 2624, PT_SCX, ucp_Old_Uyghur },
{ 2634, PT_SCX, ucp_Ol_Onal },
{ 2641, PT_SCX, ucp_Ol_Onal },
{ 2646, PT_SCX, ucp_Oriya },
{ 2652, PT_SCX, ucp_Old_Turkic },
{ 2657, PT_SCX, ucp_Oriya },
{ 2662, PT_SCX, ucp_Osage },
{ 2668, PT_SCX, ucp_Osage },
{ 2673, PT_SC, ucp_Osmanya },
{ 2678, PT_SC, ucp_Osmanya },
{ 2686, PT_SCX, ucp_Old_Uyghur },
{ 2691, PT_GC, ucp_P },
{ 2693, PT_SC, ucp_Pahawh_Hmong },
{ 2705, PT_SC, ucp_Palmyrene },
{ 2710, PT_SC, ucp_Palmyrene },
{ 2720, PT_BOOL, ucp_Pattern_Syntax },
{ 2727, PT_BOOL, ucp_Pattern_Syntax },
{ 2741, PT_BOOL, ucp_Pattern_White_Space },
{ 2759, PT_BOOL, ucp_Pattern_White_Space },
{ 2765, PT_SC, ucp_Pau_Cin_Hau },
{ 2770, PT_SC, ucp_Pau_Cin_Hau },
{ 2780, PT_PC, ucp_Pc },
{ 2783, PT_BOOL, ucp_Prepended_Concatenation_Mark },
{ 2787, PT_PC, ucp_Pd },
{ 2790, PT_PC, ucp_Pe },
{ 2793, PT_SCX, ucp_Old_Permic },
{ 2798, PT_PC, ucp_Pf },
{ 2801, PT_SCX, ucp_Phags_Pa },
{ 2806, PT_SCX, ucp_Phags_Pa },
{ 2814, PT_SC, ucp_Inscriptional_Pahlavi },
{ 2819, PT_SCX, ucp_Psalter_Pahlavi },
{ 2824, PT_SC, ucp_Phoenician },
{ 2829, PT_SC, ucp_Phoenician },
{ 2840, PT_PC, ucp_Pi },
{ 2843, PT_SC, ucp_Miao },
{ 2848, PT_PC, ucp_Po },
{ 2851, PT_BOOL, ucp_Prepended_Concatenation_Mark },
{ 2878, PT_SC, ucp_Inscriptional_Parthian },
{ 2883, PT_PC, ucp_Ps },
{ 2886, PT_SCX, ucp_Psalter_Pahlavi },
{ 2901, PT_SCX, ucp_Coptic },
{ 2906, PT_SC, ucp_Inherited },
{ 2911, PT_BOOL, ucp_Quotation_Mark },
{ 2917, PT_BOOL, ucp_Quotation_Mark },
{ 2931, PT_BOOL, ucp_Radical },
{ 2939, PT_BOOL, ucp_Regional_Indicator },
{ 2957, PT_SC, ucp_Rejang },
{ 2964, PT_BOOL, ucp_Regional_Indicator },
{ 2967, PT_SC, ucp_Rejang },
{ 2972, PT_SCX, ucp_Hanifi_Rohingya },
{ 2977, PT_SCX, ucp_Runic },
{ 2983, PT_SCX, ucp_Runic },
{ 2988, PT_GC, ucp_S },
{ 2990, PT_SCX, ucp_Samaritan },
{ 3000, PT_SCX, ucp_Samaritan },
{ 3005, PT_SC, ucp_Old_South_Arabian },
{ 3010, PT_SC, ucp_Saurashtra },
{ 3015, PT_SC, ucp_Saurashtra },
{ 3026, PT_PC, ucp_Sc },
{ 3029, PT_BOOL, ucp_Soft_Dotted },
{ 3032, PT_BOOL, ucp_Sentence_Terminal },
{ 3049, PT_SC, ucp_SignWriting },
{ 3054, PT_SCX, ucp_Sharada },
{ 3062, PT_SCX, ucp_Shavian },
{ 3070, PT_SCX, ucp_Shavian },
{ 3075, PT_SCX, ucp_Sharada },
{ 3080, PT_SC, ucp_Siddham },
{ 3085, PT_SC, ucp_Siddham },
{ 3093, PT_SC, ucp_SignWriting },
{ 3105, PT_SCX, ucp_Khudawadi },
{ 3110, PT_SCX, ucp_Sinhala },
{ 3115, PT_SCX, ucp_Sinhala },
{ 3123, PT_PC, ucp_Sk },
{ 3126, PT_PC, ucp_Sm },
{ 3129, PT_PC, ucp_So },
{ 3132, PT_BOOL, ucp_Soft_Dotted },
{ 3143, PT_SCX, ucp_Sogdian },
{ 3148, PT_SCX, ucp_Sogdian },
{ 3156, PT_SC, ucp_Old_Sogdian },
{ 3161, PT_SC, ucp_Sora_Sompeng },
{ 3166, PT_SC, ucp_Sora_Sompeng },
{ 3178, PT_SC, ucp_Soyombo },
{ 3183, PT_SC, ucp_Soyombo },
{ 3191, PT_BOOL, ucp_White_Space },
{ 3197, PT_BOOL, ucp_Sentence_Terminal },
{ 3203, PT_SC, ucp_Sundanese },
{ 3208, PT_SC, ucp_Sundanese },
{ 3218, PT_SCX, ucp_Sunuwar },
{ 3223, PT_SCX, ucp_Sunuwar },
{ 3231, PT_SCX, ucp_Syloti_Nagri },
{ 3236, PT_SCX, ucp_Syloti_Nagri },
{ 3248, PT_SCX, ucp_Syriac },
{ 3253, PT_SCX, ucp_Syriac },
{ 3260, PT_SCX, ucp_Tagalog },
{ 3268, PT_SCX, ucp_Tagbanwa },
{ 3273, PT_SCX, ucp_Tagbanwa },
{ 3282, PT_SCX, ucp_Tai_Le },
{ 3288, PT_SC, ucp_Tai_Tham },
{ 3296, PT_SC, ucp_Tai_Viet },
{ 3304, PT_SCX, ucp_Takri },
{ 3309, PT_SCX, ucp_Takri },
{ 3315, PT_SCX, ucp_Tai_Le },
{ 3320, PT_SC, ucp_New_Tai_Lue },
{ 3325, PT_SCX, ucp_Tamil },
{ 3331, PT_SCX, ucp_Tamil },
{ 3336, PT_SCX, ucp_Tangut },
{ 3341, PT_SC, ucp_Tangsa },
{ 3348, PT_SCX, ucp_Tangut },
{ 3355, PT_SC, ucp_Tai_Viet },
{ 3360, PT_SCX, ucp_Telugu },
{ 3365, PT_SCX, ucp_Telugu },
{ 3372, PT_BOOL, ucp_Terminal_Punctuation },
{ 3377, PT_BOOL, ucp_Terminal_Punctuation },
{ 3397, PT_SCX, ucp_Tifinagh },
{ 3402, PT_SCX, ucp_Tagalog },
{ 3407, PT_SCX, ucp_Thaana },
{ 3412, PT_SCX, ucp_Thaana },
{ 3419, PT_SCX, ucp_Thai },
{ 3424, PT_SCX, ucp_Tibetan },
{ 3432, PT_SCX, ucp_Tibetan },
{ 3437, PT_SCX, ucp_Tifinagh },
{ 3446, PT_SCX, ucp_Tirhuta },
{ 3451, PT_SCX, ucp_Tirhuta },
{ 3459, PT_SC, ucp_Tangsa },
{ 3464, PT_SCX, ucp_Todhri },
{ 3471, PT_SCX, ucp_Todhri },
{ 3476, PT_SCX, ucp_Toto },
{ 3481, PT_SCX, ucp_Tulu_Tigalari },
{ 3494, PT_SCX, ucp_Tulu_Tigalari },
{ 3499, PT_SC, ucp_Ugaritic },
{ 3504, PT_SC, ucp_Ugaritic },
{ 3513, PT_BOOL, ucp_Unified_Ideograph },
{ 3519, PT_BOOL, ucp_Unified_Ideograph },
{ 3536, PT_SC, ucp_Unknown },
{ 3544, PT_BOOL, ucp_Uppercase },
{ 3550, PT_BOOL, ucp_Uppercase },
{ 3560, PT_SC, ucp_Vai },
{ 3564, PT_SC, ucp_Vai },
{ 3569, PT_BOOL, ucp_Variation_Selector },
{ 3587, PT_SC, ucp_Vithkuqi },
{ 3592, PT_SC, ucp_Vithkuqi },
{ 3601, PT_BOOL, ucp_Variation_Selector },
{ 3604, PT_SC, ucp_Wancho },
{ 3611, PT_SC, ucp_Warang_Citi },
{ 3616, PT_SC, ucp_Warang_Citi },
{ 3627, PT_SC, ucp_Wancho },
{ 3632, PT_BOOL, ucp_White_Space },
{ 3643, PT_BOOL, ucp_White_Space },
{ 3650, PT_ALNUM, 0 },
{ 3654, PT_BOOL, ucp_XID_Continue },
{ 3659, PT_BOOL, ucp_XID_Continue },
{ 3671, PT_BOOL, ucp_XID_Start },
{ 3676, PT_BOOL, ucp_XID_Start },
{ 3685, PT_SC, ucp_Old_Persian },
{ 3690, PT_PXSPACE, 0 },
{ 3694, PT_SPACE, 0 },
{ 3698, PT_SC, ucp_Cuneiform },
{ 3703, PT_UCNC, 0 },
{ 3707, PT_WORD, 0 },
{ 3711, PT_SCX, ucp_Yezidi },
{ 3716, PT_SCX, ucp_Yezidi },
{ 3723, PT_SCX, ucp_Yi },
{ 3726, PT_SCX, ucp_Yi },
{ 3731, PT_GC, ucp_Z },
{ 3733, PT_SC, ucp_Zanabazar_Square },
{ 3749, PT_SC, ucp_Zanabazar_Square },
{ 3754, PT_SC, ucp_Inherited },
{ 3759, PT_PC, ucp_Zl },
{ 3762, PT_PC, ucp_Zp },
{ 3765, PT_PC, ucp_Zs },
{ 3768, PT_SC, ucp_Common },
{ 3773, PT_SC, ucp_Unknown }
};
const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);

132
engine/thirdparty/pcre2/src/pcre2_util.h vendored Normal file
View file

@ -0,0 +1,132 @@
/*************************************************
* Perl-Compatible Regular Expressions *
*************************************************/
/* PCRE2 is a library of functions to support regular expressions whose syntax
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-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of Cambridge nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
#ifndef PCRE2_UTIL_H_IDEMPOTENT_GUARD
#define PCRE2_UTIL_H_IDEMPOTENT_GUARD
/* Assertion macros */
#ifdef PCRE2_DEBUG
#if defined(HAVE_ASSERT_H) && !defined(NDEBUG)
#include <assert.h>
#endif
/* PCRE2_ASSERT(x) can be used to inject an assert() for conditions
that the code below doesn't support. It is a NOP for non debug builds
but in debug builds will print information about the location of the
code where it triggered and crash.
It is meant to work like assert(), and therefore the expression used
should indicate what the expected state is, and shouldn't have any
side-effects. */
#if defined(HAVE_ASSERT_H) && !defined(NDEBUG)
#define PCRE2_ASSERT(x) assert(x)
#else
#define PCRE2_ASSERT(x) do \
{ \
if (!(x)) \
{ \
fprintf(stderr, "Assertion failed at " __FILE__ ":%d\n", __LINE__); \
abort(); \
} \
} while(0)
#endif
/* PCRE2_UNREACHABLE() can be used to mark locations on the code that
shouldn't be reached. In non debug builds is defined as a hint for
the compiler to eliminate any code after it, so it is useful also for
performance reasons, but should be used with care because if it is
ever reached will trigger Undefined Behaviour and if you are lucky a
crash. In debug builds it will report the location where it was triggered
and crash. One important point to consider when using this macro, is
that it is only implemented for a few compilers, and therefore can't
be relied on to always be active either, so if it is followed by some
code it is important to make sure that the whole thing is safe to
use even if the macro is not there (ex: make sure there is a `break`
after it if used at the end of a `case`) and to test your code also
with a configuration where the macro will be a NOP. */
#if defined(HAVE_ASSERT_H) && !defined(NDEBUG)
#define PCRE2_UNREACHABLE() \
assert(((void)"Execution reached unexpected point", 0))
#else
#define PCRE2_UNREACHABLE() do \
{ \
fprintf(stderr, "Execution reached unexpected point at " __FILE__ \
":%d\n", __LINE__); \
abort(); \
} while(0)
#endif
/* PCRE2_DEBUG_UNREACHABLE() is a debug only version of the previous
macro. It is meant to be used in places where the code is handling
an error situation in code that shouldn't be reached, but that has
some sort of fallback code to normally handle the error. When in
doubt you should use this instead of the previous macro. Like in
the previous case, it is a good idea to document as much as possible
the reason and the actions that should be taken if it ever triggers. */
#define PCRE2_DEBUG_UNREACHABLE() PCRE2_UNREACHABLE()
#endif /* PCRE2_DEBUG */
#ifndef PCRE2_DEBUG_UNREACHABLE
#define PCRE2_DEBUG_UNREACHABLE() do {} while(0)
#endif
#ifndef PCRE2_UNREACHABLE
#ifdef HAVE_BUILTIN_UNREACHABLE
#define PCRE2_UNREACHABLE() __builtin_unreachable()
#elif defined(HAVE_BUILTIN_ASSUME)
#define PCRE2_UNREACHABLE() __assume(0)
#else
#define PCRE2_UNREACHABLE() do {} while(0)
#endif
#endif /* !PCRE2_UNREACHABLE */
#ifndef PCRE2_ASSERT
#define PCRE2_ASSERT(x) do {} while(0)
#endif
#endif /* PCRE2_UTIL_H_IDEMPOTENT_GUARD */
/* End of pcre2_util.h */

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-2023 University of Cambridge
New API code Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -38,9 +38,9 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
/* This module contains an internal function that is used to match an extended
class. It is used by pcre2_auto_possessify() and by both pcre2_match() and
pcre2_def_match(). */
/* This module contains two internal functions that are used to match
OP_XCLASS and OP_ECLASS. It is used by pcre2_auto_possessify() and by both
pcre2_match() and pcre2_dfa_match(). */
#ifdef HAVE_CONFIG_H
@ -66,114 +66,75 @@ Returns: TRUE if character matches, else FALSE
*/
BOOL
PRIV(xclass)(uint32_t c, PCRE2_SPTR data, BOOL utf)
PRIV(xclass)(uint32_t c, PCRE2_SPTR data, const uint8_t *char_lists_end, BOOL utf)
{
/* Update PRIV(update_classbits) when this function is changed. */
PCRE2_UCHAR t;
BOOL negated = (*data & XCL_NOT) != 0;
BOOL not_negated = (*data & XCL_NOT) == 0;
uint32_t type, max_index, min_index, value;
const uint8_t *next_char;
#if PCRE2_CODE_UNIT_WIDTH == 8
/* In 8 bit mode, this must always be TRUE. Help the compiler to know that. */
utf = TRUE;
#endif
/* Code points < 256 are matched against a bitmap, if one is present. If not,
we still carry on, because there may be ranges that start below 256 in the
additional data. */
/* Code points < 256 are matched against a bitmap, if one is present. */
if (c < 256)
if ((*data++ & XCL_MAP) != 0)
{
if ((*data & XCL_HASPROP) == 0)
{
if ((*data & XCL_MAP) == 0) return negated;
return (((uint8_t *)(data + 1))[c/8] & (1u << (c&7))) != 0;
}
if ((*data & XCL_MAP) != 0 &&
(((uint8_t *)(data + 1))[c/8] & (1u << (c&7))) != 0)
return !negated; /* char found */
if (c < 256)
return (((const uint8_t *)data)[c/8] & (1u << (c&7))) != 0;
/* Skip bitmap. */
data += 32 / sizeof(PCRE2_UCHAR);
}
/* First skip the bit map if present. Then match against the list of Unicode
properties or large chars or ranges that end with a large char. We won't ever
/* Match against the list of Unicode properties. We won't ever
encounter XCL_PROP or XCL_NOTPROP when UTF support is not compiled. */
if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(PCRE2_UCHAR);
while ((t = *data++) != XCL_END)
#ifdef SUPPORT_UNICODE
if (*data == XCL_PROP || *data == XCL_NOTPROP)
{
uint32_t x, y;
if (t == XCL_SINGLE)
{
#ifdef SUPPORT_UNICODE
if (utf)
{
GETCHARINC(x, data); /* macro generates multiple statements */
}
else
#endif
x = *data++;
if (c == x) return !negated;
}
else if (t == XCL_RANGE)
{
#ifdef SUPPORT_UNICODE
if (utf)
{
GETCHARINC(x, data); /* macro generates multiple statements */
GETCHARINC(y, data); /* macro generates multiple statements */
}
else
#endif
{
x = *data++;
y = *data++;
}
if (c >= x && c <= y) return !negated;
}
/* The UCD record is the same for all properties. */
const ucd_record *prop = GET_UCD(c);
#ifdef SUPPORT_UNICODE
else /* XCL_PROP & XCL_NOTPROP */
do
{
int chartype;
const ucd_record *prop = GET_UCD(c);
BOOL isprop = t == XCL_PROP;
BOOL isprop = (*data++) == XCL_PROP;
BOOL ok;
switch(*data)
{
case PT_ANY:
if (isprop) return !negated;
break;
case PT_LAMP:
chartype = prop->chartype;
if ((chartype == ucp_Lu || chartype == ucp_Ll ||
chartype == ucp_Lt) == isprop) return !negated;
chartype == ucp_Lt) == isprop) return not_negated;
break;
case PT_GC:
if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == isprop)
return !negated;
return not_negated;
break;
case PT_PC:
if ((data[1] == prop->chartype) == isprop) return !negated;
if ((data[1] == prop->chartype) == isprop) return not_negated;
break;
case PT_SC:
if ((data[1] == prop->script) == isprop) return !negated;
if ((data[1] == prop->script) == isprop) return not_negated;
break;
case PT_SCX:
ok = (data[1] == prop->script ||
MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), data[1]) != 0);
if (ok == isprop) return !negated;
if (ok == isprop) return not_negated;
break;
case PT_ALNUM:
chartype = prop->chartype;
if ((PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N) == isprop)
return !negated;
return not_negated;
break;
/* Perl space used to exclude VT, but from Perl 5.18 it is included,
@ -186,12 +147,12 @@ while ((t = *data++) != XCL_END)
{
HSPACE_CASES:
VSPACE_CASES:
if (isprop) return !negated;
if (isprop) return not_negated;
break;
default:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == isprop)
return !negated;
return not_negated;
break;
}
break;
@ -201,7 +162,7 @@ while ((t = *data++) != XCL_END)
if ((PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N ||
chartype == ucp_Mn || chartype == ucp_Pc) == isprop)
return !negated;
return not_negated;
break;
case PT_UCNC:
@ -209,24 +170,24 @@ while ((t = *data++) != XCL_END)
{
if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
c == CHAR_GRAVE_ACCENT) == isprop)
return !negated;
return not_negated;
}
else
{
if ((c < 0xd800 || c > 0xdfff) == isprop)
return !negated;
return not_negated;
}
break;
case PT_BIDICL:
if ((UCD_BIDICLASS_PROP(prop) == data[1]) == isprop)
return !negated;
return not_negated;
break;
case PT_BOOL:
ok = MAPBIT(PRIV(ucd_boolprop_sets) +
UCD_BPROPS_PROP(prop), data[1]) != 0;
if (ok == isprop) return !negated;
if (ok == isprop) return not_negated;
break;
/* The following three properties can occur only in an XCLASS, as there
@ -248,7 +209,7 @@ while ((t = *data++) != XCL_END)
(chartype == ucp_Cf &&
c != 0x061c && c != 0x180e && (c < 0x2066 || c > 0x2069))
)) == isprop)
return !negated;
return not_negated;
break;
/* Printable character: same as graphic, with the addition of Zs, i.e.
@ -262,7 +223,7 @@ while ((t = *data++) != XCL_END)
(chartype == ucp_Cf &&
c != 0x061c && (c < 0x2066 || c > 0x2069))
)) == isprop)
return !negated;
return not_negated;
break;
/* Punctuation: all Unicode punctuation, plus ASCII characters that
@ -273,7 +234,7 @@ while ((t = *data++) != XCL_END)
chartype = prop->chartype;
if ((PRIV(ucp_gentype)[chartype] == ucp_P ||
(c < 128 && PRIV(ucp_gentype)[chartype] == ucp_S)) == isprop)
return !negated;
return not_negated;
break;
/* Perl has two sets of hex digits */
@ -285,24 +246,300 @@ while ((t = *data++) != XCL_END)
(c >= 0xff10 && c <= 0xff19) || /* Fullwidth digits */
(c >= 0xff21 && c <= 0xff26) || /* Fullwidth letters */
(c >= 0xff41 && c <= 0xff46)) == isprop)
return !negated;
return not_negated;
break;
/* This should never occur, but compilers may mutter if there is no
default. */
default:
PCRE2_DEBUG_UNREACHABLE();
return FALSE;
}
data += 2;
}
while (*data == XCL_PROP || *data == XCL_NOTPROP);
}
#else
(void)utf; /* Avoid compiler warning */
#endif /* SUPPORT_UNICODE */
/* Match against large chars or ranges that end with a large char. */
if (*data < XCL_LIST)
{
while ((t = *data++) != XCL_END)
{
uint32_t x, y;
#ifdef SUPPORT_UNICODE
if (utf)
{
GETCHARINC(x, data); /* macro generates multiple statements */
}
else
#endif
x = *data++;
if (t == XCL_SINGLE)
{
/* Since character ranges follow the properties, and they are
sorted, early return is possible for all characters <= x. */
if (c <= x) return (c == x) ? not_negated : !not_negated;
continue;
}
PCRE2_ASSERT(t == XCL_RANGE);
#ifdef SUPPORT_UNICODE
if (utf)
{
GETCHARINC(y, data); /* macro generates multiple statements */
}
else
#endif
y = *data++;
/* Since character ranges follow the properties, and they are
sorted, early return is possible for all characters <= y. */
if (c <= y) return (c >= x) ? not_negated : !not_negated;
}
return !not_negated; /* char did not match */
}
return negated; /* char did not match */
#if PCRE2_CODE_UNIT_WIDTH == 8
type = (uint32_t)(data[0] << 8) | data[1];
data += 2;
#else
type = data[0];
data++;
#endif /* CODE_UNIT_WIDTH */
/* Align characters. */
next_char = char_lists_end - (GET(data, 0) << 1);
type &= XCL_TYPE_MASK;
/* Alignment check. */
PCRE2_ASSERT(((uintptr_t)next_char & 0x1) == 0);
if (c >= XCL_CHAR_LIST_HIGH_16_START)
{
max_index = type & XCL_ITEM_COUNT_MASK;
if (max_index == XCL_ITEM_COUNT_MASK)
{
max_index = *(const uint16_t*)next_char;
PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK);
next_char += 2;
}
next_char += max_index << 1;
type >>= XCL_TYPE_BIT_LEN;
}
if (c < XCL_CHAR_LIST_LOW_32_START)
{
max_index = type & XCL_ITEM_COUNT_MASK;
c = (uint16_t)((c << XCL_CHAR_SHIFT) | XCL_CHAR_END);
if (max_index == XCL_ITEM_COUNT_MASK)
{
max_index = *(const uint16_t*)next_char;
PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK);
next_char += 2;
}
if (max_index == 0 || c < *(const uint16_t*)next_char)
return ((type & XCL_BEGIN_WITH_RANGE) != 0) == not_negated;
min_index = 0;
value = ((const uint16_t*)next_char)[--max_index];
if (c >= value)
return (value == c || (value & XCL_CHAR_END) == 0) == not_negated;
max_index--;
/* Binary search of a range. */
while (TRUE)
{
uint32_t mid_index = (min_index + max_index) >> 1;
value = ((const uint16_t*)next_char)[mid_index];
if (c < value)
max_index = mid_index - 1;
else if (((const uint16_t*)next_char)[mid_index + 1] <= c)
min_index = mid_index + 1;
else
return (value == c || (value & XCL_CHAR_END) == 0) == not_negated;
}
}
/* Skip the 16 bit ranges. */
max_index = type & XCL_ITEM_COUNT_MASK;
if (max_index == XCL_ITEM_COUNT_MASK)
{
max_index = *(const uint16_t*)next_char;
PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK);
next_char += 2;
}
next_char += (max_index << 1);
type >>= XCL_TYPE_BIT_LEN;
/* Alignment check. */
PCRE2_ASSERT(((uintptr_t)next_char & 0x3) == 0);
max_index = type & XCL_ITEM_COUNT_MASK;
#if PCRE2_CODE_UNIT_WIDTH == 32
if (c >= XCL_CHAR_LIST_HIGH_32_START)
{
if (max_index == XCL_ITEM_COUNT_MASK)
{
max_index = *(const uint32_t*)next_char;
PCRE2_ASSERT(max_index >= XCL_ITEM_COUNT_MASK);
next_char += 4;
}
next_char += max_index << 2;
type >>= XCL_TYPE_BIT_LEN;
max_index = type & XCL_ITEM_COUNT_MASK;
}
#endif
c = (uint32_t)((c << XCL_CHAR_SHIFT) | XCL_CHAR_END);
if (max_index == XCL_ITEM_COUNT_MASK)
{
max_index = *(const uint32_t*)next_char;
next_char += 4;
}
if (max_index == 0 || c < *(const uint32_t*)next_char)
return ((type & XCL_BEGIN_WITH_RANGE) != 0) == not_negated;
min_index = 0;
value = ((const uint32_t*)next_char)[--max_index];
if (c >= value)
return (value == c || (value & XCL_CHAR_END) == 0) == not_negated;
max_index--;
/* Binary search of a range. */
while (TRUE)
{
uint32_t mid_index = (min_index + max_index) >> 1;
value = ((const uint32_t*)next_char)[mid_index];
if (c < value)
max_index = mid_index - 1;
else if (((const uint32_t*)next_char)[mid_index + 1] <= c)
min_index = mid_index + 1;
else
return (value == c || (value & XCL_CHAR_END) == 0) == not_negated;
}
}
/*************************************************
* Match character against an ECLASS *
*************************************************/
/* This function is called to match a character against an extended class
used for describing characters using boolean operations on sets.
Arguments:
c the character
data_start points to the start of the ECLASS data
data_end points one-past-the-last of the ECLASS data
utf TRUE if in UTF mode
Returns: TRUE if character matches, else FALSE
*/
BOOL
PRIV(eclass)(uint32_t c, PCRE2_SPTR data_start, PCRE2_SPTR data_end,
const uint8_t *char_lists_end, BOOL utf)
{
PCRE2_SPTR ptr = data_start;
PCRE2_UCHAR flags;
uint32_t stack = 0;
int stack_depth = 0;
PCRE2_ASSERT(data_start < data_end);
flags = *ptr++;
PCRE2_ASSERT((flags & ECL_MAP) == 0 ||
(data_end - ptr) >= 32 / (int)sizeof(PCRE2_UCHAR));
/* Code points < 256 are matched against a bitmap, if one is present.
Otherwise all codepoints are checked later. */
if ((flags & ECL_MAP) != 0)
{
if (c < 256)
return (((const uint8_t *)ptr)[c/8] & (1u << (c&7))) != 0;
/* Skip the bitmap. */
ptr += 32 / sizeof(PCRE2_UCHAR);
}
/* Do a little loop, until we reach the end of the ECLASS. */
while (ptr < data_end)
{
switch (*ptr)
{
case ECL_AND:
++ptr;
stack = (stack >> 1) & (stack | ~(uint32_t)1u);
PCRE2_ASSERT(stack_depth >= 2);
--stack_depth;
break;
case ECL_OR:
++ptr;
stack = (stack >> 1) | (stack & (uint32_t)1u);
PCRE2_ASSERT(stack_depth >= 2);
--stack_depth;
break;
case ECL_XOR:
++ptr;
stack = (stack >> 1) ^ (stack & (uint32_t)1u);
PCRE2_ASSERT(stack_depth >= 2);
--stack_depth;
break;
case ECL_NOT:
++ptr;
stack ^= (uint32_t)1u;
PCRE2_ASSERT(stack_depth >= 1);
break;
case ECL_XCLASS:
{
uint32_t matched = PRIV(xclass)(c, ptr + 1 + LINK_SIZE, char_lists_end, utf);
ptr += GET(ptr, 1);
stack = (stack << 1) | matched;
++stack_depth;
break;
}
/* This should never occur, but compilers may mutter if there is no
default. */
default:
PCRE2_DEBUG_UNREACHABLE();
return FALSE;
}
}
PCRE2_ASSERT(stack_depth == 1);
(void)stack_depth; /* Ignore unused variable, if assertions are disabled. */
/* The final bit left on the stack now holds the match result. */
return (stack & 1u) != 0;
}
/* End of pcre2_xclass.c */

View file

@ -1,133 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/mman.h>
/*
On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a
version where it's OK to have more than one JIT block or where MAP_JIT is
required.
On non-macOS systems, returns MAP_JIT if it is defined.
*/
#include <TargetConditionals.h>
#if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (TARGET_OS_MAC && !TARGET_OS_IPHONE)
#if defined(SLJIT_CONFIG_X86) && SLJIT_CONFIG_X86
#include <sys/utsname.h>
#include <stdlib.h>
#define SLJIT_MAP_JIT (get_map_jit_flag())
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
static SLJIT_INLINE int get_map_jit_flag(void)
{
size_t page_size;
void *ptr;
struct utsname name;
static int map_jit_flag = -1;
if (map_jit_flag < 0) {
map_jit_flag = 0;
uname(&name);
/* Kernel version for 10.14.0 (Mojave) or later */
if (atoi(name.release) >= 18) {
page_size = get_page_alignment() + 1;
/* Only use MAP_JIT if a hardened runtime is used */
ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr != MAP_FAILED)
munmap(ptr, page_size);
else
map_jit_flag = MAP_JIT;
}
}
return map_jit_flag;
}
#elif defined(SLJIT_CONFIG_ARM) && SLJIT_CONFIG_ARM
#include <AvailabilityMacros.h>
#include <pthread.h>
#define SLJIT_MAP_JIT (MAP_JIT)
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
apple_update_wx_flags(enable_exec)
static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec)
{
#if MAC_OS_X_VERSION_MIN_REQUIRED < 110000
if (__builtin_available(macos 11, *))
#endif /* BigSur */
pthread_jit_write_protect_np(enable_exec);
}
#elif defined(SLJIT_CONFIG_PPC) && SLJIT_CONFIG_PPC
#define SLJIT_MAP_JIT (0)
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
#else
#error "Unsupported architecture"
#endif /* SLJIT_CONFIG */
#else /* !TARGET_OS_OSX */
#ifdef MAP_JIT
#define SLJIT_MAP_JIT (MAP_JIT)
#else
#define SLJIT_MAP_JIT (0)
#endif
#endif /* TARGET_OS_OSX */
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
{
void *retval;
int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
int flags = MAP_PRIVATE;
int fd = -1;
flags |= MAP_ANON | SLJIT_MAP_JIT;
retval = mmap(NULL, size, prot, flags, fd, 0);
if (retval == MAP_FAILED)
return NULL;
SLJIT_UPDATE_WX_FLAGS(retval, (uint8_t *)retval + size, 0);
return retval;
}
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
{
munmap(chunk, size);
}
#include "sljitExecAllocatorCore.c"

View file

@ -1,330 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
This file contains a simple executable memory allocator
It is assumed, that executable code blocks are usually medium (or sometimes
large) memory blocks, and the allocator is not too frequently called (less
optimized than other allocators). Thus, using it as a generic allocator is
not suggested.
How does it work:
Memory is allocated in continuous memory areas called chunks by alloc_chunk()
Chunk format:
[ block ][ block ] ... [ block ][ block terminator ]
All blocks and the block terminator is started with block_header. The block
header contains the size of the previous and the next block. These sizes
can also contain special values.
Block size:
0 - The block is a free_block, with a different size member.
1 - The block is a block terminator.
n - The block is used at the moment, and the value contains its size.
Previous block size:
0 - This is the first block of the memory chunk.
n - The size of the previous block.
Using these size values we can go forward or backward on the block chain.
The unused blocks are stored in a chain list pointed by free_blocks. This
list is useful if we need to find a suitable memory area when the allocator
is called.
When a block is freed, the new free block is connected to its adjacent free
blocks if possible.
[ free block ][ used block ][ free block ]
and "used block" is freed, the three blocks are connected together:
[ one big free block ]
*/
/* Expected functions:
alloc_chunk / free_chunk :
* allocate executable system memory chunks
* the size is always divisible by CHUNK_SIZE
SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK :
* provided as part of sljitUtils
* only the allocator requires this lock, sljit is fully thread safe
as it only uses local variables
Supported defines:
SLJIT_HAS_CHUNK_HEADER - (optional) sljit_chunk_header is defined
SLJIT_HAS_EXECUTABLE_OFFSET - (optional) has executable offset data
SLJIT_UPDATE_WX_FLAGS - (optional) update WX flags
*/
#ifdef SLJIT_HAS_CHUNK_HEADER
#define CHUNK_HEADER_SIZE (sizeof(struct sljit_chunk_header))
#else /* !SLJIT_HAS_CHUNK_HEADER */
#define CHUNK_HEADER_SIZE 0
#endif /* SLJIT_HAS_CHUNK_HEADER */
#ifndef SLJIT_UPDATE_WX_FLAGS
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
#endif /* SLJIT_UPDATE_WX_FLAGS */
#ifndef CHUNK_SIZE
/* 64 KByte if not specified. */
#define CHUNK_SIZE (sljit_uw)0x10000
#endif /* CHUNK_SIZE */
struct block_header {
sljit_uw size;
sljit_uw prev_size;
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
sljit_sw executable_offset;
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
};
struct free_block {
struct block_header header;
struct free_block *next;
struct free_block *prev;
sljit_uw size;
};
#define AS_BLOCK_HEADER(base, offset) \
((struct block_header*)(((sljit_u8*)base) + offset))
#define AS_FREE_BLOCK(base, offset) \
((struct free_block*)(((sljit_u8*)base) + offset))
#define MEM_START(base) ((void*)((base) + 1))
#define CHUNK_MASK (~(CHUNK_SIZE - 1))
#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7u) & ~(sljit_uw)7)
#define CHUNK_EXTRA_SIZE (sizeof(struct block_header) + CHUNK_HEADER_SIZE)
static struct free_block* free_blocks;
static sljit_uw allocated_size;
static sljit_uw total_size;
static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)
{
free_block->header.size = 0;
free_block->size = size;
free_block->next = free_blocks;
free_block->prev = NULL;
if (free_blocks)
free_blocks->prev = free_block;
free_blocks = free_block;
}
static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)
{
if (free_block->next)
free_block->next->prev = free_block->prev;
if (free_block->prev)
free_block->prev->next = free_block->next;
else {
SLJIT_ASSERT(free_blocks == free_block);
free_blocks = free_block->next;
}
}
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
{
struct block_header *header;
struct block_header *next_header;
struct free_block *free_block;
sljit_uw chunk_size;
#ifdef SLJIT_HAS_CHUNK_HEADER
struct sljit_chunk_header *chunk_header;
#else /* !SLJIT_HAS_CHUNK_HEADER */
void *chunk_header;
#endif /* SLJIT_HAS_CHUNK_HEADER */
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
sljit_sw executable_offset;
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
if (size < (64 - sizeof(struct block_header)))
size = (64 - sizeof(struct block_header));
size = ALIGN_SIZE(size);
SLJIT_ALLOCATOR_LOCK();
free_block = free_blocks;
while (free_block) {
if (free_block->size >= size) {
chunk_size = free_block->size;
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
if (chunk_size > size + 64) {
/* We just cut a block from the end of the free block. */
chunk_size -= size;
free_block->size = chunk_size;
header = AS_BLOCK_HEADER(free_block, chunk_size);
header->prev_size = chunk_size;
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
header->executable_offset = free_block->header.executable_offset;
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
AS_BLOCK_HEADER(header, size)->prev_size = size;
}
else {
sljit_remove_free_block(free_block);
header = (struct block_header*)free_block;
size = chunk_size;
}
allocated_size += size;
header->size = size;
SLJIT_ALLOCATOR_UNLOCK();
return MEM_START(header);
}
free_block = free_block->next;
}
chunk_size = (size + CHUNK_EXTRA_SIZE + CHUNK_SIZE - 1) & CHUNK_MASK;
chunk_header = alloc_chunk(chunk_size);
if (!chunk_header) {
SLJIT_ALLOCATOR_UNLOCK();
return NULL;
}
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
executable_offset = (sljit_sw)((sljit_u8*)chunk_header->executable - (sljit_u8*)chunk_header);
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
chunk_size -= CHUNK_EXTRA_SIZE;
total_size += chunk_size;
header = (struct block_header*)(((sljit_u8*)chunk_header) + CHUNK_HEADER_SIZE);
header->prev_size = 0;
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
header->executable_offset = executable_offset;
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
if (chunk_size > size + 64) {
/* Cut the allocated space into a free and a used block. */
allocated_size += size;
header->size = size;
chunk_size -= size;
free_block = AS_FREE_BLOCK(header, size);
free_block->header.prev_size = size;
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
free_block->header.executable_offset = executable_offset;
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
sljit_insert_free_block(free_block, chunk_size);
next_header = AS_BLOCK_HEADER(free_block, chunk_size);
}
else {
/* All space belongs to this allocation. */
allocated_size += chunk_size;
header->size = chunk_size;
next_header = AS_BLOCK_HEADER(header, chunk_size);
}
SLJIT_ALLOCATOR_UNLOCK();
next_header->size = 1;
next_header->prev_size = chunk_size;
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
next_header->executable_offset = executable_offset;
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
return MEM_START(header);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
{
struct block_header *header;
struct free_block* free_block;
SLJIT_ALLOCATOR_LOCK();
header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
header = AS_BLOCK_HEADER(header, -header->executable_offset);
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
allocated_size -= header->size;
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
/* Connecting free blocks together if possible. */
/* If header->prev_size == 0, free_block will equal to header.
In this case, free_block->header.size will be > 0. */
free_block = AS_FREE_BLOCK(header, -(sljit_sw)header->prev_size);
if (SLJIT_UNLIKELY(!free_block->header.size)) {
free_block->size += header->size;
header = AS_BLOCK_HEADER(free_block, free_block->size);
header->prev_size = free_block->size;
}
else {
free_block = (struct free_block*)header;
sljit_insert_free_block(free_block, header->size);
}
header = AS_BLOCK_HEADER(free_block, free_block->size);
if (SLJIT_UNLIKELY(!header->size)) {
free_block->size += ((struct free_block*)header)->size;
sljit_remove_free_block((struct free_block*)header);
header = AS_BLOCK_HEADER(free_block, free_block->size);
header->prev_size = free_block->size;
}
/* The whole chunk is free. */
if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {
/* If this block is freed, we still have (allocated_size / 2) free space. */
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 + CHUNK_EXTRA_SIZE);
}
}
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);
SLJIT_ALLOCATOR_UNLOCK();
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
{
struct free_block* free_block;
struct free_block* next_free_block;
SLJIT_ALLOCATOR_LOCK();
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
free_block = free_blocks;
while (free_block) {
next_free_block = free_block->next;
if (!free_block->header.prev_size &&
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 + CHUNK_EXTRA_SIZE);
}
free_block = next_free_block;
}
SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks));
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);
SLJIT_ALLOCATOR_UNLOCK();
}
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr)
{
return ((struct block_header *)(ptr))[-1].executable_offset;
}
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */

View file

@ -1,89 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/mman.h>
#include <sys/procctl.h>
#ifdef PROC_WXMAP_CTL
static SLJIT_INLINE int sljit_is_wx_block(void)
{
static int wx_block = -1;
if (wx_block < 0) {
int sljit_wx_enable = PROC_WX_MAPPINGS_PERMIT;
wx_block = !!procctl(P_PID, 0, PROC_WXMAP_CTL, &sljit_wx_enable);
}
return wx_block;
}
#define SLJIT_IS_WX_BLOCK sljit_is_wx_block()
#else /* !PROC_WXMAP_CTL */
#define SLJIT_IS_WX_BLOCK (1)
#endif /* PROC_WXMAP_CTL */
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
{
void *retval;
int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
int flags = MAP_PRIVATE;
int fd = -1;
#ifdef PROT_MAX
prot |= PROT_MAX(prot);
#endif
#ifdef MAP_ANON
flags |= MAP_ANON;
#else /* !MAP_ANON */
if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero()))
return NULL;
fd = dev_zero;
#endif /* MAP_ANON */
retry:
retval = mmap(NULL, size, prot, flags, fd, 0);
if (retval == MAP_FAILED) {
if (!SLJIT_IS_WX_BLOCK)
goto retry;
return NULL;
}
/* HardenedBSD's mmap lies, so check permissions again. */
if (mprotect(retval, size, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {
munmap(retval, size);
return NULL;
}
return retval;
}
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
{
munmap(chunk, size);
}
#include "sljitExecAllocatorCore.c"

View file

@ -1,62 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/mman.h>
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
{
void *retval;
int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
int flags = MAP_PRIVATE;
int fd = -1;
#ifdef PROT_MAX
prot |= PROT_MAX(prot);
#endif
#ifdef MAP_ANON
flags |= MAP_ANON;
#else /* !MAP_ANON */
if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero()))
return NULL;
fd = dev_zero;
#endif /* MAP_ANON */
retval = mmap(NULL, size, prot, flags, fd, 0);
if (retval == MAP_FAILED)
return NULL;
return retval;
}
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
{
munmap(chunk, size);
}
#include "sljitExecAllocatorCore.c"

View file

@ -1,40 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec)
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
{
return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
}
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
{
SLJIT_UNUSED_ARG(size);
VirtualFree(chunk, 0, MEM_RELEASE);
}
#include "sljitExecAllocatorCore.c"

View file

@ -1,72 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define SLJIT_HAS_CHUNK_HEADER
#define SLJIT_HAS_EXECUTABLE_OFFSET
struct sljit_chunk_header {
void *executable;
};
/*
* MAP_REMAPDUP is a NetBSD extension available sinde 8.0, make sure to
* adjust your feature macros (ex: -D_NETBSD_SOURCE) as needed
*/
static SLJIT_INLINE struct sljit_chunk_header* alloc_chunk(sljit_uw size)
{
struct sljit_chunk_header *retval;
retval = (struct sljit_chunk_header *)mmap(NULL, size,
PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC),
MAP_ANON | MAP_SHARED, -1, 0);
if (retval == MAP_FAILED)
return NULL;
retval->executable = mremap(retval, size, NULL, size, MAP_REMAPDUP);
if (retval->executable == MAP_FAILED) {
munmap((void *)retval, size);
return NULL;
}
if (mprotect(retval->executable, size, PROT_READ | PROT_EXEC) == -1) {
munmap(retval->executable, size);
munmap((void *)retval, size);
return NULL;
}
return retval;
}
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
{
struct sljit_chunk_header *header = ((struct sljit_chunk_header *)chunk) - 1;
munmap(header->executable, size);
munmap((void *)header, size);
}
#include "sljitExecAllocatorCore.c"

View file

@ -1,172 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define SLJIT_HAS_CHUNK_HEADER
#define SLJIT_HAS_EXECUTABLE_OFFSET
struct sljit_chunk_header {
void *executable;
};
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#ifndef O_NOATIME
#define O_NOATIME 0
#endif
/* this is a linux extension available since kernel 3.11 */
#ifndef O_TMPFILE
#define O_TMPFILE 0x404000
#endif
#ifndef _GNU_SOURCE
char *secure_getenv(const char *name);
int mkostemp(char *template, int flags);
#endif
static SLJIT_INLINE int create_tempfile(void)
{
int fd;
char tmp_name[256];
size_t tmp_name_len = 0;
char *dir;
struct stat st;
#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
mode_t mode;
#endif
#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) {
fchmod(fd, 0);
return fd;
}
#endif
dir = secure_getenv("TMPDIR");
if (dir) {
size_t len = strlen(dir);
if (len > 0 && len < sizeof(tmp_name)) {
if ((stat(dir, &st) == 0) && S_ISDIR(st.st_mode)) {
memcpy(tmp_name, dir, len + 1);
tmp_name_len = len;
}
}
}
#ifdef P_tmpdir
if (!tmp_name_len) {
tmp_name_len = strlen(P_tmpdir);
if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name))
strcpy(tmp_name, P_tmpdir);
}
#endif
if (!tmp_name_len) {
strcpy(tmp_name, "/tmp");
tmp_name_len = 4;
}
SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name));
if (tmp_name_len > 1 && tmp_name[tmp_name_len - 1] == '/')
tmp_name[--tmp_name_len] = '\0';
fd = open(tmp_name, O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, 0);
if (fd != -1)
return fd;
if (tmp_name_len >= sizeof(tmp_name) - 7)
return -1;
strcpy(tmp_name + tmp_name_len, "/XXXXXX");
#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
mode = umask(0777);
#endif
fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME);
#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
umask(mode);
#else
fchmod(fd, 0);
#endif
if (fd == -1)
return -1;
if (unlink(tmp_name)) {
close(fd);
return -1;
}
return fd;
}
static SLJIT_INLINE struct sljit_chunk_header* alloc_chunk(sljit_uw size)
{
struct sljit_chunk_header *retval;
int fd;
fd = create_tempfile();
if (fd == -1)
return NULL;
if (ftruncate(fd, (off_t)size)) {
close(fd);
return NULL;
}
retval = (struct sljit_chunk_header *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (retval == MAP_FAILED) {
close(fd);
return NULL;
}
retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);
if (retval->executable == MAP_FAILED) {
munmap((void *)retval, size);
close(fd);
return NULL;
}
close(fd);
return retval;
}
static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
{
struct sljit_chunk_header *header = ((struct sljit_chunk_header *)chunk) - 1;
munmap(header->executable, size);
munmap((void *)header, size);
}
#include "sljitExecAllocatorCore.c"

View file

@ -1,141 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
This file contains a simple W^X executable memory allocator
In *NIX, MAP_ANON is required (that is considered a feature) so make
sure to set the right availability macros for your system or the code
will fail to build.
If your system doesn't support mapping of anonymous pages (ex: IRIX) it
is also likely that it doesn't need this allocator and should be using
the standard one instead.
It allocates a separate map for each code block and may waste a lot of
memory, because whatever was requested, will be rounded up to the page
size (minimum 4KB, but could be even bigger).
It changes the page permissions (RW <-> RX) as needed and therefore, if you
will be updating the code after it has been generated, need to make sure to
block any concurrent execution, or could result in a SIGBUS, that could
even manifest itself at a different address than the one that was being
modified.
Only use if you are unable to use the regular allocator because of security
restrictions and adding exceptions to your application or the system are
not possible.
*/
#include <sys/types.h>
#include <sys/mman.h>
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
sljit_update_wx_flags((from), (to), (enable_exec))
#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
#include <pthread.h>
#define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock)
#define SLJIT_SE_UNLOCK() pthread_mutex_unlock(&se_lock)
#else
#define SLJIT_SE_LOCK()
#define SLJIT_SE_UNLOCK()
#endif /* !SLJIT_SINGLE_THREADED */
#define SLJIT_WX_IS_BLOCK(ptr, size) generic_check_is_wx_block(ptr, size)
static SLJIT_INLINE int generic_check_is_wx_block(void *ptr, sljit_uw size)
{
if (SLJIT_LIKELY(!mprotect(ptr, size, PROT_EXEC)))
return !!mprotect(ptr, size, PROT_READ | PROT_WRITE);
return 1;
}
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
{
#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
static pthread_mutex_t se_lock = PTHREAD_MUTEX_INITIALIZER;
#endif
static int wx_block = -1;
int prot = PROT_READ | PROT_WRITE;
sljit_uw* ptr;
if (SLJIT_UNLIKELY(wx_block > 0))
return NULL;
#ifdef PROT_MAX
prot |= PROT_MAX(PROT_READ | PROT_WRITE | PROT_EXEC);
#endif
size += sizeof(sljit_uw);
ptr = (sljit_uw*)mmap(NULL, size, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED)
return NULL;
if (SLJIT_UNLIKELY(wx_block < 0)) {
SLJIT_SE_LOCK();
wx_block = SLJIT_WX_IS_BLOCK(ptr, size);
SLJIT_SE_UNLOCK();
if (SLJIT_UNLIKELY(wx_block)) {
munmap((void *)ptr, size);
return NULL;
}
}
*ptr++ = size;
return ptr;
}
#undef SLJIT_SE_UNLOCK
#undef SLJIT_SE_LOCK
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
{
sljit_uw *start_ptr = ((sljit_uw*)ptr) - 1;
munmap((void*)start_ptr, *start_ptr);
}
static void sljit_update_wx_flags(void *from, void *to, int enable_exec)
{
sljit_uw page_mask = (sljit_uw)get_page_alignment();
sljit_uw start = (sljit_uw)from;
sljit_uw end = (sljit_uw)to;
int prot = PROT_READ | (enable_exec ? PROT_EXEC : PROT_WRITE);
SLJIT_ASSERT(start < end);
start &= ~page_mask;
end = (end + page_mask) & ~page_mask;
mprotect((void*)start, end - start, prot);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
{
/* This allocator does not keep unused memory for future allocations. */
}

View file

@ -1,102 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
This file contains a simple W^X executable memory allocator
In *NIX, MAP_ANON is required (that is considered a feature) so make
sure to set the right availability macros for your system or the code
will fail to build.
If your system doesn't support mapping of anonymous pages (ex: IRIX) it
is also likely that it doesn't need this allocator and should be using
the standard one instead.
It allocates a separate map for each code block and may waste a lot of
memory, because whatever was requested, will be rounded up to the page
size (minimum 4KB, but could be even bigger).
It changes the page permissions (RW <-> RX) as needed and therefore, if you
will be updating the code after it has been generated, need to make sure to
block any concurrent execution, or could result in a SIGBUS, that could
even manifest itself at a different address than the one that was being
modified.
Only use if you are unable to use the regular allocator because of security
restrictions and adding exceptions to your application or the system are
not possible.
*/
#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \
sljit_update_wx_flags((from), (to), (enable_exec))
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
{
sljit_uw *ptr;
size += sizeof(sljit_uw);
ptr = (sljit_uw*)VirtualAlloc(NULL, size,
MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!ptr)
return NULL;
*ptr++ = size;
return ptr;
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
{
sljit_uw start = (sljit_uw)ptr - sizeof(sljit_uw);
#if defined(SLJIT_DEBUG) && SLJIT_DEBUG
sljit_uw page_mask = (sljit_uw)get_page_alignment();
SLJIT_ASSERT(!(start & page_mask));
#endif
VirtualFree((void*)start, 0, MEM_RELEASE);
}
static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec)
{
DWORD oldprot;
sljit_uw page_mask = (sljit_uw)get_page_alignment();
sljit_uw start = (sljit_uw)from;
sljit_uw end = (sljit_uw)to;
DWORD prot = enable_exec ? PAGE_EXECUTE : PAGE_READWRITE;
SLJIT_ASSERT(start < end);
start &= ~page_mask;
end = (end + page_mask) & ~page_mask;
VirtualProtect((void*)start, end - start, prot, &oldprot);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
{
/* This allocator does not keep unused memory for future allocations. */
}

View file

@ -1,142 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SLJIT_CONFIG_H_
#define SLJIT_CONFIG_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
This file contains the basic configuration options for the SLJIT compiler
and their default values. These options can be overridden in the
sljitConfigPre.h header file when SLJIT_HAVE_CONFIG_PRE is set to a
non-zero value.
*/
/* --------------------------------------------------------------------- */
/* Utilities */
/* --------------------------------------------------------------------- */
/* Implements a stack like data structure (by using mmap / VirtualAlloc */
/* or a custom allocator). */
#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. */
#define SLJIT_SINGLE_THREADED 0
#endif
/* --------------------------------------------------------------------- */
/* Configuration */
/* --------------------------------------------------------------------- */
/* If SLJIT_STD_MACROS_DEFINED is not defined, the application should
define SLJIT_MALLOC, SLJIT_FREE, SLJIT_MEMCPY, and NULL. */
#ifndef SLJIT_STD_MACROS_DEFINED
/* Disabled by default. */
#define SLJIT_STD_MACROS_DEFINED 0
#endif
/* Executable code allocation:
If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should
define SLJIT_MALLOC_EXEC and SLJIT_FREE_EXEC.
Optionally, depending on the implementation used for the allocator,
SLJIT_EXEC_OFFSET and SLJIT_UPDATE_WX_FLAGS might also be needed. */
#ifndef SLJIT_EXECUTABLE_ALLOCATOR
/* Enabled by default. */
#define SLJIT_EXECUTABLE_ALLOCATOR 1
/* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses
an allocator which does not set writable and executable
permission flags at the same time.
Instead, it creates a shared memory segment (usually backed by a file)
and maps it twice, with different permissions, depending on the use
case.
The trade-off is increased use of virtual memory, incompatibility with
fork(), and some possible additional security risks by the use of
publicly accessible files for the generated code. */
#ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR
/* Disabled by default. */
#define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0
#endif
/* When SLJIT_WX_EXECUTABLE_ALLOCATOR is enabled SLJIT uses an
allocator which does not set writable and executable permission
flags at the same time.
Instead, it creates a new independent map on each invocation and
switches permissions at the underlying pages as needed.
The trade-off is increased memory use and degraded performance. */
#ifndef SLJIT_WX_EXECUTABLE_ALLOCATOR
/* Disabled by default. */
#define SLJIT_WX_EXECUTABLE_ALLOCATOR 0
#endif
#endif /* !SLJIT_EXECUTABLE_ALLOCATOR */
/* Return with error when an invalid argument is passed. */
#ifndef SLJIT_ARGUMENT_CHECKS
/* Disabled by default */
#define SLJIT_ARGUMENT_CHECKS 0
#endif
/* Debug checks (assertions, etc.). */
#ifndef SLJIT_DEBUG
/* Enabled by default */
#define SLJIT_DEBUG 1
#endif
/* Verbose operations. */
#ifndef SLJIT_VERBOSE
/* Enabled by default */
#define SLJIT_VERBOSE 1
#endif
/*
SLJIT_IS_FPU_AVAILABLE
The availability of the FPU can be controlled by SLJIT_IS_FPU_AVAILABLE.
zero value - FPU is NOT present.
nonzero value - FPU is present.
*/
/* For further configurations, see the beginning of sljitConfigInternal.h */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SLJIT_CONFIG_H_ */

View file

@ -1,188 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SLJIT_CONFIG_CPU_H_
#define SLJIT_CONFIG_CPU_H_
/* --------------------------------------------------------------------- */
/* Architecture */
/* --------------------------------------------------------------------- */
/* Architecture selection. */
/* #define SLJIT_CONFIG_X86_32 1 */
/* #define SLJIT_CONFIG_X86_64 1 */
/* #define SLJIT_CONFIG_ARM_V6 1 */
/* #define SLJIT_CONFIG_ARM_V7 1 */
/* #define SLJIT_CONFIG_ARM_THUMB2 1 */
/* #define SLJIT_CONFIG_ARM_64 1 */
/* #define SLJIT_CONFIG_PPC_32 1 */
/* #define SLJIT_CONFIG_PPC_64 1 */
/* #define SLJIT_CONFIG_MIPS_32 1 */
/* #define SLJIT_CONFIG_MIPS_64 1 */
/* #define SLJIT_CONFIG_RISCV_32 1 */
/* #define SLJIT_CONFIG_RISCV_64 1 */
/* #define SLJIT_CONFIG_S390X 1 */
/* #define SLJIT_CONFIG_LOONGARCH_64 */
/* #define SLJIT_CONFIG_AUTO 1 */
/* #define SLJIT_CONFIG_UNSUPPORTED 1 */
/*****************/
/* Sanity check. */
/*****************/
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
+ (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
+ (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) \
+ (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
+ (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
+ (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
+ (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
+ (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
+ (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
+ (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
+ (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
+ (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
+ (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
+ (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) \
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
#error "Multiple architectures are selected"
#endif
#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \
&& !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
&& !(defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) \
&& !(defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
&& !(defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
&& !(defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
&& !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
&& !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
&& !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
&& !(defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) \
&& !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
&& !(defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64) \
&& !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \
&& !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
#if defined SLJIT_CONFIG_AUTO && !SLJIT_CONFIG_AUTO
#error "An architecture must be selected"
#else /* SLJIT_CONFIG_AUTO */
#define SLJIT_CONFIG_AUTO 1
#endif /* !SLJIT_CONFIG_AUTO */
#endif /* !SLJIT_CONFIG */
/********************************************************/
/* Automatic CPU detection (requires compiler support). */
/********************************************************/
#if (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO)
#ifndef _WIN32
#if defined(__i386__) || defined(__i386)
#define SLJIT_CONFIG_X86_32 1
#elif defined(__x86_64__)
#define SLJIT_CONFIG_X86_64 1
#elif defined(__aarch64__)
#define SLJIT_CONFIG_ARM_64 1
#elif defined(__thumb2__)
#define SLJIT_CONFIG_ARM_THUMB2 1
#elif (defined(__ARM_ARCH) && __ARM_ARCH >= 7) || \
((defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7S__)) \
|| (defined(__ARM_ARCH_8A__) || defined(__ARM_ARCH_8R__)) \
|| (defined(__ARM_ARCH_9A__)))
#define SLJIT_CONFIG_ARM_V7 1
#elif defined(__arm__) || defined (__ARM__)
#define SLJIT_CONFIG_ARM_V6 1
#elif defined(__ppc64__) || defined(__powerpc64__) || (defined(_ARCH_PPC64) && defined(__64BIT__)) || (defined(_POWER) && defined(__64BIT__))
#define SLJIT_CONFIG_PPC_64 1
#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER)
#define SLJIT_CONFIG_PPC_32 1
#elif defined(__mips__) && !defined(_LP64)
#define SLJIT_CONFIG_MIPS_32 1
#elif defined(__mips64)
#define SLJIT_CONFIG_MIPS_64 1
#elif defined (__riscv_xlen) && (__riscv_xlen == 32)
#define SLJIT_CONFIG_RISCV_32 1
#elif defined (__riscv_xlen) && (__riscv_xlen == 64)
#define SLJIT_CONFIG_RISCV_64 1
#elif defined (__loongarch_lp64)
#define SLJIT_CONFIG_LOONGARCH_64 1
#elif defined(__s390x__)
#define SLJIT_CONFIG_S390X 1
#else
/* Unsupported architecture */
#define SLJIT_CONFIG_UNSUPPORTED 1
#endif
#else /* _WIN32 */
#if defined(_M_X64) || defined(__x86_64__)
#define SLJIT_CONFIG_X86_64 1
#elif (defined(_M_ARM) && _M_ARM >= 7 && defined(_M_ARMT)) || defined(__thumb2__)
#define SLJIT_CONFIG_ARM_THUMB2 1
#elif (defined(_M_ARM) && _M_ARM >= 7)
#define SLJIT_CONFIG_ARM_V7 1
#elif defined(_ARM_)
#define SLJIT_CONFIG_ARM_V6 1
#elif defined(_M_ARM64) || defined(__aarch64__)
#define SLJIT_CONFIG_ARM_64 1
#else
#define SLJIT_CONFIG_X86_32 1
#endif
#endif /* !_WIN32 */
#endif /* SLJIT_CONFIG_AUTO */
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
#undef SLJIT_EXECUTABLE_ALLOCATOR
#endif /* SLJIT_CONFIG_UNSUPPORTED */
/******************************/
/* CPU family type detection. */
/******************************/
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
#define SLJIT_CONFIG_ARM_32 1
#endif
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
#define SLJIT_CONFIG_X86 1
#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
#define SLJIT_CONFIG_ARM 1
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#define SLJIT_CONFIG_PPC 1
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
#define SLJIT_CONFIG_MIPS 1
#elif (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
#define SLJIT_CONFIG_RISCV 1
#elif (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64)
#define SLJIT_CONFIG_LOONGARCH 1
#endif
#endif /* SLJIT_CONFIG_CPU_H_ */

View file

@ -1,881 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#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:
Types:
sljit_s8, sljit_u8 : signed and unsigned 8 bit integer type
sljit_s16, sljit_u16 : signed and unsigned 16 bit integer type
sljit_s32, sljit_u32 : signed and unsigned 32 bit integer type
sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer
sljit_p : unsgined pointer value (usually the same as sljit_uw, but
some 64 bit ABIs may use 32 bit pointers)
sljit_f32 : 32 bit single precision floating point value
sljit_f64 : 64 bit double precision floating point value
Macros for feature detection (boolean):
SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
SLJIT_LITTLE_ENDIAN : little endian architecture
SLJIT_BIG_ENDIAN : big endian architecture
SLJIT_UNALIGNED : unaligned memory accesses for non-fpu operations are supported
SLJIT_FPU_UNALIGNED : unaligned memory accesses for fpu operations are supported
SLJIT_MASKED_SHIFT : all word shifts are always masked
SLJIT_MASKED_SHIFT32 : all 32 bit shifts are always masked
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_ADDR() for more information
Constants:
SLJIT_NUMBER_OF_REGISTERS : number of available registers
SLJIT_NUMBER_OF_SCRATCH_REGISTERS : number of available scratch registers
SLJIT_NUMBER_OF_SAVED_REGISTERS : number of available saved registers
SLJIT_NUMBER_OF_FLOAT_REGISTERS : number of available floating point registers
SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS : number of available floating point scratch registers
SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS : number of available floating point saved registers
SLJIT_NUMBER_OF_TEMPORARY_REGISTERS : number of available temporary registers
SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS : number of available temporary floating point registers
SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index
SLJIT_F32_SHIFT : the shift required to apply when accessing
a single precision floating point array by index
SLJIT_F64_SHIFT : the shift required to apply when accessing
a double precision floating point array by index
SLJIT_PREF_SHIFT_REG : x86 systems prefers ecx for shifting by register
the scratch register index of ecx is stored in this variable
SLJIT_LOCALS_OFFSET : local space starting offset (SLJIT_SP + SLJIT_LOCALS_OFFSET)
SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
SLJIT_CONV_MAX_FLOAT : result when a floating point value is converted to integer
and the floating point value is higher than the maximum integer value
(possible values: SLJIT_CONV_RESULT_MAX_INT or SLJIT_CONV_RESULT_MIN_INT)
SLJIT_CONV_MIN_FLOAT : result when a floating point value is converted to integer
and the floating point value is lower than the minimum integer value
(possible values: SLJIT_CONV_RESULT_MAX_INT or SLJIT_CONV_RESULT_MIN_INT)
SLJIT_CONV_NAN_FLOAT : result when a NaN floating point value is converted to integer
(possible values: SLJIT_CONV_RESULT_MAX_INT, SLJIT_CONV_RESULT_MIN_INT,
or SLJIT_CONV_RESULT_ZERO)
Other macros:
SLJIT_TMP_R0 .. R9 : accessing temporary registers
SLJIT_TMP_R(i) : accessing temporary registers
SLJIT_TMP_FR0 .. FR9 : accessing temporary floating point registers
SLJIT_TMP_FR(i) : accessing temporary floating point registers
SLJIT_FUNC : calling convention attribute for both calling JIT from C and C calling back from JIT
SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (platform independent helper)
SLJIT_F64_SECOND(reg) : provides the register index of the second 32 bit part of a 64 bit
floating point register when SLJIT_HAS_F64_AS_F32_PAIR returns non-zero
*/
/***********************************************************/
/* Intel Control-flow Enforcement Technology (CET) spport. */
/***********************************************************/
#ifdef SLJIT_CONFIG_X86
#if defined(__CET__) && !(defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET)
#define SLJIT_CONFIG_X86_CET 1
#endif
#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined(__GNUC__)
#include <x86intrin.h>
#endif
#endif /* SLJIT_CONFIG_X86 */
/**********************************/
/* External function definitions. */
/**********************************/
/* General macros:
Note: SLJIT is designed to be independent from them as possible.
In release mode (SLJIT_DEBUG is not defined) only the following
external functions are needed:
*/
#ifndef SLJIT_MALLOC
#define SLJIT_MALLOC(size, allocator_data) malloc(size)
#endif
#ifndef SLJIT_FREE
#define SLJIT_FREE(ptr, allocator_data) free(ptr)
#endif
#ifndef SLJIT_MEMCPY
#define SLJIT_MEMCPY(dest, src, len) memcpy(dest, src, len)
#endif
#ifndef SLJIT_MEMMOVE
#define SLJIT_MEMMOVE(dest, src, len) memmove(dest, src, len)
#endif
#ifndef SLJIT_ZEROMEM
#define SLJIT_ZEROMEM(dest, len) memset(dest, 0, len)
#endif
/***************************/
/* Compiler helper macros. */
/***************************/
#if !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY)
#if defined(__GNUC__) && (__GNUC__ >= 3)
#define SLJIT_LIKELY(x) __builtin_expect((x), 1)
#define SLJIT_UNLIKELY(x) __builtin_expect((x), 0)
#else
#define SLJIT_LIKELY(x) (x)
#define SLJIT_UNLIKELY(x) (x)
#endif
#endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */
#ifndef SLJIT_INLINE
/* Inline functions. Some old compilers do not support them. */
#ifdef __SUNPRO_C
#if __SUNPRO_C < 0x560
#define SLJIT_INLINE
#else
#define SLJIT_INLINE inline
#endif /* __SUNPRO_C */
#else
#define SLJIT_INLINE __inline
#endif
#endif /* !SLJIT_INLINE */
#ifndef SLJIT_NOINLINE
/* Not inline functions. */
#if defined(__GNUC__)
#define SLJIT_NOINLINE __attribute__ ((noinline))
#else
#define SLJIT_NOINLINE
#endif
#endif /* !SLJIT_INLINE */
#ifndef SLJIT_UNUSED_ARG
/* Unused arguments. */
#define SLJIT_UNUSED_ARG(arg) (void)arg
#endif
/*********************************/
/* 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. */
#if defined(__GNUC__)
/* Disable unused warnings in gcc. */
#define SLJIT_API_FUNC_ATTRIBUTE static __attribute__((unused))
#else
#define SLJIT_API_FUNC_ATTRIBUTE static
#endif
#else
#define SLJIT_API_FUNC_ATTRIBUTE
#endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */
#endif /* defined SLJIT_API_FUNC_ATTRIBUTE */
/****************************/
/* Instruction cache flush. */
/****************************/
#ifdef __APPLE__
#include <AvailabilityMacros.h>
#endif
/*
* TODO:
*
* clang >= 15 could be safe to enable below
* older versions are known to abort in some targets
* https://github.com/PhilipHazel/pcre2/issues/92
*
* beware some vendors (ex: Microsoft, Apple) are known to have
* removed the code to support this builtin even if the call for
* __has_builtin reports it is available.
*
* make sure linking doesn't fail because __clear_cache() is
* missing before changing it or add an exception so that the
* system provided method that should be defined below is used
* instead.
*/
#if (!defined SLJIT_CACHE_FLUSH && defined __has_builtin)
#if __has_builtin(__builtin___clear_cache) && !defined(__clang__)
/*
* https://gcc.gnu.org/bugzilla//show_bug.cgi?id=91248
* https://gcc.gnu.org/bugzilla//show_bug.cgi?id=93811
* gcc's clear_cache builtin for power is broken
*/
#if !defined(SLJIT_CONFIG_PPC)
#define SLJIT_CACHE_FLUSH(from, to) \
__builtin___clear_cache((char*)(from), (char*)(to))
#endif
#endif /* gcc >= 10 */
#endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */
#ifndef SLJIT_CACHE_FLUSH
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
/* Not required to implement on archs with unified caches. */
#define SLJIT_CACHE_FLUSH(from, to)
#elif defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
/* Supported by all macs since Mac OS 10.5.
However, it does not work on non-jailbroken iOS devices,
although the compilation is successful. */
#include <libkern/OSCacheControl.h>
#define SLJIT_CACHE_FLUSH(from, to) \
sys_icache_invalidate((void*)(from), (size_t)((char*)(to) - (char*)(from)))
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
#define SLJIT_CACHE_FLUSH(from, to) \
ppc_cache_flush((from), (to))
#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
#elif defined(_WIN32)
#define SLJIT_CACHE_FLUSH(from, to) \
FlushInstructionCache(GetCurrentProcess(), (void*)(from), (char*)(to) - (char*)(from))
#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || defined(__clang__)
#define SLJIT_CACHE_FLUSH(from, to) \
__builtin___clear_cache((char*)(from), (char*)(to))
#elif defined __ANDROID__
/* Android ARMv7 with gcc lacks __clear_cache; use cacheflush instead. */
#include <sys/cachectl.h>
#define SLJIT_CACHE_FLUSH(from, to) \
cacheflush((long)(from), (long)(to), 0)
#else
/* Call __ARM_NR_cacheflush on ARM-Linux or the corresponding MIPS syscall. */
#define SLJIT_CACHE_FLUSH(from, to) \
__clear_cache((char*)(from), (char*)(to))
#endif
#endif /* !SLJIT_CACHE_FLUSH */
/******************************************************/
/* Integer and floating point type definitions. */
/******************************************************/
/* 8 bit byte type. */
typedef unsigned char sljit_u8;
typedef signed char sljit_s8;
/* 16 bit half-word type. */
typedef unsigned short int sljit_u16;
typedef signed short int sljit_s16;
/* 32 bit integer type. */
typedef unsigned int sljit_u32;
typedef signed int sljit_s32;
/* Machine word type. Enough for storing a pointer.
32 bit for 32 bit machines.
64 bit for 64 bit machines. */
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
/* Just to have something. */
#define SLJIT_WORD_SHIFT 0
typedef unsigned int sljit_uw;
typedef int sljit_sw;
#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
&& !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
&& !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
&& !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \
&& !(defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) \
&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
&& !(defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64)
#define SLJIT_32BIT_ARCHITECTURE 1
#define SLJIT_WORD_SHIFT 2
typedef unsigned int sljit_uw;
typedef int sljit_sw;
#else
#define SLJIT_64BIT_ARCHITECTURE 1
#define SLJIT_WORD_SHIFT 3
#ifdef _WIN32
#ifdef __GNUC__
/* These types do not require windows.h */
typedef unsigned long long sljit_uw;
typedef long long sljit_sw;
#else
typedef unsigned __int64 sljit_uw;
typedef __int64 sljit_sw;
#endif
#else /* !_WIN32 */
typedef unsigned long int sljit_uw;
typedef long int sljit_sw;
#endif /* _WIN32 */
#endif
typedef sljit_uw sljit_p;
/* Floating point types. */
typedef float sljit_f32;
typedef double sljit_f64;
/* Shift for pointer sized data. */
#define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT
/* Shift for double precision sized data. */
#define SLJIT_F32_SHIFT 2
#define SLJIT_F64_SHIFT 3
#define SLJIT_CONV_RESULT_MAX_INT 0
#define SLJIT_CONV_RESULT_MIN_INT 1
#define SLJIT_CONV_RESULT_ZERO 2
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MIN_INT
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT
#elif (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_ZERO
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MAX_INT
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MAX_INT
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT
#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MAX_INT
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
#define SLJIT_CONV_MAX_FLOAT SLJIT_CONV_RESULT_MAX_INT
#define SLJIT_CONV_MIN_FLOAT SLJIT_CONV_RESULT_MIN_INT
#define SLJIT_CONV_NAN_FLOAT SLJIT_CONV_RESULT_MIN_INT
#else
#error "Result for float to integer conversion is not defined"
#endif
#ifndef SLJIT_W
/* Defining long constants. */
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
#ifdef _WIN64
#define SLJIT_W(w) (w##ll)
#else /* !windows */
#define SLJIT_W(w) (w##l)
#endif /* windows */
#else /* 32 bit */
#define SLJIT_W(w) (w)
#endif /* unknown */
#endif /* !SLJIT_W */
/*************************/
/* Endianness detection. */
/*************************/
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
/* These macros are mostly useful for the applications. */
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
#ifdef __LITTLE_ENDIAN__
#define SLJIT_LITTLE_ENDIAN 1
#else
#define SLJIT_BIG_ENDIAN 1
#endif
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
#ifdef __MIPSEL__
#define SLJIT_LITTLE_ENDIAN 1
#else
#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
#define SLJIT_MIPS_REV __mips_isa_rev
#elif defined(__clang__) \
&& (defined(_MIPS_ARCH_OCTEON) || 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_S390X && SLJIT_CONFIG_S390X)
#define SLJIT_BIG_ENDIAN 1
#else
#define SLJIT_LITTLE_ENDIAN 1
#endif
#endif /* !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN) */
/* Sanity check. */
#if (defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && (defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
#error "Exactly one endianness must be selected"
#endif
#if !(defined SLJIT_BIG_ENDIAN && SLJIT_BIG_ENDIAN) && !(defined SLJIT_LITTLE_ENDIAN && SLJIT_LITTLE_ENDIAN)
#error "Exactly one endianness must be selected"
#endif
#ifndef SLJIT_UNALIGNED
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|| (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \
|| (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
|| (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|| (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
#define SLJIT_UNALIGNED 1
#endif
#endif /* !SLJIT_UNALIGNED */
#ifndef SLJIT_FPU_UNALIGNED
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|| (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|| (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
#define SLJIT_FPU_UNALIGNED 1
#endif
#endif /* !SLJIT_FPU_UNALIGNED */
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
/* Auto detect SSE2 support using CPUID.
On 64 bit x86 cpus, sse2 must be present. */
#define SLJIT_DETECT_SSE2 1
#endif
/*****************************************************************************************/
/* Calling convention of functions generated by SLJIT or called from the generated code. */
/*****************************************************************************************/
#ifndef SLJIT_FUNC
#define SLJIT_FUNC
#endif /* !SLJIT_FUNC */
/* Disable instrumentation for these functions as they may not be sound */
#ifndef SLJIT_FUNC_ATTRIBUTE
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
#define SLJIT_FUNC_ATTRIBUTE __attribute__((no_sanitize("memory")))
#endif /* __has_feature(memory_sanitizer) */
#endif /* defined(__has_feature) */
#endif
#ifndef SLJIT_FUNC_ATTRIBUTE
#define SLJIT_FUNC_ATTRIBUTE
#endif
#ifndef SLJIT_INDIRECT_CALL
#if ((defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) && (!defined _CALL_ELF || _CALL_ELF == 1)) \
|| ((defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) && defined _AIX)
/* It seems certain ppc compilers use an indirect addressing for functions
which makes things complicated. */
#define SLJIT_INDIRECT_CALL 1
#endif
#endif /* SLJIT_INDIRECT_CALL */
/* The offset which needs to be subtracted from the return address to
determine the next executed instruction after return. */
#ifndef SLJIT_RETURN_ADDRESS_OFFSET
#define SLJIT_RETURN_ADDRESS_OFFSET 0
#endif /* SLJIT_RETURN_ADDRESS_OFFSET */
/***************************************************/
/* Functions of the built-in executable allocator. */
/***************************************************/
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size);
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
#define SLJIT_BUILTIN_MALLOC_EXEC(size, exec_allocator_data) sljit_malloc_exec(size)
#define SLJIT_BUILTIN_FREE_EXEC(ptr, exec_allocator_data) sljit_free_exec(ptr)
#ifndef SLJIT_MALLOC_EXEC
#define SLJIT_MALLOC_EXEC(size, exec_allocator_data) SLJIT_BUILTIN_MALLOC_EXEC((size), (exec_allocator_data))
#endif /* SLJIT_MALLOC_EXEC */
#ifndef SLJIT_FREE_EXEC
#define SLJIT_FREE_EXEC(ptr, exec_allocator_data) SLJIT_BUILTIN_FREE_EXEC((ptr), (exec_allocator_data))
#endif /* SLJIT_FREE_EXEC */
#if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR)
SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#define SLJIT_EXEC_OFFSET(ptr) sljit_exec_offset(ptr)
#endif
#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
#ifndef SLJIT_EXEC_OFFSET
#define SLJIT_EXEC_OFFSET(ptr) 0
#endif
/**********************************************/
/* Registers and locals offset determination. */
/**********************************************/
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#define SLJIT_NUMBER_OF_REGISTERS 12
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 7
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 1
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 7
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1
#define SLJIT_LOCALS_OFFSET_BASE (8 * SSIZE_OF(sw))
#define SLJIT_PREF_SHIFT_REG SLJIT_R2
#define SLJIT_MASKED_SHIFT 1
#define SLJIT_MASKED_SHIFT32 1
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
#define SLJIT_NUMBER_OF_REGISTERS 13
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 2
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1
#ifndef _WIN64
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 6
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
#define SLJIT_LOCALS_OFFSET_BASE 0
#else /* _WIN64 */
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 10
#define SLJIT_LOCALS_OFFSET_BASE (4 * SSIZE_OF(sw))
#endif /* !_WIN64 */
#define SLJIT_PREF_SHIFT_REG SLJIT_R3
#define SLJIT_MASKED_SHIFT 1
#define SLJIT_MASKED_SHIFT32 1
#elif (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32)
#define SLJIT_NUMBER_OF_REGISTERS 12
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 2
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
#define SLJIT_LOCALS_OFFSET_BASE 0
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
#define SLJIT_NUMBER_OF_REGISTERS 26
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
#define SLJIT_LOCALS_OFFSET_BASE (2 * (sljit_s32)sizeof(sljit_sw))
#define SLJIT_MASKED_SHIFT 1
#define SLJIT_MASKED_SHIFT32 1
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
#define SLJIT_NUMBER_OF_REGISTERS 23
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 17
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 18
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX)
#define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * (sljit_s32)sizeof(sljit_sw))
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
/* Add +1 for double alignment. */
#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1) * (sljit_s32)sizeof(sljit_sw))
#else
#define SLJIT_LOCALS_OFFSET_BASE (3 * (sljit_s32)sizeof(sljit_sw))
#endif /* SLJIT_CONFIG_PPC_64 || _AIX */
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
#define SLJIT_NUMBER_OF_REGISTERS 21
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 13
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 6
#else
#define SLJIT_LOCALS_OFFSET_BASE 0
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 29
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#endif
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 3
#define SLJIT_MASKED_SHIFT 1
#define SLJIT_MASKED_SHIFT32 1
#elif (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
#define SLJIT_NUMBER_OF_REGISTERS 23
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 12
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
#define SLJIT_LOCALS_OFFSET_BASE 0
#define SLJIT_MASKED_SHIFT 1
#define SLJIT_MASKED_SHIFT32 1
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
/*
* https://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html#STACKFRAME
*
* 160
* .. FR6
* .. FR4
* .. FR2
* 128 FR0
* 120 R15 (used for SP)
* 112 R14
* 104 R13
* 96 R12
* ..
* 48 R6
* ..
* 16 R2
* 8 RESERVED
* 0 SP
*/
#define SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE 160
#define SLJIT_NUMBER_OF_REGISTERS 12
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 3
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1
#define SLJIT_LOCALS_OFFSET_BASE SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE
#define SLJIT_MASKED_SHIFT 1
#elif (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
#define SLJIT_NUMBER_OF_REGISTERS 23
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
#define SLJIT_LOCALS_OFFSET_BASE 0
#define SLJIT_MASKED_SHIFT 1
#define SLJIT_MASKED_SHIFT32 1
#elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
/* Just to have something. */
#define SLJIT_NUMBER_OF_REGISTERS 0
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 0
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 0
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 0
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 0
#define SLJIT_LOCALS_OFFSET_BASE 0
#endif
#define SLJIT_LOCALS_OFFSET (SLJIT_LOCALS_OFFSET_BASE)
#define SLJIT_NUMBER_OF_SCRATCH_REGISTERS \
(SLJIT_NUMBER_OF_REGISTERS - SLJIT_NUMBER_OF_SAVED_REGISTERS)
#define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \
(SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)
/**********************************/
/* Temporary register management. */
/**********************************/
#define SLJIT_TMP_REGISTER_BASE (SLJIT_NUMBER_OF_REGISTERS + 2)
#define SLJIT_TMP_FREGISTER_BASE (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1)
/* WARNING: Accessing temporary registers is not recommended, because they
are also used by the JIT compiler for various computations. Using them
might have any side effects including incorrect operations and crashes,
so use them at your own risk. The machine registers themselves might have
limitations, e.g. the r0 register on s390x / ppc cannot be used as
base address for memory operations. */
/* Temporary registers */
#define SLJIT_TMP_R0 (SLJIT_TMP_REGISTER_BASE + 0)
#define SLJIT_TMP_R1 (SLJIT_TMP_REGISTER_BASE + 1)
#define SLJIT_TMP_R2 (SLJIT_TMP_REGISTER_BASE + 2)
#define SLJIT_TMP_R3 (SLJIT_TMP_REGISTER_BASE + 3)
#define SLJIT_TMP_R4 (SLJIT_TMP_REGISTER_BASE + 4)
#define SLJIT_TMP_R5 (SLJIT_TMP_REGISTER_BASE + 5)
#define SLJIT_TMP_R6 (SLJIT_TMP_REGISTER_BASE + 6)
#define SLJIT_TMP_R7 (SLJIT_TMP_REGISTER_BASE + 7)
#define SLJIT_TMP_R8 (SLJIT_TMP_REGISTER_BASE + 8)
#define SLJIT_TMP_R9 (SLJIT_TMP_REGISTER_BASE + 9)
#define SLJIT_TMP_R(i) (SLJIT_TMP_REGISTER_BASE + (i))
#define SLJIT_TMP_FR0 (SLJIT_TMP_FREGISTER_BASE + 0)
#define SLJIT_TMP_FR1 (SLJIT_TMP_FREGISTER_BASE + 1)
#define SLJIT_TMP_FR2 (SLJIT_TMP_FREGISTER_BASE + 2)
#define SLJIT_TMP_FR3 (SLJIT_TMP_FREGISTER_BASE + 3)
#define SLJIT_TMP_FR4 (SLJIT_TMP_FREGISTER_BASE + 4)
#define SLJIT_TMP_FR5 (SLJIT_TMP_FREGISTER_BASE + 5)
#define SLJIT_TMP_FR6 (SLJIT_TMP_FREGISTER_BASE + 6)
#define SLJIT_TMP_FR7 (SLJIT_TMP_FREGISTER_BASE + 7)
#define SLJIT_TMP_FR8 (SLJIT_TMP_FREGISTER_BASE + 8)
#define SLJIT_TMP_FR9 (SLJIT_TMP_FREGISTER_BASE + 9)
#define SLJIT_TMP_FR(i) (SLJIT_TMP_FREGISTER_BASE + (i))
/********************************/
/* CPU status flags management. */
/********************************/
#if (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|| (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
|| (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|| (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
#define SLJIT_HAS_STATUS_FLAGS_STATE 1
#endif
/***************************************/
/* Floating point register management. */
/***************************************/
#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
|| (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#define SLJIT_F64_SECOND(reg) \
((reg) + SLJIT_FS0 + SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS)
#else /* !SLJIT_CONFIG_ARM_32 && !SLJIT_CONFIG_MIPS_32 */
#define SLJIT_F64_SECOND(reg) \
(reg)
#endif /* SLJIT_CONFIG_ARM_32 || SLJIT_CONFIG_MIPS_32 */
/*************************************/
/* Debug and verbose related macros. */
/*************************************/
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
#if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE)
/* SLJIT_HALT_PROCESS must halt the process. */
#ifndef SLJIT_HALT_PROCESS
#define SLJIT_HALT_PROCESS() \
abort();
#endif /* !SLJIT_HALT_PROCESS */
#endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */
/* Feel free to redefine these two macros. */
#ifndef SLJIT_ASSERT
#define SLJIT_ASSERT(x) \
do { \
if (SLJIT_UNLIKELY(!(x))) { \
printf("Assertion failed at " __FILE__ ":%d\n", __LINE__); \
SLJIT_HALT_PROCESS(); \
} \
} while (0)
#endif /* !SLJIT_ASSERT */
#ifndef SLJIT_UNREACHABLE
#define SLJIT_UNREACHABLE() \
do { \
printf("Should never been reached " __FILE__ ":%d\n", __LINE__); \
SLJIT_HALT_PROCESS(); \
} while (0)
#endif /* !SLJIT_UNREACHABLE */
#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
/* Forcing empty, but valid statements. */
#undef SLJIT_ASSERT
#undef SLJIT_UNREACHABLE
#define SLJIT_ASSERT(x) \
do { } while (0)
#define SLJIT_UNREACHABLE() \
do { } while (0)
#endif /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
#ifndef SLJIT_COMPILE_ASSERT
#define SLJIT_COMPILE_ASSERT(x, description) \
switch(0) { case 0: case ((x) ? 1 : 0): break; }
#endif /* !SLJIT_COMPILE_ASSERT */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SLJIT_CONFIG_INTERNAL_H_ */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,472 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* mips 32-bit arch dependent functions. */
static sljit_s32 emit_copysign(struct sljit_compiler *compiler, sljit_s32 op,
sljit_sw src1, sljit_sw src2, sljit_sw dst)
{
int is_32 = (op & SLJIT_32);
sljit_ins mfhc = MFC1, mthc = MTC1;
sljit_ins src1_r = FS(src1), src2_r = FS(src2), dst_r = FS(dst);
if (!is_32) {
switch (cpu_feature_list & CPU_FEATURE_FR) {
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
case CPU_FEATURE_FR:
mfhc = MFHC1;
mthc = MTHC1;
break;
#endif /* SLJIT_MIPS_REV >= 2 */
default:
src1_r |= (1 << 11);
src2_r |= (1 << 11);
dst_r |= (1 << 11);
break;
}
}
FAIL_IF(push_inst(compiler, mfhc | T(TMP_REG1) | src1_r, DR(TMP_REG1)));
FAIL_IF(push_inst(compiler, mfhc | T(TMP_REG2) | src2_r, DR(TMP_REG2)));
if (!is_32 && src1 != dst)
FAIL_IF(push_inst(compiler, MOV_fmt(FMT_S) | FS(src1) | FD(dst), MOVABLE_INS));
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
else
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif /* MIPS III */
FAIL_IF(push_inst(compiler, XOR | T(TMP_REG1) | D(TMP_REG2) | S(TMP_REG2), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, SRL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, XOR | T(TMP_REG2) | D(TMP_REG1) | S(TMP_REG1), DR(TMP_REG1)));
FAIL_IF(push_inst(compiler, mthc | T(TMP_REG1) | dst_r, MOVABLE_INS));
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
if (mthc == MTC1)
return push_inst(compiler, NOP, UNMOVABLE_INS);
#endif /* MIPS III */
return SLJIT_SUCCESS;
}
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
{
if (!(imm & ~0xffff))
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
if (imm < 0 && imm >= SIMM_MIN)
return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
}
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
{
FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f64 value)
{
union {
struct {
#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN
sljit_s32 lo;
sljit_s32 hi;
#else /* !SLJIT_LITTLE_ENDIAN */
sljit_s32 hi;
sljit_s32 lo;
#endif /* SLJIT_LITTLE_ENDIAN */
} bin;
sljit_f64 value;
} u;
CHECK_ERROR();
CHECK(check_sljit_emit_fset64(compiler, freg, value));
u.value = value;
if (u.bin.lo != 0)
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.bin.lo));
if (u.bin.hi != 0)
FAIL_IF(load_immediate(compiler, DR(TMP_REG2), u.bin.hi));
FAIL_IF(push_inst(compiler, MTC1 | (u.bin.lo != 0 ? T(TMP_REG1) : TA(0)) | FS(freg), MOVABLE_INS));
switch (cpu_feature_list & CPU_FEATURE_FR) {
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
case CPU_FEATURE_FR:
return push_inst(compiler, MTHC1 | (u.bin.hi != 0 ? T(TMP_REG2) : TA(0)) | FS(freg), MOVABLE_INS);
#endif /* SLJIT_MIPS_REV >= 2 */
default:
FAIL_IF(push_inst(compiler, MTC1 | (u.bin.hi != 0 ? T(TMP_REG2) : TA(0)) | FS(freg) | (1 << 11), MOVABLE_INS));
break;
}
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif /* MIPS III */
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 freg, sljit_s32 reg)
{
sljit_s32 reg2 = 0;
sljit_ins inst = FS(freg);
sljit_ins mthc = MTC1, mfhc = MFC1;
int is_32 = (op & SLJIT_32);
CHECK_ERROR();
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
op = GET_OPCODE(op);
if (reg & REG_PAIR_MASK) {
reg2 = REG_PAIR_SECOND(reg);
reg = REG_PAIR_FIRST(reg);
inst |= T(reg2);
if (op == SLJIT_COPY_TO_F64)
FAIL_IF(push_inst(compiler, MTC1 | inst, MOVABLE_INS));
else
FAIL_IF(push_inst(compiler, MFC1 | inst, DR(reg2)));
inst = FS(freg) | (1 << 11);
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
if (cpu_feature_list & CPU_FEATURE_FR) {
mthc = MTHC1;
mfhc = MFHC1;
inst = FS(freg);
}
#endif /* SLJIT_MIPS_REV >= 2 */
}
inst |= T(reg);
if (!is_32 && !reg2) {
switch (cpu_feature_list & CPU_FEATURE_FR) {
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
case CPU_FEATURE_FR:
mthc = MTHC1;
mfhc = MFHC1;
break;
#endif /* SLJIT_MIPS_REV >= 2 */
default:
inst |= (1 << 11);
break;
}
}
if (op == SLJIT_COPY_TO_F64)
FAIL_IF(push_inst(compiler, mthc | inst, MOVABLE_INS));
else
FAIL_IF(push_inst(compiler, mfhc | inst, DR(reg)));
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
if (mthc == MTC1 || mfhc == MFC1)
return push_inst(compiler, NOP, UNMOVABLE_INS);
#endif /* MIPS III */
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_ins *inst = (sljit_ins *)addr;
SLJIT_UNUSED_ARG(executable_offset);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
}
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr, sljit_u32 *extra_space)
{
sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;
sljit_u32 offset = 0;
sljit_s32 float_arg_count = 0;
sljit_s32 word_arg_count = 0;
sljit_s32 types = 0;
sljit_ins prev_ins = NOP;
sljit_ins ins = NOP;
sljit_u8 offsets[4];
sljit_u8 *offsets_ptr = offsets;
#if defined(SLJIT_LITTLE_ENDIAN) && SLJIT_LITTLE_ENDIAN
sljit_ins f64_hi = TA(7), f64_lo = TA(6);
#else
sljit_ins f64_hi = TA(6), f64_lo = TA(7);
#endif /* SLJIT_LITTLE_ENDIAN */
SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);
arg_types >>= SLJIT_ARG_SHIFT;
/* See ABI description in sljit_emit_enter. */
while (arg_types) {
types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
*offsets_ptr = (sljit_u8)offset;
switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
if (offset & 0x7) {
offset += sizeof(sljit_sw);
*offsets_ptr = (sljit_u8)offset;
}
if (word_arg_count == 0 && float_arg_count <= 1)
*offsets_ptr = (sljit_u8)(254 + float_arg_count);
offset += sizeof(sljit_f64);
float_arg_count++;
break;
case SLJIT_ARG_TYPE_F32:
if (word_arg_count == 0 && float_arg_count <= 1)
*offsets_ptr = (sljit_u8)(254 + float_arg_count);
offset += sizeof(sljit_f32);
float_arg_count++;
break;
default:
offset += sizeof(sljit_sw);
word_arg_count++;
break;
}
arg_types >>= SLJIT_ARG_SHIFT;
offsets_ptr++;
}
/* Stack is aligned to 16 bytes. */
SLJIT_ASSERT(offset <= 8 * sizeof(sljit_sw));
if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {
if (is_tail_call) {
offset = (offset + sizeof(sljit_sw) + 15) & ~(sljit_uw)0xf;
FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset, &prev_ins));
*extra_space = offset;
} else {
FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP)));
*extra_space = 16;
}
} else {
if (is_tail_call)
FAIL_IF(emit_stack_frame_release(compiler, 0, &prev_ins));
*extra_space = 0;
}
while (types) {
--offsets_ptr;
switch (types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
if (*offsets_ptr < 4 * sizeof(sljit_sw)) {
if (prev_ins != NOP)
FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
/* Must be preceded by at least one other argument,
* and its starting offset must be 8 because of alignment. */
SLJIT_ASSERT((*offsets_ptr >> 2) == 2);
switch (cpu_feature_list & CPU_FEATURE_FR) {
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 2
case CPU_FEATURE_FR:
prev_ins = MFHC1 | f64_hi | FS(float_arg_count);
break;
#endif /* SLJIT_MIPS_REV >= 2 */
default:
prev_ins = MFC1 | f64_hi | FS(float_arg_count) | (1 << 11);
break;
}
ins = MFC1 | f64_lo | FS(float_arg_count);
} else if (*offsets_ptr < 254)
ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr);
else if (*offsets_ptr == 254)
ins = MOV_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1);
float_arg_count--;
break;
case SLJIT_ARG_TYPE_F32:
if (*offsets_ptr < 4 * sizeof (sljit_sw))
ins = MFC1 | TA(4 + (*offsets_ptr >> 2)) | FS(float_arg_count);
else if (*offsets_ptr < 254)
ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr);
else if (*offsets_ptr == 254)
ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);
float_arg_count--;
break;
default:
if (*offsets_ptr >= 4 * sizeof (sljit_sw))
ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(*offsets_ptr);
else if ((*offsets_ptr >> 2) != word_arg_count - 1)
ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (*offsets_ptr >> 2));
else if (*offsets_ptr == 0)
ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4);
word_arg_count--;
break;
}
if (ins != NOP) {
if (prev_ins != NOP)
FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
prev_ins = ins;
ins = NOP;
}
types >>= SLJIT_ARG_SHIFT;
}
*ins_ptr = prev_ins;
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 arg_types)
{
struct sljit_jump *jump;
sljit_u32 extra_space = 0;
sljit_ins ins = NOP;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
if ((type & 0xff) != SLJIT_CALL_REG_ARG) {
extra_space = (sljit_u32)type;
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
} else if (type & SLJIT_CALL_RETURN)
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)
jump->flags |= IS_MOVABLE;
if (!(type & SLJIT_CALL_RETURN) || extra_space > 0) {
jump->flags |= IS_JAL;
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
jump->flags |= IS_CALL;
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
} else
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
jump->addr = compiler->size;
PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
/* Maximum number of instructions required for generating a constant. */
compiler->size += 2;
if (extra_space == 0)
return jump;
if (type & SLJIT_CALL_RETURN)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,
SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));
if (type & SLJIT_CALL_RETURN)
PTR_FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
PTR_FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),
(type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP)));
return jump;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 arg_types,
sljit_s32 src, sljit_sw srcw)
{
sljit_u32 extra_space = (sljit_u32)type;
sljit_ins ins;
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
if (src & SLJIT_MEM) {
ADJUST_LOCAL_OFFSET(src, srcw);
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
src = PIC_ADDR_REG;
srcw = 0;
}
if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
if (type & SLJIT_CALL_RETURN) {
if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
src = PIC_ADDR_REG;
srcw = 0;
}
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
if (ins != NOP)
FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
}
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_ijump(compiler, type, src, srcw);
}
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
if (src == SLJIT_IMM)
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
else if (src != PIC_ADDR_REG)
FAIL_IF(push_inst(compiler, ADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
/* Register input. */
if (!(type & SLJIT_CALL_RETURN) || extra_space > 0)
FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
else
FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
if (extra_space == 0)
return SLJIT_SUCCESS;
if (type & SLJIT_CALL_RETURN)
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,
SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));
if (type & SLJIT_CALL_RETURN)
FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),
(type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP));
}

View file

@ -1,387 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* mips 64-bit arch dependent functions. */
static sljit_s32 emit_copysign(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src1, sljit_s32 src2, sljit_s32 dst)
{
FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | T(TMP_REG1) | FS(src1), DR(TMP_REG1)));
FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | T(TMP_REG2) | FS(src2), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG2) | T(TMP_REG1) | D(TMP_REG2), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, SELECT_OP(DSLL32, SLL) | T(TMP_REG2) | D(TMP_REG2) | SH_IMM(31), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, XOR | S(TMP_REG1) | T(TMP_REG2) | D(TMP_REG1), DR(TMP_REG1)));
FAIL_IF(push_inst(compiler, SELECT_OP(DMTC1, MTC1) | T(TMP_REG1) | FS(dst), MOVABLE_INS));
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
if (!(op & SLJIT_32))
return push_inst(compiler, NOP, UNMOVABLE_INS);
#endif /* MIPS III */
return SLJIT_SUCCESS;
}
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm)
{
sljit_s32 shift = 32;
sljit_s32 shift2;
sljit_s32 inv = 0;
sljit_ins ins;
sljit_uw uimm;
if (!(imm & ~0xffff))
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
if (imm < 0 && imm >= SIMM_MIN)
return push_inst(compiler, ADDIU | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(imm >> 16), dst_ar));
return (imm & 0xffff) ? push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar) : SLJIT_SUCCESS;
}
/* Zero extended number. */
uimm = (sljit_uw)imm;
if (imm < 0) {
uimm = ~(sljit_uw)imm;
inv = 1;
}
while (!(uimm & 0xff00000000000000l)) {
shift -= 8;
uimm <<= 8;
}
if (!(uimm & 0xf000000000000000l)) {
shift -= 4;
uimm <<= 4;
}
if (!(uimm & 0xc000000000000000l)) {
shift -= 2;
uimm <<= 2;
}
if ((sljit_sw)uimm < 0) {
uimm >>= 1;
shift += 1;
}
SLJIT_ASSERT(((uimm & 0xc000000000000000l) == 0x4000000000000000l) && (shift > 0) && (shift <= 32));
if (inv)
uimm = ~uimm;
FAIL_IF(push_inst(compiler, LUI | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
if (uimm & 0x0000ffff00000000l)
FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 32), dst_ar));
imm &= (1l << shift) - 1;
if (!(imm & ~0xffff)) {
ins = (shift == 32) ? DSLL32 : DSLL;
if (shift < 32)
ins |= SH_IMM(shift);
FAIL_IF(push_inst(compiler, ins | TA(dst_ar) | DA(dst_ar), dst_ar));
return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
}
/* Double shifts needs to be performed. */
uimm <<= 32;
shift2 = shift - 16;
while (!(uimm & 0xf000000000000000l)) {
shift2 -= 4;
uimm <<= 4;
}
if (!(uimm & 0xc000000000000000l)) {
shift2 -= 2;
uimm <<= 2;
}
if (!(uimm & 0x8000000000000000l)) {
shift2--;
uimm <<= 1;
}
SLJIT_ASSERT((uimm & 0x8000000000000000l) && (shift2 > 0) && (shift2 <= 16));
FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift - shift2), dst_ar));
FAIL_IF(push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(uimm >> 48), dst_ar));
FAIL_IF(push_inst(compiler, DSLL | TA(dst_ar) | DA(dst_ar) | SH_IMM(shift2), dst_ar));
imm &= (1l << shift2) - 1;
return !(imm & 0xffff) ? SLJIT_SUCCESS : push_inst(compiler, ORI | SA(dst_ar) | TA(dst_ar) | IMM(imm), dst_ar);
}
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value)
{
FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 48), DR(dst)));
FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 32), DR(dst)));
FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
FAIL_IF(push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value >> 16), DR(dst)));
FAIL_IF(push_inst(compiler, DSLL | T(dst) | D(dst) | SH_IMM(16), DR(dst)));
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f64 value)
{
union {
sljit_sw imm;
sljit_f64 value;
} u;
CHECK_ERROR();
CHECK(check_sljit_emit_fset64(compiler, freg, value));
u.value = value;
if (u.imm == 0) {
FAIL_IF(push_inst(compiler, DMTC1 | TA(0) | FS(freg), MOVABLE_INS));
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif /* MIPS III */
return SLJIT_SUCCESS;
}
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), u.imm));
FAIL_IF(push_inst(compiler, DMTC1 | T(TMP_REG1) | FS(freg), MOVABLE_INS));
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
#endif /* MIPS III */
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 freg, sljit_s32 reg)
{
sljit_ins inst;
CHECK_ERROR();
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
inst = T(reg) | FS(freg);
if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)
FAIL_IF(push_inst(compiler, SELECT_OP(DMTC1, MTC1) | inst, MOVABLE_INS));
else
FAIL_IF(push_inst(compiler, SELECT_OP(DMFC1, MFC1) | inst, DR(reg)));
#if !defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV <= 1
if (!(op & SLJIT_32))
return push_inst(compiler, NOP, UNMOVABLE_INS);
#endif /* MIPS III */
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_ins *inst = (sljit_ins *)addr;
SLJIT_UNUSED_ARG(executable_offset);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 0);
inst[0] = (inst[0] & 0xffff0000) | ((sljit_ins)(new_target >> 48) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | ((sljit_ins)(new_target >> 32) & 0xffff);
inst[3] = (inst[3] & 0xffff0000) | ((sljit_ins)(new_target >> 16) & 0xffff);
inst[5] = (inst[5] & 0xffff0000) | ((sljit_ins)new_target & 0xffff);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 6);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
}
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
{
sljit_s32 arg_count = 0;
sljit_s32 word_arg_count = 0;
sljit_s32 float_arg_count = 0;
sljit_s32 types = 0;
sljit_ins prev_ins = *ins_ptr;
sljit_ins ins = NOP;
SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);
arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
case SLJIT_ARG_TYPE_F32:
arg_count++;
float_arg_count++;
break;
default:
arg_count++;
word_arg_count++;
break;
}
arg_types >>= SLJIT_ARG_SHIFT;
}
while (types) {
switch (types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
if (arg_count != float_arg_count)
ins = MOV_fmt(FMT_D) | FS(float_arg_count) | FD(arg_count);
else if (arg_count == 1)
ins = MOV_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1);
arg_count--;
float_arg_count--;
break;
case SLJIT_ARG_TYPE_F32:
if (arg_count != float_arg_count)
ins = MOV_fmt(FMT_S) | FS(float_arg_count) | FD(arg_count);
else if (arg_count == 1)
ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);
arg_count--;
float_arg_count--;
break;
default:
if (arg_count != word_arg_count)
ins = DADDU | S(word_arg_count) | TA(0) | D(arg_count);
else if (arg_count == 1)
ins = DADDU | S(SLJIT_R0) | TA(0) | DA(4);
arg_count--;
word_arg_count--;
break;
}
if (ins != NOP) {
if (prev_ins != NOP)
FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
prev_ins = ins;
ins = NOP;
}
types >>= SLJIT_ARG_SHIFT;
}
*ins_ptr = prev_ins;
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 arg_types)
{
struct sljit_jump *jump;
sljit_ins ins = NOP;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
if (type & SLJIT_CALL_RETURN)
PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
if (ins == NOP && compiler->delay_slot != UNMOVABLE_INS)
jump->flags |= IS_MOVABLE;
if (!(type & SLJIT_CALL_RETURN)) {
jump->flags |= IS_JAL;
if ((type & 0xff) != SLJIT_CALL_REG_ARG)
jump->flags |= IS_CALL;
PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
} else
PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
jump->addr = compiler->size;
PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
/* Maximum number of instructions required for generating a constant. */
compiler->size += 6;
return jump;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 arg_types,
sljit_s32 src, sljit_sw srcw)
{
sljit_ins ins = NOP;
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
if (src & SLJIT_MEM) {
ADJUST_LOCAL_OFFSET(src, srcw);
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
src = PIC_ADDR_REG;
srcw = 0;
}
if ((type & 0xff) == SLJIT_CALL_REG_ARG) {
if (type & SLJIT_CALL_RETURN) {
if (src >= SLJIT_FIRST_SAVED_REG && src <= (SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options))) {
FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
src = PIC_ADDR_REG;
srcw = 0;
}
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
if (ins != NOP)
FAIL_IF(push_inst(compiler, ins, MOVABLE_INS));
}
SLJIT_SKIP_CHECKS(compiler);
return sljit_emit_ijump(compiler, type, src, srcw);
}
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
if (src == SLJIT_IMM)
FAIL_IF(load_immediate(compiler, DR(PIC_ADDR_REG), srcw));
else if (src != PIC_ADDR_REG)
FAIL_IF(push_inst(compiler, DADDU | S(src) | TA(0) | D(PIC_ADDR_REG), DR(PIC_ADDR_REG)));
if (type & SLJIT_CALL_RETURN)
FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
FAIL_IF(call_with_args(compiler, arg_types, &ins));
/* Register input. */
if (!(type & SLJIT_CALL_RETURN))
FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
else
FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
return push_inst(compiler, ins, UNMOVABLE_INS);
}

File diff suppressed because it is too large Load diff

View file

@ -1,485 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* ppc 32-bit arch dependent functions. */
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
{
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
if (!(imm & ~0xffff))
return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
}
/* Simplified mnemonics: clrlwi. */
#define INS_CLEAR_LEFT(dst, src, from) \
(RLWINM | S(src) | A(dst) | RLWI_MBE(from, 31))
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_s32 src2)
{
sljit_u32 imm;
switch (op) {
case SLJIT_MOV:
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
case SLJIT_MOV_P:
SLJIT_ASSERT(src1 == TMP_REG1);
if (dst != src2)
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
return SLJIT_SUCCESS;
case SLJIT_MOV_U8:
case SLJIT_MOV_S8:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_S8)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
}
else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
else {
SLJIT_ASSERT(dst == src2);
}
return SLJIT_SUCCESS;
case SLJIT_MOV_U16:
case SLJIT_MOV_S16:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_S16)
return push_inst(compiler, EXTSH | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
}
else {
SLJIT_ASSERT(dst == src2);
}
return SLJIT_SUCCESS;
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, CNTLZW | S(src2) | A(dst));
case SLJIT_CTZ:
SLJIT_ASSERT(src1 == TMP_REG1);
FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2)));
FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1)));
FAIL_IF(push_inst(compiler, CNTLZW | S(dst) | A(dst)));
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM(-32)));
/* The highest bits are set, if dst < 32, zero otherwise. */
FAIL_IF(push_inst(compiler, SRWI(27) | S(TMP_REG1) | A(TMP_REG1)));
return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1));
case SLJIT_ADD:
if (flags & ALT_FORM1) {
/* Setting XER SO is not enough, CR SO is also needed. */
return push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
}
if (flags & ALT_FORM2) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
SLJIT_ASSERT(src2 == TMP_REG2);
if (flags & ALT_FORM3)
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
imm = compiler->imm;
if (flags & ALT_FORM4) {
FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));
src1 = dst;
}
return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));
}
if (flags & ALT_FORM3) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
}
SLJIT_ASSERT(!(flags & ALT_FORM4));
if (!(flags & ALT_SET_FLAGS))
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
if (flags & ALT_FORM5)
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
case SLJIT_ADDC:
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
case SLJIT_SUB:
if (flags & ALT_FORM1) {
if (flags & ALT_FORM2) {
FAIL_IF(push_inst(compiler, CMPLI | CRD(0) | A(src1) | compiler->imm));
if (!(flags & ALT_FORM3))
return SLJIT_SUCCESS;
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
}
FAIL_IF(push_inst(compiler, CMPL | CRD(0) | A(src1) | B(src2)));
if (!(flags & ALT_FORM3))
return SLJIT_SUCCESS;
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
}
if (flags & ALT_FORM2) {
if (flags & ALT_FORM3) {
FAIL_IF(push_inst(compiler, CMPI | CRD(0) | A(src1) | compiler->imm));
if (!(flags & ALT_FORM4))
return SLJIT_SUCCESS;
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
}
FAIL_IF(push_inst(compiler, CMP | CRD(0) | A(src1) | B(src2)));
if (!(flags & ALT_FORM4))
return SLJIT_SUCCESS;
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
}
if (flags & ALT_FORM3) {
/* Setting XER SO is not enough, CR SO is also needed. */
if (src1 != TMP_ZERO)
return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
return push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
}
if (flags & ALT_FORM4) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
}
if (!(flags & ALT_SET_FLAGS)) {
SLJIT_ASSERT(src1 != TMP_ZERO);
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
}
if (flags & ALT_FORM5)
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
if (src1 != TMP_ZERO)
return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
case SLJIT_SUBC:
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
case SLJIT_MUL:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
}
return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
case SLJIT_AND:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
}
if (flags & ALT_FORM2) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
}
return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_OR:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
}
if (flags & ALT_FORM2) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
}
if (flags & ALT_FORM3) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm;
FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm)));
return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16));
}
return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_XOR:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
}
if (flags & ALT_FORM2) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
}
if (flags & ALT_FORM3) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm;
FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm)));
return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16));
}
if (flags & ALT_FORM4) {
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
}
return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_SHL:
case SLJIT_MSHL:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm & 0x1f;
return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst));
}
if (op == SLJIT_MSHL) {
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
src2 = TMP_REG2;
}
return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_LSHR:
case SLJIT_MLSHR:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm & 0x1f;
/* Since imm can be 0, SRWI() cannot be used. */
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31));
}
if (op == SLJIT_MLSHR) {
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
src2 = TMP_REG2;
}
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_ASHR:
case SLJIT_MASHR:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm & 0x1f;
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11));
}
if (op == SLJIT_MASHR) {
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | 0x1f));
src2 = TMP_REG2;
}
return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_ROTL:
case SLJIT_ROTR:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm;
if (op == SLJIT_ROTR)
imm = (sljit_u32)(-(sljit_s32)imm);
imm &= 0x1f;
return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31));
}
if (op == SLJIT_ROTR) {
FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0));
src2 = TMP_REG2;
}
return push_inst(compiler, RLWNM | S(src1) | A(dst) | B(src2) | RLWI_MBE(0, 31));
}
SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
}
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
{
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
}
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
sljit_s32 invert_sign = 1;
if (src == SLJIT_IMM) {
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ (sljit_sw)0x80000000));
src = TMP_REG1;
invert_sign = 0;
} else if (!FAST_IS_REG(src)) {
FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
src = TMP_REG1;
}
/* First, a special double precision floating point value is constructed:
(2^53 + (src xor (2^31)))
The upper 32 bits of this number is a constant, and the lower 32 bits
is simply the value of the source argument. The xor 2^31 operation adds
0x80000000 to the source argument, which moves it into the 0 - 0xffffffff
range. Finally we substract 2^53 + 2^31 to get the converted value. */
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
if (invert_sign)
FAIL_IF(push_inst(compiler, XORIS | S(src) | A(TMP_REG1) | 0x8000));
FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG1) | A(0) | 0x8000));
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, STW | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
if (op & SLJIT_32)
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
if (dst & SLJIT_MEM)
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
return SLJIT_SUCCESS;
}
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
if (src == SLJIT_IMM) {
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
src = TMP_REG1;
} else if (!FAST_IS_REG(src)) {
FAIL_IF(emit_op_mem(compiler, WORD_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
src = TMP_REG1;
}
/* First, a special double precision floating point value is constructed:
(2^53 + src)
The upper 32 bits of this number is a constant, and the lower 32 bits
is simply the value of the source argument. Finally we substract 2^53
to get the converted value. */
FAIL_IF(push_inst(compiler, ADDIS | D(TMP_REG2) | A(0) | 0x4330));
FAIL_IF(push_inst(compiler, STW | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
FAIL_IF(push_inst(compiler, STW | S(TMP_REG2) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, STW | S(TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG2) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, FSUB | FD(dst_r) | FA(TMP_FREG1) | FB(TMP_FREG2)));
if (op & SLJIT_32)
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
if (dst & SLJIT_MEM)
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f64 value)
{
union {
sljit_s32 imm[2];
sljit_f64 value;
} u;
CHECK_ERROR();
CHECK(check_sljit_emit_fset64(compiler, freg, value));
u.value = value;
if (u.imm[0] != 0)
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0]));
if (u.imm[1] != 0)
FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1]));
/* Saved in the same endianness. */
FAIL_IF(push_inst(compiler, STW | S(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, STW | S(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | A(SLJIT_SP) | (TMP_MEM_OFFSET + sizeof(sljit_s32))));
return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 freg, sljit_s32 reg)
{
sljit_s32 reg2 = 0;
CHECK_ERROR();
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
if (op & SLJIT_32) {
if (op == SLJIT_COPY32_TO_F32) {
FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
return push_inst(compiler, LFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
}
FAIL_IF(push_inst(compiler, STFS | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
}
if (reg & REG_PAIR_MASK) {
reg2 = REG_PAIR_SECOND(reg);
reg = REG_PAIR_FIRST(reg);
}
if (op == SLJIT_COPY_TO_F64) {
FAIL_IF(push_inst(compiler, STW | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI));
if (reg2 != 0)
FAIL_IF(push_inst(compiler, STW | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
else
FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
}
FAIL_IF(push_inst(compiler, STFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
if (reg2 != 0)
FAIL_IF(push_inst(compiler, LWZ | S(reg2) | A(SLJIT_SP) | TMP_MEM_OFFSET_LO));
return push_inst(compiler, LWZ | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET_HI);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_ins *inst = (sljit_ins *)addr;
SLJIT_UNUSED_ARG(executable_offset);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}

View file

@ -1,719 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* ppc 64-bit arch dependent functions. */
#if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
#define ASM_SLJIT_CLZ(src, dst) \
__asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
#elif defined(__xlc__)
#error "Please enable GCC syntax for inline assembly statements"
#else
#error "Must implement count leading zeroes"
#endif
/* Computes SLDI(63 - shift). */
#define PUSH_SLDI_NEG(reg, shift) \
push_inst(compiler, RLDICR | S(reg) | A(reg) | RLDI_SH(63 - shift) | RLDI_ME(shift))
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
{
sljit_uw tmp;
sljit_uw shift;
sljit_uw tmp2;
sljit_uw shift2;
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
if (((sljit_uw)imm >> 16) == 0)
return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 16)));
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
}
if (((sljit_uw)imm >> 32) == 0) {
FAIL_IF(push_inst(compiler, ORIS | S(TMP_ZERO) | A(reg) | IMM(imm >> 16)));
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm)) : SLJIT_SUCCESS;
}
/* Count leading zeroes. */
tmp = (sljit_uw)((imm >= 0) ? imm : ~imm);
ASM_SLJIT_CLZ(tmp, shift);
SLJIT_ASSERT(shift > 0);
shift--;
tmp = ((sljit_uw)imm << shift);
if ((tmp & ~0xffff000000000000ul) == 0) {
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
shift += 15;
return PUSH_SLDI_NEG(reg, shift);
}
if ((tmp & ~0xffffffff00000000ul) == 0) {
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32)));
shift += 31;
return PUSH_SLDI_NEG(reg, shift);
}
/* Cut out the 16 bit from immediate. */
shift += 15;
tmp2 = (sljit_uw)imm & (((sljit_uw)1 << (63 - shift)) - 1);
if (tmp2 <= 0xffff) {
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
FAIL_IF(PUSH_SLDI_NEG(reg, shift));
return push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)tmp2);
}
if (tmp2 <= 0xffffffff) {
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
FAIL_IF(PUSH_SLDI_NEG(reg, shift));
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 16)));
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS;
}
ASM_SLJIT_CLZ(tmp2, shift2);
tmp2 <<= shift2;
if ((tmp2 & ~0xffff000000000000ul) == 0) {
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
shift2 += 15;
shift += (63 - shift2);
FAIL_IF(PUSH_SLDI_NEG(reg, shift));
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 48)));
return PUSH_SLDI_NEG(reg, shift2);
}
/* The general version. */
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)((sljit_uw)imm >> 48)));
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32)));
FAIL_IF(PUSH_SLDI_NEG(reg, 31));
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16)));
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm));
}
#undef PUSH_SLDI_NEG
#define CLRLDI(dst, src, n) \
(RLDICL | S(src) | A(dst) | RLDI_SH(0) | RLDI_MB(n))
/* Sign extension for integer operations. */
#define UN_EXTS() \
if ((flags & (ALT_SIGN_EXT | REG2_SOURCE)) == (ALT_SIGN_EXT | REG2_SOURCE)) { \
FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
src2 = TMP_REG2; \
}
#define BIN_EXTS() \
if (flags & ALT_SIGN_EXT) { \
if (flags & REG1_SOURCE) { \
FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
src1 = TMP_REG1; \
} \
if (flags & REG2_SOURCE) { \
FAIL_IF(push_inst(compiler, EXTSW | S(src2) | A(TMP_REG2))); \
src2 = TMP_REG2; \
} \
}
#define BIN_IMM_EXTS() \
if ((flags & (ALT_SIGN_EXT | REG1_SOURCE)) == (ALT_SIGN_EXT | REG1_SOURCE)) { \
FAIL_IF(push_inst(compiler, EXTSW | S(src1) | A(TMP_REG1))); \
src1 = TMP_REG1; \
}
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_s32 src2)
{
sljit_u32 imm;
switch (op) {
case SLJIT_MOV:
case SLJIT_MOV_P:
SLJIT_ASSERT(src1 == TMP_REG1);
if (dst != src2)
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
return SLJIT_SUCCESS;
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_S32)
return push_inst(compiler, EXTSW | S(src2) | A(dst));
return push_inst(compiler, CLRLDI(dst, src2, 32));
}
else {
SLJIT_ASSERT(dst == src2);
}
return SLJIT_SUCCESS;
case SLJIT_MOV_U8:
case SLJIT_MOV_S8:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_S8)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
return push_inst(compiler, CLRLDI(dst, src2, 56));
}
else if ((flags & REG_DEST) && op == SLJIT_MOV_S8)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
else {
SLJIT_ASSERT(dst == src2);
}
return SLJIT_SUCCESS;
case SLJIT_MOV_U16:
case SLJIT_MOV_S16:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_S16)
return push_inst(compiler, EXTSH | S(src2) | A(dst));
return push_inst(compiler, CLRLDI(dst, src2, 48));
}
else {
SLJIT_ASSERT(dst == src2);
}
return SLJIT_SUCCESS;
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(src2) | A(dst));
case SLJIT_CTZ:
SLJIT_ASSERT(src1 == TMP_REG1);
FAIL_IF(push_inst(compiler, NEG | D(TMP_REG1) | A(src2)));
FAIL_IF(push_inst(compiler, AND | S(src2) | A(dst) | B(TMP_REG1)));
FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(dst) | A(dst)));
FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(dst) | IMM((flags & ALT_FORM1) ? -32 : -64)));
/* The highest bits are set, if dst < bit width, zero otherwise. */
FAIL_IF(push_inst(compiler, ((flags & ALT_FORM1) ? SRWI(27) : SRDI(58)) | S(TMP_REG1) | A(TMP_REG1)));
return push_inst(compiler, XOR | S(dst) | A(dst) | B(TMP_REG1));
case SLJIT_ADD:
if (flags & ALT_FORM1) {
if (flags & ALT_SIGN_EXT) {
FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1)));
src1 = TMP_REG1;
FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2)));
src2 = TMP_REG2;
}
/* Setting XER SO is not enough, CR SO is also needed. */
FAIL_IF(push_inst(compiler, ADD | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2)));
if (flags & ALT_SIGN_EXT)
return push_inst(compiler, SRDI(32) | S(dst) | A(dst));
return SLJIT_SUCCESS;
}
if (flags & ALT_FORM2) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
SLJIT_ASSERT(src2 == TMP_REG2);
if (flags & ALT_FORM3)
return push_inst(compiler, ADDIS | D(dst) | A(src1) | compiler->imm);
imm = compiler->imm;
if (flags & ALT_FORM4) {
FAIL_IF(push_inst(compiler, ADDIS | D(dst) | A(src1) | (((imm >> 16) & 0xffff) + ((imm >> 15) & 0x1))));
src1 = dst;
}
return push_inst(compiler, ADDI | D(dst) | A(src1) | (imm & 0xffff));
}
if (flags & ALT_FORM3) {
SLJIT_ASSERT(src2 == TMP_REG2);
BIN_IMM_EXTS();
return push_inst(compiler, ADDIC | D(dst) | A(src1) | compiler->imm);
}
if (flags & ALT_FORM4) {
if (flags & ALT_FORM5)
FAIL_IF(push_inst(compiler, ADDI | D(dst) | A(src1) | compiler->imm));
else
FAIL_IF(push_inst(compiler, ADD | D(dst) | A(src1) | B(src2)));
return push_inst(compiler, CMPI | A(dst) | 0);
}
if (!(flags & ALT_SET_FLAGS))
return push_inst(compiler, ADD | D(dst) | A(src1) | B(src2));
BIN_EXTS();
if (flags & ALT_FORM5)
return push_inst(compiler, ADDC | RC(ALT_SET_FLAGS) | D(dst) | A(src1) | B(src2));
return push_inst(compiler, ADD | RC(flags) | D(dst) | A(src1) | B(src2));
case SLJIT_ADDC:
BIN_EXTS();
return push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2));
case SLJIT_SUB:
if (flags & ALT_FORM1) {
if (flags & ALT_FORM2) {
FAIL_IF(push_inst(compiler, CMPLI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
if (!(flags & ALT_FORM3))
return SLJIT_SUCCESS;
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
}
FAIL_IF(push_inst(compiler, CMPL | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
if (!(flags & ALT_FORM3))
return SLJIT_SUCCESS;
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
}
if (flags & ALT_FORM2) {
if (flags & ALT_FORM3) {
FAIL_IF(push_inst(compiler, CMPI | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | compiler->imm));
if (!(flags & ALT_FORM4))
return SLJIT_SUCCESS;
return push_inst(compiler, ADDI | D(dst) | A(src1) | (-compiler->imm & 0xffff));
}
FAIL_IF(push_inst(compiler, CMP | CRD(0 | ((flags & ALT_SIGN_EXT) ? 0 : 1)) | A(src1) | B(src2)));
if (!(flags & ALT_FORM4))
return SLJIT_SUCCESS;
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
}
if (flags & ALT_FORM3) {
if (flags & ALT_SIGN_EXT) {
if (src1 != TMP_ZERO) {
FAIL_IF(push_inst(compiler, SLDI(32) | S(src1) | A(TMP_REG1)));
src1 = TMP_REG1;
}
if (src2 != TMP_ZERO) {
FAIL_IF(push_inst(compiler, SLDI(32) | S(src2) | A(TMP_REG2)));
src2 = TMP_REG2;
}
}
/* Setting XER SO is not enough, CR SO is also needed. */
if (src1 != TMP_ZERO)
FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));
else
FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2)));
if (flags & ALT_SIGN_EXT)
return push_inst(compiler, SRDI(32) | S(dst) | A(dst));
return SLJIT_SUCCESS;
}
if (flags & ALT_FORM4) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
}
if (!(flags & ALT_SET_FLAGS)) {
SLJIT_ASSERT(src1 != TMP_ZERO);
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
}
BIN_EXTS();
if (flags & ALT_FORM5)
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
if (src1 != TMP_ZERO)
return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
case SLJIT_SUBC:
BIN_EXTS();
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
case SLJIT_MUL:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, MULLI | D(dst) | A(src1) | compiler->imm);
}
BIN_EXTS();
if (flags & ALT_FORM2)
return push_inst(compiler, MULLW | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
return push_inst(compiler, MULLD | OE(flags) | RC(flags) | D(dst) | A(src2) | B(src1));
case SLJIT_AND:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, ANDI | S(src1) | A(dst) | compiler->imm);
}
if (flags & ALT_FORM2) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, ANDIS | S(src1) | A(dst) | compiler->imm);
}
return push_inst(compiler, AND | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_OR:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, ORI | S(src1) | A(dst) | compiler->imm);
}
if (flags & ALT_FORM2) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, ORIS | S(src1) | A(dst) | compiler->imm);
}
if (flags & ALT_FORM3) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm;
FAIL_IF(push_inst(compiler, ORI | S(src1) | A(dst) | IMM(imm)));
return push_inst(compiler, ORIS | S(dst) | A(dst) | IMM(imm >> 16));
}
return push_inst(compiler, OR | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_XOR:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, XORI | S(src1) | A(dst) | compiler->imm);
}
if (flags & ALT_FORM2) {
SLJIT_ASSERT(src2 == TMP_REG2);
return push_inst(compiler, XORIS | S(src1) | A(dst) | compiler->imm);
}
if (flags & ALT_FORM3) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm;
FAIL_IF(push_inst(compiler, XORI | S(src1) | A(dst) | IMM(imm)));
return push_inst(compiler, XORIS | S(dst) | A(dst) | IMM(imm >> 16));
}
if (flags & ALT_FORM4) {
SLJIT_ASSERT(src1 == TMP_REG1);
UN_EXTS();
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
}
return push_inst(compiler, XOR | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_SHL:
case SLJIT_MSHL:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm;
if (flags & ALT_FORM2) {
imm &= 0x1f;
return push_inst(compiler, SLWI(imm) | RC(flags) | S(src1) | A(dst));
}
imm &= 0x3f;
return push_inst(compiler, SLDI(imm) | RC(flags) | S(src1) | A(dst));
}
if (op == SLJIT_MSHL) {
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
src2 = TMP_REG2;
}
return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_LSHR:
case SLJIT_MLSHR:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm;
if (flags & ALT_FORM2) {
imm &= 0x1f;
/* Since imm can be 0, SRWI() cannot be used. */
return push_inst(compiler, RLWINM | RC(flags) | S(src1) | A(dst) | RLWI_SH((32 - imm) & 0x1f) | RLWI_MBE(imm, 31));
}
imm &= 0x3f;
/* Since imm can be 0, SRDI() cannot be used. */
return push_inst(compiler, RLDICL | RC(flags) | S(src1) | A(dst) | RLDI_SH((64 - imm) & 0x3f) | RLDI_MB(imm));
}
if (op == SLJIT_MLSHR) {
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
src2 = TMP_REG2;
}
return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_ASHR:
case SLJIT_MASHR:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm;
if (flags & ALT_FORM2) {
imm &= 0x1f;
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (imm << 11));
}
imm &= 0x3f;
return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | RLDI_SH(imm));
}
if (op == SLJIT_MASHR) {
FAIL_IF(push_inst(compiler, ANDI | S(src2) | A(TMP_REG2) | ((flags & ALT_FORM2) ? 0x1f : 0x3f)));
src2 = TMP_REG2;
}
return push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_ROTL:
case SLJIT_ROTR:
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
imm = compiler->imm;
if (op == SLJIT_ROTR)
imm = (sljit_u32)(-(sljit_s32)imm);
if (flags & ALT_FORM2) {
imm &= 0x1f;
return push_inst(compiler, RLWINM | S(src1) | A(dst) | RLWI_SH(imm) | RLWI_MBE(0, 31));
}
imm &= 0x3f;
return push_inst(compiler, RLDICL | S(src1) | A(dst) | RLDI_SH(imm));
}
if (op == SLJIT_ROTR) {
FAIL_IF(push_inst(compiler, SUBFIC | D(TMP_REG2) | A(src2) | 0));
src2 = TMP_REG2;
}
return push_inst(compiler, ((flags & ALT_FORM2) ? (RLWNM | RLWI_MBE(0, 31)) : (RLDCL | RLDI_MB(0))) | S(src1) | A(dst) | B(src2));
}
SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
}
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)
{
sljit_s32 arg_count = 0;
sljit_s32 word_arg_count = 0;
sljit_s32 types = 0;
sljit_s32 reg = 0;
if (src)
reg = *src & REG_MASK;
arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
case SLJIT_ARG_TYPE_F32:
arg_count++;
break;
default:
arg_count++;
word_arg_count++;
if (arg_count != word_arg_count && arg_count == reg) {
FAIL_IF(push_inst(compiler, OR | S(reg) | A(TMP_CALL_REG) | B(reg)));
*src = TMP_CALL_REG;
}
break;
}
arg_types >>= SLJIT_ARG_SHIFT;
}
while (types) {
switch (types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
case SLJIT_ARG_TYPE_F32:
arg_count--;
break;
default:
if (arg_count != word_arg_count)
FAIL_IF(push_inst(compiler, OR | S(word_arg_count) | A(arg_count) | B(word_arg_count)));
arg_count--;
word_arg_count--;
break;
}
types >>= SLJIT_ARG_SHIFT;
}
return SLJIT_SUCCESS;
}
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw init_value)
{
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
FAIL_IF(push_inst(compiler, SLDI(32) | S(reg) | A(reg)));
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(init_value >> 16)));
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
}
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
if (src == SLJIT_IMM) {
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
srcw = (sljit_s32)srcw;
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
src = TMP_REG1;
} else if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) {
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, EXTSW | S(src) | A(TMP_REG1)));
else
FAIL_IF(emit_op_mem(compiler, INT_DATA | SIGNED_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
src = TMP_REG1;
}
if (FAST_IS_REG(src)) {
FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
} else
FAIL_IF(emit_op_mem(compiler, DOUBLE_DATA | LOAD_DATA, TMP_FREG1, src, srcw, TMP_REG1));
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
if (op & SLJIT_32)
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
if (dst & SLJIT_MEM)
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
return SLJIT_SUCCESS;
}
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_uw(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {
if (src == SLJIT_IMM) {
FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_u32)srcw));
src = TMP_REG1;
} else {
if (FAST_IS_REG(src))
FAIL_IF(push_inst(compiler, CLRLDI(TMP_REG1, src, 32)));
else
FAIL_IF(emit_op_mem(compiler, INT_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
src = TMP_REG1;
}
FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
} else {
if (src == SLJIT_IMM) {
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
src = TMP_REG1;
} else if (src & SLJIT_MEM) {
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
src = TMP_REG1;
}
FAIL_IF(push_inst(compiler, CMPI | CRD(0 | 1) | A(src) | 0));
FAIL_IF(push_inst(compiler, BCx | (12 << 21) | (0 << 16) | 20));
FAIL_IF(push_inst(compiler, STD | S(src) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
FAIL_IF(push_inst(compiler, Bx | ((op & SLJIT_32) ? 36 : 32)));
if (op & SLJIT_32)
FAIL_IF(push_inst(compiler, RLWINM | S(src) | A(TMP_REG2) | RLWI_SH(10) | RLWI_MBE(10, 21)));
else
FAIL_IF(push_inst(compiler, ANDI | S(src) | A(TMP_REG2) | 0x1));
/* Shift right. */
FAIL_IF(push_inst(compiler, RLDICL | S(src) | A(TMP_REG1) | RLDI_SH(63) | RLDI_MB(1)));
if (op & SLJIT_32)
FAIL_IF(push_inst(compiler, RLDICR | S(TMP_REG1) | A(TMP_REG1) | RLDI_SH(0) | RLDI_ME(53)));
FAIL_IF(push_inst(compiler, OR | S(TMP_REG1) | A(TMP_REG1) | B(TMP_REG2)));
FAIL_IF(push_inst(compiler, STD | S(TMP_REG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, LFD | FS(TMP_FREG1) | A(SLJIT_SP) | TMP_MEM_OFFSET));
FAIL_IF(push_inst(compiler, FCFID | FD(dst_r) | FB(TMP_FREG1)));
FAIL_IF(push_inst(compiler, FADD | FD(dst_r) | FA(dst_r) | FB(dst_r)));
}
if (op & SLJIT_32)
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r)));
if (dst & SLJIT_MEM)
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f64 value)
{
union {
sljit_sw imm;
sljit_f64 value;
} u;
CHECK_ERROR();
CHECK(check_sljit_emit_fset64(compiler, freg, value));
u.value = value;
if (u.imm != 0)
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm));
FAIL_IF(push_inst(compiler, STD | S(u.imm != 0 ? TMP_REG1 : TMP_ZERO) | A(SLJIT_SP) | TMP_MEM_OFFSET));
return push_inst(compiler, LFD | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 freg, sljit_s32 reg)
{
CHECK_ERROR();
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) {
FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STW : STD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
return push_inst(compiler, ((op & SLJIT_32) ? LFS : LFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
}
FAIL_IF(push_inst(compiler, ((op & SLJIT_32) ? STFS : STFD) | FS(freg) | A(SLJIT_SP) | TMP_MEM_OFFSET));
return push_inst(compiler, ((op & SLJIT_32) ? LWZ : LD) | S(reg) | A(SLJIT_SP) | TMP_MEM_OFFSET);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_ins *inst = (sljit_ins*)addr;
SLJIT_UNUSED_ARG(executable_offset);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
inst[0] = (inst[0] & 0xffff0000u) | ((sljit_ins)(new_target >> 48) & 0xffff);
inst[1] = (inst[1] & 0xffff0000u) | ((sljit_ins)(new_target >> 32) & 0xffff);
inst[3] = (inst[3] & 0xffff0000u) | ((sljit_ins)(new_target >> 16) & 0xffff);
inst[4] = (inst[4] & 0xffff0000u) | ((sljit_ins)new_target & 0xffff);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 5);
}

File diff suppressed because it is too large Load diff

View file

@ -1,142 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r)
{
SLJIT_UNUSED_ARG(tmp_r);
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));
if (imm & 0x800)
imm += 0x1000;
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));
if ((imm & 0xfff) == 0)
return SLJIT_SUCCESS;
return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f64 value)
{
union {
sljit_s32 imm[2];
sljit_f64 value;
} u;
CHECK_ERROR();
CHECK(check_sljit_emit_fset64(compiler, freg, value));
u.value = value;
if (u.imm[0] != 0)
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm[0], TMP_REG3));
if (u.imm[1] != 0)
FAIL_IF(load_immediate(compiler, TMP_REG2, u.imm[1], TMP_REG3));
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-16)));
FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(u.imm[0] != 0 ? TMP_REG1 : TMP_ZERO) | (8 << 7)));
FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(u.imm[1] != 0 ? TMP_REG2 : TMP_ZERO) | (12 << 7)));
FAIL_IF(push_inst(compiler, FLD | FRD(freg) | RS1(SLJIT_SP) | IMM_I(8)));
return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(16));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 freg, sljit_s32 reg)
{
sljit_ins inst;
sljit_s32 reg2 = 0;
CHECK_ERROR();
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
if (op & SLJIT_32) {
if (op == SLJIT_COPY32_TO_F32)
inst = FMV_W_X | RS1(reg) | FRD(freg);
else
inst = FMV_X_W | FRS1(freg) | RD(reg);
return push_inst(compiler, inst);
}
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-16)));
if (reg & REG_PAIR_MASK) {
reg2 = REG_PAIR_SECOND(reg);
reg = REG_PAIR_FIRST(reg);
}
if (op == SLJIT_COPY_TO_F64) {
if (reg2 != 0)
FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(reg2) | (8 << 7)));
else
FAIL_IF(push_inst(compiler, FSW | RS1(SLJIT_SP) | FRS2(freg) | (8 << 7)));
FAIL_IF(push_inst(compiler, SW | RS1(SLJIT_SP) | RS2(reg) | (12 << 7)));
FAIL_IF(push_inst(compiler, FLD | FRD(freg) | RS1(SLJIT_SP) | IMM_I(8)));
} else {
FAIL_IF(push_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(freg) | (8 << 7)));
if (reg2 != 0)
FAIL_IF(push_inst(compiler, FMV_X_W | FRS1(freg) | RD(reg2)));
FAIL_IF(push_inst(compiler, LW | RD(reg) | RS1(SLJIT_SP) | IMM_I(12)));
}
return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(16));
}
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins)
{
if ((init_value & 0x800) != 0)
init_value += 0x1000;
FAIL_IF(push_inst(compiler, LUI | RD(dst) | (sljit_ins)(init_value & ~0xfff)));
return push_inst(compiler, last_ins | RS1(dst) | IMM_I(init_value));
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_ins *inst = (sljit_ins*)addr;
SLJIT_UNUSED_ARG(executable_offset);
if ((new_target & 0x800) != 0)
new_target += 0x1000;
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
SLJIT_ASSERT((inst[0] & 0x7f) == LUI);
inst[0] = (inst[0] & 0xfff) | (sljit_ins)((sljit_sw)new_target & ~0xfff);
SLJIT_ASSERT((inst[1] & 0x707f) == ADDI || (inst[1] & 0x707f) == JALR);
inst[1] = (inst[1] & 0xfffff) | IMM_I(new_target);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 5);
}

View file

@ -1,222 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r)
{
sljit_sw high;
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));
if (imm <= 0x7fffffffl && imm >= S32_MIN) {
if (imm > S32_MAX) {
SLJIT_ASSERT((imm & 0x800) != 0);
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));
return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
}
if ((imm & 0x800) != 0)
imm += 0x1000;
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));
if ((imm & 0xfff) == 0)
return SLJIT_SUCCESS;
return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
}
/* Trailing zeroes could be used to produce shifted immediates. */
if (imm <= 0x7ffffffffffl && imm >= -0x80000000000l) {
high = imm >> 12;
if (imm & 0x800)
high = ~high;
if (high > S32_MAX) {
SLJIT_ASSERT((high & 0x800) != 0);
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));
FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(high)));
} else {
if ((high & 0x800) != 0)
high += 0x1000;
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(high & ~0xfff)));
if ((high & 0xfff) != 0)
FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(high)));
}
FAIL_IF(push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(12)));
if ((imm & 0xfff) != 0)
return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
return SLJIT_SUCCESS;
}
SLJIT_ASSERT(dst_r != tmp_r);
high = imm >> 32;
imm = (sljit_s32)imm;
if ((imm & 0x80000000l) != 0)
high = ~high;
if (high <= 0x7ffff && high >= -0x80000) {
FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high << 12)));
high = 0x1000;
} else {
if ((high & 0x800) != 0)
high += 0x1000;
FAIL_IF(push_inst(compiler, LUI | RD(tmp_r) | (sljit_ins)(high & ~0xfff)));
high &= 0xfff;
}
if (imm <= SIMM_MAX && imm >= SIMM_MIN) {
FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)));
imm = 0;
} else if (imm > S32_MAX) {
SLJIT_ASSERT((imm & 0x800) != 0);
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));
imm = 0x1000 | (imm & 0xfff);
} else {
if ((imm & 0x800) != 0)
imm += 0x1000;
FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));
imm &= 0xfff;
}
if ((high & 0xfff) != 0)
FAIL_IF(push_inst(compiler, ADDI | RD(tmp_r) | RS1(tmp_r) | IMM_I(high)));
if (imm & 0x1000)
FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));
else if (imm != 0)
FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));
FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(tmp_r) | IMM_I((high & 0x1000) ? 20 : 32)));
return push_inst(compiler, XOR | RD(dst_r) | RS1(dst_r) | RS2(tmp_r));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f64 value)
{
union {
sljit_sw imm;
sljit_f64 value;
} u;
CHECK_ERROR();
CHECK(check_sljit_emit_fset64(compiler, freg, value));
u.value = value;
if (u.imm == 0)
return push_inst(compiler, FMV_W_X | (1 << 25) | RS1(TMP_ZERO) | FRD(freg));
FAIL_IF(load_immediate(compiler, TMP_REG1, u.imm, TMP_REG3));
return push_inst(compiler, FMV_W_X | (1 << 25) | RS1(TMP_REG1) | FRD(freg));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 freg, sljit_s32 reg)
{
sljit_ins inst;
CHECK_ERROR();
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
if (GET_OPCODE(op) == SLJIT_COPY_TO_F64)
inst = FMV_W_X | RS1(reg) | FRD(freg);
else
inst = FMV_X_W | FRS1(freg) | RD(reg);
if (!(op & SLJIT_32))
inst |= (sljit_ins)1 << 25;
return push_inst(compiler, inst);
}
static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw init_value, sljit_ins last_ins)
{
sljit_sw high;
if ((init_value & 0x800) != 0)
init_value += 0x1000;
high = init_value >> 32;
if ((init_value & 0x80000000l) != 0)
high = ~high;
if ((high & 0x800) != 0)
high += 0x1000;
FAIL_IF(push_inst(compiler, LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff)));
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high)));
FAIL_IF(push_inst(compiler, LUI | RD(dst) | (sljit_ins)(init_value & ~0xfff)));
FAIL_IF(push_inst(compiler, SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(32)));
FAIL_IF(push_inst(compiler, XOR | RD(dst) | RS1(dst) | RS2(TMP_REG3)));
return push_inst(compiler, last_ins | RS1(dst) | IMM_I(init_value));
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_ins *inst = (sljit_ins*)addr;
sljit_sw high;
SLJIT_UNUSED_ARG(executable_offset);
if ((new_target & 0x800) != 0)
new_target += 0x1000;
high = (sljit_sw)new_target >> 32;
if ((new_target & 0x80000000l) != 0)
high = ~high;
if ((high & 0x800) != 0)
high += 0x1000;
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
SLJIT_ASSERT((inst[0] & 0x7f) == LUI);
inst[0] = (inst[0] & 0xfff) | (sljit_ins)(high & ~0xfff);
SLJIT_ASSERT((inst[1] & 0x707f) == ADDI);
inst[1] = (inst[1] & 0xfffff) | IMM_I(high);
SLJIT_ASSERT((inst[2] & 0x7f) == LUI);
inst[2] = (inst[2] & 0xfff) | (sljit_ins)((sljit_sw)new_target & ~0xfff);
SLJIT_ASSERT((inst[5] & 0x707f) == ADDI || (inst[5] & 0x707f) == JALR);
inst[5] = (inst[5] & 0xfffff) | IMM_I(new_target);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 5);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,344 +0,0 @@
/*
* Stack-less Just-In-Time compiler
*
* Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* ------------------------------------------------------------------------ */
/* Locks */
/* ------------------------------------------------------------------------ */
/* Executable Allocator */
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \
&& !(defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)
#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
#define SLJIT_ALLOCATOR_LOCK()
#define SLJIT_ALLOCATOR_UNLOCK()
#elif !(defined _WIN32)
#include <pthread.h>
static pthread_mutex_t allocator_lock = PTHREAD_MUTEX_INITIALIZER;
#define SLJIT_ALLOCATOR_LOCK() pthread_mutex_lock(&allocator_lock)
#define SLJIT_ALLOCATOR_UNLOCK() pthread_mutex_unlock(&allocator_lock)
#else /* windows */
static HANDLE allocator_lock;
static SLJIT_INLINE void allocator_grab_lock(void)
{
HANDLE lock;
if (SLJIT_UNLIKELY(!InterlockedCompareExchangePointer(&allocator_lock, NULL, NULL))) {
lock = CreateMutex(NULL, FALSE, NULL);
if (InterlockedCompareExchangePointer(&allocator_lock, lock, NULL))
CloseHandle(lock);
}
WaitForSingleObject(allocator_lock, INFINITE);
}
#define SLJIT_ALLOCATOR_LOCK() allocator_grab_lock()
#define SLJIT_ALLOCATOR_UNLOCK() ReleaseMutex(allocator_lock)
#endif /* thread implementation */
#endif /* SLJIT_EXECUTABLE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */
/* ------------------------------------------------------------------------ */
/* Stack */
/* ------------------------------------------------------------------------ */
#if ((defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \
&& !(defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)) \
|| ((defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \
&& !((defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) \
|| (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR)))
#ifndef _WIN32
/* 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 MAP_ANON
#include <fcntl.h>
#ifdef O_CLOEXEC
#define SLJIT_CLOEXEC O_CLOEXEC
#else /* !O_CLOEXEC */
#define SLJIT_CLOEXEC 0
#endif /* O_CLOEXEC */
/* Some old systems do not have MAP_ANON. */
static int dev_zero = -1;
#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
static SLJIT_INLINE int open_dev_zero(void)
{
dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);
return dev_zero < 0;
}
#else /* !SLJIT_SINGLE_THREADED */
#include <pthread.h>
static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;
static SLJIT_INLINE int open_dev_zero(void)
{
pthread_mutex_lock(&dev_zero_mutex);
if (SLJIT_UNLIKELY(dev_zero < 0))
dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC);
pthread_mutex_unlock(&dev_zero_mutex);
return dev_zero < 0;
}
#endif /* SLJIT_SINGLE_THREADED */
#undef SLJIT_CLOEXEC
#endif /* !MAP_ANON */
#endif /* !_WIN32 */
#endif /* open_dev_zero */
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \
|| (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
#ifdef _WIN32
static SLJIT_INLINE sljit_uw get_page_alignment(void) {
SYSTEM_INFO si;
static sljit_uw sljit_page_align = 0;
if (!sljit_page_align) {
GetSystemInfo(&si);
sljit_page_align = (sljit_uw)si.dwPageSize - 1;
}
return sljit_page_align;
}
#else
#include <unistd.h>
static SLJIT_INLINE sljit_uw get_page_alignment(void) {
static sljit_uw sljit_page_align = 0;
sljit_sw align;
if (!sljit_page_align) {
#ifdef _SC_PAGESIZE
align = sysconf(_SC_PAGESIZE);
#else
align = getpagesize();
#endif
/* Should never happen. */
if (align < 0)
align = 4096;
sljit_page_align = (sljit_uw)align - 1;
}
return sljit_page_align;
}
#endif /* _WIN32 */
#endif /* get_page_alignment() */
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
#if (defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)
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_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_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 /* !_WIN32 */
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, (size_t)(stack->end - stack->min_start));
SLJIT_FREE(stack, allocator_data);
}
#endif /* _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_uw page_align;
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;
/* Align max_size. */
page_align = get_page_alignment();
max_size = (max_size + page_align) & ~page_align;
#ifdef _WIN32
ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE);
if (!ptr) {
SLJIT_FREE(stack, allocator_data);
return NULL;
}
stack->min_start = (sljit_u8 *)ptr;
stack->end = stack->min_start + max_size;
stack->start = stack->end;
if (sljit_stack_resize(stack, stack->end - start_size) == NULL) {
sljit_free_stack(stack, allocator_data);
return NULL;
}
#else /* !_WIN32 */
#ifdef MAP_ANON
ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
#else /* !MAP_ANON */
if (SLJIT_UNLIKELY((dev_zero < 0) && 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 */
if (ptr == MAP_FAILED) {
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;
#endif /* _WIN32 */
stack->top = stack->end;
return stack;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start)
{
#if defined _WIN32 || defined(POSIX_MADV_DONTNEED)
sljit_uw aligned_old_start;
sljit_uw aligned_new_start;
sljit_uw 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;
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))
return NULL;
}
else {
if (!VirtualFree((void*)aligned_old_start, aligned_new_start - aligned_old_start, MEM_DECOMMIT))
return NULL;
}
}
#elif defined(POSIX_MADV_DONTNEED)
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;
if (aligned_new_start > aligned_old_start) {
posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED);
#ifdef MADV_FREE
madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_FREE);
#endif /* MADV_FREE */
}
}
#endif /* _WIN32 */
stack->start = new_start;
return new_start;
}
#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */
#endif /* SLJIT_UTIL_STACK */