Merge pull request #89371 from Chubercik/pcre2-10.43

pcre2: Update to 10.43
This commit is contained in:
Rémi Verschelde 2024-03-11 14:02:39 +01:00
commit a2edcf83ab
No known key found for this signature in database
GPG Key ID: C3336907360768E1
65 changed files with 23221 additions and 8808 deletions

View File

@ -457,8 +457,8 @@ License: Apache-2.0
Files: ./thirdparty/pcre2/
Comment: PCRE2
Copyright: 1997-2022, University of Cambridge
2009-2022, Zoltan Herczeg
Copyright: 1997-2024, University of Cambridge
2009-2024, Zoltan Herczeg
License: BSD-3-clause
Files: ./thirdparty/recastnavigation/

View File

@ -19,6 +19,7 @@ if env["builtin_pcre2"]:
thirdparty_sources = [
"pcre2_auto_possess.c",
"pcre2_chartables.c",
"pcre2_chkdint.c",
"pcre2_compile.c",
"pcre2_config.c",
"pcre2_context.c",

View File

@ -756,7 +756,7 @@ Exclude:
## pcre2
- Upstream: http://www.pcre.org
- Version: 10.42 (52c08847921a324c804cabf2814549f50bce1265, 2022)
- Version: 10.43 (3864abdb713f78831dd12d898ab31bbb0fa630b6, 2024)
- License: BSD-3-Clause
Files extracted from upstream source:
@ -765,6 +765,7 @@ Files extracted from upstream source:
- All `.h` files in `src/` apart from `pcre2posix.h`
- `src/pcre2_jit_match.c`
- `src/pcre2_jit_misc.c`
- `src/pcre2_ucptables.c`
- `src/sljit/`
- `AUTHORS` and `LICENCE`

View File

@ -8,7 +8,7 @@ Email domain: gmail.com
Retired from University of Cambridge Computing Service,
Cambridge, England.
Copyright (c) 1997-2022 University of Cambridge
Copyright (c) 1997-2024 University of Cambridge
All rights reserved
@ -19,7 +19,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
Copyright(c) 2010-2022 Zoltan Herczeg
Copyright(c) 2010-2024 Zoltan Herczeg
All rights reserved.
@ -30,7 +30,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
Copyright(c) 2009-2022 Zoltan Herczeg
Copyright(c) 2009-2024 Zoltan Herczeg
All rights reserved.
####

View File

@ -26,7 +26,7 @@ Email domain: gmail.com
Retired from University of Cambridge Computing Service,
Cambridge, England.
Copyright (c) 1997-2022 University of Cambridge
Copyright (c) 1997-2024 University of Cambridge
All rights reserved.
@ -37,7 +37,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Email domain: freemail.hu
Copyright(c) 2010-2022 Zoltan Herczeg
Copyright(c) 2010-2024 Zoltan Herczeg
All rights reserved.
@ -48,7 +48,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Email domain: freemail.hu
Copyright(c) 2009-2022 Zoltan Herczeg
Copyright(c) 2009-2024 Zoltan Herczeg
All rights reserved.

View File

@ -12,13 +12,13 @@ if the toolchain allows it.
Fixes: PCRE2Project/pcre2#109
---
sljit_src/sljitExecAllocator.c | 3 +++
thirdparty/pcre2/src/sljit/sljitExecAllocator.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sljit_src/sljitExecAllocator.c b/sljit_src/sljitExecAllocator.c
index 92d940dd..6359848c 100644
--- a/sljit_src/sljitExecAllocator.c
+++ b/sljit_src/sljitExecAllocator.c
diff --git a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
index 92d940ddc2..6359848cd5 100644
--- a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
+++ b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
@@ -152,6 +152,9 @@ static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec)
{
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 110000

View File

@ -55,9 +55,12 @@ sure both macros are undefined; an emulation function will then be used. */
/* 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 __builtin_mul_overflow() */
/* #undef HAVE_BUILTIN_MUL_OVERFLOW */
/* Define to 1 if you have the <bzlib.h> header file. */
/* #undef HAVE_BZLIB_H */
@ -79,16 +82,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. */
@ -109,7 +112,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. */
@ -121,7 +124,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. */
@ -181,7 +184,7 @@ sure both macros are undefined; an emulation function will then be used. */
matching attempt. The value is also used to limit a loop counter in
pcre2_dfa_match(). There is a runtime interface for setting a different
limit. The limit exists in order to catch runaway regular expressions that
take for ever to determine that they do not match. The default is set very
take forever to determine that they do not match. The default is set very
large so that it does not accidentally catch legitimate cases. */
#ifndef MATCH_LIMIT
#define MATCH_LIMIT 10000000
@ -215,6 +218,12 @@ sure both macros are undefined; an emulation function will then be used. */
#define MAX_NAME_SIZE 32
#endif
/* The value of MAX_VARLOOKBEHIND specifies the default maximum length, in
characters, for a variable-length lookbehind assertion. */
#ifndef MAX_VARLOOKBEHIND
#define MAX_VARLOOKBEHIND 255
#endif
/* Defining NEVER_BACKSLASH_C locks out the use of \C in all patterns. */
/* #undef NEVER_BACKSLASH_C */
@ -236,7 +245,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.42"
#define PACKAGE_STRING "PCRE2 10.43"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre2"
@ -245,7 +254,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.42"
#define PACKAGE_VERSION "10.43"
/* 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
@ -275,12 +284,16 @@ sure both macros are undefined; an emulation function will then be used. */
/* Define to any value to include debugging code. */
/* #undef PCRE2_DEBUG */
/* to make a symbol visible */
#define PCRE2_EXPORT
/* If you are compiling for a system other than a Unix-like system or
Win32, and it needs some magic to be inserted before the definition
of a function that is exported by the library, define this macro to
contain the relevant magic. If you do not define this macro, a suitable
__declspec value is used for Windows systems; in other environments
"extern" is used for a C compiler and "extern C" for a C++ compiler.
__declspec value is used for Windows systems; in other environments
a compiler relevant "extern" is used with any "visibility" related
attributes from PCRE2_EXPORT included.
This macro apears at the start of every exported function that is part
of the external API. It does not appear on functions that are "external"
in the C sense, but which are internal to the library. */
@ -298,11 +311,14 @@ 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 C90 standard headers exist (not just the ones
/* Define to 1 if all of the C89 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 */
/* Define to any value to enable differential fuzzing support. */
/* #undef SUPPORT_DIFF_FUZZ */
/* Define to any value to enable support for Just-In-Time compiling. */
/* #undef SUPPORT_JIT */
@ -350,7 +366,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 3, Interix. */
/* Enable extensions on AIX, Interix, z/OS. */
#ifndef _ALL_SOURCE
# define _ALL_SOURCE 1
#endif
@ -411,11 +427,15 @@ 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 ISO/IEC TS 18661-3:2015. */
/* Enable extensions specified by C23 Annex H and ISO/IEC TS 18661-3:2015. */
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
# define __STDC_WANT_IEC_60559_TYPES_EXT__ 1
#endif
@ -438,20 +458,26 @@ sure both macros are undefined; an emulation function will then be used. */
#endif
/* Version number of package */
#define VERSION "10.42"
#define VERSION "10.43"
/* Number of bits in a file offset, on hosts where this is settable. */
/* #undef _FILE_OFFSET_BITS */
/* Define for large files, on AIX-style hosts. */
/* Define to 1 on platforms where this makes off_t a 64-bit type. */
/* #undef _LARGE_FILES */
/* Define to empty if `const' does not conform to ANSI C. */
/* 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. */
/* #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 to `unsigned int' if <sys/types.h> does not define. */
/* Define as 'unsigned int' if <stddef.h> doesn't define. */
/* #undef size_t */

View File

@ -5,7 +5,7 @@
/* This is the public header file for the PCRE library, second API, to be
#included by applications that call PCRE2 functions.
Copyright (c) 2016-2021 University of Cambridge
Copyright (c) 2016-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE2_MAJOR 10
#define PCRE2_MINOR 42
#define PCRE2_MINOR 43
#define PCRE2_PRERELEASE
#define PCRE2_DATE 2022-12-11
#define PCRE2_DATE 2024-02-16
/* 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
@ -153,6 +153,12 @@ D is inspected during pcre2_dfa_match() execution
#define PCRE2_EXTRA_ESCAPED_CR_IS_LF 0x00000010u /* C */
#define PCRE2_EXTRA_ALT_BSUX 0x00000020u /* C */
#define PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK 0x00000040u /* C */
#define PCRE2_EXTRA_CASELESS_RESTRICT 0x00000080u /* C */
#define PCRE2_EXTRA_ASCII_BSD 0x00000100u /* C */
#define PCRE2_EXTRA_ASCII_BSS 0x00000200u /* C */
#define PCRE2_EXTRA_ASCII_BSW 0x00000400u /* C */
#define PCRE2_EXTRA_ASCII_POSIX 0x00000800u /* C */
#define PCRE2_EXTRA_ASCII_DIGIT 0x00001000u /* C */
/* These are for pcre2_jit_compile(). */
@ -180,11 +186,12 @@ pcre2_jit_match() ignores the latter since it bypasses all sanity checks). */
#define PCRE2_SUBSTITUTE_UNSET_EMPTY 0x00000400u /* pcre2_substitute() only */
#define PCRE2_SUBSTITUTE_UNKNOWN_UNSET 0x00000800u /* pcre2_substitute() only */
#define PCRE2_SUBSTITUTE_OVERFLOW_LENGTH 0x00001000u /* pcre2_substitute() only */
#define PCRE2_NO_JIT 0x00002000u /* Not for pcre2_dfa_match() */
#define PCRE2_NO_JIT 0x00002000u /* not for pcre2_dfa_match() */
#define PCRE2_COPY_MATCHED_SUBJECT 0x00004000u
#define PCRE2_SUBSTITUTE_LITERAL 0x00008000u /* pcre2_substitute() only */
#define PCRE2_SUBSTITUTE_MATCHED 0x00010000u /* pcre2_substitute() only */
#define PCRE2_SUBSTITUTE_REPLACEMENT_ONLY 0x00020000u /* pcre2_substitute() only */
#define PCRE2_DISABLE_RECURSELOOP_CHECK 0x00040000u /* not for pcre2_dfa_match() or pcre2_jit_match() */
/* Options for pcre2_pattern_convert(). */
@ -399,6 +406,7 @@ released, the numbers must not be changed. */
#define PCRE2_ERROR_CONVERT_SYNTAX (-64)
#define PCRE2_ERROR_INTERNAL_DUPMATCH (-65)
#define PCRE2_ERROR_DFA_UINVALID_UTF (-66)
#define PCRE2_ERROR_INVALIDOFFSET (-67)
/* Request types for pcre2_pattern_info() */
@ -575,7 +583,7 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION pcre2_config(uint32_t, void *);
PCRE2_EXP_DECL pcre2_general_context *PCRE2_CALL_CONVENTION \
pcre2_general_context_copy(pcre2_general_context *); \
PCRE2_EXP_DECL pcre2_general_context *PCRE2_CALL_CONVENTION \
pcre2_general_context_create(void *(*)(PCRE2_SIZE, void *), \
pcre2_general_context_create(void *(*)(size_t, void *), \
void (*)(void *, void *), void *); \
PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
pcre2_general_context_free(pcre2_general_context *);
@ -595,6 +603,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_varlookbehind(pcre2_compile_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_newline(pcre2_compile_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
@ -628,7 +638,7 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_recursion_limit(pcre2_match_context *, uint32_t); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_set_recursion_memory_management(pcre2_match_context *, \
void *(*)(PCRE2_SIZE, void *), void (*)(void *, void *), void *);
void *(*)(size_t, void *), void (*)(void *, void *), void *);
#define PCRE2_CONVERT_CONTEXT_FUNCTIONS \
PCRE2_EXP_DECL pcre2_convert_context *PCRE2_CALL_CONVENTION \
@ -687,6 +697,8 @@ PCRE2_EXP_DECL PCRE2_SPTR PCRE2_CALL_CONVENTION \
pcre2_get_mark(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
pcre2_get_match_data_size(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
pcre2_get_match_data_heapframes_size(pcre2_match_data *); \
PCRE2_EXP_DECL uint32_t PCRE2_CALL_CONVENTION \
pcre2_get_ovector_count(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SIZE *PCRE2_CALL_CONVENTION \
@ -722,7 +734,7 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_substring_number_from_name(const pcre2_code *, PCRE2_SPTR); \
PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
pcre2_substring_list_free(PCRE2_SPTR *); \
pcre2_substring_list_free(PCRE2_UCHAR **); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_substring_list_get(pcre2_match_data *, PCRE2_UCHAR ***, PCRE2_SIZE **);
@ -771,7 +783,7 @@ PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
pcre2_jit_free_unused_memory(pcre2_general_context *); \
PCRE2_EXP_DECL pcre2_jit_stack *PCRE2_CALL_CONVENTION \
pcre2_jit_stack_create(PCRE2_SIZE, PCRE2_SIZE, pcre2_general_context *); \
pcre2_jit_stack_create(size_t, size_t, pcre2_general_context *); \
PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
pcre2_jit_stack_assign(pcre2_match_context *, pcre2_jit_callback, void *); \
PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
@ -851,6 +863,7 @@ pcre2_compile are called by application code. */
#define pcre2_general_context_free PCRE2_SUFFIX(pcre2_general_context_free_)
#define pcre2_get_error_message PCRE2_SUFFIX(pcre2_get_error_message_)
#define pcre2_get_mark PCRE2_SUFFIX(pcre2_get_mark_)
#define pcre2_get_match_data_heapframes_size PCRE2_SUFFIX(pcre2_get_match_data_heapframes_size_)
#define pcre2_get_match_data_size PCRE2_SUFFIX(pcre2_get_match_data_size_)
#define pcre2_get_ovector_pointer PCRE2_SUFFIX(pcre2_get_ovector_pointer_)
#define pcre2_get_ovector_count PCRE2_SUFFIX(pcre2_get_ovector_count_)
@ -886,6 +899,7 @@ pcre2_compile are called by application code. */
#define pcre2_set_glob_separator PCRE2_SUFFIX(pcre2_set_glob_separator_)
#define pcre2_set_heap_limit PCRE2_SUFFIX(pcre2_set_heap_limit_)
#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_newline PCRE2_SUFFIX(pcre2_set_newline_)
#define pcre2_set_parens_nest_limit PCRE2_SUFFIX(pcre2_set_parens_nest_limit_)

View File

@ -560,6 +560,8 @@ matches to an empty string (also represented by a non-zero value). */
for(;;)
{
PCRE2_SPTR bracode;
/* All operations move the code pointer forward.
Therefore infinite recursions are not possible. */
@ -617,7 +619,8 @@ for(;;)
recursions. (This could be improved by keeping a list of group numbers that
are called by recursion.) */
switch(*(code - GET(code, 1)))
bracode = code - GET(code, 1);
switch(*bracode)
{
case OP_CBRA:
case OP_SCBRA:
@ -636,16 +639,19 @@ for(;;)
break;
/* Atomic sub-patterns and 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. */
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. */
case OP_ASSERT:
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
case OP_ONCE:
return !entered_a_group;
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
return (bracode[1+LINK_SIZE] == OP_VREVERSE)? FALSE : !entered_a_group;
/* Non-atomic assertions - don't possessify last iterator. This needs
more thought. */

View File

@ -5,7 +5,8 @@
/* This file was automatically written by the pcre2_dftables auxiliary
program. It contains character tables that are used when no external
tables are passed to PCRE2 by the application that calls it. The tables
are used only for characters whose code values are less than 256. */
are used only for characters whose code values are less than 256, and
only relevant if not in UCP mode. */
/* This set of tables was written in the C locale. */
@ -18,13 +19,6 @@ PCRE2 is configured with --enable-rebuild-chartables. However, you can run
pcre2_dftables manually with the -L option to build tables using the LC_ALL
locale. */
/* The following #include is present because without it gcc 4.x may remove
the array definition from the final binary if PCRE2 is built into a static
library and dead code stripping is activated. This leads to link errors.
Pulling in the header ensures that the array gets flagged as "someone
outside this compilation unit might reference this" and so it will always
be supplied to the linker. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@ -163,7 +157,7 @@ graph, print, punct, and cntrl. Other classes are built from combinations. */
0x02 letter
0x04 lower case letter
0x08 decimal digit
0x10 alphanumeric or '_'
0x10 word (alphanumeric or '_')
*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */

96
thirdparty/pcre2/src/pcre2_chkdint.c vendored Normal file
View File

@ -0,0 +1,96 @@
/*************************************************
* Perl-Compatible Regular Expressions *
*************************************************/
/* PCRE 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
Copyright (c) 2023 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.
-----------------------------------------------------------------------------
*/
/* This file contains functions to implement checked integer operation */
#ifndef PCRE2_PCRE2TEST
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "pcre2_internal.h"
#endif
/*************************************************
* Checked Integer Multiplication *
*************************************************/
/*
Arguments:
r A pointer to PCRE2_SIZE to store the answer
a, b Two integers
Returns: Bool indicating if the operation overflows
It is modeled after C23's <stdckdint.h> interface
The INT64_OR_DOUBLE type is a 64-bit integer type when available,
otherwise double. */
BOOL
PRIV(ckd_smul)(PCRE2_SIZE *r, int a, int b)
{
#ifdef HAVE_BUILTIN_MUL_OVERFLOW
PCRE2_SIZE m;
if (__builtin_mul_overflow(a, b, &m)) return TRUE;
*r = m;
#else
INT64_OR_DOUBLE m;
#ifdef PCRE2_DEBUG
if (a < 0 || b < 0) abort();
#endif
m = (INT64_OR_DOUBLE)a * (INT64_OR_DOUBLE)b;
#if defined INT64_MAX || defined int64_t
if (sizeof(m) > sizeof(*r) && m > (INT64_OR_DOUBLE)PCRE2_SIZE_MAX) return TRUE;
*r = (PCRE2_SIZE)m;
#else
if (m > PCRE2_SIZE_MAX) return TRUE;
*r = m;
#endif
#endif
return FALSE;
}
/* End of pcre_chkdint.c */

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-2023 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -139,7 +139,9 @@ const pcre2_compile_context PRIV(default_compile_context) = {
BSR_DEFAULT, /* Backslash R default */
NEWLINE_DEFAULT, /* Newline convention */
PARENS_NEST_LIMIT, /* As it says */
0 }; /* Extra options */
0, /* Extra options */
MAX_VARLOOKBEHIND /* As it says */
};
/* The create function copies the default into the new memory, but must
override the default memory handling functions if a gcontext was provided. */
@ -228,49 +230,48 @@ return ccontext;
PCRE2_EXP_DEFN pcre2_general_context * PCRE2_CALL_CONVENTION
pcre2_general_context_copy(pcre2_general_context *gcontext)
{
pcre2_general_context *new =
pcre2_general_context *newcontext =
gcontext->memctl.malloc(sizeof(pcre2_real_general_context),
gcontext->memctl.memory_data);
if (new == NULL) return NULL;
memcpy(new, gcontext, sizeof(pcre2_real_general_context));
return new;
if (newcontext == NULL) return NULL;
memcpy(newcontext, gcontext, sizeof(pcre2_real_general_context));
return newcontext;
}
PCRE2_EXP_DEFN pcre2_compile_context * PCRE2_CALL_CONVENTION
pcre2_compile_context_copy(pcre2_compile_context *ccontext)
{
pcre2_compile_context *new =
pcre2_compile_context *newcontext =
ccontext->memctl.malloc(sizeof(pcre2_real_compile_context),
ccontext->memctl.memory_data);
if (new == NULL) return NULL;
memcpy(new, ccontext, sizeof(pcre2_real_compile_context));
return new;
if (newcontext == NULL) return NULL;
memcpy(newcontext, ccontext, sizeof(pcre2_real_compile_context));
return newcontext;
}
PCRE2_EXP_DEFN pcre2_match_context * PCRE2_CALL_CONVENTION
pcre2_match_context_copy(pcre2_match_context *mcontext)
{
pcre2_match_context *new =
pcre2_match_context *newcontext =
mcontext->memctl.malloc(sizeof(pcre2_real_match_context),
mcontext->memctl.memory_data);
if (new == NULL) return NULL;
memcpy(new, mcontext, sizeof(pcre2_real_match_context));
return new;
if (newcontext == NULL) return NULL;
memcpy(newcontext, mcontext, sizeof(pcre2_real_match_context));
return newcontext;
}
PCRE2_EXP_DEFN pcre2_convert_context * PCRE2_CALL_CONVENTION
pcre2_convert_context_copy(pcre2_convert_context *ccontext)
{
pcre2_convert_context *new =
pcre2_convert_context *newcontext =
ccontext->memctl.malloc(sizeof(pcre2_real_convert_context),
ccontext->memctl.memory_data);
if (new == NULL) return NULL;
memcpy(new, ccontext, sizeof(pcre2_real_convert_context));
return new;
if (newcontext == NULL) return NULL;
memcpy(newcontext, ccontext, sizeof(pcre2_real_convert_context));
return newcontext;
}
@ -370,6 +371,13 @@ switch(newline)
}
}
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_max_varlookbehind(pcre2_compile_context *ccontext, uint32_t limit)
{
ccontext->max_varlookbehind = limit;
return 0;
}
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_parens_nest_limit(pcre2_compile_context *ccontext, uint32_t limit)
{

View File

@ -540,6 +540,14 @@ Returns: !0 => character is found in the class
static BOOL
convert_glob_char_in_class(int class_index, PCRE2_UCHAR c)
{
#if PCRE2_CODE_UNIT_WIDTH != 8
if (c > 0xff)
{
/* ctype functions are not sane for c > 0xff */
return 0;
}
#endif
switch (class_index)
{
case 1: return isalnum(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-2022 University of Cambridge
New API code Copyright (c) 2016-2023 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -168,7 +168,7 @@ static const uint8_t coptable[] = {
0, /* KetRmax */
0, /* KetRmin */
0, /* KetRpos */
0, /* Reverse */
0, 0, /* Reverse, Vreverse */
0, /* Assert */
0, /* Assert not */
0, /* Assert behind */
@ -187,7 +187,8 @@ static const uint8_t coptable[] = {
0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */
0, 0, /* COMMIT, COMMIT_ARG */
0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */
0, 0, 0 /* CLOSE, SKIPZERO, DEFINE */
0, 0, 0, /* CLOSE, SKIPZERO, DEFINE */
0, 0 /* \B and \b in UCP mode */
};
/* This table identifies those opcodes that inspect a character. It is used to
@ -245,7 +246,7 @@ static const uint8_t poptable[] = {
0, /* KetRmax */
0, /* KetRmin */
0, /* KetRpos */
0, /* Reverse */
0, 0, /* Reverse, Vreverse */
0, /* Assert */
0, /* Assert not */
0, /* Assert behind */
@ -264,7 +265,8 @@ static const uint8_t poptable[] = {
0, 0, 0, 0, /* SKIP, SKIP_ARG, THEN, THEN_ARG */
0, 0, /* COMMIT, COMMIT_ARG */
0, 0, 0, /* FAIL, ACCEPT, ASSERT_ACCEPT */
0, 0, 0 /* CLOSE, SKIPZERO, DEFINE */
0, 0, 0, /* CLOSE, SKIPZERO, DEFINE */
1, 1 /* \B and \b in UCP mode */
};
/* These 2 tables allow for compact code for testing for \D, \d, \S, \s, \W,
@ -426,7 +428,7 @@ overflow. */
else
{
uint32_t newsize = (rws->size >= UINT32_MAX/2)? UINT32_MAX/2 : rws->size * 2;
uint32_t newsize = (rws->size >= UINT32_MAX/(sizeof(int)*2))? UINT32_MAX/sizeof(int) : rws->size * 2;
uint32_t newsizeK = newsize/(1024/sizeof(int));
if (newsizeK + mb->heap_used > mb->heap_limit)
@ -589,7 +591,7 @@ if (*this_start_code == OP_ASSERTBACK || *this_start_code == OP_ASSERTBACK_NOT)
end_code = this_start_code;
do
{
size_t back = (size_t)GET(end_code, 2+LINK_SIZE);
size_t back = (size_t)GET2(end_code, 2+LINK_SIZE);
if (back > max_back) max_back = back;
end_code += GET(end_code, 1);
}
@ -633,8 +635,8 @@ if (*this_start_code == OP_ASSERTBACK || *this_start_code == OP_ASSERTBACK_NOT)
end_code = this_start_code;
do
{
uint32_t revlen = (end_code[1+LINK_SIZE] == OP_REVERSE)? 1 + LINK_SIZE : 0;
size_t back = (revlen == 0)? 0 : (size_t)GET(end_code, 2+LINK_SIZE);
uint32_t revlen = (end_code[1+LINK_SIZE] == OP_REVERSE)? 1 + IMM2_SIZE : 0;
size_t back = (revlen == 0)? 0 : (size_t)GET2(end_code, 2+LINK_SIZE);
if (back <= gone_back)
{
int bstate = (int)(end_code - start_code + 1 + LINK_SIZE + revlen);
@ -1100,6 +1102,8 @@ for (;;)
/*-----------------------------------------------------------------*/
case OP_WORD_BOUNDARY:
case OP_NOT_WORD_BOUNDARY:
case OP_NOT_UCP_WORD_BOUNDARY:
case OP_UCP_WORD_BOUNDARY:
{
int left_word, right_word;
@ -1112,13 +1116,13 @@ for (;;)
#endif
GETCHARTEST(d, temp);
#ifdef SUPPORT_UNICODE
if ((mb->poptions & PCRE2_UCP) != 0)
if (codevalue == OP_UCP_WORD_BOUNDARY ||
codevalue == OP_NOT_UCP_WORD_BOUNDARY)
{
if (d == '_') left_word = TRUE; else
{
uint32_t cat = UCD_CATEGORY(d);
left_word = (cat == ucp_L || cat == ucp_N);
}
int chartype = UCD_CHARTYPE(d);
int category = PRIV(ucp_gentype)[chartype];
left_word = (category == ucp_L || category == ucp_N ||
chartype == ucp_Mn || chartype == ucp_Pc);
}
else
#endif
@ -1137,13 +1141,13 @@ for (;;)
mb->last_used_ptr = temp;
}
#ifdef SUPPORT_UNICODE
if ((mb->poptions & PCRE2_UCP) != 0)
if (codevalue == OP_UCP_WORD_BOUNDARY ||
codevalue == OP_NOT_UCP_WORD_BOUNDARY)
{
if (c == '_') right_word = TRUE; else
{
uint32_t cat = UCD_CATEGORY(c);
right_word = (cat == ucp_L || cat == ucp_N);
}
int chartype = UCD_CHARTYPE(c);
int category = PRIV(ucp_gentype)[chartype];
right_word = (category == ucp_L || category == ucp_N ||
chartype == ucp_Mn || chartype == ucp_Pc);
}
else
#endif
@ -1151,7 +1155,9 @@ for (;;)
}
else right_word = FALSE;
if ((left_word == right_word) == (codevalue == OP_NOT_WORD_BOUNDARY))
if ((left_word == right_word) ==
(codevalue == OP_NOT_WORD_BOUNDARY ||
codevalue == OP_NOT_UCP_WORD_BOUNDARY))
{ ADD_ACTIVE(state_offset + 1, 0); }
}
break;
@ -1168,6 +1174,7 @@ for (;;)
if (clen > 0)
{
BOOL OK;
int chartype;
const uint32_t *cp;
const ucd_record * prop = GET_UCD(c);
switch(code[1])
@ -1177,8 +1184,9 @@ for (;;)
break;
case PT_LAMP:
OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
prop->chartype == ucp_Lt;
chartype = prop->chartype;
OK = chartype == ucp_Lu || chartype == ucp_Ll ||
chartype == ucp_Lt;
break;
case PT_GC:
@ -1201,8 +1209,9 @@ for (;;)
/* These are specials for combination cases. */
case PT_ALNUM:
OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N;
chartype = prop->chartype;
OK = PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N;
break;
/* Perl space used to exclude VT, but from Perl 5.18 it is included,
@ -1225,12 +1234,20 @@ for (;;)
break;
case PT_WORD:
OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
c == CHAR_UNDERSCORE;
chartype = prop->chartype;
OK = PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N ||
chartype == ucp_Mn || chartype == ucp_Pc;
break;
case PT_CLIST:
#if PCRE2_CODE_UNIT_WIDTH == 32
if (c > MAX_UTF_CODE_POINT)
{
OK = FALSE;
break;
}
#endif
cp = PRIV(ucd_caseless_sets) + code[2];
for (;;)
{
@ -1440,6 +1457,7 @@ for (;;)
if (clen > 0)
{
BOOL OK;
int chartype;
const uint32_t *cp;
const ucd_record * prop = GET_UCD(c);
switch(code[2])
@ -1449,8 +1467,8 @@ for (;;)
break;
case PT_LAMP:
OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
prop->chartype == ucp_Lt;
chartype = prop->chartype;
OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;
break;
case PT_GC:
@ -1473,8 +1491,9 @@ for (;;)
/* These are specials for combination cases. */
case PT_ALNUM:
OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N;
chartype = prop->chartype;
OK = PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N;
break;
/* Perl space used to exclude VT, but from Perl 5.18 it is included,
@ -1497,12 +1516,20 @@ for (;;)
break;
case PT_WORD:
OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
c == CHAR_UNDERSCORE;
chartype = prop->chartype;
OK = PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N ||
chartype == ucp_Mn || chartype == ucp_Pc;
break;
case PT_CLIST:
#if PCRE2_CODE_UNIT_WIDTH == 32
if (c > MAX_UTF_CODE_POINT)
{
OK = FALSE;
break;
}
#endif
cp = PRIV(ucd_caseless_sets) + code[3];
for (;;)
{
@ -1695,6 +1722,7 @@ for (;;)
if (clen > 0)
{
BOOL OK;
int chartype;
const uint32_t *cp;
const ucd_record * prop = GET_UCD(c);
switch(code[2])
@ -1704,8 +1732,8 @@ for (;;)
break;
case PT_LAMP:
OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
prop->chartype == ucp_Lt;
chartype = prop->chartype;
OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;
break;
case PT_GC:
@ -1728,8 +1756,9 @@ for (;;)
/* These are specials for combination cases. */
case PT_ALNUM:
OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N;
chartype = prop->chartype;
OK = PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N;
break;
/* Perl space used to exclude VT, but from Perl 5.18 it is included,
@ -1752,12 +1781,20 @@ for (;;)
break;
case PT_WORD:
OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
c == CHAR_UNDERSCORE;
chartype = prop->chartype;
OK = PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N ||
chartype == ucp_Mn || chartype == ucp_Pc;
break;
case PT_CLIST:
#if PCRE2_CODE_UNIT_WIDTH == 32
if (c > MAX_UTF_CODE_POINT)
{
OK = FALSE;
break;
}
#endif
cp = PRIV(ucd_caseless_sets) + code[3];
for (;;)
{
@ -1975,6 +2012,7 @@ for (;;)
if (clen > 0)
{
BOOL OK;
int chartype;
const uint32_t *cp;
const ucd_record * prop = GET_UCD(c);
switch(code[1 + IMM2_SIZE + 1])
@ -1984,8 +2022,8 @@ for (;;)
break;
case PT_LAMP:
OK = prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
prop->chartype == ucp_Lt;
chartype = prop->chartype;
OK = chartype == ucp_Lu || chartype == ucp_Ll || chartype == ucp_Lt;
break;
case PT_GC:
@ -2009,8 +2047,9 @@ for (;;)
/* These are specials for combination cases. */
case PT_ALNUM:
OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N;
chartype = prop->chartype;
OK = PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N;
break;
/* Perl space used to exclude VT, but from Perl 5.18 it is included,
@ -2033,12 +2072,20 @@ for (;;)
break;
case PT_WORD:
OK = PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
c == CHAR_UNDERSCORE;
chartype = prop->chartype;
OK = PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N ||
chartype == ucp_Mn || chartype == ucp_Pc;
break;
case PT_CLIST:
#if PCRE2_CODE_UNIT_WIDTH == 32
if (c > MAX_UTF_CODE_POINT)
{
OK = FALSE;
break;
}
#endif
cp = PRIV(ucd_caseless_sets) + code[1 + IMM2_SIZE + 2];
for (;;)
{
@ -2894,7 +2941,6 @@ for (;;)
int *local_workspace;
PCRE2_SIZE *local_offsets;
RWS_anchor *rws = (RWS_anchor *)RWS;
dfa_recursion_info *ri;
PCRE2_SPTR callpat = start_code + GET(code, 1);
uint32_t recno = (callpat == mb->start_code)? 0 :
GET2(callpat, 1 + LINK_SIZE);
@ -2911,18 +2957,24 @@ for (;;)
rws->free -= RWS_RSIZE + RWS_OVEC_RSIZE;
/* Check for repeating a recursion without advancing the subject
pointer. This should catch convoluted mutual recursions. (Some simple
cases are caught at compile time.) */
pointer or last used character. This should catch convoluted mutual
recursions. (Some simple cases are caught at compile time.) */
for (ri = mb->recursive; ri != NULL; ri = ri->prevrec)
if (recno == ri->group_num && ptr == ri->subject_position)
for (dfa_recursion_info *ri = mb->recursive;
ri != NULL;
ri = ri->prevrec)
{
if (recno == ri->group_num && ptr == ri->subject_position &&
mb->last_used_ptr == ri->last_used_ptr)
return PCRE2_ERROR_RECURSELOOP;
}
/* Remember this recursion and where we started it so as to
catch infinite loops. */
new_recursive.group_num = recno;
new_recursive.subject_position = ptr;
new_recursive.last_used_ptr = mb->last_used_ptr;
new_recursive.prevrec = mb->recursive;
mb->recursive = &new_recursive;
@ -3424,7 +3476,7 @@ anchored = (options & (PCRE2_ANCHORED|PCRE2_DFA_RESTART)) != 0 ||
where to start. */
startline = (re->flags & PCRE2_STARTLINE) != 0;
firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0;
firstline = !anchored && (re->overall_options & PCRE2_FIRSTLINE) != 0;
bumpalong_limit = end_subject;
/* Initialize and set up the fixed fields in the callout block, with a pointer
@ -3994,8 +4046,9 @@ for (;;)
match_data->ovector[0] = (PCRE2_SIZE)(start_match - subject);
match_data->ovector[1] = (PCRE2_SIZE)(end_subject - subject);
}
match_data->subject_length = length;
match_data->leftchar = (PCRE2_SIZE)(mb->start_used_ptr - subject);
match_data->rightchar = (PCRE2_SIZE)( mb->last_used_ptr - subject);
match_data->rightchar = (PCRE2_SIZE)(mb->last_used_ptr - subject);
match_data->startchar = (PCRE2_SIZE)(start_match - subject);
match_data->rc = rc;

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-2023 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -82,7 +82,7 @@ static const unsigned char compile_error_texts[] =
"missing closing parenthesis\0"
/* 15 */
"reference to non-existent subpattern\0"
"pattern passed as NULL\0"
"pattern passed as NULL with non-zero length\0"
"unrecognised compile-time option bit(s)\0"
"missing ) after (?# comment\0"
"parentheses are too deeply nested\0"
@ -93,7 +93,7 @@ static const unsigned char compile_error_texts[] =
"internal error: code overflow\0"
"missing closing parenthesis for condition\0"
/* 25 */
"lookbehind assertion is not fixed length\0"
"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"
@ -187,6 +187,8 @@ static const unsigned char compile_error_texts[] =
"too many capturing groups (maximum 65535)\0"
"atomic assertion expected after (?( or (?(?C)\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"
;
/* Match-time and UTF error texts are in the same format. */
@ -272,6 +274,7 @@ static const unsigned char match_error_texts[] =
/* 65 */
"internal error - duplicate substitution match\0"
"PCRE2_MATCH_INVALID_UTF is not supported for DFA matching\0"
"INTERNAL ERROR: invalid substring offset\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-2018 University of Cambridge
New API code Copyright (c) 2016-2023 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -41,9 +41,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* This module contains a single function that scans through a compiled pattern
until it finds a capturing bracket with the given number, or, if the number is
negative, an instance of OP_REVERSE for a lookbehind. The function is called
from pcre2_compile.c and also from pcre2_study.c when finding the minimum
matching length. */
negative, an instance of OP_REVERSE or OP_VREVERSE for a lookbehind. The
function is called from pcre2_compile.c and also from pcre2_study.c when
finding the minimum matching length. */
#ifdef HAVE_CONFIG_H
@ -85,7 +85,7 @@ for (;;)
/* Handle lookbehind */
else if (c == OP_REVERSE)
else if (c == OP_REVERSE || c == OP_VREVERSE)
{
if (number < 0) return (PCRE2_UCHAR *)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-2022 University of Cambridge
New API code Copyright (c) 2016-2023 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -51,6 +51,24 @@ pcre2test.c with CODE_UNIT_WIDTH == 0. */
#error The use of both EBCDIC and SUPPORT_UNICODE is not supported.
#endif
/* When compiling one of the libraries, the value of PCRE2_CODE_UNIT_WIDTH must
be 8, 16, or 32. AutoTools and CMake ensure that this is always the case, but
other other building methods may not, so here is a check. It is cut out when
building pcre2test, bcause that sets the value to zero. No other source should
be including this file. There is no explicit way of forcing a compile to be
abandoned, but trying to include a non-existent file seems cleanest. Otherwise
there will be many irrelevant consequential errors. */
#if (!defined PCRE2_BUILDING_PCRE2TEST && !defined PCRE2_DFTABLES) && \
(!defined PCRE2_CODE_UNIT_WIDTH || \
(PCRE2_CODE_UNIT_WIDTH != 8 && \
PCRE2_CODE_UNIT_WIDTH != 16 && \
PCRE2_CODE_UNIT_WIDTH != 32))
#error PCRE2_CODE_UNIT_WIDTH must be defined as 8, 16, or 32.
#include <AbandonCompile>
#endif
/* Standard C headers */
#include <ctype.h>
@ -119,20 +137,20 @@ only if it is not already set. */
#ifndef PCRE2_EXP_DECL
# ifdef _WIN32
# ifndef PCRE2_STATIC
# define PCRE2_EXP_DECL extern __declspec(dllexport)
# define PCRE2_EXP_DEFN __declspec(dllexport)
# define PCRE2_EXP_DECL extern __declspec(dllexport)
# define PCRE2_EXP_DEFN __declspec(dllexport)
# else
# define PCRE2_EXP_DECL extern
# define PCRE2_EXP_DECL extern PCRE2_EXPORT
# define PCRE2_EXP_DEFN
# endif
# else
# ifdef __cplusplus
# define PCRE2_EXP_DECL extern "C"
# define PCRE2_EXP_DECL extern "C" PCRE2_EXPORT
# else
# define PCRE2_EXP_DECL extern
# define PCRE2_EXP_DECL extern PCRE2_EXPORT
# endif
# ifndef PCRE2_EXP_DEFN
# define PCRE2_EXP_DEFN PCRE2_EXP_DECL
# define PCRE2_EXP_DEFN PCRE2_EXP_DECL
# endif
# endif
#endif
@ -156,8 +174,8 @@ pcre2_match() because of the way it backtracks. */
#define PCRE2_SPTR CUSTOM_SUBJECT_PTR
#endif
/* When checking for integer overflow in pcre2_compile(), we need to handle
large integers. If a 64-bit integer type is available, we can use that.
/* When checking for integer overflow, we need to handle large integers.
If a 64-bit integer type is available, we can use that.
Otherwise we have to cast to double, which of course requires floating point
arithmetic. Handle this by defining a macro for the appropriate type. */
@ -1281,7 +1299,7 @@ match. */
#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 plus N plus underscore */
#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 */
@ -1297,6 +1315,7 @@ table. */
#define PT_PXGRAPH 14 /* [:graph:] - characters that mark the paper */
#define PT_PXPRINT 15 /* [:print:] - [:graph:] plus non-control spaces */
#define PT_PXPUNCT 16 /* [:punct:] - punctuation characters */
#define PT_PXXDIGIT 17 /* [:xdigit:] - hex digits */
/* This value is used when parsing \p and \P escapes to indicate that neither
\p{script:...} nor \p{scx:...} has been encountered. */
@ -1327,6 +1346,12 @@ mode rather than an escape sequence. It is also used for [^] in JavaScript
compatibility mode, and for \C in non-utf mode. In non-DOTALL mode, "." behaves
like \N.
ESC_ub is a special return from check_escape() when, in BSUX mode, \u{ is not
followed by hex digits and }, in which case it should mean a literal "u"
followed by a literal "{". This hack is necessary for cases like \u{ 12}
because without it, this is interpreted as u{12} now that spaces are allowed in
quantifiers.
Negative numbers are used to encode a backreference (\1, \2, \3, etc.) in
check_escape(). There are tests in the code for an escape greater than ESC_b
and less than ESC_Z to detect the types that may be repeated. These are the
@ -1336,7 +1361,7 @@ consume a character, that code will have to change. */
enum { ESC_A = 1, ESC_G, ESC_K, ESC_B, ESC_b, ESC_D, ESC_d, ESC_S, ESC_s,
ESC_W, ESC_w, ESC_N, ESC_dum, ESC_C, ESC_P, ESC_p, ESC_R, ESC_H,
ESC_h, ESC_V, ESC_v, ESC_X, ESC_Z, ESC_z,
ESC_E, ESC_Q, ESC_g, ESC_k };
ESC_E, ESC_Q, ESC_g, ESC_k, ESC_ub };
/********************** Opcode definitions ******************/
@ -1372,8 +1397,8 @@ enum {
OP_SOD, /* 1 Start of data: \A */
OP_SOM, /* 2 Start of match (subject + offset): \G */
OP_SET_SOM, /* 3 Set start of match (\K) */
OP_NOT_WORD_BOUNDARY, /* 4 \B */
OP_WORD_BOUNDARY, /* 5 \b */
OP_NOT_WORD_BOUNDARY, /* 4 \B -- see also OP_NOT_UCP_WORD_BOUNDARY */
OP_WORD_BOUNDARY, /* 5 \b -- see also OP_UCP_WORD_BOUNDARY */
OP_NOT_DIGIT, /* 6 \D */
OP_DIGIT, /* 7 \d */
OP_NOT_WHITESPACE, /* 8 \S */
@ -1547,78 +1572,85 @@ enum {
/* The assertions must come before BRA, CBRA, ONCE, and COND. */
OP_REVERSE, /* 125 Move pointer back - used in lookbehind assertions */
OP_ASSERT, /* 126 Positive lookahead */
OP_ASSERT_NOT, /* 127 Negative lookahead */
OP_ASSERTBACK, /* 128 Positive lookbehind */
OP_ASSERTBACK_NOT, /* 129 Negative lookbehind */
OP_ASSERT_NA, /* 130 Positive non-atomic lookahead */
OP_ASSERTBACK_NA, /* 131 Positive non-atomic lookbehind */
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 */
/* 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, /* 132 Atomic group, contains captures */
OP_SCRIPT_RUN, /* 133 Non-capture, but check characters' scripts */
OP_BRA, /* 134 Start of non-capturing bracket */
OP_BRAPOS, /* 135 Ditto, with unlimited, possessive repeat */
OP_CBRA, /* 136 Start of capturing bracket */
OP_CBRAPOS, /* 137 Ditto, with unlimited, possessive repeat */
OP_COND, /* 138 Conditional group */
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 */
/* These five must follow the previous five, in the same order. There's a
check for >= SBRA to distinguish the two sets. */
OP_SBRA, /* 139 Start of non-capturing bracket, check empty */
OP_SBRAPOS, /* 149 Ditto, with unlimited, possessive repeat */
OP_SCBRA, /* 141 Start of capturing bracket, check empty */
OP_SCBRAPOS, /* 142 Ditto, with unlimited, possessive repeat */
OP_SCOND, /* 143 Conditional group, check empty */
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 */
/* The next two pairs must (respectively) be kept together. */
OP_CREF, /* 144 Used to hold a capture number as condition */
OP_DNCREF, /* 145 Used to point to duplicate names as a condition */
OP_RREF, /* 146 Used to hold a recursion number as condition */
OP_DNRREF, /* 147 Used to point to duplicate names as a condition */
OP_FALSE, /* 148 Always false (used by DEFINE and VERSION) */
OP_TRUE, /* 149 Always true (used by VERSION) */
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_BRAZERO, /* 150 These two must remain together and in this */
OP_BRAMINZERO, /* 151 order. */
OP_BRAPOSZERO, /* 152 */
OP_BRAZERO, /* 151 These two must remain together and in this */
OP_BRAMINZERO, /* 152 order. */
OP_BRAPOSZERO, /* 153 */
/* These are backtracking control verbs */
OP_MARK, /* 153 always has an argument */
OP_PRUNE, /* 154 */
OP_PRUNE_ARG, /* 155 same, but with argument */
OP_SKIP, /* 156 */
OP_SKIP_ARG, /* 157 same, but with argument */
OP_THEN, /* 158 */
OP_THEN_ARG, /* 159 same, but with argument */
OP_COMMIT, /* 160 */
OP_COMMIT_ARG, /* 161 same, but with argument */
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 */
/* 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, /* 162 */
OP_ACCEPT, /* 163 */
OP_ASSERT_ACCEPT, /* 164 Used inside assertions */
OP_CLOSE, /* 165 Used before OP_ACCEPT to close open captures */
OP_FAIL, /* 163 */
OP_ACCEPT, /* 164 */
OP_ASSERT_ACCEPT, /* 165 Used inside assertions */
OP_CLOSE, /* 166 Used before OP_ACCEPT to close open captures */
/* This is used to skip a subpattern with a {0} quantifier */
OP_SKIPZERO, /* 166 */
OP_SKIPZERO, /* 167 */
/* 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, /* 167 */
OP_DEFINE, /* 168 */
/* 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 */
/* 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
@ -1664,7 +1696,7 @@ some cases doesn't actually use these names at all). */
"class", "nclass", "xclass", "Ref", "Refi", "DnRef", "DnRefi", \
"Recurse", "Callout", "CalloutStr", \
"Alt", "Ket", "KetRmax", "KetRmin", "KetRpos", \
"Reverse", "Assert", "Assert not", \
"Reverse", "VReverse", "Assert", "Assert not", \
"Assert back", "Assert back not", \
"Non-atomic assert", "Non-atomic assert back", \
"Once", \
@ -1679,7 +1711,7 @@ some cases doesn't actually use these names at all). */
"*MARK", "*PRUNE", "*PRUNE", "*SKIP", "*SKIP", \
"*THEN", "*THEN", "*COMMIT", "*COMMIT", "*FAIL", \
"*ACCEPT", "*ASSERT_ACCEPT", \
"Close", "Skip zero", "Define"
"Close", "Skip zero", "Define", "\\B (ucp)", "\\b (ucp)"
/* This macro defines the length of fixed length operations in the compiled
@ -1746,7 +1778,8 @@ in UTF-8 mode. The code that uses this table must know about such things. */
1+LINK_SIZE, /* KetRmax */ \
1+LINK_SIZE, /* KetRmin */ \
1+LINK_SIZE, /* KetRpos */ \
1+LINK_SIZE, /* Reverse */ \
1+IMM2_SIZE, /* Reverse */ \
1+2*IMM2_SIZE, /* VReverse */ \
1+LINK_SIZE, /* Assert */ \
1+LINK_SIZE, /* Assert not */ \
1+LINK_SIZE, /* Assert behind */ \
@ -1775,7 +1808,8 @@ in UTF-8 mode. The code that uses this table must know about such things. */
1, 3, /* COMMIT, COMMIT_ARG */ \
1, 1, 1, /* FAIL, ACCEPT, ASSERT_ACCEPT */ \
1+IMM2_SIZE, 1, /* CLOSE, SKIPZERO */ \
1 /* DEFINE */
1, /* DEFINE */ \
1, 1 /* \B and \b in UCP mode */
/* A magic value for OP_RREF to indicate the "any recursion" condition. */
@ -2042,6 +2076,9 @@ extern void * _pcre2_memmove(void *, const void *, size_t);
#endif
#endif /* PCRE2_CODE_UNIT_WIDTH */
extern BOOL PRIV(ckd_smul)(PCRE2_SIZE *, int, int);
#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-2022 University of Cambridge
New API code Copyright (c) 2016-2023 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -572,6 +572,7 @@ typedef struct pcre2_real_compile_context {
uint16_t newline_convention;
uint32_t parens_nest_limit;
uint32_t extra_options;
uint32_t max_varlookbehind;
} pcre2_real_compile_context;
/* The real match context structure. */
@ -605,12 +606,12 @@ defined specially because it is required in pcre2_serialize_decode() when
copying the size from possibly unaligned memory into a variable of the same
type. Use a macro rather than a typedef to avoid compiler warnings when this
file is included multiple times by pcre2test. LOOKBEHIND_MAX specifies the
largest lookbehind that is supported. (OP_REVERSE in a pattern has a 16-bit
argument in 8-bit and 16-bit modes, so we need no more than a 16-bit field
here.) */
largest lookbehind that is supported. (OP_REVERSE and OP_VREVERSE in a pattern
have 16-bit arguments in 8-bit and 16-bit modes, so we need no more than a
16-bit field here.) */
#undef CODE_BLOCKSIZE_TYPE
#define CODE_BLOCKSIZE_TYPE size_t
#define CODE_BLOCKSIZE_TYPE PCRE2_SIZE
#undef LOOKBEHIND_MAX
#define LOOKBEHIND_MAX UINT16_MAX
@ -658,6 +659,7 @@ typedef struct pcre2_real_match_data {
PCRE2_SPTR mark; /* Pointer to last mark */
struct heapframe *heapframes; /* Backtracking frames heap memory */
PCRE2_SIZE heapframes_size; /* Malloc-ed size */
PCRE2_SIZE subject_length; /* Subject length */
PCRE2_SIZE leftchar; /* Offset to leftmost code unit */
PCRE2_SIZE rightchar; /* Offset to rightmost code unit */
PCRE2_SIZE startchar; /* Offset to starting code unit */
@ -675,8 +677,8 @@ typedef struct pcre2_real_match_data {
#ifndef PCRE2_PCRE2TEST
/* Structures for checking for mutual recursion when scanning compiled or
parsed code. */
/* Structures for checking for mutual function recursion when scanning compiled
or parsed code. */
typedef struct recurse_check {
struct recurse_check *prev;
@ -688,7 +690,7 @@ typedef struct parsed_recurse_check {
uint32_t *groupptr;
} parsed_recurse_check;
/* Structure for building a cache when filling in recursion offsets. */
/* Structure for building a cache when filling in pattern recursion offsets. */
typedef struct recurse_cache {
PCRE2_SPTR group;
@ -734,7 +736,6 @@ typedef struct compile_block {
uint16_t name_entry_size; /* Size of each entry */
uint16_t parens_depth; /* Depth of nested parentheses */
uint16_t assert_depth; /* Depth of nested assertions */
open_capitem *open_caps; /* Chain of open capture items */
named_group *named_groups; /* Points to vector in pre-compile */
uint32_t named_group_list_size; /* Number of entries in the list */
uint32_t external_options; /* External (initial) options */
@ -752,10 +753,11 @@ typedef struct compile_block {
uint32_t class_range_end; /* Overall class range end */
PCRE2_UCHAR nl[4]; /* Newline string when fixed length */
uint32_t req_varyopt; /* "After variable item" flag for reqbyte */
int max_lookbehind; /* Maximum lookbehind (characters) */
uint32_t max_varlookbehind; /* Limit for variable lookbehinds */
int max_lookbehind; /* Maximum lookbehind encountered (characters) */
BOOL had_accept; /* (*ACCEPT) encountered */
BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
BOOL had_recurse; /* Had a recursion or subroutine call */
BOOL had_recurse; /* Had a pattern recursion or subroutine call */
BOOL dupnames; /* Duplicate names exist */
} compile_block;
@ -773,6 +775,7 @@ call within the pattern when running pcre2_dfa_match(). */
typedef struct dfa_recursion_info {
struct dfa_recursion_info *prevrec;
PCRE2_SPTR subject_position;
PCRE2_SPTR last_used_ptr;
uint32_t group_num;
} dfa_recursion_info;
@ -793,7 +796,7 @@ typedef struct heapframe {
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 */
uint32_t rdepth; /* "Recursion" depth */
uint32_t rdepth; /* Function "recursion" depth within pcre2_match() */
uint32_t group_frame_type; /* Type information for group frames */
uint32_t temp_32[4]; /* Used for short-term 32-bit or BOOL values */
uint8_t return_id; /* Where to go on in internal "return" */
@ -826,14 +829,15 @@ typedef struct heapframe {
allows for exactly the right size ovector for the number of capturing
parentheses. (See also the comment for pcre2_real_match_data above.) */
PCRE2_SPTR eptr; /* MUST BE FIRST */
PCRE2_SPTR start_match; /* Can be adjusted by \K */
PCRE2_SPTR mark; /* Most recent mark on the success path */
uint32_t current_recurse; /* Current (deepest) recursion number */
uint32_t capture_last; /* Most recent capture */
PCRE2_SIZE last_group_offset; /* Saved offset to most recent group frame */
PCRE2_SIZE offset_top; /* Offset after highest capture */
PCRE2_SIZE ovector[131072]; /* Must be last in the structure */
PCRE2_SPTR eptr; /* MUST BE FIRST */
PCRE2_SPTR start_match; /* Can be adjusted by \K */
PCRE2_SPTR mark; /* Most recent mark on the success path */
PCRE2_SPTR recurse_last_used; /* Last character used at time of pattern recursion */
uint32_t current_recurse; /* Group number of current (deepest) pattern recursion */
uint32_t capture_last; /* Most recent capture */
PCRE2_SIZE last_group_offset; /* Saved offset to most recent group frame */
PCRE2_SIZE offset_top; /* Offset after highest capture */
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
@ -858,7 +862,7 @@ doing traditional NFA matching (pcre2_match() and friends). */
typedef struct match_block {
pcre2_memctl memctl; /* For general use */
PCRE2_SIZE heap_limit; /* As it says */
uint32_t heap_limit; /* As it says */
uint32_t match_limit; /* As it says */
uint32_t match_limit_depth; /* As it says */
uint32_t match_call_count; /* Number of times a new frame is created */
@ -875,10 +879,11 @@ typedef struct match_block {
uint16_t name_count; /* Number of names in name table */
uint16_t name_entry_size; /* Size of entry in names table */
PCRE2_SPTR name_table; /* Table of group names */
PCRE2_SPTR start_code; /* For use when recursing */
PCRE2_SPTR start_code; /* For use in pattern recursion */
PCRE2_SPTR start_subject; /* Start of the subject string */
PCRE2_SPTR check_subject; /* Where UTF-checked from */
PCRE2_SPTR end_subject; /* End of the subject string */
PCRE2_SPTR end_subject; /* Usable end of the subject string */
PCRE2_SPTR true_end_subject; /* Actual end of the subject string */
PCRE2_SPTR end_match_ptr; /* Subject position at end match */
PCRE2_SPTR start_used_ptr; /* Earliest consulted character */
PCRE2_SPTR last_used_ptr; /* Latest consulted character */
@ -886,7 +891,7 @@ typedef struct match_block {
PCRE2_SPTR nomatch_mark; /* Mark pointer to pass back on failure */
PCRE2_SPTR verb_ecode_ptr; /* For passing back info */
PCRE2_SPTR verb_skip_ptr; /* For passing back a (*SKIP) name */
uint32_t verb_current_recurse; /* Current recurse when (*VERB) happens */
uint32_t verb_current_recurse; /* Current recursion group when (*VERB) happens */
uint32_t moptions; /* Match options */
uint32_t poptions; /* Pattern options */
uint32_t skip_arg_count; /* For counting SKIP_ARGs */
@ -911,7 +916,7 @@ typedef struct dfa_match_block {
PCRE2_SPTR last_used_ptr; /* Latest consulted character */
const uint8_t *tables; /* Character tables */
PCRE2_SIZE start_offset; /* The start offset value */
PCRE2_SIZE heap_limit; /* As it says */
uint32_t heap_limit; /* As it says */
PCRE2_SIZE heap_used; /* As it says */
uint32_t match_limit; /* As it says */
uint32_t match_limit_depth; /* As it says */
@ -926,7 +931,7 @@ typedef struct dfa_match_block {
pcre2_callout_block *cb; /* Points to a callout block */
void *callout_data; /* To pass back to callouts */
int (*callout)(pcre2_callout_block *,void *); /* Callout function or NULL */
dfa_recursion_info *recursive; /* Linked list of recursion data */
dfa_recursion_info *recursive; /* Linked list of pattern recursion data */
} dfa_match_block;
#endif /* PCRE2_PCRE2TEST */

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-2018 University of Cambridge
New API code Copyright (c) 2016-2023 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -42,6 +42,12 @@ POSSIBILITY OF SUCH DAMAGE.
#error This file must be included from pcre2_jit_compile.c.
#endif
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
#include <sanitizer/msan_interface.h>
#endif /* __has_feature(memory_sanitizer) */
#endif /* defined(__has_feature) */
#ifdef SUPPORT_JIT
static SLJIT_NOINLINE int jit_machine_stack_exec(jit_arguments *arguments, jit_function executable_func)
@ -171,6 +177,7 @@ if (rc > (int)oveccount)
rc = 0;
match_data->code = re;
match_data->subject = (rc >= 0 || rc == PCRE2_ERROR_PARTIAL)? subject : NULL;
match_data->subject_length = length;
match_data->rc = rc;
match_data->startchar = arguments.startchar_ptr - subject;
match_data->leftchar = 0;
@ -178,6 +185,13 @@ match_data->rightchar = 0;
match_data->mark = arguments.mark_ptr;
match_data->matchedby = PCRE2_MATCHEDBY_JIT;
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
if (rc > 0)
__msan_unpoison(match_data->ovector, 2 * rc * sizeof(match_data->ovector[0]));
#endif /* __has_feature(memory_sanitizer) */
#endif /* defined(__has_feature) */
return match_data->rc;
#endif /* SUPPORT_JIT */

View File

@ -82,7 +82,12 @@ POSSIBILITY OF SUCH DAMAGE.
# endif
# endif
static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 *str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars)
#if (defined(__GNUC__) && __SANITIZE_ADDRESS__) \
|| (defined(__clang__) \
&& ((__clang_major__ == 3 && __clang_minor__ >= 3) || (__clang_major__ > 3)))
__attribute__((no_sanitize_address))
#endif
static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 **str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars)
#undef FF_FUN
{
quad_word qw;
@ -171,7 +176,7 @@ else
}
# endif
str_ptr += IN_UCHARS(offs1);
*str_ptr += IN_UCHARS(offs1);
#endif
#if PCRE2_CODE_UNIT_WIDTH != 8
@ -183,13 +188,13 @@ restart:;
#endif
#if defined(FFCPS)
if (str_ptr >= str_end)
if (*str_ptr >= str_end)
return NULL;
sljit_u8 *p1 = str_ptr - diff;
sljit_u8 *p1 = *str_ptr - diff;
#endif
sljit_s32 align_offset = ((uint64_t)str_ptr & 0xf);
str_ptr = (sljit_u8 *) ((uint64_t)str_ptr & ~0xf);
vect_t data = VLD1Q(str_ptr);
sljit_s32 align_offset = ((uint64_t)*str_ptr & 0xf);
*str_ptr = (sljit_u8 *) ((uint64_t)*str_ptr & ~0xf);
vect_t data = VLD1Q(*str_ptr);
#if PCRE2_CODE_UNIT_WIDTH != 8
data = VANDQ(data, char_mask);
#endif
@ -212,9 +217,9 @@ vect_t prev_data = data;
# endif
vect_t data2;
if (p1 < str_ptr)
if (p1 < *str_ptr)
{
data2 = VLD1Q(str_ptr - diff);
data2 = VLD1Q(*str_ptr - diff);
#if PCRE2_CODE_UNIT_WIDTH != 8
data2 = VANDQ(data2, char_mask);
#endif
@ -242,12 +247,12 @@ if (align_offset < 8)
qw.dw[0] >>= align_offset * 8;
if (qw.dw[0])
{
str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
*str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
goto match;
}
if (qw.dw[1])
{
str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
*str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
goto match;
}
}
@ -256,15 +261,15 @@ else
qw.dw[1] >>= (align_offset - 8) * 8;
if (qw.dw[1])
{
str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
*str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
goto match;
}
}
str_ptr += 16;
*str_ptr += 16;
while (str_ptr < str_end)
while (*str_ptr < str_end)
{
vect_t orig_data = VLD1Q(str_ptr);
vect_t orig_data = VLD1Q(*str_ptr);
#if PCRE2_CODE_UNIT_WIDTH != 8
orig_data = VANDQ(orig_data, char_mask);
#endif
@ -287,7 +292,7 @@ while (str_ptr < str_end)
# if defined (FFCPS_DIFF1)
data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);
# else
data2 = VLD1Q(str_ptr - diff);
data2 = VLD1Q(*str_ptr - diff);
# if PCRE2_CODE_UNIT_WIDTH != 8
data2 = VANDQ(data2, char_mask);
# endif
@ -312,11 +317,11 @@ while (str_ptr < str_end)
VST1Q(qw.mem, eq);
if (qw.dw[0])
str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
*str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
else if (qw.dw[1])
str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
*str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
else {
str_ptr += 16;
*str_ptr += 16;
#if defined (FFCPS_DIFF1)
prev_data = orig_data;
#endif
@ -324,24 +329,24 @@ while (str_ptr < str_end)
}
match:;
if (str_ptr >= str_end)
if (*str_ptr >= str_end)
/* Failed match. */
return NULL;
#if defined(FF_UTF)
if (utf_continue((PCRE2_SPTR)str_ptr - offs1))
if (utf_continue((PCRE2_SPTR)*str_ptr - offs1))
{
/* Not a match. */
str_ptr += IN_UCHARS(1);
*str_ptr += IN_UCHARS(1);
goto restart;
}
#endif
/* Match. */
#if defined (FFCPS)
str_ptr -= IN_UCHARS(offs1);
*str_ptr -= IN_UCHARS(offs1);
#endif
return str_ptr;
return *str_ptr;
}
/* Failed match. */

File diff suppressed because it is too large Load Diff

View File

@ -52,8 +52,6 @@ PCRE2_DFTABLES is defined. */
# include "pcre2_internal.h"
#endif
/*************************************************
* Create PCRE2 character tables *
*************************************************/
@ -98,7 +96,11 @@ for (i = 0; i < 256; i++) *p++ = tolower(i);
/* Next the case-flipping table */
for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(i);
for (i = 0; i < 256; i++)
{
int c = islower(i)? toupper(i) : tolower(i);
*p++ = (c < 256)? c : i;
}
/* Then the character class tables. Don't try to be clever and save effort on
exclusive ones - in some locales things may be different.

View File

@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
New API code Copyright (c) 2015-2022 University of Cambridge
New API code Copyright (c) 2015-2024 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -43,6 +43,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "config.h"
#endif
#include "pcre2_internal.h"
/* These defines enable debugging code */
/* #define DEBUG_FRAMES_DISPLAY */
@ -53,6 +55,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
#endif
#ifdef DEBUG_SHOW_OPS
static const char *OP_names[] = { OP_NAME_LIST };
#endif
/* These defines identify the name of the block containing "static"
information, and fields within it. */
@ -60,8 +66,6 @@ information, and fields within it. */
#define PSSTART start_subject /* Field containing processed string start */
#define PSEND end_subject /* Field containing processed string end */
#include "pcre2_internal.h"
#define RECURSE_UNSET 0xffffffffu /* Bigger than max group number */
/* Masks for identifying the public options that are permitted at match time. */
@ -69,7 +73,8 @@ information, and fields within it. */
#define PUBLIC_MATCH_OPTIONS \
(PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \
PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK|PCRE2_PARTIAL_HARD| \
PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT|PCRE2_COPY_MATCHED_SUBJECT)
PCRE2_PARTIAL_SOFT|PCRE2_NO_JIT|PCRE2_COPY_MATCHED_SUBJECT| \
PCRE2_DISABLE_RECURSELOOP_CHECK)
#define PUBLIC_JIT_MATCH_OPTIONS \
(PCRE2_NO_UTF_CHECK|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY|\
@ -150,7 +155,7 @@ changed, the code at RETURN_SWITCH below must be updated in sync. */
enum { RM1=1, RM2, RM3, RM4, RM5, RM6, RM7, RM8, RM9, RM10,
RM11, RM12, RM13, RM14, RM15, RM16, RM17, RM18, RM19, RM20,
RM21, RM22, RM23, RM24, RM25, RM26, RM27, RM28, RM29, RM30,
RM31, RM32, RM33, RM34, RM35, RM36 };
RM31, RM32, RM33, RM34, RM35, RM36, RM37 };
#ifdef SUPPORT_WIDE_CHARS
enum { RM100=100, RM101 };
@ -597,11 +602,12 @@ heapframe *P = NULL;
heapframe *frames_top; /* End of frames vector */
heapframe *assert_accept_frame = NULL; /* For passing back a frame with captures */
PCRE2_SIZE heapframes_size; /* Usable size of frames vector */
PCRE2_SIZE frame_copy_size; /* Amount to copy when creating a new frame */
/* Local variables that do not need to be preserved over calls to RRMATCH(). */
PCRE2_SPTR branch_end = NULL;
PCRE2_SPTR branch_start;
PCRE2_SPTR bracode; /* Temp pointer to start of group */
PCRE2_SIZE offset; /* Used for group offsets */
PCRE2_SIZE length; /* Used for various length calculations */
@ -635,13 +641,10 @@ copied when a new frame is created. */
frame_copy_size = frame_size - offsetof(heapframe, eptr);
/* Set up the first frame and the end of the frames vector. We set the local
heapframes_size to the usuable amount of the vector, that is, a whole number of
frames. */
/* Set up the first frame and the end of the frames vector. */
F = match_data->heapframes;
heapframes_size = (match_data->heapframes_size / frame_size) * frame_size;
frames_top = (heapframe *)((char *)F + heapframes_size);
frames_top = (heapframe *)((char *)F + match_data->heapframes_size);
Frdepth = 0; /* "Recursion" depth */
Fcapture_last = 0; /* Number of most recent capture */
@ -662,35 +665,54 @@ MATCH_RECURSE:
doubling the size, but constrained by the heap limit (which is in KiB). */
N = (heapframe *)((char *)F + frame_size);
if (N >= frames_top)
if ((heapframe *)((char *)N + frame_size) >= frames_top)
{
heapframe *new;
PCRE2_SIZE newsize = match_data->heapframes_size * 2;
PCRE2_SIZE newsize;
PCRE2_SIZE usedsize = (char *)N - (char *)(match_data->heapframes);
if (newsize > mb->heap_limit)
if (match_data->heapframes_size >= PCRE2_SIZE_MAX / 2)
{
PCRE2_SIZE maxsize = (mb->heap_limit/frame_size) * frame_size;
if (match_data->heapframes_size >= maxsize) return PCRE2_ERROR_HEAPLIMIT;
newsize = maxsize;
if (match_data->heapframes_size == PCRE2_SIZE_MAX - 1)
return PCRE2_ERROR_NOMEMORY;
newsize = PCRE2_SIZE_MAX - 1;
}
else
newsize = match_data->heapframes_size * 2;
if (newsize / 1024 >= mb->heap_limit)
{
PCRE2_SIZE old_size = match_data->heapframes_size / 1024;
if (mb->heap_limit <= old_size)
return PCRE2_ERROR_HEAPLIMIT;
else
{
PCRE2_SIZE max_delta = 1024 * (mb->heap_limit - old_size);
int over_bytes = match_data->heapframes_size % 1024;
if (over_bytes) max_delta -= (1024 - over_bytes);
newsize = match_data->heapframes_size + max_delta;
}
}
/* With a heap limit set, the permitted additional size may not be enough for
another frame, so do a final check. */
if (newsize - usedsize < frame_size) return PCRE2_ERROR_HEAPLIMIT;
new = match_data->memctl.malloc(newsize, match_data->memctl.memory_data);
if (new == NULL) return PCRE2_ERROR_NOMEMORY;
memcpy(new, match_data->heapframes, heapframes_size);
memcpy(new, match_data->heapframes, usedsize);
F = (heapframe *)((char *)new + ((char *)F - (char *)match_data->heapframes));
N = (heapframe *)((char *)F + frame_size);
N = (heapframe *)((char *)new + usedsize);
F = (heapframe *)((char *)N - frame_size);
match_data->memctl.free(match_data->heapframes, match_data->memctl.memory_data);
match_data->heapframes = new;
match_data->heapframes_size = newsize;
heapframes_size = (newsize / frame_size) * frame_size;
frames_top = (heapframe *)((char *)new + heapframes_size);
frames_top = (heapframe *)((char *)new + newsize);
}
#ifdef DEBUG_SHOW_RMATCH
fprintf(stderr, "++ RMATCH %2d frame=%d", Freturn_id, Frdepth + 1);
fprintf(stderr, "++ RMATCH %d frame=%d", Freturn_id, Frdepth + 1);
if (group_frame_type != 0)
{
fprintf(stderr, " type=%x ", group_frame_type);
@ -760,10 +782,16 @@ opcodes. */
if (mb->match_call_count++ >= mb->match_limit) return PCRE2_ERROR_MATCHLIMIT;
if (Frdepth >= mb->match_limit_depth) return PCRE2_ERROR_DEPTHLIMIT;
#ifdef DEBUG_SHOW_OPS
fprintf(stderr, "\n++ New frame: type=0x%x subject offset %ld\n",
GF_IDMASK(Fgroup_frame_type), Feptr - mb->start_subject);
#endif
for (;;)
{
#ifdef DEBUG_SHOW_OPS
fprintf(stderr, "++ op=%d\n", *Fecode);
fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
OP_names[*Fecode]);
#endif
Fop = (uint8_t)(*Fecode); /* Cast needed for 16-bit and 32-bit modes */
@ -811,15 +839,16 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
assert_accept_frame = F;
RRETURN(MATCH_ACCEPT);
/* If recursing, we have to find the most recent recursion. */
/* For ACCEPT within a recursion, we have to find the most recent
recursion. If not in a recursion, fall through to code that is common with
OP_END. */
case OP_ACCEPT:
case OP_END:
/* Handle end of a recursion. */
if (Fcurrent_recurse != RECURSE_UNSET)
{
#ifdef DEBUG_SHOW_OPS
fprintf(stderr, "++ Accept within recursion\n");
#endif
offset = Flast_group_offset;
for(;;)
{
@ -842,27 +871,49 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
Fecode += 1 + LINK_SIZE;
continue;
}
/* Fall through */
/* Not a recursion. Fail for an empty string match if either PCRE2_NOTEMPTY
is set, or if PCRE2_NOTEMPTY_ATSTART is set and we have matched at the
start of the subject. In both cases, backtracking will then try other
alternatives, if any. */
/* OP_END itself can never be reached within a recursion because that is
picked up when the OP_KET that always precedes OP_END is reached. */
case OP_END:
/* Fail for an empty string match if either PCRE2_NOTEMPTY is set, or if
PCRE2_NOTEMPTY_ATSTART is set and we have matched at the start of the
subject. In both cases, backtracking will then try other alternatives, if
any. */
if (Feptr == Fstart_match &&
((mb->moptions & PCRE2_NOTEMPTY) != 0 ||
((mb->moptions & PCRE2_NOTEMPTY_ATSTART) != 0 &&
Fstart_match == mb->start_subject + mb->start_offset)))
{
#ifdef DEBUG_SHOW_OPS
fprintf(stderr, "++ Backtrack because empty string\n");
#endif
RRETURN(MATCH_NOMATCH);
}
/* Also fail if PCRE2_ENDANCHORED is set and the end of the match is not
/* Fail if PCRE2_ENDANCHORED is set and the end of the match is not
the end of the subject. After (*ACCEPT) we fail the entire match (at this
position) but backtrack on reaching the end of the pattern. */
position) but backtrack if we've reached the end of the pattern. This
applies whether or not we are in a recursion. */
if (Feptr < mb->end_subject &&
((mb->moptions | mb->poptions) & PCRE2_ENDANCHORED) != 0)
{
if (Fop == OP_END) RRETURN(MATCH_NOMATCH);
return MATCH_NOMATCH;
if (Fop == OP_END)
{
#ifdef DEBUG_SHOW_OPS
fprintf(stderr, "++ Backtrack because not at end (endanchored set)\n");
#endif
RRETURN(MATCH_NOMATCH);
}
#ifdef DEBUG_SHOW_OPS
fprintf(stderr, "++ Failed ACCEPT not at end (endanchnored set)\n");
#endif
return MATCH_NOMATCH; /* (*ACCEPT) */
}
/* We have a successful match of the whole pattern. Record the result and
@ -2435,6 +2486,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
GETCHARINCTEST(fc, Feptr);
{
const uint32_t *cp;
uint32_t chartype;
const ucd_record *prop = GET_UCD(fc);
BOOL notmatch = Fop == OP_NOTPROP;
@ -2445,9 +2497,10 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
break;
case PT_LAMP:
if ((prop->chartype == ucp_Lu ||
prop->chartype == ucp_Ll ||
prop->chartype == ucp_Lt) == notmatch)
chartype = prop->chartype;
if ((chartype == ucp_Lu ||
chartype == ucp_Ll ||
chartype == ucp_Lt) == notmatch)
RRETURN(MATCH_NOMATCH);
break;
@ -2477,8 +2530,9 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* These are specials */
case PT_ALNUM:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N) == notmatch)
chartype = prop->chartype;
if ((PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N) == notmatch)
RRETURN(MATCH_NOMATCH);
break;
@ -2503,13 +2557,22 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
break;
case PT_WORD:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
fc == CHAR_UNDERSCORE) == notmatch)
chartype = prop->chartype;
if ((PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N ||
chartype == ucp_Mn ||
chartype == ucp_Pc) == notmatch)
RRETURN(MATCH_NOMATCH);
break;
case PT_CLIST:
#if PCRE2_CODE_UNIT_WIDTH == 32
if (fc > MAX_UTF_CODE_POINT)
{
if (notmatch) break;;
RRETURN(MATCH_NOMATCH);
}
#endif
cp = PRIV(ucd_caseless_sets) + Fecode[2];
for (;;)
{
@ -2805,16 +2868,17 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case PT_WORD:
for (i = 1; i <= Lmin; i++)
{
int category;
int chartype, category;
if (Feptr >= mb->end_subject)
{
SCHECK_PARTIAL();
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(fc, Feptr);
category = UCD_CATEGORY(fc);
chartype = UCD_CHARTYPE(fc);
category = PRIV(ucp_gentype)[chartype];
if ((category == ucp_L || category == ucp_N ||
fc == CHAR_UNDERSCORE) == notmatch)
chartype == ucp_Mn || chartype == ucp_Pc) == notmatch)
RRETURN(MATCH_NOMATCH);
}
break;
@ -2829,6 +2893,13 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(fc, Feptr);
#if PCRE2_CODE_UNIT_WIDTH == 32
if (fc > MAX_UTF_CODE_POINT)
{
if (notmatch) continue;
RRETURN(MATCH_NOMATCH);
}
#endif
cp = PRIV(ucd_caseless_sets) + Lpropvalue;
for (;;)
{
@ -3609,7 +3680,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case PT_WORD:
for (;;)
{
int category;
int chartype, category;
RMATCH(Fecode, RM215);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
@ -3619,10 +3690,12 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(fc, Feptr);
category = UCD_CATEGORY(fc);
chartype = UCD_CHARTYPE(fc);
category = PRIV(ucp_gentype)[chartype];
if ((category == ucp_L ||
category == ucp_N ||
fc == CHAR_UNDERSCORE) == (Lctype == OP_NOTPROP))
chartype == ucp_Mn ||
chartype == ucp_Pc) == (Lctype == OP_NOTPROP))
RRETURN(MATCH_NOMATCH);
}
/* Control never gets here */
@ -3640,6 +3713,13 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(fc, Feptr);
#if PCRE2_CODE_UNIT_WIDTH == 32
if (fc > MAX_UTF_CODE_POINT)
{
if (Lctype == OP_NOTPROP) continue;
RRETURN(MATCH_NOMATCH);
}
#endif
cp = PRIV(ucd_caseless_sets) + Lpropvalue;
for (;;)
{
@ -4190,7 +4270,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case PT_WORD:
for (i = Lmin; i < Lmax; i++)
{
int category;
int chartype, category;
int len = 1;
if (Feptr >= mb->end_subject)
{
@ -4198,9 +4278,12 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
break;
}
GETCHARLENTEST(fc, Feptr, len);
category = UCD_CATEGORY(fc);
if ((category == ucp_L || category == ucp_N ||
fc == CHAR_UNDERSCORE) == notmatch)
chartype = UCD_CHARTYPE(fc);
category = PRIV(ucp_gentype)[chartype];
if ((category == ucp_L ||
category == ucp_N ||
chartype == ucp_Mn ||
chartype == ucp_Pc) == notmatch)
break;
Feptr+= len;
}
@ -4217,14 +4300,24 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
break;
}
GETCHARLENTEST(fc, Feptr, len);
cp = PRIV(ucd_caseless_sets) + Lpropvalue;
for (;;)
#if PCRE2_CODE_UNIT_WIDTH == 32
if (fc > MAX_UTF_CODE_POINT)
{
if (fc < *cp)
{ if (notmatch) break; else goto GOT_MAX; }
if (fc == *cp++)
{ if (notmatch) goto GOT_MAX; else break; }
if (!notmatch) goto GOT_MAX;
}
else
#endif
{
cp = PRIV(ucd_caseless_sets) + Lpropvalue;
for (;;)
{
if (fc < *cp)
{ if (notmatch) break; else goto GOT_MAX; }
if (fc == *cp++)
{ if (notmatch) goto GOT_MAX; else break; }
}
}
Feptr += len;
}
GOT_MAX:
@ -5322,9 +5415,11 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* ===================================================================== */
/* Recursion either matches the current regex, or some subexpression. The
offset data is the offset to the starting bracket from the start of the
whole pattern. (This is so that it works from duplicated subpatterns.) */
/* Pattern recursion either matches the current regex, or some
subexpression. The offset data is the offset to the starting bracket from
the start of the whole pattern. This is so that it works from duplicated
subpatterns. For a whole-pattern recursion, we have to infer the number
zero. */
#define Lframe_type F->temp_32[0]
#define Lstart_branch F->temp_sptr[0]
@ -5333,9 +5428,12 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
bracode = mb->start_code + GET(Fecode, 1);
number = (bracode == mb->start_code)? 0 : GET2(bracode, 1 + LINK_SIZE);
/* If we are already in a recursion, check for repeating the same one
without advancing the subject pointer. This should catch convoluted mutual
recursions. (Some simple cases are caught at compile time.) */
/* If we are already in a pattern recursion, check for repeating the same
one without changing the subject pointer or the last referenced character
in the subject. This should catch convoluted mutual recursions; some
simple cases are caught at compile time. However, there are rare cases when
this check needs to be turned off. In this case, actual recursion loops
will be caught by the match or heap limits. */
if (Fcurrent_recurse != RECURSE_UNSET)
{
@ -5346,15 +5444,19 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
P = (heapframe *)((char *)N - frame_size);
if (N->group_frame_type == (GF_RECURSE | number))
{
if (Feptr == P->eptr) return PCRE2_ERROR_RECURSELOOP;
if (Feptr == P->eptr && mb->last_used_ptr == P->recurse_last_used &&
(mb->moptions & PCRE2_DISABLE_RECURSELOOP_CHECK) == 0)
return PCRE2_ERROR_RECURSELOOP;
break;
}
offset = P->last_group_offset;
}
}
/* Now run the recursion, branch by branch. */
/* Remember the current last referenced character and then run the
recursion branch by branch. */
F->recurse_last_used = mb->last_used_ptr;
Lstart_branch = bracode;
Lframe_type = GF_RECURSE | number;
@ -5683,13 +5785,13 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* ===================================================================== */
/* Move the subject pointer back. This occurs only at the start of each
branch of a lookbehind assertion. If we are too close to the start to move
back, fail. When working with UTF-8 we move back a number of characters,
not bytes. */
/* Move the subject pointer back by one fixed amount. This occurs at the
start of each branch that has a fixed length in a lookbehind assertion. If
we are too close to the start to move back, fail. When working with UTF-8
we move back a number of characters, not bytes. */
case OP_REVERSE:
number = GET(Fecode, 1);
number = GET2(Fecode, 1);
#ifdef SUPPORT_UNICODE
if (utf)
{
@ -5703,7 +5805,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
else
#endif
/* No UTF-8 support, or not in UTF-8 mode: count is code unit count */
/* No UTF support, or not in UTF mode: count is code unit count */
{
if ((ptrdiff_t)number > Feptr - mb->start_subject) RRETURN(MATCH_NOMATCH);
@ -5713,15 +5815,84 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* Save the earliest consulted character, then skip to next opcode */
if (Feptr < mb->start_used_ptr) mb->start_used_ptr = Feptr;
Fecode += 1 + LINK_SIZE;
Fecode += 1 + IMM2_SIZE;
break;
/* ===================================================================== */
/* Move the subject pointer back by a variable amount. This occurs at the
start of each branch of a lookbehind assertion when the branch has a
variable, but limited, length. A loop is needed to try matching the branch
after moving back different numbers of characters. If we are too close to
the start to move back even the minimum amount, fail. When working with
UTF-8 we move back a number of characters, not bytes. */
#define Lmin F->temp_32[0]
#define Lmax F->temp_32[1]
#define Leptr F->temp_sptr[0]
case OP_VREVERSE:
Lmin = GET2(Fecode, 1);
Lmax = GET2(Fecode, 1 + IMM2_SIZE);
Leptr = Feptr;
/* Move back by the maximum branch length and then work forwards. This
ensures that items such as \d{3,5} get the maximum length, which is
relevant for captures, and makes for Perl compatibility. */
#ifdef SUPPORT_UNICODE
if (utf)
{
for (i = 0; i < Lmax; i++)
{
if (Feptr == mb->start_subject)
{
if (i < Lmin) RRETURN(MATCH_NOMATCH);
Lmax = i;
break;
}
Feptr--;
BACKCHAR(Feptr);
}
}
else
#endif
/* No UTF support or not in UTF mode */
{
ptrdiff_t diff = Feptr - mb->start_subject;
uint32_t available = (diff > 65535)? 65535 : ((diff > 0)? diff : 0);
if (Lmin > available) RRETURN(MATCH_NOMATCH);
if (Lmax > available) Lmax = available;
Feptr -= Lmax;
}
/* Now try matching, moving forward one character on failure, until we
reach the mimimum back length. */
for (;;)
{
RMATCH(Fecode + 1 + 2 * IMM2_SIZE, RM37);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
if (Lmax-- <= Lmin) RRETURN(MATCH_NOMATCH);
Feptr++;
#ifdef SUPPORT_UNICODE
if (utf) { FORWARDCHARTEST(Feptr, mb->end_subject); }
#endif
}
/* Control never reaches here */
#undef Lmin
#undef Lmax
#undef Leptr
/* ===================================================================== */
/* An alternation is the end of a branch; scan along to find the end of the
bracketed group. */
case OP_ALT:
branch_end = Fecode;
do Fecode += GET(Fecode,1); while (*Fecode == OP_ALT);
break;
@ -5729,7 +5900,8 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* ===================================================================== */
/* The end of a parenthesized group. For all but OP_BRA and OP_COND, the
starting frame was added to the chained frames in order to remember the
starting subject position for the group. */
starting subject position for the group. (Not true for OP_BRA when it's a
whole pattern recursion, but that is handled separately below.)*/
case OP_KET:
case OP_KETRMIN:
@ -5738,8 +5910,14 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
bracode = Fecode - GET(Fecode, 1);
/* Point N to the frame at the start of the most recent group.
Remember the subject pointer at the start of the group. */
if (branch_end == NULL) branch_end = Fecode;
branch_start = bracode;
while (branch_start + GET(branch_start, 1) != branch_end)
branch_start += GET(branch_start, 1);
branch_end = NULL;
/* Point N to the frame at the start of the most recent group, and P to its
predecessor. Remember the subject pointer at the start of the group. */
if (*bracode != OP_BRA && *bracode != OP_COND)
{
@ -5775,27 +5953,64 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
switch (*bracode)
{
case OP_BRA: /* No need to do anything for these */
case OP_COND:
/* Whole pattern recursion is handled as a recursion into group 0, but
the entire pattern is wrapped in OP_BRA/OP_KET rather than a capturing
group - a design mistake: it should perhaps have been capture group 0.
Anyway, that means the end of such recursion must be handled here. It is
detected by checking for an immediately following OP_END when we are
recursing in group 0. If this is not the end of a whole-pattern
recursion, there is nothing to be done. */
case OP_BRA:
if (Fcurrent_recurse != 0 || Fecode[1+LINK_SIZE] != OP_END) break;
/* It is the end of whole-pattern recursion. */
offset = Flast_group_offset;
if (offset == PCRE2_UNSET) return PCRE2_ERROR_INTERNAL;
N = (heapframe *)((char *)match_data->heapframes + offset);
P = (heapframe *)((char *)N - frame_size);
Flast_group_offset = P->last_group_offset;
/* Reinstate the previous set of captures and then carry on after the
recursion call. */
memcpy((char *)F + offsetof(heapframe, ovector), P->ovector,
Foffset_top * sizeof(PCRE2_SIZE));
Foffset_top = P->offset_top;
Fcapture_last = P->capture_last;
Fcurrent_recurse = P->current_recurse;
Fecode = P->ecode + 1 + LINK_SIZE;
continue; /* With next opcode */
case OP_COND: /* No need to do anything for these */
case OP_SCOND:
break;
/* Non-atomic positive assertions are like OP_BRA, except that the
subject pointer must be put back to where it was at the start of the
assertion. */
assertion. For a variable lookbehind, check its end point. */
case OP_ASSERTBACK_NA:
if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr)
RRETURN(MATCH_NOMATCH);
/* Fall through */
case OP_ASSERT_NA:
case OP_ASSERTBACK_NA:
if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
Feptr = P->eptr;
break;
/* Atomic positive assertions are like OP_ONCE, except that in addition
the subject pointer must be put back to where it was at the start of the
assertion. */
assertion. For a variable lookbehind, check its end point. */
case OP_ASSERTBACK:
if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr)
RRETURN(MATCH_NOMATCH);
/* Fall through */
case OP_ASSERT:
case OP_ASSERTBACK:
if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
Feptr = P->eptr;
/* Fall through */
@ -5816,10 +6031,15 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
break;
/* A matching negative assertion returns MATCH, which is turned into
NOMATCH at the assertion level. */
NOMATCH at the assertion level. For a variable lookbehind, check its end
point. */
case OP_ASSERTBACK_NOT:
if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr)
RRETURN(MATCH_NOMATCH);
/* Fall through */
case OP_ASSERT_NOT:
case OP_ASSERTBACK_NOT:
RRETURN(MATCH_MATCH);
/* At the end of a script run, apply the script-checking rules. This code
@ -5830,9 +6050,8 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (!PRIV(script_run)(P->eptr, Feptr, utf)) RRETURN(MATCH_NOMATCH);
break;
/* Whole-pattern recursion is coded as a recurse into group 0, so it
won't be picked up here. Instead, we catch it when the OP_END is reached.
Other recursion is handled here. */
/* Whole-pattern recursion is coded as a recurse into group 0, and is
handled with OP_BRA above. Other recursion is handled here. */
case OP_CBRA:
case OP_CBRAPOS:
@ -5847,7 +6066,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
{
P = (heapframe *)((char *)N - frame_size);
memcpy((char *)F + offsetof(heapframe, ovector), P->ovector,
P->offset_top * sizeof(PCRE2_SIZE));
Foffset_top * sizeof(PCRE2_SIZE));
Foffset_top = P->offset_top;
Fcapture_last = P->capture_last;
Fcurrent_recurse = P->current_recurse;
@ -5930,10 +6149,10 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0) goto ASSERT_NL_OR_EOS;
/* Fall through */
/* Unconditional end of subject assertion (\z) */
/* Unconditional end of subject assertion (\z). */
case OP_EOD:
if (Feptr < mb->end_subject) RRETURN(MATCH_NOMATCH);
if (Feptr < mb->true_end_subject) RRETURN(MATCH_NOMATCH);
if (mb->partial != 0)
{
mb->hitend = TRUE;
@ -6045,6 +6264,8 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
case OP_NOT_UCP_WORD_BOUNDARY:
case OP_UCP_WORD_BOUNDARY:
if (Feptr == mb->check_subject) prev_is_word = FALSE; else
{
PCRE2_SPTR lastptr = Feptr - 1;
@ -6059,13 +6280,12 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
fc = *lastptr;
if (lastptr < mb->start_used_ptr) mb->start_used_ptr = lastptr;
#ifdef SUPPORT_UNICODE
if ((mb->poptions & PCRE2_UCP) != 0)
if (Fop == OP_UCP_WORD_BOUNDARY || Fop == OP_NOT_UCP_WORD_BOUNDARY)
{
if (fc == '_') prev_is_word = TRUE; else
{
int cat = UCD_CATEGORY(fc);
prev_is_word = (cat == ucp_L || cat == ucp_N);
}
int chartype = UCD_CHARTYPE(fc);
int category = PRIV(ucp_gentype)[chartype];
prev_is_word = (category == ucp_L || category == ucp_N ||
chartype == ucp_Mn || chartype == ucp_Pc);
}
else
#endif /* SUPPORT_UNICODE */
@ -6093,13 +6313,12 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
fc = *Feptr;
if (nextptr > mb->last_used_ptr) mb->last_used_ptr = nextptr;
#ifdef SUPPORT_UNICODE
if ((mb->poptions & PCRE2_UCP) != 0)
if (Fop == OP_UCP_WORD_BOUNDARY || Fop == OP_NOT_UCP_WORD_BOUNDARY)
{
if (fc == '_') cur_is_word = TRUE; else
{
int cat = UCD_CATEGORY(fc);
cur_is_word = (cat == ucp_L || cat == ucp_N);
}
int chartype = UCD_CHARTYPE(fc);
int category = PRIV(ucp_gentype)[chartype];
cur_is_word = (category == ucp_L || category == ucp_N ||
chartype == ucp_Mn || chartype == ucp_Pc);
}
else
#endif /* SUPPORT_UNICODE */
@ -6108,7 +6327,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* Now see if the situation is what we want */
if ((*Fecode++ == OP_WORD_BOUNDARY)?
if ((*Fecode++ == OP_WORD_BOUNDARY || Fop == OP_UCP_WORD_BOUNDARY)?
cur_is_word == prev_is_word : cur_is_word != prev_is_word)
RRETURN(MATCH_NOMATCH);
break;
@ -6254,7 +6473,7 @@ F = (heapframe *)((char *)F - Fback_frame); /* Backtrack */
mb->cb->callout_flags |= PCRE2_CALLOUT_BACKTRACK; /* Note for callouts */
#ifdef DEBUG_SHOW_RMATCH
fprintf(stderr, "++ RETURN %d to %d\n", rrc, Freturn_id);
fprintf(stderr, "++ RETURN %d to RM%d\n", rrc, Freturn_id);
#endif
switch (Freturn_id)
@ -6263,7 +6482,7 @@ switch (Freturn_id)
LBL( 9) LBL(10) LBL(11) LBL(12) LBL(13) LBL(14) LBL(15) LBL(16)
LBL(17) LBL(18) LBL(19) LBL(20) LBL(21) LBL(22) LBL(23) LBL(24)
LBL(25) LBL(26) LBL(27) LBL(28) LBL(29) LBL(30) LBL(31) LBL(32)
LBL(33) LBL(34) LBL(35) LBL(36)
LBL(33) LBL(34) LBL(35) LBL(36) LBL(37)
#ifdef SUPPORT_WIDE_CHARS
LBL(100) LBL(101)
@ -6551,6 +6770,7 @@ if (use_jit)
match_data, mcontext);
if (rc != PCRE2_ERROR_JIT_BADOPTION)
{
match_data->subject_length = length;
if (rc >= 0 && (options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
{
length = CU2BYTES(length + was_zero_terminated);
@ -6719,7 +6939,7 @@ if (mcontext == NULL)
else mb->memctl = mcontext->memctl;
anchored = ((re->overall_options | options) & PCRE2_ANCHORED) != 0;
firstline = (re->overall_options & PCRE2_FIRSTLINE) != 0;
firstline = !anchored && (re->overall_options & PCRE2_FIRSTLINE) != 0;
startline = (re->flags & PCRE2_STARTLINE) != 0;
bumpalong_limit = (mcontext->offset_limit == PCRE2_UNSET)?
true_end_subject : subject + mcontext->offset_limit;
@ -6742,6 +6962,7 @@ mb->callout_data = mcontext->callout_data;
mb->start_subject = subject;
mb->start_offset = start_offset;
mb->end_subject = end_subject;
mb->true_end_subject = true_end_subject;
mb->hasthen = (re->flags & PCRE2_HASTHEN) != 0;
mb->allowemptypartial = (re->max_lookbehind > 0) ||
(re->flags & PCRE2_MATCH_EMPTY) != 0;
@ -6801,7 +7022,7 @@ the pattern. It is not used at all if there are no capturing parentheses.
frame_size is the total size of each frame
match_data->heapframes is the pointer to the frames vector
match_data->heapframes_size is the total size of the vector
match_data->heapframes_size is the allocated size of the vector
We must pad the frame_size for alignment to ensure subsequent frames are as
aligned as heapframe. Whilst ovector is word-aligned due to being a PCRE2_SIZE
@ -6816,7 +7037,7 @@ frame_size = (offsetof(heapframe, ovector) +
smaller. */
mb->heap_limit = ((mcontext->heap_limit < re->limit_heap)?
mcontext->heap_limit : re->limit_heap) * 1024;
mcontext->heap_limit : re->limit_heap);
mb->match_limit = (mcontext->match_limit < re->limit_match)?
mcontext->match_limit : re->limit_match;
@ -6827,19 +7048,19 @@ mb->match_limit_depth = (mcontext->depth_limit < re->limit_depth)?
/* If a pattern has very many capturing parentheses, the frame size may be very
large. Set the initial frame vector size to ensure that there are at least 10
available frames, but enforce a minimum of START_FRAMES_SIZE. If this is
greater than the heap limit, get as large a vector as possible. Always round
the size to a multiple of the frame size. */
greater than the heap limit, get as large a vector as possible. */
heapframes_size = frame_size * 10;
if (heapframes_size < START_FRAMES_SIZE) heapframes_size = START_FRAMES_SIZE;
if (heapframes_size > mb->heap_limit)
if (heapframes_size / 1024 > mb->heap_limit)
{
if (frame_size > mb->heap_limit ) return PCRE2_ERROR_HEAPLIMIT;
heapframes_size = mb->heap_limit;
PCRE2_SIZE max_size = 1024 * mb->heap_limit;
if (max_size < frame_size) return PCRE2_ERROR_HEAPLIMIT;
heapframes_size = max_size;
}
/* If an existing frame vector in the match_data block is large enough, we can
use it.Otherwise, free any pre-existing vector and get a new one. */
use it. Otherwise, free any pre-existing vector and get a new one. */
if (match_data->heapframes_size < heapframes_size)
{
@ -7286,9 +7507,17 @@ for(;;)
mb->end_offset_top = 0;
mb->skip_arg_count = 0;
#ifdef DEBUG_SHOW_OPS
fprintf(stderr, "++ Calling match()\n");
#endif
rc = match(start_match, mb->start_code, re->top_bracket, frame_size,
match_data, mb);
#ifdef DEBUG_SHOW_OPS
fprintf(stderr, "++ match() returned %d\n\n", rc);
#endif
if (mb->hitend && start_partial == NULL)
{
start_partial = mb->start_used_ptr;
@ -7436,6 +7665,7 @@ if (utf && end_subject != true_end_subject &&
if (start_match >= true_end_subject)
{
rc = MATCH_NOMATCH; /* In case it was partial */
match_partial = NULL;
break;
}
@ -7485,6 +7715,7 @@ if (rc == MATCH_MATCH)
{
match_data->rc = ((int)mb->end_offset_top >= 2 * match_data->oveccount)?
0 : (int)mb->end_offset_top/2 + 1;
match_data->subject_length = length;
match_data->startchar = start_match - subject;
match_data->leftchar = mb->start_used_ptr - subject;
match_data->rightchar = ((mb->last_used_ptr > mb->end_match_ptr)?
@ -7499,6 +7730,7 @@ if (rc == MATCH_MATCH)
match_data->flags |= PCRE2_MD_COPIED_SUBJECT;
}
else match_data->subject = subject;
return match_data->rc;
}
@ -7520,6 +7752,7 @@ PCRE2_ERROR_PARTIAL. */
else if (match_partial != NULL)
{
match_data->subject = subject;
match_data->subject_length = length;
match_data->ovector[0] = match_partial - subject;
match_data->ovector[1] = end_subject - subject;
match_data->startchar = match_partial - subject;

View File

@ -170,4 +170,16 @@ return offsetof(pcre2_match_data, ovector) +
2 * (match_data->oveccount) * sizeof(PCRE2_SIZE);
}
/*************************************************
* Get heapframes size *
*************************************************/
PCRE2_EXP_DEFN PCRE2_SIZE PCRE2_CALL_CONVENTION
pcre2_get_match_data_heapframes_size(pcre2_match_data *match_data)
{
return match_data->heapframes_size;
}
/* End of pcre2_match_data.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-2021 University of Cambridge
New API code Copyright (c) 2016-2023 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -256,6 +256,7 @@ for (;;)
/* Skip over things that don't match chars */
case OP_REVERSE:
case OP_VREVERSE:
case OP_CREF:
case OP_DNCREF:
case OP_RREF:
@ -273,6 +274,8 @@ for (;;)
case OP_DOLLM:
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
case OP_NOT_UCP_WORD_BOUNDARY:
case OP_UCP_WORD_BOUNDARY:
cc += PRIV(OP_lengths)[*cc];
break;
@ -976,6 +979,7 @@ do
while (try_next) /* Loop for items in this branch */
{
int rc;
PCRE2_SPTR ncode;
uint8_t *classmap = NULL;
#ifdef SUPPORT_WIDE_CHARS
PCRE2_UCHAR xclassflags;
@ -1054,6 +1058,7 @@ do
case OP_REF:
case OP_REFI:
case OP_REVERSE:
case OP_VREVERSE:
case OP_RREF:
case OP_SCOND:
case OP_SET_SOM:
@ -1101,13 +1106,100 @@ do
case OP_WORD_BOUNDARY:
case OP_NOT_WORD_BOUNDARY:
case OP_UCP_WORD_BOUNDARY:
case OP_NOT_UCP_WORD_BOUNDARY:
tcode++;
break;
/* If we hit a bracket or a positive lookahead assertion, recurse to set
bits from within the subpattern. If it can't find anything, we have to
give up. If it finds some mandatory character(s), we are done for this
branch. Otherwise, carry on scanning after the subpattern. */
/* For a positive lookahead assertion, inspect what immediately follows,
ignoring intermediate assertions and callouts. If the next item is one
that sets a mandatory character, skip this assertion. Otherwise, treat it
the same as other bracket groups. */
case OP_ASSERT:
case OP_ASSERT_NA:
ncode = tcode + GET(tcode, 1);
while (*ncode == OP_ALT) ncode += GET(ncode, 1);
ncode += 1 + LINK_SIZE;
/* Skip irrelevant items */
for (BOOL done = FALSE; !done;)
{
switch (*ncode)
{
case OP_ASSERT:
case OP_ASSERT_NOT:
case OP_ASSERTBACK:
case OP_ASSERTBACK_NOT:
case OP_ASSERT_NA:
case OP_ASSERTBACK_NA:
ncode += GET(ncode, 1);
while (*ncode == OP_ALT) ncode += GET(ncode, 1);
ncode += 1 + LINK_SIZE;
break;
case OP_WORD_BOUNDARY:
case OP_NOT_WORD_BOUNDARY:
case OP_UCP_WORD_BOUNDARY:
case OP_NOT_UCP_WORD_BOUNDARY:
ncode++;
break;
case OP_CALLOUT:
ncode += PRIV(OP_lengths)[OP_CALLOUT];
break;
case OP_CALLOUT_STR:
ncode += GET(ncode, 1 + 2*LINK_SIZE);
break;
default:
done = TRUE;
break;
}
}
/* Now check the next significant item. */
switch(*ncode)
{
default:
break;
case OP_PROP:
if (ncode[1] != PT_CLIST) break;
/* Fall through */
case OP_ANYNL:
case OP_CHAR:
case OP_CHARI:
case OP_EXACT:
case OP_EXACTI:
case OP_HSPACE:
case OP_MINPLUS:
case OP_MINPLUSI:
case OP_PLUS:
case OP_PLUSI:
case OP_POSPLUS:
case OP_POSPLUSI:
case OP_VSPACE:
/* Note that these types will only be present in non-UCP mode. */
case OP_DIGIT:
case OP_NOT_DIGIT:
case OP_WORDCHAR:
case OP_NOT_WORDCHAR:
case OP_WHITESPACE:
case OP_NOT_WHITESPACE:
tcode = ncode;
continue; /* With the following significant opcode */
}
/* Fall through */
/* For a group bracket or a positive assertion without an immediately
following mandatory setting, recurse to set bits from within the
subpattern. If it can't find anything, we have to give up. If it finds
some mandatory character(s), we are done for this branch. Otherwise,
carry on scanning after the subpattern. */
case OP_BRA:
case OP_SBRA:
@ -1119,8 +1211,6 @@ do
case OP_SCBRAPOS:
case OP_ONCE:
case OP_SCRIPT_RUN:
case OP_ASSERT:
case OP_ASSERT_NA:
rc = set_start_bits(re, tcode, utf, ucp, depthptr);
if (rc == SSB_DONE)
{

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-2023 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -309,6 +309,7 @@ Returns: if successful: 0
PCRE2_ERROR_NOSUBSTRING: no such substring
PCRE2_ERROR_UNAVAILABLE: ovector is too small
PCRE2_ERROR_UNSET: substring is not set
PCRE2_ERROR_INVALIDOFFSET: internal error, should not occur
*/
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
@ -341,6 +342,8 @@ else /* Matched using pcre2_dfa_match() */
left = match_data->ovector[stringnumber*2];
right = match_data->ovector[stringnumber*2+1];
if (left > match_data->subject_length || right > match_data->subject_length)
return PCRE2_ERROR_INVALIDOFFSET;
if (sizeptr != NULL) *sizeptr = (left > right)? 0 : right - left;
return 0;
}
@ -442,7 +445,7 @@ Returns: nothing
*/
PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
pcre2_substring_list_free(PCRE2_SPTR *list)
pcre2_substring_list_free(PCRE2_UCHAR **list)
{
if (list != NULL)
{

File diff suppressed because it is too large Load Diff

View File

@ -166,29 +166,29 @@ enum {
/* These are the bidi class values. */
enum {
ucp_bidiAL, /* Arabic letter */
ucp_bidiAN, /* Arabic number */
ucp_bidiB, /* Paragraph separator */
ucp_bidiBN, /* Boundary neutral */
ucp_bidiCS, /* Common separator */
ucp_bidiEN, /* European number */
ucp_bidiES, /* European separator */
ucp_bidiET, /* European terminator */
ucp_bidiFSI, /* First strong isolate */
ucp_bidiL, /* Left to right */
ucp_bidiLRE, /* Left to right embedding */
ucp_bidiLRI, /* Left to right isolate */
ucp_bidiLRO, /* Left to right override */
ucp_bidiNSM, /* Non-spacing mark */
ucp_bidiON, /* Other neutral */
ucp_bidiPDF, /* Pop directional format */
ucp_bidiPDI, /* Pop directional isolate */
ucp_bidiR, /* Right to left */
ucp_bidiRLE, /* Right to left embedding */
ucp_bidiRLI, /* Right to left isolate */
ucp_bidiRLO, /* Right to left override */
ucp_bidiS, /* Segment separator */
ucp_bidiWS, /* White space */
ucp_bidiAL, /* Arabic_Letter */
ucp_bidiAN, /* Arabic_Number */
ucp_bidiB, /* Paragraph_Separator */
ucp_bidiBN, /* Boundary_Neutral */
ucp_bidiCS, /* Common_Separator */
ucp_bidiEN, /* European_Number */
ucp_bidiES, /* European_Separator */
ucp_bidiET, /* European_Terminator */
ucp_bidiFSI, /* First_Strong_Isolate */
ucp_bidiL, /* Left_To_Right */
ucp_bidiLRE, /* Left_To_Right_Embedding */
ucp_bidiLRI, /* Left_To_Right_Isolate */
ucp_bidiLRO, /* Left_To_Right_Override */
ucp_bidiNSM, /* Nonspacing_Mark */
ucp_bidiON, /* Other_Neutral */
ucp_bidiPDF, /* Pop_Directional_Format */
ucp_bidiPDI, /* Pop_Directional_Isolate */
ucp_bidiR, /* Right_To_Left */
ucp_bidiRLE, /* Right_To_Left_Embedding */
ucp_bidiRLI, /* Right_To_Left_Isolate */
ucp_bidiRLO, /* Right_To_Left_Override */
ucp_bidiS, /* Segment_Separator */
ucp_bidiWS, /* White_Space */
};
/* These are grapheme break properties. The Extended Pictographic property
@ -380,6 +380,8 @@ enum {
ucp_Tangsa,
ucp_Toto,
ucp_Vithkuqi,
ucp_Kawi,
ucp_Nag_Mundari,
/* This must be last */
ucp_Script_Count

View File

@ -265,6 +265,7 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_kana0 STR_k STR_a STR_n STR_a "\0"
#define STRING_kannada0 STR_k STR_a STR_n STR_n STR_a STR_d STR_a "\0"
#define STRING_katakana0 STR_k STR_a STR_t STR_a STR_k STR_a STR_n STR_a "\0"
#define STRING_kawi0 STR_k STR_a STR_w STR_i "\0"
#define STRING_kayahli0 STR_k STR_a STR_y STR_a STR_h STR_l STR_i "\0"
#define STRING_khar0 STR_k STR_h STR_a STR_r "\0"
#define STRING_kharoshthi0 STR_k STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0"
@ -347,6 +348,8 @@ the "loose matching" rules that Unicode advises and Perl uses. */
#define STRING_mymr0 STR_m STR_y STR_m STR_r "\0"
#define STRING_n0 STR_n "\0"
#define STRING_nabataean0 STR_n STR_a STR_b STR_a STR_t STR_a STR_e STR_a STR_n "\0"
#define STRING_nagm0 STR_n STR_a STR_g STR_m "\0"
#define STRING_nagmundari0 STR_n STR_a STR_g STR_m STR_u STR_n STR_d STR_a STR_r STR_i "\0"
#define STRING_nand0 STR_n STR_a STR_n STR_d "\0"
#define STRING_nandinagari0 STR_n STR_a STR_n STR_d STR_i STR_n STR_a STR_g STR_a STR_r STR_i "\0"
#define STRING_narb0 STR_n STR_a STR_r STR_b "\0"
@ -753,6 +756,7 @@ const char PRIV(utt_names)[] =
STRING_kana0
STRING_kannada0
STRING_katakana0
STRING_kawi0
STRING_kayahli0
STRING_khar0
STRING_kharoshthi0
@ -835,6 +839,8 @@ const char PRIV(utt_names)[] =
STRING_mymr0
STRING_n0
STRING_nabataean0
STRING_nagm0
STRING_nagmundari0
STRING_nand0
STRING_nandinagari0
STRING_narb0
@ -1241,280 +1247,283 @@ const ucp_type_table PRIV(utt)[] = {
{ 1665, PT_SCX, ucp_Katakana },
{ 1670, PT_SCX, ucp_Kannada },
{ 1678, PT_SCX, ucp_Katakana },
{ 1687, PT_SCX, ucp_Kayah_Li },
{ 1695, PT_SC, ucp_Kharoshthi },
{ 1687, PT_SC, ucp_Kawi },
{ 1692, PT_SCX, ucp_Kayah_Li },
{ 1700, PT_SC, ucp_Kharoshthi },
{ 1711, PT_SC, ucp_Khitan_Small_Script },
{ 1729, PT_SC, ucp_Khmer },
{ 1735, PT_SC, ucp_Khmer },
{ 1740, PT_SCX, ucp_Khojki },
{ 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 },
{ 1752, PT_SCX, ucp_Khudawadi },
{ 1762, PT_SC, ucp_Khitan_Small_Script },
{ 1767, PT_SCX, ucp_Kannada },
{ 1772, PT_SCX, ucp_Kaithi },
{ 1777, PT_GC, ucp_L },
{ 1779, PT_LAMP, 0 },
{ 1782, PT_SC, ucp_Tai_Tham },
{ 1787, PT_SC, ucp_Lao },
{ 1791, PT_SC, ucp_Lao },
{ 1796, PT_SCX, ucp_Latin },
{ 1802, PT_SCX, ucp_Latin },
{ 1807, PT_LAMP, 0 },
{ 1810, PT_SC, ucp_Lepcha },
{ 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 },
{ 1822, PT_SCX, ucp_Limbu },
{ 1820, PT_SC, ucp_Lepcha },
{ 1827, PT_SCX, ucp_Limbu },
{ 1833, PT_SCX, ucp_Linear_A },
{ 1838, PT_SCX, ucp_Linear_B },
{ 1843, PT_SCX, ucp_Linear_A },
{ 1851, PT_SCX, ucp_Linear_B },
{ 1859, PT_SC, ucp_Lisu },
{ 1864, PT_PC, ucp_Ll },
{ 1867, PT_PC, ucp_Lm },
{ 1870, PT_PC, ucp_Lo },
{ 1873, PT_BOOL, ucp_Logical_Order_Exception },
{ 1877, PT_BOOL, ucp_Logical_Order_Exception },
{ 1899, PT_BOOL, ucp_Lowercase },
{ 1905, PT_BOOL, ucp_Lowercase },
{ 1915, PT_PC, ucp_Lt },
{ 1918, PT_PC, ucp_Lu },
{ 1921, PT_SC, ucp_Lycian },
{ 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 },
{ 1933, PT_SC, ucp_Lydian },
{ 1931, PT_SC, ucp_Lycian },
{ 1938, PT_SC, ucp_Lydian },
{ 1945, PT_GC, ucp_M },
{ 1947, PT_SCX, ucp_Mahajani },
{ 1956, PT_SCX, ucp_Mahajani },
{ 1961, PT_SC, ucp_Makasar },
{ 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 },
{ 1974, PT_SCX, ucp_Malayalam },
{ 1984, PT_SCX, ucp_Mandaic },
{ 1971, PT_SC, ucp_Makasar },
{ 1979, PT_SCX, ucp_Malayalam },
{ 1989, PT_SCX, ucp_Mandaic },
{ 1997, PT_SCX, ucp_Manichaean },
{ 1994, PT_SCX, ucp_Mandaic },
{ 2002, PT_SCX, ucp_Manichaean },
{ 2013, PT_SC, ucp_Marchen },
{ 2007, PT_SCX, ucp_Manichaean },
{ 2018, PT_SC, ucp_Marchen },
{ 2026, PT_SCX, ucp_Masaram_Gondi },
{ 2039, PT_BOOL, ucp_Math },
{ 2044, PT_PC, ucp_Mc },
{ 2047, PT_PC, ucp_Me },
{ 2050, PT_SC, ucp_Medefaidrin },
{ 2062, PT_SC, ucp_Medefaidrin },
{ 2067, PT_SC, ucp_Meetei_Mayek },
{ 2079, PT_SC, ucp_Mende_Kikakui },
{ 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 },
{ 2097, PT_SC, ucp_Meroitic_Cursive },
{ 2102, PT_SC, ucp_Meroitic_Hieroglyphs },
{ 2107, PT_SC, ucp_Meroitic_Cursive },
{ 2123, PT_SC, ucp_Meroitic_Hieroglyphs },
{ 2143, PT_SC, ucp_Miao },
{ 2148, PT_SCX, ucp_Malayalam },
{ 2153, PT_PC, ucp_Mn },
{ 2156, PT_SCX, ucp_Modi },
{ 2161, PT_SCX, ucp_Mongolian },
{ 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 },
{ 2176, PT_SC, ucp_Mro },
{ 2180, PT_SC, ucp_Mro },
{ 2185, PT_SC, ucp_Meetei_Mayek },
{ 2190, PT_SCX, ucp_Multani },
{ 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 },
{ 2203, PT_SCX, ucp_Myanmar },
{ 2211, PT_SCX, ucp_Myanmar },
{ 2216, PT_GC, ucp_N },
{ 2218, PT_SC, ucp_Nabataean },
{ 2228, PT_SCX, ucp_Nandinagari },
{ 2233, PT_SCX, ucp_Nandinagari },
{ 2245, PT_SC, ucp_Old_North_Arabian },
{ 2250, PT_SC, ucp_Nabataean },
{ 2255, PT_BOOL, ucp_Noncharacter_Code_Point },
{ 2261, PT_PC, ucp_Nd },
{ 2264, PT_SC, ucp_Newa },
{ 2269, PT_SC, ucp_New_Tai_Lue },
{ 2279, PT_SCX, ucp_Nko },
{ 2283, PT_SCX, ucp_Nko },
{ 2288, PT_PC, ucp_Nl },
{ 2291, PT_PC, ucp_No },
{ 2294, PT_BOOL, ucp_Noncharacter_Code_Point },
{ 2316, PT_SC, ucp_Nushu },
{ 2321, PT_SC, ucp_Nushu },
{ 2327, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
{ 2348, PT_SC, ucp_Ogham },
{ 2353, PT_SC, ucp_Ogham },
{ 2359, PT_SC, ucp_Ol_Chiki },
{ 2367, PT_SC, ucp_Ol_Chiki },
{ 2372, PT_SC, ucp_Old_Hungarian },
{ 2385, PT_SC, ucp_Old_Italic },
{ 2395, PT_SC, ucp_Old_North_Arabian },
{ 2411, PT_SCX, ucp_Old_Permic },
{ 2421, PT_SC, ucp_Old_Persian },
{ 2432, PT_SC, ucp_Old_Sogdian },
{ 2443, PT_SC, ucp_Old_South_Arabian },
{ 2459, PT_SC, ucp_Old_Turkic },
{ 2469, PT_SCX, ucp_Old_Uyghur },
{ 2479, PT_SCX, ucp_Oriya },
{ 2485, PT_SC, ucp_Old_Turkic },
{ 2490, PT_SCX, ucp_Oriya },
{ 2495, PT_SC, ucp_Osage },
{ 2501, PT_SC, ucp_Osage },
{ 2506, PT_SC, ucp_Osmanya },
{ 2511, PT_SC, ucp_Osmanya },
{ 2519, PT_SCX, ucp_Old_Uyghur },
{ 2524, PT_GC, ucp_P },
{ 2526, PT_SC, ucp_Pahawh_Hmong },
{ 2538, PT_SC, ucp_Palmyrene },
{ 2543, PT_SC, ucp_Palmyrene },
{ 2553, PT_BOOL, ucp_Pattern_Syntax },
{ 2560, PT_BOOL, ucp_Pattern_Syntax },
{ 2574, PT_BOOL, ucp_Pattern_White_Space },
{ 2592, PT_BOOL, ucp_Pattern_White_Space },
{ 2598, PT_SC, ucp_Pau_Cin_Hau },
{ 2603, PT_SC, ucp_Pau_Cin_Hau },
{ 2613, PT_PC, ucp_Pc },
{ 2616, PT_BOOL, ucp_Prepended_Concatenation_Mark },
{ 2620, PT_PC, ucp_Pd },
{ 2623, PT_PC, ucp_Pe },
{ 2626, PT_SCX, ucp_Old_Permic },
{ 2631, PT_PC, ucp_Pf },
{ 2634, PT_SCX, ucp_Phags_Pa },
{ 2639, PT_SCX, ucp_Phags_Pa },
{ 2647, PT_SC, ucp_Inscriptional_Pahlavi },
{ 2652, PT_SCX, ucp_Psalter_Pahlavi },
{ 2657, PT_SC, ucp_Phoenician },
{ 2662, PT_SC, ucp_Phoenician },
{ 2673, PT_PC, ucp_Pi },
{ 2676, PT_SC, ucp_Miao },
{ 2681, PT_PC, ucp_Po },
{ 2684, PT_BOOL, ucp_Prepended_Concatenation_Mark },
{ 2711, PT_SC, ucp_Inscriptional_Parthian },
{ 2716, PT_PC, ucp_Ps },
{ 2719, PT_SCX, ucp_Psalter_Pahlavi },
{ 2734, PT_SCX, ucp_Coptic },
{ 2739, PT_SC, ucp_Inherited },
{ 2744, PT_BOOL, ucp_Quotation_Mark },
{ 2750, PT_BOOL, ucp_Quotation_Mark },
{ 2764, PT_BOOL, ucp_Radical },
{ 2772, PT_BOOL, ucp_Regional_Indicator },
{ 2790, PT_SC, ucp_Rejang },
{ 2797, PT_BOOL, ucp_Regional_Indicator },
{ 2800, PT_SC, ucp_Rejang },
{ 2805, PT_SCX, ucp_Hanifi_Rohingya },
{ 2810, PT_SC, ucp_Runic },
{ 2816, PT_SC, ucp_Runic },
{ 2821, PT_GC, ucp_S },
{ 2823, PT_SC, ucp_Samaritan },
{ 2833, PT_SC, ucp_Samaritan },
{ 2838, PT_SC, ucp_Old_South_Arabian },
{ 2843, PT_SC, ucp_Saurashtra },
{ 2848, PT_SC, ucp_Saurashtra },
{ 2859, PT_PC, ucp_Sc },
{ 2862, PT_BOOL, ucp_Soft_Dotted },
{ 2865, PT_BOOL, ucp_Sentence_Terminal },
{ 2882, PT_SC, ucp_SignWriting },
{ 2887, PT_SCX, ucp_Sharada },
{ 2895, PT_SC, ucp_Shavian },
{ 2903, PT_SC, ucp_Shavian },
{ 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 },
{ 2913, PT_SC, ucp_Siddham },
{ 2918, PT_SC, ucp_Siddham },
{ 2926, PT_SC, ucp_SignWriting },
{ 2938, PT_SCX, ucp_Khudawadi },
{ 2943, PT_SCX, ucp_Sinhala },
{ 2948, PT_SCX, ucp_Sinhala },
{ 2956, PT_PC, ucp_Sk },
{ 2959, PT_PC, ucp_Sm },
{ 2962, PT_PC, ucp_So },
{ 2965, PT_BOOL, ucp_Soft_Dotted },
{ 2976, PT_SCX, ucp_Sogdian },
{ 2981, PT_SCX, ucp_Sogdian },
{ 2989, PT_SC, ucp_Old_Sogdian },
{ 2994, PT_SC, ucp_Sora_Sompeng },
{ 2999, PT_SC, ucp_Sora_Sompeng },
{ 3011, PT_SC, ucp_Soyombo },
{ 3016, PT_SC, ucp_Soyombo },
{ 3024, PT_BOOL, ucp_White_Space },
{ 3030, PT_BOOL, ucp_Sentence_Terminal },
{ 3036, PT_SC, ucp_Sundanese },
{ 3041, PT_SC, ucp_Sundanese },
{ 3051, PT_SCX, ucp_Syloti_Nagri },
{ 3056, PT_SCX, ucp_Syloti_Nagri },
{ 3068, PT_SCX, ucp_Syriac },
{ 3073, PT_SCX, ucp_Syriac },
{ 3080, PT_SCX, ucp_Tagalog },
{ 3088, PT_SCX, ucp_Tagbanwa },
{ 3093, PT_SCX, ucp_Tagbanwa },
{ 3102, PT_SCX, ucp_Tai_Le },
{ 3108, PT_SC, ucp_Tai_Tham },
{ 3116, PT_SC, ucp_Tai_Viet },
{ 3124, PT_SCX, ucp_Takri },
{ 3129, PT_SCX, ucp_Takri },
{ 3135, PT_SCX, ucp_Tai_Le },
{ 3140, PT_SC, ucp_New_Tai_Lue },
{ 3145, PT_SCX, ucp_Tamil },
{ 3151, PT_SCX, ucp_Tamil },
{ 3156, PT_SC, ucp_Tangut },
{ 3161, PT_SC, ucp_Tangsa },
{ 3168, PT_SC, ucp_Tangut },
{ 3175, PT_SC, ucp_Tai_Viet },
{ 3180, PT_SCX, ucp_Telugu },
{ 3185, PT_SCX, ucp_Telugu },
{ 3192, PT_BOOL, ucp_Terminal_Punctuation },
{ 3197, PT_BOOL, ucp_Terminal_Punctuation },
{ 3217, PT_SC, ucp_Tifinagh },
{ 3222, PT_SCX, ucp_Tagalog },
{ 3227, PT_SCX, ucp_Thaana },
{ 3232, PT_SCX, ucp_Thaana },
{ 3239, PT_SC, ucp_Thai },
{ 3244, PT_SC, ucp_Tibetan },
{ 3252, PT_SC, ucp_Tibetan },
{ 3257, PT_SC, ucp_Tifinagh },
{ 3266, PT_SCX, ucp_Tirhuta },
{ 3271, PT_SCX, ucp_Tirhuta },
{ 3279, PT_SC, ucp_Tangsa },
{ 3284, PT_SC, ucp_Toto },
{ 3289, PT_SC, ucp_Ugaritic },
{ 3294, PT_SC, ucp_Ugaritic },
{ 3303, PT_BOOL, ucp_Unified_Ideograph },
{ 3309, PT_BOOL, ucp_Unified_Ideograph },
{ 3326, PT_SC, ucp_Unknown },
{ 3334, PT_BOOL, ucp_Uppercase },
{ 3340, PT_BOOL, ucp_Uppercase },
{ 3350, PT_SC, ucp_Vai },
{ 3354, PT_SC, ucp_Vai },
{ 3359, PT_BOOL, ucp_Variation_Selector },
{ 3377, PT_SC, ucp_Vithkuqi },
{ 3382, PT_SC, ucp_Vithkuqi },
{ 3391, PT_BOOL, ucp_Variation_Selector },
{ 3394, PT_SC, ucp_Wancho },
{ 3401, PT_SC, ucp_Warang_Citi },
{ 3406, PT_SC, ucp_Warang_Citi },
{ 3417, PT_SC, ucp_Wancho },
{ 3422, PT_BOOL, ucp_White_Space },
{ 3433, PT_BOOL, ucp_White_Space },
{ 3440, PT_ALNUM, 0 },
{ 3444, PT_BOOL, ucp_XID_Continue },
{ 3449, PT_BOOL, ucp_XID_Continue },
{ 3461, PT_BOOL, ucp_XID_Start },
{ 3466, PT_BOOL, ucp_XID_Start },
{ 3475, PT_SC, ucp_Old_Persian },
{ 3480, PT_PXSPACE, 0 },
{ 3484, PT_SPACE, 0 },
{ 3488, PT_SC, ucp_Cuneiform },
{ 3493, PT_UCNC, 0 },
{ 3497, PT_WORD, 0 },
{ 3501, PT_SCX, ucp_Yezidi },
{ 3506, PT_SCX, ucp_Yezidi },
{ 3513, PT_SCX, ucp_Yi },
{ 3516, PT_SCX, ucp_Yi },
{ 3521, PT_GC, ucp_Z },
{ 3523, PT_SC, ucp_Zanabazar_Square },
{ 3539, PT_SC, ucp_Zanabazar_Square },
{ 3544, PT_SC, ucp_Inherited },
{ 3549, PT_PC, ucp_Zl },
{ 3552, PT_PC, ucp_Zp },
{ 3555, PT_PC, ucp_Zs },
{ 3558, PT_SC, ucp_Common },
{ 3563, PT_SC, ucp_Unknown }
{ 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 }
};
const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);

View File

@ -171,7 +171,7 @@ for (p = string; length > 0; p++)
if (((d = *(++p)) & 0xc0) != 0x80)
{
*erroroffset = (int)(p - string) - 1;
*erroroffset = (PCRE2_SIZE)(p - string) - 1;
return PCRE2_ERROR_UTF8_ERR6;
}
@ -186,7 +186,7 @@ for (p = string; length > 0; p++)
case 1: if ((c & 0x3e) == 0)
{
*erroroffset = (int)(p - string) - 1;
*erroroffset = (PCRE2_SIZE)(p - string) - 1;
return PCRE2_ERROR_UTF8_ERR15;
}
break;
@ -198,17 +198,17 @@ for (p = string; length > 0; p++)
case 2:
if ((*(++p) & 0xc0) != 0x80) /* Third byte */
{
*erroroffset = (int)(p - string) - 2;
*erroroffset = (PCRE2_SIZE)(p - string) - 2;
return PCRE2_ERROR_UTF8_ERR7;
}
if (c == 0xe0 && (d & 0x20) == 0)
{
*erroroffset = (int)(p - string) - 2;
*erroroffset = (PCRE2_SIZE)(p - string) - 2;
return PCRE2_ERROR_UTF8_ERR16;
}
if (c == 0xed && d >= 0xa0)
{
*erroroffset = (int)(p - string) - 2;
*erroroffset = (PCRE2_SIZE)(p - string) - 2;
return PCRE2_ERROR_UTF8_ERR14;
}
break;
@ -220,22 +220,22 @@ for (p = string; length > 0; p++)
case 3:
if ((*(++p) & 0xc0) != 0x80) /* Third byte */
{
*erroroffset = (int)(p - string) - 2;
*erroroffset = (PCRE2_SIZE)(p - string) - 2;
return PCRE2_ERROR_UTF8_ERR7;
}
if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */
{
*erroroffset = (int)(p - string) - 3;
*erroroffset = (PCRE2_SIZE)(p - string) - 3;
return PCRE2_ERROR_UTF8_ERR8;
}
if (c == 0xf0 && (d & 0x30) == 0)
{
*erroroffset = (int)(p - string) - 3;
*erroroffset = (PCRE2_SIZE)(p - string) - 3;
return PCRE2_ERROR_UTF8_ERR17;
}
if (c > 0xf4 || (c == 0xf4 && d > 0x8f))
{
*erroroffset = (int)(p - string) - 3;
*erroroffset = (PCRE2_SIZE)(p - string) - 3;
return PCRE2_ERROR_UTF8_ERR13;
}
break;
@ -251,22 +251,22 @@ for (p = string; length > 0; p++)
case 4:
if ((*(++p) & 0xc0) != 0x80) /* Third byte */
{
*erroroffset = (int)(p - string) - 2;
*erroroffset = (PCRE2_SIZE)(p - string) - 2;
return PCRE2_ERROR_UTF8_ERR7;
}
if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */
{
*erroroffset = (int)(p - string) - 3;
*erroroffset = (PCRE2_SIZE)(p - string) - 3;
return PCRE2_ERROR_UTF8_ERR8;
}
if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */
{
*erroroffset = (int)(p - string) - 4;
*erroroffset = (PCRE2_SIZE)(p - string) - 4;
return PCRE2_ERROR_UTF8_ERR9;
}
if (c == 0xf8 && (d & 0x38) == 0)
{
*erroroffset = (int)(p - string) - 4;
*erroroffset = (PCRE2_SIZE)(p - string) - 4;
return PCRE2_ERROR_UTF8_ERR18;
}
break;
@ -277,27 +277,27 @@ for (p = string; length > 0; p++)
case 5:
if ((*(++p) & 0xc0) != 0x80) /* Third byte */
{
*erroroffset = (int)(p - string) - 2;
*erroroffset = (PCRE2_SIZE)(p - string) - 2;
return PCRE2_ERROR_UTF8_ERR7;
}
if ((*(++p) & 0xc0) != 0x80) /* Fourth byte */
{
*erroroffset = (int)(p - string) - 3;
*erroroffset = (PCRE2_SIZE)(p - string) - 3;
return PCRE2_ERROR_UTF8_ERR8;
}
if ((*(++p) & 0xc0) != 0x80) /* Fifth byte */
{
*erroroffset = (int)(p - string) - 4;
*erroroffset = (PCRE2_SIZE)(p - string) - 4;
return PCRE2_ERROR_UTF8_ERR9;
}
if ((*(++p) & 0xc0) != 0x80) /* Sixth byte */
{
*erroroffset = (int)(p - string) - 5;
*erroroffset = (PCRE2_SIZE)(p - string) - 5;
return PCRE2_ERROR_UTF8_ERR10;
}
if (c == 0xfc && (d & 0x3c) == 0)
{
*erroroffset = (int)(p - string) - 5;
*erroroffset = (PCRE2_SIZE)(p - string) - 5;
return PCRE2_ERROR_UTF8_ERR19;
}
break;
@ -309,7 +309,7 @@ for (p = string; length > 0; p++)
if (ab > 3)
{
*erroroffset = (int)(p - string) - ab;
*erroroffset = (PCRE2_SIZE)(p - string) - ab;
return (ab == 4)? PCRE2_ERROR_UTF8_ERR11 : PCRE2_ERROR_UTF8_ERR12;
}
}
@ -340,21 +340,21 @@ for (p = string; length > 0; p++)
/* High surrogate. Must be a followed by a low surrogate. */
if (length == 0)
{
*erroroffset = p - string;
*erroroffset = (PCRE2_SIZE)(p - string);
return PCRE2_ERROR_UTF16_ERR1;
}
p++;
length--;
if ((*p & 0xfc00) != 0xdc00)
{
*erroroffset = p - string - 1;
*erroroffset = (PCRE2_SIZE)(p - string) - 1;
return PCRE2_ERROR_UTF16_ERR2;
}
}
else
{
/* Isolated low surrogate. Always an error. */
*erroroffset = p - string;
*erroroffset = (PCRE2_SIZE)(p - string);
return PCRE2_ERROR_UTF16_ERR3;
}
}
@ -379,14 +379,14 @@ for (p = string; length > 0; length--, p++)
/* Normal UTF-32 code point. Neither high nor low surrogate. */
if (c > 0x10ffffu)
{
*erroroffset = p - string;
*erroroffset = (PCRE2_SIZE)(p - string);
return PCRE2_ERROR_UTF32_ERR2;
}
}
else
{
/* A surrogate */
*erroroffset = p - string;
*erroroffset = (PCRE2_SIZE)(p - string);
return PCRE2_ERROR_UTF32_ERR1;
}
}

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-2023 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@ -133,6 +133,7 @@ while ((t = *data++) != XCL_END)
#ifdef SUPPORT_UNICODE
else /* XCL_PROP & XCL_NOTPROP */
{
int chartype;
const ucd_record *prop = GET_UCD(c);
BOOL isprop = t == XCL_PROP;
BOOL ok;
@ -144,8 +145,9 @@ while ((t = *data++) != XCL_END)
break;
case PT_LAMP:
if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
prop->chartype == ucp_Lt) == isprop) return !negated;
chartype = prop->chartype;
if ((chartype == ucp_Lu || chartype == ucp_Ll ||
chartype == ucp_Lt) == isprop) return !negated;
break;
case PT_GC:
@ -168,8 +170,9 @@ while ((t = *data++) != XCL_END)
break;
case PT_ALNUM:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N) == isprop)
chartype = prop->chartype;
if ((PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N) == isprop)
return !negated;
break;
@ -194,9 +197,10 @@ while ((t = *data++) != XCL_END)
break;
case PT_WORD:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE)
== isprop)
chartype = prop->chartype;
if ((PRIV(ucp_gentype)[chartype] == ucp_L ||
PRIV(ucp_gentype)[chartype] == ucp_N ||
chartype == ucp_Mn || chartype == ucp_Pc) == isprop)
return !negated;
break;
@ -238,9 +242,10 @@ while ((t = *data++) != XCL_END)
*/
case PT_PXGRAPH:
if ((PRIV(ucp_gentype)[prop->chartype] != ucp_Z &&
(PRIV(ucp_gentype)[prop->chartype] != ucp_C ||
(prop->chartype == ucp_Cf &&
chartype = prop->chartype;
if ((PRIV(ucp_gentype)[chartype] != ucp_Z &&
(PRIV(ucp_gentype)[chartype] != ucp_C ||
(chartype == ucp_Cf &&
c != 0x061c && c != 0x180e && (c < 0x2066 || c > 0x2069))
)) == isprop)
return !negated;
@ -250,10 +255,11 @@ while ((t = *data++) != XCL_END)
not Zl and not Zp, and U+180E. */
case PT_PXPRINT:
if ((prop->chartype != ucp_Zl &&
prop->chartype != ucp_Zp &&
(PRIV(ucp_gentype)[prop->chartype] != ucp_C ||
(prop->chartype == ucp_Cf &&
chartype = prop->chartype;
if ((chartype != ucp_Zl &&
chartype != ucp_Zp &&
(PRIV(ucp_gentype)[chartype] != ucp_C ||
(chartype == ucp_Cf &&
c != 0x061c && (c < 0x2066 || c > 0x2069))
)) == isprop)
return !negated;
@ -264,8 +270,21 @@ while ((t = *data++) != XCL_END)
compatibility (these are $+<=>^`|~). */
case PT_PXPUNCT:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_P ||
(c < 128 && PRIV(ucp_gentype)[prop->chartype] == ucp_S)) == isprop)
chartype = prop->chartype;
if ((PRIV(ucp_gentype)[chartype] == ucp_P ||
(c < 128 && PRIV(ucp_gentype)[chartype] == ucp_S)) == isprop)
return !negated;
break;
/* Perl has two sets of hex digits */
case PT_PXXDIGIT:
if (((c >= CHAR_0 && c <= CHAR_9) ||
(c >= CHAR_A && c <= CHAR_F) ||
(c >= CHAR_a && c <= CHAR_f) ||
(c >= 0xff10 && c <= 0xff19) || /* Fullwidth digits */
(c >= 0xff21 && c <= 0xff26) || /* Fullwidth letters */
(c >= 0xff41 && c <= 0xff46)) == isprop)
return !negated;
break;

View File

@ -0,0 +1,133 @@
/*
* 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

@ -0,0 +1,330 @@
/*
* 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

@ -0,0 +1,89 @@
/*
* 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

@ -0,0 +1,62 @@
/*
* 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

@ -0,0 +1,40 @@
/*
* 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

@ -0,0 +1,72 @@
/*
* 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

@ -0,0 +1,172 @@
/*
* 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

@ -0,0 +1,141 @@
/*
* 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

@ -0,0 +1,102 @@
/*
* 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

@ -38,28 +38,6 @@ extern "C" {
non-zero value.
*/
/* --------------------------------------------------------------------- */
/* Architecture */
/* --------------------------------------------------------------------- */
/* Architecture selection. */
/* #define SLJIT_CONFIG_X86_32 1 */
/* #define SLJIT_CONFIG_X86_64 1 */
/* #define SLJIT_CONFIG_ARM_V5 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_AUTO 1 */
/* #define SLJIT_CONFIG_UNSUPPORTED 1 */
/* --------------------------------------------------------------------- */
/* Utilities */
/* --------------------------------------------------------------------- */
@ -96,7 +74,9 @@ extern "C" {
/* Executable code allocation:
If SLJIT_EXECUTABLE_ALLOCATOR is not defined, the application should
define SLJIT_MALLOC_EXEC, SLJIT_FREE_EXEC, and SLJIT_EXEC_OFFSET. */
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

View File

@ -0,0 +1,188 @@
/*
* 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

@ -61,6 +61,8 @@ extern "C" {
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:
@ -70,6 +72,8 @@ extern "C" {
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
@ -79,141 +83,27 @@ extern "C" {
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
*/
/*****************/
/* 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_V5 && SLJIT_CONFIG_ARM_V5) \
+ (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_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_V5 && SLJIT_CONFIG_ARM_V5) \
&& !(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_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(__arm__) || defined(__ARM__)
#ifdef __thumb2__
#define SLJIT_CONFIG_ARM_THUMB2 1
#elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__)
#define SLJIT_CONFIG_ARM_V7 1
#else
#define SLJIT_CONFIG_ARM_V5 1
#endif
#elif defined (__aarch64__)
#define SLJIT_CONFIG_ARM_64 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(__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_V5 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
/******************************/
/* CPU family type detection. */
/******************************/
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (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
#endif
/***********************************************************/
/* Intel Control-flow Enforcement Technology (CET) spport. */
/***********************************************************/
@ -328,6 +218,10 @@ extern "C" {
/* Instruction cache flush. */
/****************************/
#ifdef __APPLE__
#include <AvailabilityMacros.h>
#endif
/*
* TODO:
*
@ -368,7 +262,7 @@ extern "C" {
/* Not required to implement on archs with unified caches. */
#define SLJIT_CACHE_FLUSH(from, to)
#elif defined __APPLE__
#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,
@ -433,14 +327,15 @@ typedef signed int sljit_s32;
#if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
/* Just to have something. */
#define SLJIT_WORD_SHIFT 0
typedef unsigned long int sljit_uw;
typedef long int sljit_sw;
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_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;
@ -476,12 +371,42 @@ typedef double sljit_f64;
#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_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
#define SLJIT_W(w) (w##l)
#elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
#ifdef _WIN64
#define SLJIT_W(w) (w##ll)
#else /* !windows */
@ -521,9 +446,10 @@ typedef double sljit_f64;
/* Auto detecting mips revision. */
#if (defined __mips_isa_rev) && (__mips_isa_rev >= 6)
#define SLJIT_MIPS_REV 6
#elif (defined __mips_isa_rev && __mips_isa_rev >= 1) \
|| (defined __clang__ && defined _MIPS_ARCH_OCTEON) \
|| (defined __clang__ && defined _MIPS_ARCH_P5600)
#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).
@ -562,7 +488,8 @@ typedef double sljit_f64;
|| (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_S390X && SLJIT_CONFIG_S390X) \
|| (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
#define SLJIT_UNALIGNED 1
#endif
@ -574,7 +501,8 @@ typedef double sljit_f64;
|| (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_S390X && SLJIT_CONFIG_S390X) \
|| (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
#define SLJIT_FPU_UNALIGNED 1
#endif
@ -594,6 +522,19 @@ typedef double sljit_f64;
#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)
@ -631,12 +572,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
#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)
#else
#define SLJIT_EXEC_OFFSET(ptr) 0
#endif
#endif /* SLJIT_EXECUTABLE_ALLOCATOR */
#ifndef SLJIT_EXEC_OFFSET
#define SLJIT_EXEC_OFFSET(ptr) 0
#endif
/**********************************************/
/* Registers and locals offset determination. */
/**********************************************/
@ -645,15 +588,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#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
@ -664,37 +613,39 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#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_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
#define SLJIT_NUMBER_OF_REGISTERS 12
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#define SLJIT_LOCALS_OFFSET_BASE 0
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
#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)
@ -717,14 +668,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#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_LOCALS_OFFSET_BASE 0
#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)
@ -751,16 +710,34 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#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
@ -773,6 +750,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#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. */
/********************************/
@ -781,10 +797,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
|| (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_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. */
/*************************************/

View File

@ -152,6 +152,9 @@ static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec)
{
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 110000
pthread_jit_write_protect_np(enable_exec);
#elif defined(__clang__)
if (__builtin_available(macOS 11.0, *))
pthread_jit_write_protect_np(enable_exec);
#else
#error "Must target Big Sur or newer"
#endif /* BigSur */

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

@ -26,6 +26,49 @@
/* 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))
@ -44,6 +87,108 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_
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;
@ -74,6 +219,11 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
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);
@ -138,20 +288,28 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
switch (types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
if (*offsets_ptr < 4 * sizeof (sljit_sw)) {
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);
prev_ins = MFC1 | TA(6) | FS(float_arg_count) | (1 << 11);
ins = MFC1 | TA(7) | FS(float_arg_count);
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_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
ins = MOV_fmt(FMT_D) | FS(SLJIT_FR0) | FD(TMP_FREG1);
float_arg_count--;
break;
@ -161,7 +319,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
else if (*offsets_ptr < 254)
ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr);
else if (*offsets_ptr == 254)
ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);
float_arg_count--;
break;
@ -285,7 +443,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
if (src & SLJIT_IMM)
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)));

View File

@ -26,6 +26,23 @@
/* 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;
@ -128,6 +145,57 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_
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;
@ -183,17 +251,17 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
switch (types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
if (arg_count != float_arg_count)
ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count);
ins = MOV_fmt(FMT_D) | FS(float_arg_count) | FD(arg_count);
else if (arg_count == 1)
ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
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_S | FMT_S | FS(float_arg_count) | FD(arg_count);
ins = MOV_fmt(FMT_S) | FS(float_arg_count) | FD(arg_count);
else if (arg_count == 1)
ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
ins = MOV_fmt(FMT_S) | FS(SLJIT_FR0) | FD(TMP_FREG1);
arg_count--;
float_arg_count--;
break;
@ -300,7 +368,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
if (src & SLJIT_IMM)
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)));

File diff suppressed because it is too large Load Diff

View File

@ -85,10 +85,6 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
}
return SLJIT_SUCCESS;
case SLJIT_NOT:
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, CNTLZW | S(src2) | A(dst));
@ -246,6 +242,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
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:
@ -325,6 +325,151 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_
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;

View File

@ -49,7 +49,7 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg,
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
if (!(imm & ~0xffff))
if (((sljit_uw)imm >> 16) == 0)
return push_inst(compiler, ORI | S(TMP_ZERO) | A(reg) | IMM(imm));
if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
@ -57,6 +57,11 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg,
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);
@ -198,11 +203,6 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
}
return SLJIT_SUCCESS;
case SLJIT_NOT:
SLJIT_ASSERT(src1 == TMP_REG1);
UN_EXTS();
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, ((flags & ALT_FORM1) ? CNTLZW : CNTLZD) | S(src2) | A(dst));
@ -399,6 +399,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
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:
@ -563,6 +568,141 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_
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;

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,6 @@
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);
SLJIT_ASSERT(dst_r != tmp_r);
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));
@ -43,6 +42,76 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r
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)

View File

@ -28,8 +28,6 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r
{
sljit_sw high;
SLJIT_ASSERT(dst_r != tmp_r);
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));
@ -81,6 +79,8 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r
return SLJIT_SUCCESS;
}
SLJIT_ASSERT(dst_r != tmp_r);
high = imm >> 32;
imm = (sljit_s32)imm;
@ -126,6 +126,45 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r
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;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -62,21 +62,19 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
/* Both size flags cannot be switched on. */
SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
/* SSE2 and immediate is not possible. */
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
&& (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
&& (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
SLJIT_ASSERT(a != SLJIT_IMM || !(flags & EX86_SSE2));
SLJIT_ASSERT(((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
& ((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);
SLJIT_ASSERT((flags & (EX86_VEX_EXT | EX86_REX)) != EX86_VEX_EXT);
size &= 0xf;
inst_size = size;
/* The mod r/m byte is always present. */
inst_size = size + 1;
if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
inst_size++;
if (flags & EX86_PREF_66)
if (flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
inst_size++;
/* Calculate size of b. */
inst_size += 1; /* mod r/m byte. */
if (b & SLJIT_MEM) {
if (!(b & REG_MASK))
inst_size += sizeof(sljit_sw);
@ -87,8 +85,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
inst_size += sizeof(sljit_s8);
else
inst_size += sizeof(sljit_sw);
}
else if (reg_map[b & REG_MASK] == 5) {
} else if (reg_map[b & REG_MASK] == 5) {
/* Swap registers if possible. */
if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_map[OFFS_REG(b)] != 5)
b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK);
@ -105,15 +102,14 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
}
/* Calculate size of a. */
if (a & SLJIT_IMM) {
if (a == SLJIT_IMM) {
if (flags & EX86_BIN_INS) {
if (imma <= 127 && imma >= -128) {
inst_size += 1;
flags |= EX86_BYTE_ARG;
} else
inst_size += 4;
}
else if (flags & EX86_SHIFT_INS) {
} else if (flags & EX86_SHIFT_INS) {
SLJIT_ASSERT(imma <= 0x1f);
if (imma != 1) {
inst_size++;
@ -125,8 +121,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
inst_size += sizeof(short);
else
inst_size += sizeof(sljit_sw);
}
else
} else
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);
@ -136,27 +131,26 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
INC_SIZE(inst_size);
if (flags & EX86_PREF_F2)
*inst++ = 0xf2;
if (flags & EX86_PREF_F3)
else if (flags & EX86_PREF_F3)
*inst++ = 0xf3;
if (flags & EX86_PREF_66)
else if (flags & EX86_PREF_66)
*inst++ = 0x66;
buf_ptr = inst + size;
/* Encode mod/rm byte. */
if (!(flags & EX86_SHIFT_INS)) {
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
if ((flags & EX86_BIN_INS) && a == SLJIT_IMM)
*inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
if (a & SLJIT_IMM)
if (a == SLJIT_IMM)
*buf_ptr = 0;
else if (!(flags & EX86_SSE2_OP1))
*buf_ptr = U8(reg_map[a] << 3);
else
*buf_ptr = U8(a << 3);
}
else {
if (a & SLJIT_IMM) {
*buf_ptr = U8(freg_map[a] << 3);
} else {
if (a == SLJIT_IMM) {
if (imma == 1)
*inst = GROUP_SHIFT_1;
else
@ -167,7 +161,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
}
if (!(b & SLJIT_MEM)) {
*buf_ptr = U8(*buf_ptr | MOD_REG | (!(flags & EX86_SSE2_OP2) ? reg_map[b] : b));
*buf_ptr = U8(*buf_ptr | MOD_REG | (!(flags & EX86_SSE2_OP2) ? reg_map[b] : freg_map[b]));
buf_ptr++;
} else if (b & REG_MASK) {
reg_map_b = reg_map[b & REG_MASK];
@ -183,8 +177,9 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
if (!(b & OFFS_REG_MASK))
*buf_ptr++ |= reg_map_b;
else {
*buf_ptr++ |= 0x04;
*buf_ptr++ = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3));
buf_ptr[0] |= 0x04;
buf_ptr[1] = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3));
buf_ptr += 2;
}
if (immb != 0 || reg_map_b == 5) {
@ -195,25 +190,24 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
buf_ptr += sizeof(sljit_sw);
}
}
}
else {
} else {
if (reg_map_b == 5)
*buf_ptr |= 0x40;
*buf_ptr++ |= 0x04;
*buf_ptr++ = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3) | (immb << 6));
buf_ptr[0] |= 0x04;
buf_ptr[1] = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3) | (immb << 6));
buf_ptr += 2;
if (reg_map_b == 5)
*buf_ptr++ = 0;
}
}
else {
} else {
*buf_ptr++ |= 0x05;
sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */
buf_ptr += sizeof(sljit_sw);
}
if (a & SLJIT_IMM) {
if (a == SLJIT_IMM) {
if (flags & EX86_BYTE_ARG)
*buf_ptr = U8(imma);
else if (flags & EX86_HALF_ARG)
@ -222,7 +216,67 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
sljit_unaligned_store_sw(buf_ptr, imma);
}
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
return inst;
}
static sljit_s32 emit_vex_instruction(struct sljit_compiler *compiler, sljit_uw op,
/* The first and second register operand. */
sljit_s32 a, sljit_s32 v,
/* The general operand (not immediate). */
sljit_s32 b, sljit_sw immb)
{
sljit_u8 *inst;
sljit_u8 vex = 0;
sljit_u8 vex_m = 0;
sljit_uw size;
SLJIT_ASSERT(((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
& ((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);
if (op & VEX_OP_0F38)
vex_m = 0x2;
else if (op & VEX_OP_0F3A)
vex_m = 0x3;
if (op & VEX_W) {
if (vex_m == 0)
vex_m = 0x1;
vex |= 0x80;
}
if (op & EX86_PREF_66)
vex |= 0x1;
else if (op & EX86_PREF_F2)
vex |= 0x3;
else if (op & EX86_PREF_F3)
vex |= 0x2;
op &= ~(EX86_PREF_66 | EX86_PREF_F2 | EX86_PREF_F3);
if (op & VEX_256)
vex |= 0x4;
vex = U8(vex | ((((op & VEX_SSE2_OPV) ? freg_map[v] : reg_map[v]) ^ 0xf) << 3));
size = op & ~(sljit_uw)0xff;
size |= (vex_m == 0) ? 3 : 4;
inst = emit_x86_instruction(compiler, size, a, 0, b, immb);
FAIL_IF(!inst);
if (vex_m == 0) {
inst[0] = 0xc5;
inst[1] = U8(vex | 0x80);
inst[2] = U8(op);
return SLJIT_SUCCESS;
}
inst[0] = 0xc4;
inst[1] = U8(vex_m | 0xe0);
inst[2] = vex;
inst[3] = U8(op);
return SLJIT_SUCCESS;
}
/* --------------------------------------------------------------------- */
@ -578,8 +632,6 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
{
sljit_u8 *inst;
CHECK_ERROR();
CHECK(check_sljit_emit_return_void(compiler));
@ -588,11 +640,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler
FAIL_IF(emit_stack_frame_release(compiler, 0));
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
RET();
return SLJIT_SUCCESS;
return emit_byte(compiler, RET_near);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
@ -782,7 +830,7 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler,
offset = stack_size + compiler->local_size;
if (!(src & SLJIT_IMM) && src != SLJIT_R0) {
if (src != SLJIT_IMM && src != SLJIT_R0) {
if (word_arg_count >= 1) {
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);
r2_offset = sizeof(sljit_sw);
@ -836,7 +884,7 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler,
stack_size = args_size + SSIZE_OF(sw);
if (word_arg_count >= 1 && !(src & SLJIT_IMM) && src != SLJIT_R0) {
if (word_arg_count >= 1 && src != SLJIT_IMM && src != SLJIT_R0) {
r2_offset = SSIZE_OF(sw);
stack_size += SSIZE_OF(sw);
}
@ -865,7 +913,7 @@ static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler,
EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), word_arg4_offset);
}
if (!(src & SLJIT_IMM) && src != SLJIT_R0) {
if (src != SLJIT_IMM && src != SLJIT_R0) {
if (word_arg_count >= 1) {
SLJIT_ASSERT(r2_offset == sizeof(sljit_sw));
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);
@ -952,13 +1000,7 @@ static sljit_s32 emit_tail_call_end(struct sljit_compiler *compiler, sljit_s32 e
sljit_u8 *inst;
BINARY_IMM32(ADD, extra_space, SLJIT_SP, 0);
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
RET();
return SLJIT_SUCCESS;
return emit_byte(compiler, RET_near);
}
static sljit_s32 tail_call_reg_arg_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
@ -1075,7 +1117,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
stack_size = type;
FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, src, srcw));
if (!(src & SLJIT_IMM)) {
if (src != SLJIT_IMM) {
src = SLJIT_R0;
srcw = 0;
}
@ -1142,30 +1184,20 @@ static SLJIT_INLINE sljit_s32 emit_fmov_before_return(struct sljit_compiler *com
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
{
sljit_u8 *inst;
CHECK_ERROR();
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
CHECK_EXTRA_REGS(dst, dstw, (void)0);
if (FAST_IS_REG(dst)) {
/* Unused dest is possible here. */
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
POP_REG(reg_map[dst]);
return SLJIT_SUCCESS;
}
/* Unused dest is possible here. */
if (FAST_IS_REG(dst))
return emit_byte(compiler, U8(POP_r + reg_map[dst]));
/* Memory. */
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
FAIL_IF(!inst);
*inst++ = POP_rm;
*inst = POP_rm;
return SLJIT_SUCCESS;
}
@ -1185,8 +1217,8 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src
else {
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = GROUP_FF;
*inst |= PUSH_rm;
inst[0] = GROUP_FF;
inst[1] |= PUSH_rm;
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
@ -1197,6 +1229,22 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src
return SLJIT_SUCCESS;
}
static sljit_s32 sljit_emit_get_return_address(struct sljit_compiler *compiler,
sljit_s32 dst, sljit_sw dstw)
{
sljit_s32 options = compiler->options;
sljit_s32 saveds = compiler->saveds;
sljit_s32 scratches = compiler->scratches;
saveds = ((scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3) - SLJIT_KEPT_SAVEDS_COUNT(options)) * SSIZE_OF(sw);
/* Saving ebp. */
if (!(options & SLJIT_ENTER_REG_ARG))
saveds += SSIZE_OF(sw);
return emit_mov(compiler, dst, dstw, SLJIT_MEM1(SLJIT_SP), compiler->local_size + saveds);
}
/* --------------------------------------------------------------------- */
/* Other operations */
/* --------------------------------------------------------------------- */
@ -1279,6 +1327,283 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
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_FREG;
sljit_u8 *inst, *jump_inst1, *jump_inst2;
sljit_uw size1, size2;
/* Binary representation of 0x80000000. */
static const sljit_f64 f64_high_bit = (sljit_f64)0x80000000ul;
CHECK_EXTRA_REGS(src, srcw, (void)0);
if (!(op & SLJIT_32)) {
EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);
FAIL_IF(!inst);
inst[1] |= ROL;
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);
FAIL_IF(!inst);
inst[1] |= SHR;
FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_PREF_F2 | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
INC_SIZE(2);
inst[0] = U8(get_jump_code(SLJIT_NOT_CARRY) - 0x10);
size1 = compiler->size;
FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_PREF_F2 | EX86_SSE2, dst_r, SLJIT_MEM0(), (sljit_sw)&f64_high_bit));
inst[1] = U8(compiler->size - size1);
if (dst_r == TMP_FREG)
return emit_sse2_store(compiler, 0, dst, dstw, TMP_FREG);
return SLJIT_SUCCESS;
}
if (!FAST_IS_REG(src)) {
EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
src = TMP_REG1;
}
BINARY_IMM32(CMP, 0, src, 0);
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
INC_SIZE(2);
inst[0] = JL_i8;
jump_inst1 = inst;
size1 = compiler->size;
FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, src, 0));
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
INC_SIZE(2);
inst[0] = JMP_i8;
jump_inst2 = inst;
size2 = compiler->size;
jump_inst1[1] = U8(size2 - size1);
if (src != TMP_REG1)
EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);
FAIL_IF(!inst);
inst[1] |= SHR;
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
INC_SIZE(2);
inst[0] = JNC_i8;
jump_inst1 = inst;
size1 = compiler->size;
BINARY_IMM32(OR, 1, TMP_REG1, 0);
jump_inst1[1] = U8(compiler->size - size1);
FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));
FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, dst_r, 0));
jump_inst2[1] = U8(compiler->size - size2);
if (dst_r == TMP_FREG)
return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f32 value)
{
sljit_u8 *inst;
union {
sljit_s32 imm;
sljit_f32 value;
} u;
CHECK_ERROR();
CHECK(check_sljit_emit_fset32(compiler, freg, value));
u.value = value;
if (u.imm != 0)
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm);
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!inst);
INC_SIZE(4);
inst[0] = GROUP_66;
inst[1] = GROUP_0F;
if (u.imm == 0) {
inst[2] = PXOR_x_xm;
inst[3] = U8(freg | (freg << 3) | MOD_REG);
} else {
inst[2] = MOVD_x_rm;
inst[3] = U8(reg_map[TMP_REG1] | (freg << 3) | MOD_REG);
}
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset64(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f64 value)
{
sljit_u8 *inst;
sljit_s32 tmp_freg = freg;
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) {
if (u.imm[1] == 0)
return emit_groupf(compiler, PXOR_x_xm | EX86_PREF_66 | EX86_SSE2, freg, freg, 0);
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[1]);
} else
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[0]);
FAIL_IF(emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, freg, TMP_REG1, 0));
if (u.imm[1] == 0)
return SLJIT_SUCCESS;
if (u.imm[0] == 0) {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!inst);
INC_SIZE(4);
inst[0] = GROUP_0F;
inst[1] = SHUFPS_x_xm;
inst[2] = U8(MOD_REG | (freg << 3) | freg);
inst[3] = 0x51;
return SLJIT_SUCCESS;
}
if (u.imm[0] != u.imm[1]) {
SLJIT_ASSERT(u.imm[1] != 0 && cpu_feature_list != 0);
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm[1]);
if (cpu_feature_list & CPU_FEATURE_SSE41) {
FAIL_IF(emit_groupf_ext(compiler, PINSRD_x_rm_i8 | EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2_OP1, freg, TMP_REG1, 0));
return emit_byte(compiler, 1);
}
FAIL_IF(emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, TMP_REG1, 0));
tmp_freg = TMP_FREG;
}
inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);
FAIL_IF(!inst);
INC_SIZE(3);
inst[0] = GROUP_0F;
inst[1] = UNPCKLPS_x_xm;
inst[2] = U8(MOD_REG | (freg << 3) | tmp_freg);
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_u8 *inst;
sljit_s32 reg2;
sljit_sw regw, reg2w;
CHECK_ERROR();
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
regw = 0;
reg2 = 0;
reg2w = 0;
SLJIT_ASSERT(cpu_feature_list != 0);
if (!(op & SLJIT_32) && (cpu_feature_list & CPU_FEATURE_SSE41)) {
if (reg & REG_PAIR_MASK) {
reg2 = REG_PAIR_FIRST(reg);
reg = REG_PAIR_SECOND(reg);
CHECK_EXTRA_REGS(reg, regw, (void)0);
FAIL_IF(emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x)
| EX86_PREF_66 | EX86_SSE2_OP1, freg, reg, regw));
} else
reg2 = reg;
CHECK_EXTRA_REGS(reg2, reg2w, (void)0);
FAIL_IF(emit_groupf_ext(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? PINSRD_x_rm_i8 : PEXTRD_rm_x_i8)
| EX86_PREF_66 | VEX_OP_0F3A | EX86_SSE2_OP1, freg, reg2, reg2w));
return emit_byte(compiler, 1);
}
if (reg & REG_PAIR_MASK) {
reg2 = REG_PAIR_SECOND(reg);
reg = REG_PAIR_FIRST(reg);
if (reg == reg2)
reg = 0;
CHECK_EXTRA_REGS(reg2, reg2w, (void)0);
}
CHECK_EXTRA_REGS(reg, regw, (void)0);
if (op & SLJIT_32)
return emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x)
| EX86_PREF_66 | EX86_SSE2_OP1, freg, reg, regw);
if (op == SLJIT_COPY_FROM_F64) {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);
FAIL_IF(!inst);
INC_SIZE(5);
inst[0] = GROUP_66;
inst[1] = GROUP_0F;
inst[2] = PSHUFD_x_xm;
inst[3] = U8(MOD_REG | (TMP_FREG << 3) | freg);
inst[4] = 1;
} else if (reg != 0)
FAIL_IF(emit_groupf(compiler, MOVD_x_rm | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, reg, regw));
if (reg2 != 0)
FAIL_IF(emit_groupf(compiler, (GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x)
| EX86_PREF_66 | EX86_SSE2_OP1, freg, reg2, reg2w));
if (GET_OPCODE(op) == SLJIT_COPY_TO_F64) {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);
FAIL_IF(!inst);
INC_SIZE(3);
inst[0] = GROUP_0F;
inst[1] = UNPCKLPS_x_xm;
inst[2] = U8(MOD_REG | (freg << 3) | (reg == 0 ? freg : TMP_FREG));
} else
FAIL_IF(emit_groupf(compiler, MOVD_rm_x | EX86_PREF_66 | EX86_SSE2_OP1, TMP_FREG, reg, regw));
return SLJIT_SUCCESS;
}
static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)
{
sljit_sw size;

View File

@ -37,9 +37,9 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg,
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_sw));
FAIL_IF(!inst);
INC_SIZE(2 + sizeof(sljit_sw));
*inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
*inst++ = U8(MOV_r_i32 | (reg_map[reg] & 0x7));
sljit_unaligned_store_sw(inst, imm);
inst[0] = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
inst[1] = U8(MOV_r_i32 | reg_lmap[reg]);
sljit_unaligned_store_sw(inst + 2, imm);
return SLJIT_SUCCESS;
}
@ -72,7 +72,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
sljit_uw inst_size;
/* The immediate operand must be 32 bit. */
SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
SLJIT_ASSERT(a != SLJIT_IMM || compiler->mode32 || IS_HALFWORD(imma));
/* Both cannot be switched on. */
SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
/* Size flags not allowed for typed instructions. */
@ -80,26 +80,24 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
/* Both size flags cannot be switched on. */
SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
/* SSE2 and immediate is not possible. */
SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
&& (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
&& (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
SLJIT_ASSERT(a != SLJIT_IMM || !(flags & EX86_SSE2));
SLJIT_ASSERT(((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
& ((flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);
SLJIT_ASSERT((flags & (EX86_VEX_EXT | EX86_REX)) != EX86_VEX_EXT);
size &= 0xf;
inst_size = size;
/* The mod r/m byte is always present. */
inst_size = size + 1;
if (!compiler->mode32 && !(flags & EX86_NO_REXW))
rex |= REX_W;
else if (flags & EX86_REX)
rex |= REX;
if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
inst_size++;
if (flags & EX86_PREF_66)
if (flags & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
inst_size++;
/* Calculate size of b. */
inst_size += 1; /* mod r/m byte. */
if (b & SLJIT_MEM) {
if (!(b & OFFS_REG_MASK) && NOT_HALFWORD(immb)) {
PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
@ -119,8 +117,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
inst_size += sizeof(sljit_s8);
else
inst_size += sizeof(sljit_s32);
}
else if (reg_lmap[b & REG_MASK] == 5) {
} else if (reg_lmap[b & REG_MASK] == 5) {
/* Swap registers if possible. */
if ((b & OFFS_REG_MASK) && (immb & 0x3) == 0 && reg_lmap[OFFS_REG(b)] != 5)
b = SLJIT_MEM | OFFS_REG(b) | TO_OFFS_REG(b & REG_MASK);
@ -140,23 +137,26 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
rex |= REX_X;
}
}
}
else if (!(flags & EX86_SSE2_OP2)) {
} else if (!(flags & EX86_SSE2_OP2)) {
if (reg_map[b] >= 8)
rex |= REX_B;
}
else if (freg_map[b] >= 8)
} else if (freg_map[b] >= 8)
rex |= REX_B;
if (a & SLJIT_IMM) {
if ((flags & EX86_VEX_EXT) && (rex & 0x3)) {
SLJIT_ASSERT(size == 2);
size++;
inst_size++;
}
if (a == SLJIT_IMM) {
if (flags & EX86_BIN_INS) {
if (imma <= 127 && imma >= -128) {
inst_size += 1;
flags |= EX86_BYTE_ARG;
} else
inst_size += 4;
}
else if (flags & EX86_SHIFT_INS) {
} else if (flags & EX86_SHIFT_INS) {
SLJIT_ASSERT(imma <= (compiler->mode32 ? 0x1f : 0x3f));
if (imma != 1) {
inst_size++;
@ -168,8 +168,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
inst_size += sizeof(short);
else
inst_size += sizeof(sljit_s32);
}
else {
} else {
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
/* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */
if (!(flags & EX86_SSE2_OP1)) {
@ -186,32 +185,34 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);
PTR_FAIL_IF(!inst);
/* Encoding the byte. */
/* Encoding prefixes. */
INC_SIZE(inst_size);
if (flags & EX86_PREF_F2)
*inst++ = 0xf2;
if (flags & EX86_PREF_F3)
else if (flags & EX86_PREF_F3)
*inst++ = 0xf3;
if (flags & EX86_PREF_66)
else if (flags & EX86_PREF_66)
*inst++ = 0x66;
/* Rex is always the last prefix. */
if (rex)
*inst++ = rex;
buf_ptr = inst + size;
/* Encode mod/rm byte. */
if (!(flags & EX86_SHIFT_INS)) {
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
if ((flags & EX86_BIN_INS) && a == SLJIT_IMM)
*inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
if (a & SLJIT_IMM)
if (a == SLJIT_IMM)
*buf_ptr = 0;
else if (!(flags & EX86_SSE2_OP1))
*buf_ptr = U8(reg_lmap[a] << 3);
else
*buf_ptr = U8(freg_lmap[a] << 3);
}
else {
if (a & SLJIT_IMM) {
} else {
if (a == SLJIT_IMM) {
if (imma == 1)
*inst = GROUP_SHIFT_1;
else
@ -238,8 +239,9 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
if (!(b & OFFS_REG_MASK))
*buf_ptr++ |= reg_lmap_b;
else {
*buf_ptr++ |= 0x04;
*buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3));
buf_ptr[0] |= 0x04;
buf_ptr[1] = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3));
buf_ptr += 2;
}
if (immb != 0 || reg_lmap_b == 5) {
@ -250,26 +252,26 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
buf_ptr += sizeof(sljit_s32);
}
}
}
else {
} else {
if (reg_lmap_b == 5)
*buf_ptr |= 0x40;
*buf_ptr++ |= 0x04;
*buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6));
buf_ptr[0] |= 0x04;
buf_ptr[1] = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6));
buf_ptr += 2;
if (reg_lmap_b == 5)
*buf_ptr++ = 0;
}
}
else {
*buf_ptr++ |= 0x04;
*buf_ptr++ = 0x25;
} else {
buf_ptr[0] |= 0x04;
buf_ptr[1] = 0x25;
buf_ptr += 2;
sljit_unaligned_store_s32(buf_ptr, (sljit_s32)immb); /* 32 bit displacement. */
buf_ptr += sizeof(sljit_s32);
}
if (a & SLJIT_IMM) {
if (a == SLJIT_IMM) {
if (flags & EX86_BYTE_ARG)
*buf_ptr = U8(imma);
else if (flags & EX86_HALF_ARG)
@ -278,7 +280,78 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
sljit_unaligned_store_s32(buf_ptr, (sljit_s32)imma);
}
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
return inst;
}
static sljit_s32 emit_vex_instruction(struct sljit_compiler *compiler, sljit_uw op,
/* The first and second register operand. */
sljit_s32 a, sljit_s32 v,
/* The general operand (not immediate). */
sljit_s32 b, sljit_sw immb)
{
sljit_u8 *inst;
sljit_u8 vex = 0;
sljit_u8 vex_m = 0;
sljit_uw size;
SLJIT_ASSERT(((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66))
& ((op & (EX86_PREF_F2 | EX86_PREF_F3 | EX86_PREF_66)) - 1)) == 0);
op |= EX86_REX;
if (op & VEX_OP_0F38)
vex_m = 0x2;
else if (op & VEX_OP_0F3A)
vex_m = 0x3;
if ((op & VEX_W) || ((op & VEX_AUTO_W) && !compiler->mode32)) {
if (vex_m == 0)
vex_m = 0x1;
vex |= 0x80;
}
if (op & EX86_PREF_66)
vex |= 0x1;
else if (op & EX86_PREF_F2)
vex |= 0x3;
else if (op & EX86_PREF_F3)
vex |= 0x2;
op &= ~(EX86_PREF_66 | EX86_PREF_F2 | EX86_PREF_F3);
if (op & VEX_256)
vex |= 0x4;
vex = U8(vex | ((((op & VEX_SSE2_OPV) ? freg_map[v] : reg_map[v]) ^ 0xf) << 3));
size = op & ~(sljit_uw)0xff;
size |= (vex_m == 0) ? (EX86_VEX_EXT | 2) : 3;
inst = emit_x86_instruction(compiler, size, a, 0, b, immb);
FAIL_IF(!inst);
SLJIT_ASSERT((inst[-1] & 0xf0) == REX);
/* If X or B is present in REX prefix. */
if (vex_m == 0 && inst[-1] & 0x3)
vex_m = 0x1;
if (vex_m == 0) {
vex |= U8(((inst[-1] >> 2) ^ 0x1) << 7);
inst[-1] = 0xc5;
inst[0] = vex;
inst[1] = U8(op);
return SLJIT_SUCCESS;
}
vex_m |= U8((inst[-1] ^ 0x7) << 5);
inst[-1] = 0xc4;
inst[0] = vex_m;
inst[1] = vex;
inst[2] = U8(op);
return SLJIT_SUCCESS;
}
/* --------------------------------------------------------------------- */
@ -370,6 +443,12 @@ static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, slji
return code_ptr;
}
#ifdef _WIN64
typedef struct {
sljit_sw regs[2];
} sljit_sse2_reg;
#endif /* _WIN64 */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
@ -423,7 +502,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
#ifdef _WIN64
local_size += SLJIT_LOCALS_OFFSET;
saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16);
saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg);
if (saved_float_regs_size > 0) {
saved_float_regs_offset = ((local_size + 0xf) & ~0xf);
@ -532,16 +611,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
tmp = SLJIT_FS0 - fsaveds;
for (i = SLJIT_FS0; i > tmp; i--) {
inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);
*inst++ = GROUP_0F;
*inst = MOVAPS_xm_x;
FAIL_IF(emit_groupf(compiler, MOVAPS_xm_x | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset));
saved_float_regs_offset += 16;
}
for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);
*inst++ = GROUP_0F;
*inst = MOVAPS_xm_x;
FAIL_IF(emit_groupf(compiler, MOVAPS_xm_x | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset));
saved_float_regs_offset += 16;
}
}
@ -565,7 +640,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
#ifdef _WIN64
local_size += SLJIT_LOCALS_OFFSET;
saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16);
saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg);
if (saved_float_regs_size > 0)
local_size = ((local_size + 0xf) & ~0xf) + saved_float_regs_size;
@ -591,7 +666,7 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit
#endif /* _WIN64 */
#ifdef _WIN64
saved_float_regs_offset = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16);
saved_float_regs_offset = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sse2_reg);
if (saved_float_regs_offset > 0) {
compiler->mode32 = 1;
@ -599,16 +674,12 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit
tmp = SLJIT_FS0 - fsaveds;
for (i = SLJIT_FS0; i > tmp; i--) {
inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);
*inst++ = GROUP_0F;
*inst = MOVAPS_x_xm;
FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset));
saved_float_regs_offset += 16;
}
for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);
*inst++ = GROUP_0F;
*inst = MOVAPS_x_xm;
FAIL_IF(emit_groupf(compiler, MOVAPS_x_xm | EX86_SSE2, i, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset));
saved_float_regs_offset += 16;
}
@ -656,20 +727,13 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
{
sljit_u8 *inst;
CHECK_ERROR();
CHECK(check_sljit_emit_return_void(compiler));
compiler->mode32 = 0;
FAIL_IF(emit_stack_frame_release(compiler, 0));
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
RET();
return SLJIT_SUCCESS;
return emit_byte(compiler, RET_near);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_to(struct sljit_compiler *compiler,
@ -863,22 +927,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
return sljit_emit_ijump(compiler, type, src, srcw);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
static sljit_s32 emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
{
sljit_u8 *inst;
CHECK_ERROR();
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
if (FAST_IS_REG(dst)) {
if (reg_map[dst] < 8) {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
POP_REG(reg_lmap[dst]);
return SLJIT_SUCCESS;
}
if (reg_map[dst] < 8)
return emit_byte(compiler, U8(POP_r + reg_lmap[dst]));
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
@ -892,7 +947,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
compiler->mode32 = 1;
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
FAIL_IF(!inst);
*inst++ = POP_rm;
*inst = POP_rm;
return SLJIT_SUCCESS;
}
@ -922,8 +977,8 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src
compiler->mode32 = 1;
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = GROUP_FF;
*inst |= PUSH_rm;
inst[0] = GROUP_FF;
inst[1] |= PUSH_rm;
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
@ -934,6 +989,16 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src
return SLJIT_SUCCESS;
}
static sljit_s32 sljit_emit_get_return_address(struct sljit_compiler *compiler,
sljit_s32 dst, sljit_sw dstw)
{
sljit_s32 saved_regs_size;
compiler->mode32 = 0;
saved_regs_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0);
return emit_mov(compiler, dst, dstw, SLJIT_MEM1(SLJIT_SP), compiler->local_size + saved_regs_size);
}
/* --------------------------------------------------------------------- */
/* Other operations */
/* --------------------------------------------------------------------- */
@ -1027,15 +1092,15 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign,
compiler->mode32 = 0;
if (src & SLJIT_IMM) {
if (src == SLJIT_IMM) {
if (FAST_IS_REG(dst)) {
if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);
FAIL_IF(!inst);
*inst = MOV_rm_i32;
return SLJIT_SUCCESS;
}
return emit_load_imm64(compiler, dst, srcw);
if (!sign || ((sljit_u32)srcw <= 0x7fffffff))
return emit_do_imm32(compiler, reg_map[dst] <= 7 ? 0 : REX_B, U8(MOV_r_i32 | reg_lmap[dst]), srcw);
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);
FAIL_IF(!inst);
*inst = MOV_rm_i32;
return SLJIT_SUCCESS;
}
compiler->mode32 = 1;
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_s32)srcw, dst, dstw);
@ -1053,10 +1118,10 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign,
if (sign) {
inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = MOVSXD_r_rm;
*inst = MOVSXD_r_rm;
} else {
compiler->mode32 = 1;
FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));
EMIT_MOV(compiler, dst_r, 0, src, srcw);
compiler->mode32 = 0;
}
}
@ -1072,6 +1137,203 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign,
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_FREG;
sljit_u8 *inst, *jump_inst1, *jump_inst2;
sljit_uw size1, size2;
compiler->mode32 = 0;
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_U32) {
if (src != SLJIT_IMM) {
compiler->mode32 = 1;
EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
compiler->mode32 = 0;
} else
FAIL_IF(emit_do_imm32(compiler, reg_map[TMP_REG1] <= 7 ? 0 : REX_B, U8(MOV_r_i32 | reg_lmap[TMP_REG1]), srcw));
FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));
compiler->mode32 = 1;
if (dst_r == TMP_FREG)
return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
return SLJIT_SUCCESS;
}
if (!FAST_IS_REG(src)) {
EMIT_MOV(compiler, TMP_REG1, 0, src, srcw);
src = TMP_REG1;
}
BINARY_IMM32(CMP, 0, src, 0);
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
INC_SIZE(2);
inst[0] = JL_i8;
jump_inst1 = inst;
size1 = compiler->size;
compiler->mode32 = 0;
FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, src, 0));
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
INC_SIZE(2);
inst[0] = JMP_i8;
jump_inst2 = inst;
size2 = compiler->size;
jump_inst1[1] = U8(size2 - size1);
if (src != TMP_REG1)
EMIT_MOV(compiler, TMP_REG1, 0, src, 0);
EMIT_MOV(compiler, TMP_REG2, 0, src, 0);
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 1, TMP_REG1, 0);
FAIL_IF(!inst);
inst[1] |= SHR;
compiler->mode32 = 1;
BINARY_IMM32(AND, 1, TMP_REG2, 0);
compiler->mode32 = 0;
inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, TMP_REG2, 0);
FAIL_IF(!inst);
inst[0] = OR_r_rm;
FAIL_IF(emit_groupf(compiler, CVTSI2SD_x_rm | EX86_SELECT_F2_F3(op) | EX86_SSE2_OP1, dst_r, TMP_REG1, 0));
compiler->mode32 = 1;
FAIL_IF(emit_groupf(compiler, ADDSD_x_xm | EX86_SELECT_F2_F3(op) | EX86_SSE2, dst_r, dst_r, 0));
jump_inst2[1] = U8(compiler->size - size2);
if (dst_r == TMP_FREG)
return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
return SLJIT_SUCCESS;
}
static sljit_s32 sljit_emit_fset(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_u8 rex, sljit_s32 is_zero)
{
sljit_u8 *inst;
sljit_u32 size;
if (is_zero) {
rex = freg_map[freg] >= 8 ? (REX_R | REX_B) : 0;
} else {
if (freg_map[freg] >= 8)
rex |= REX_R;
if (reg_map[TMP_REG1] >= 8)
rex |= REX_B;
}
size = (rex != 0) ? 5 : 4;
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
FAIL_IF(!inst);
INC_SIZE(size);
*inst++ = GROUP_66;
if (rex != 0)
*inst++ = rex;
inst[0] = GROUP_0F;
if (is_zero) {
inst[1] = PXOR_x_xm;
inst[2] = U8(freg_lmap[freg] | (freg_lmap[freg] << 3) | MOD_REG);
} else {
inst[1] = MOVD_x_rm;
inst[2] = U8(reg_lmap[TMP_REG1] | (freg_lmap[freg] << 3) | MOD_REG);
}
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fset32(struct sljit_compiler *compiler,
sljit_s32 freg, sljit_f32 value)
{
union {
sljit_s32 imm;
sljit_f32 value;
} u;
CHECK_ERROR();
CHECK(check_sljit_emit_fset32(compiler, freg, value));
u.value = value;
if (u.imm != 0) {
compiler->mode32 = 1;
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm);
}
return sljit_emit_fset(compiler, freg, 0, u.imm == 0);
}
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) {
compiler->mode32 = 0;
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, u.imm);
}
return sljit_emit_fset(compiler, freg, REX_W, u.imm == 0);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 freg, sljit_s32 reg)
{
sljit_u8 *inst;
sljit_u32 size;
sljit_u8 rex = 0;
CHECK_ERROR();
CHECK(check_sljit_emit_fcopy(compiler, op, freg, reg));
if (!(op & SLJIT_32))
rex = REX_W;
if (freg_map[freg] >= 8)
rex |= REX_R;
if (reg_map[reg] >= 8)
rex |= REX_B;
size = (rex != 0) ? 5 : 4;
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
FAIL_IF(!inst);
INC_SIZE(size);
*inst++ = GROUP_66;
if (rex != 0)
*inst++ = rex;
inst[0] = GROUP_0F;
inst[1] = GET_OPCODE(op) == SLJIT_COPY_TO_F64 ? MOVD_x_rm : MOVD_rm_x;
inst[2] = U8(reg_lmap[reg] | (freg_lmap[freg] << 3) | MOD_REG);
return SLJIT_SUCCESS;
}
static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)
{
sljit_s32 tmp, size;

File diff suppressed because it is too large Load Diff