2014-02-03 09:09 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)

* src/3rd/pcre/*
    * updated PCRE 8.31 -> 8.34
This commit is contained in:
Przemysław Czerpak
2014-02-03 09:09:07 +01:00
parent dfcdf0f843
commit 65973e04e2
44 changed files with 17898 additions and 11767 deletions

View File

@@ -10,6 +10,10 @@
* Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment
*/
2014-02-03 09:09 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* src/3rd/pcre/*
* updated PCRE 8.31 -> 8.34
2014-02-02 19:22 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* contrib/3rd/sqlite3/*
* sqlite3 update 3.7.16.2. -> 3.8.2

View File

@@ -24,7 +24,7 @@ Email domain: cam.ac.uk
University of Cambridge Computing Service,
Cambridge, England.
Copyright (c) 1997-2012 University of Cambridge
Copyright (c) 1997-2013 University of Cambridge
All rights reserved.
@@ -35,7 +35,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
Copyright(c) 2010-2012 Zoltan Herczeg
Copyright(c) 2010-2013 Zoltan Herczeg
All rights reserved.
@@ -46,7 +46,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
Copyright(c) 2009-2012 Zoltan Herczeg
Copyright(c) 2009-2013 Zoltan Herczeg
All rights reserved.

View File

@@ -31,17 +31,18 @@ LIBNAME := hbpcre
ifneq ($(HB_HAS_PCRE_LOCAL),)
HB_CFLAGS += -DHAVE_STDINT_H=0
HB_CFLAGS += -DSUPPORT_UTF -DSUPPORT_UCP
# only needed for win/wce, for other platforms this is noop
HB_CFLAGS_STA := -DPCRE_STATIC
ifneq ($(filter $(HB_COMPILER),bcc msvc msvc64 msvcia64 msvcarm icc iccia64 djgpp),)
HB_CFLAGS += -DHAVE_INTTYPES_H=0
ifeq ($(filter $(HB_PLATFORM),win wince dos vxworks),)
HB_CFLAGS += -DHAVE_STDINT_H
else
ifneq ($(filter $(HB_PLATFORM),vxworks),)
HB_CFLAGS += -DHAVE_INTTYPES_H=0
endif
ifeq ($(filter $(HB_COMPILER),bcc msvc msvc64 msvcia64 msvcarm icc iccia64 djgpp),)
ifeq ($(filter $(HB_PLATFORM),vxworks),)
HB_CFLAGS += -DHAVE_STDINT_H
endif
endif
endif
# ifneq ($(filter $(HB_COMPILER),mingw mingw64 msvc mvc64)$(filter $(HB_PLATFORM),darwin linux),)
@@ -73,8 +74,8 @@ else
endif
# ORIGIN http://www.pcre.org/
# VER 8.31
# URL ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.31.tar.gz
# VER 8.34
# URL ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.34.tar.gz
# DIFF pcre.dif
#
# MAP LICENCE

View File

@@ -163,7 +163,7 @@ graph, print, punct, and cntrl. Other classes are built from combinations. */
*/
0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
0x00,0x01,0x01,0x00,0x01,0x01,0x00,0x00, /* 8- 15 */
0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */

View File

@@ -1,62 +1,70 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* PCRE is written in Standard C, but there are a few non-standard things it
can cope with, allowing it to run on SunOS4 and other "close to standard"
systems.
/* On Unix-like systems config.h.in is converted by "configure" into config.h.
Some other environments also support the use of "configure". PCRE is written in
Standard C, but there are a few non-standard things it can cope with, allowing
it to run on SunOS4 and other "close to standard" systems.
If you are going to build PCRE "by hand" on a system without "configure" you
should copy the distributed config.h.generic to config.h, and then set up the
macro definitions the way you need them. You must then add -DHAVE_CONFIG_H to
all of your compile commands, so that config.h is included at the start of
every source.
In environments that support the GNU autotools, config.h.in is converted into
config.h by the "configure" script. In environments that use CMake,
config-cmake.in is converted into config.h. If you are going to build PCRE "by
hand" without using "configure" or CMake, you should copy the distributed
config.h.generic to config.h, and edit the macro definitions to be the way you
need them. You must then add -DHAVE_CONFIG_H to all of your compile commands,
so that config.h is included at the start of every source.
Alternatively, you can avoid editing by using -D on the compiler command line
to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H.
to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H,
but if you do, default values will be taken from config.h for non-boolean
macros that are not defined on the command line.
PCRE uses memmove() if HAVE_MEMMOVE is set to 1; otherwise it uses bcopy() if
HAVE_BCOPY is set to 1. If your system has neither bcopy() nor memmove(), set
them both to 0; an emulation function will be used. */
Boolean macros such as HAVE_STDLIB_H and SUPPORT_PCRE8 should either be defined
(conventionally to 1) for TRUE, and not defined at all for FALSE. All such
macros are listed as a commented #undef in config.h.generic. Macros such as
MATCH_LIMIT, whose actual value is relevant, have defaults defined, but are
surrounded by #ifndef/#endif lines so that the value can be overridden by -D.
PCRE uses memmove() if HAVE_MEMMOVE is defined; otherwise it uses bcopy() if
HAVE_BCOPY is defined. If your system has neither bcopy() nor memmove(), make
sure both macros are undefined; an emulation function will then be used. */
/* By default, the \R escape sequence matches any Unicode line ending
character or sequence of characters. If BSR_ANYCRLF is defined, this is
changed so that backslash-R matches only CR, LF, or CRLF. The build- time
default can be overridden by the user of PCRE at runtime. On systems that
support it, "configure" can be used to override the default. */
character or sequence of characters. If BSR_ANYCRLF is defined (to any
value), this is changed so that backslash-R matches only CR, LF, or CRLF.
The build-time default can be overridden by the user of PCRE at runtime. */
/* #undef BSR_ANYCRLF */
/* If you are compiling for a system that uses EBCDIC instead of ASCII
character codes, define this macro as 1. On systems that can use
"configure", this can be done via --enable-ebcdic. PCRE will then assume
that all input strings are in EBCDIC. If you do not define this macro, PCRE
will assume input strings are ASCII or UTF-8/16 Unicode. It is not possible
to build a version of PCRE that supports both EBCDIC and UTF-8/16. */
character codes, define this macro to any value. You must also edit the
NEWLINE macro below to set a suitable EBCDIC newline, commonly 21 (0x15).
On systems that can use "configure" or CMake to set EBCDIC, NEWLINE is
automatically adjusted. When EBCDIC is set, PCRE assumes that all input
strings are in EBCDIC. If you do not define this macro, PCRE will assume
input strings are ASCII or UTF-8/16/32 Unicode. It is not possible to build
a version of PCRE that supports both EBCDIC and UTF-8/16/32. */
/* #undef EBCDIC */
/* In an EBCDIC environment, define this macro to any value to arrange for the
NL character to be 0x25 instead of the default 0x15. NL plays the role that
LF does in an ASCII/Unicode environment. The value must also be set in the
NEWLINE macro below. On systems that can use "configure" or CMake to set
EBCDIC_NL25, the adjustment of NEWLINE is automatic. */
/* #undef EBCDIC_NL25 */
/* Define to 1 if you have the `bcopy' function. */
#ifndef HAVE_BCOPY
#define HAVE_BCOPY 1
#endif
/* #undef HAVE_BCOPY */
/* Define to 1 if you have the <bits/type_traits.h> header file. */
/* #undef HAVE_BITS_TYPE_TRAITS_H */
/* Define to 1 if you have the <bzlib.h> header file. */
#ifndef HAVE_BZLIB_H
#define HAVE_BZLIB_H 1
#endif
/* #undef HAVE_BZLIB_H */
/* Define to 1 if you have the <dirent.h> header file. */
#ifndef HAVE_DIRENT_H
#define HAVE_DIRENT_H 1
#endif
/* #undef HAVE_DIRENT_H */
/* Define to 1 if you have the <dlfcn.h> header file. */
#ifndef HAVE_DLFCN_H
#define HAVE_DLFCN_H 1
#endif
/* #undef HAVE_DLFCN_H */
/* Define to 1 if you have the <editline/readline.h> header file. */
/* #undef HAVE_EDITLINE_READLINE_H */
@@ -65,29 +73,25 @@ them both to 0; an emulation function will be used. */
/* #undef HAVE_EDIT_READLINE_READLINE_H */
/* Define to 1 if you have the <inttypes.h> header file. */
#ifndef HAVE_INTTYPES_H
#define HAVE_INTTYPES_H 1
#endif
/* #undef HAVE_INTTYPES_H */
/* Define to 1 if you have the <limits.h> header file. */
#ifndef HAVE_LIMITS_H
#define HAVE_LIMITS_H 1
#endif
/* #undef HAVE_LIMITS_H */
/* Define to 1 if the system has the type `long long'. */
#ifndef HAVE_LONG_LONG
#define HAVE_LONG_LONG 1
#endif
/* #undef HAVE_LONG_LONG */
/* Define to 1 if you have the `memmove' function. */
#ifndef HAVE_MEMMOVE
#define HAVE_MEMMOVE 1
#endif
/* #undef HAVE_MEMMOVE */
/* Define to 1 if you have the <memory.h> header file. */
#ifndef HAVE_MEMORY_H
#define HAVE_MEMORY_H 1
#endif
/* #undef HAVE_MEMORY_H */
/* Define if you have POSIX threads libraries and header files. */
/* #undef HAVE_PTHREAD */
/* Have PTHREAD_PRIO_INHERIT. */
/* #undef HAVE_PTHREAD_PRIO_INHERIT */
/* Define to 1 if you have the <readline/history.h> header file. */
/* #undef HAVE_READLINE_HISTORY_H */
@@ -96,34 +100,22 @@ them both to 0; an emulation function will be used. */
/* #undef HAVE_READLINE_READLINE_H */
/* Define to 1 if you have the <stdint.h> header file. */
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H 1
#endif
/* #undef HAVE_STDINT_H */
/* Define to 1 if you have the <stdlib.h> header file. */
#ifndef HAVE_STDLIB_H
#define HAVE_STDLIB_H 1
#endif
/* #undef HAVE_STDLIB_H */
/* Define to 1 if you have the `strerror' function. */
#ifndef HAVE_STRERROR
#define HAVE_STRERROR 1
#endif
/* #undef HAVE_STRERROR */
/* Define to 1 if you have the <string> header file. */
#ifndef HAVE_STRING
#define HAVE_STRING 1
#endif
/* #undef HAVE_STRING */
/* Define to 1 if you have the <strings.h> header file. */
#ifndef HAVE_STRINGS_H
#define HAVE_STRINGS_H 1
#endif
/* #undef HAVE_STRINGS_H */
/* Define to 1 if you have the <string.h> header file. */
#ifndef HAVE_STRING_H
#define HAVE_STRING_H 1
#endif
/* #undef HAVE_STRING_H */
/* Define to 1 if you have `strtoimax'. */
/* #undef HAVE_STRTOIMAX */
@@ -132,40 +124,31 @@ them both to 0; an emulation function will be used. */
/* #undef HAVE_STRTOLL */
/* Define to 1 if you have `strtoq'. */
#ifndef HAVE_STRTOQ
#define HAVE_STRTOQ 1
#endif
/* #undef HAVE_STRTOQ */
/* Define to 1 if you have the <sys/stat.h> header file. */
#ifndef HAVE_SYS_STAT_H
#define HAVE_SYS_STAT_H 1
#endif
/* #undef HAVE_SYS_STAT_H */
/* Define to 1 if you have the <sys/types.h> header file. */
#ifndef HAVE_SYS_TYPES_H
#define HAVE_SYS_TYPES_H 1
#endif
/* #undef HAVE_SYS_TYPES_H */
/* Define to 1 if you have the <type_traits.h> header file. */
/* #undef HAVE_TYPE_TRAITS_H */
/* Define to 1 if you have the <unistd.h> header file. */
#ifndef HAVE_UNISTD_H
#define HAVE_UNISTD_H 1
#endif
/* #undef HAVE_UNISTD_H */
/* Define to 1 if the system has the type `unsigned long long'. */
#ifndef HAVE_UNSIGNED_LONG_LONG
#define HAVE_UNSIGNED_LONG_LONG 1
#endif
/* #undef HAVE_UNSIGNED_LONG_LONG */
/* Define to 1 if the compiler supports simple visibility declarations. */
/* #undef HAVE_VISIBILITY */
/* Define to 1 if you have the <windows.h> header file. */
/* #undef HAVE_WINDOWS_H */
/* Define to 1 if you have the <zlib.h> header file. */
#ifndef HAVE_ZLIB_H
#define HAVE_ZLIB_H 1
#endif
/* #undef HAVE_ZLIB_H */
/* Define to 1 if you have `_strtoi64'. */
/* #undef HAVE__STRTOI64 */
@@ -174,14 +157,14 @@ them both to 0; an emulation function will be used. */
as offsets within the compiled regex. The default is 2, which allows for
compiled patterns up to 64K long. This covers the vast majority of cases.
However, PCRE can also be compiled to use 3 or 4 bytes instead. This allows
for longer patterns in extreme cases. On systems that support it,
"configure" can be used to override this default. */
for longer patterns in extreme cases. */
#ifndef LINK_SIZE
#define LINK_SIZE 2
#endif
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
/* This is ignored unless you are using libtool. */
#ifndef LT_OBJDIR
#define LT_OBJDIR ".libs/"
#endif
@@ -191,8 +174,7 @@ them both to 0; an emulation function will be used. */
pcre_exec(). 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 large
so that it does not accidentally catch legitimate cases. On systems that
support it, "configure" can be used to override this default default. */
so that it does not accidentally catch legitimate cases. */
#ifndef MATCH_LIMIT
#define MATCH_LIMIT 10000000
#endif
@@ -204,8 +186,7 @@ them both to 0; an emulation function will be used. */
used. The value of MATCH_LIMIT_RECURSION applies only to recursive calls of
match(). To have any useful effect, it must be less than the value of
MATCH_LIMIT. The default is to use the same value as MATCH_LIMIT. There is
a runtime method for setting a different limit. On systems that support it,
"configure" can be used to override the default. */
a runtime method for setting a different limit. */
#ifndef MATCH_LIMIT_RECURSION
#define MATCH_LIMIT_RECURSION MATCH_LIMIT
#endif
@@ -224,22 +205,25 @@ them both to 0; an emulation function will be used. */
#define MAX_NAME_SIZE 32
#endif
/* The value of NEWLINE determines the newline character sequence. On systems
that support it, "configure" can be used to override the default, which is
10. The possible values are 10 (LF), 13 (CR), 3338 (CRLF), -1 (ANY), or -2
(ANYCRLF). */
/* The value of NEWLINE determines the default newline character sequence.
PCRE client programs can override this by selecting other values at run
time. In ASCII environments, the value can be 10 (LF), 13 (CR), or 3338
(CRLF); in EBCDIC environments the value can be 21 or 37 (LF), 13 (CR), or
3349 or 3365 (CRLF) because there are two alternative codepoints (0x15 and
0x25) that are used as the NL line terminator that is equivalent to ASCII
LF. In both ASCII and EBCDIC environments the value can also be -1 (ANY),
or -2 (ANYCRLF). */
#ifndef NEWLINE
#define NEWLINE 10
#endif
/* PCRE uses recursive function calls to handle backtracking while matching.
This can sometimes be a problem on systems that have stacks of limited
size. Define NO_RECURSE to get a version that doesn't use recursion in the
match() function; instead it creates its own stack by steam using
pcre_recurse_malloc() to obtain memory from the heap. For more detail, see
the comments and other stuff just above the match() function. On systems
that support it, "configure" can be used to set this in the Makefile (use
--disable-stack-for-recursion). */
size. Define NO_RECURSE to any value to get a version that doesn't use
recursion in the match() function; instead it creates its own stack by
steam using pcre_recurse_malloc() to obtain memory from the heap. For more
detail, see the comments and other stuff just above the match() function.
*/
/* #undef NO_RECURSE */
/* Name of package */
@@ -252,7 +236,7 @@ them both to 0; an emulation function will be used. */
#define PACKAGE_NAME "PCRE"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "PCRE 8.31"
#define PACKAGE_STRING "PCRE 8.34"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre"
@@ -261,31 +245,36 @@ them both to 0; an emulation function will be used. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "8.31"
#define PACKAGE_VERSION "8.34"
/* 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
stack that is used while compiling a pattern. */
#ifndef PARENS_NEST_LIMIT
#define PARENS_NEST_LIMIT 250
#endif
/* The value of PCREGREP_BUFSIZE determines the size of buffer used by
pcregrep to hold parts of the file it is searching. On systems that support
it, "configure" can be used to override the default, which is 8192. This is
also the minimum value. The actual amount of memory used by pcregrep is
three times this number, because it allows for the buffering of "before"
and "after" lines. */
pcregrep to hold parts of the file it is searching. This is also the
minimum value. The actual amount of memory used by pcregrep is three times
this number, because it allows for the buffering of "before" and "after"
lines. */
#ifndef PCREGREP_BUFSIZE
#define PCREGREP_BUFSIZE 20480
#endif
/* 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, it
defaults to "extern" for a C compiler and "extern C" for a C++
compiler on non-Win32 systems. 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. */
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.
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. */
/* #undef PCRE_EXP_DEFN */
/* Define if linking statically (TODO: make nice with Libtool) */
/* Define to any value if linking statically (TODO: make nice with Libtool) */
/* #undef PCRE_STATIC */
/* When calling PCRE via the POSIX interface, additional working storage is
@@ -294,58 +283,61 @@ them both to 0; an emulation function will be used. */
only two. If the number of expected substrings is small, the wrapper
function uses space on the stack, because this is faster than using
malloc() for each call. The threshold above which the stack is no longer
used is defined by POSIX_MALLOC_THRESHOLD. On systems that support it,
"configure" can be used to override this default. */
used is defined by POSIX_MALLOC_THRESHOLD. */
#ifndef POSIX_MALLOC_THRESHOLD
#define POSIX_MALLOC_THRESHOLD 10
#endif
/* Define to 1 if you have the ANSI C header files. */
#ifndef STDC_HEADERS
#define STDC_HEADERS 1
#endif
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
/* #undef PTHREAD_CREATE_JOINABLE */
/* Define to enable support for Just-In-Time compiling. */
/* Define to 1 if you have the ANSI C header files. */
/* #undef STDC_HEADERS */
/* Define to any value to enable support for Just-In-Time compiling. */
/* #undef SUPPORT_JIT */
/* Define to allow pcregrep to be linked with libbz2, so that it is able to
handle .bz2 files. */
/* Define to any value to allow pcregrep to be linked with libbz2, so that it
is able to handle .bz2 files. */
/* #undef SUPPORT_LIBBZ2 */
/* Define to allow pcretest to be linked with libedit. */
/* Define to any value to allow pcretest to be linked with libedit. */
/* #undef SUPPORT_LIBEDIT */
/* Define to allow pcretest to be linked with libreadline. */
/* Define to any value to allow pcretest to be linked with libreadline. */
/* #undef SUPPORT_LIBREADLINE */
/* Define to allow pcregrep to be linked with libz, so that it is able to
handle .gz files. */
/* Define to any value to allow pcregrep to be linked with libz, so that it is
able to handle .gz files. */
/* #undef SUPPORT_LIBZ */
/* Define to enable the 16 bit PCRE library. */
/* Define to any value to enable the 16 bit PCRE library. */
/* #undef SUPPORT_PCRE16 */
/* Define to enable the 8 bit PCRE library. */
#ifndef SUPPORT_PCRE8
#define SUPPORT_PCRE8 /**/
#endif
/* Define to any value to enable the 32 bit PCRE library. */
/* #undef SUPPORT_PCRE32 */
/* Define to enable JIT support in pcregrep. */
/* Define to any value to enable the 8 bit PCRE library. */
/* #undef SUPPORT_PCRE8 */
/* Define to any value to enable JIT support in pcregrep. */
/* #undef SUPPORT_PCREGREP_JIT */
/* Define to enable support for Unicode properties. */
/* Define to any value to enable support for Unicode properties. */
/* #undef SUPPORT_UCP */
/* Define to enable support for the UTF-8/16 Unicode encoding. This will work
even in an EBCDIC environment, but it is incompatible with the EBCDIC
macro. That is, PCRE can support *either* EBCDIC code *or* ASCII/UTF-8/16,
but not both at once. */
/* Define to any value to enable support for the UTF-8/16/32 Unicode encoding.
This will work even in an EBCDIC environment, but it is incompatible with
the EBCDIC macro. That is, PCRE can support *either* EBCDIC code *or*
ASCII/UTF-8/16/32, but not both at once. */
/* #undef SUPPORT_UTF */
/* Define to any value for valgrind support to find invalid memory reads. */
/* #undef SUPPORT_VALGRIND */
/* Version number of package */
#ifndef VERSION
#define VERSION "8.31"
#endif
#define VERSION "8.34"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */

View File

@@ -1,6 +1,6 @@
diff -urN pcre.orig/pcrejitc.c pcre/pcrejitc.c
--- pcre.orig/pcrejitc.c Wed Jul 11 12:26:04 2012
+++ pcre/pcrejitc.c Wed Jul 11 12:26:05 2012
--- pcre.orig/pcrejitc.c 2014-02-03 09:05:44.496039042 +0100
+++ pcre/pcrejitc.c 2014-02-03 09:05:44.496039042 +0100
@@ -59,7 +59,7 @@
#define SLJIT_VERBOSE 0
#define SLJIT_DEBUG 0
@@ -11,11 +11,11 @@ diff -urN pcre.orig/pcrejitc.c pcre/pcrejitc.c
#if defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED
#error Unsupported architecture
diff -urN pcre.orig/sjconfi.h pcre/sjconfi.h
--- pcre.orig/sjconfi.h Wed Jul 11 12:26:04 2012
+++ pcre/sjconfi.h Wed Jul 11 12:26:05 2012
@@ -282,8 +282,12 @@
--- pcre.orig/sjconfi.h 2014-02-03 09:05:44.536039042 +0100
+++ pcre/sjconfi.h 2014-02-03 09:05:44.536039042 +0100
@@ -323,8 +323,12 @@
#if defined(__GNUC__)
#if defined(__GNUC__) && !defined(__APPLE__)
+#if ( __GNUC__ > 3 ) || ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 4 ) )
#define SLJIT_CALL __attribute__ ((fastcall))
@@ -24,5 +24,5 @@ diff -urN pcre.orig/sjconfi.h pcre/sjconfi.h
+#define SLJIT_CALL
+#endif
#elif defined(_WIN32)
#elif defined(_MSC_VER)

View File

@@ -5,7 +5,7 @@
/* This is the public header file for the PCRE library, to be #included by
applications that call the PCRE functions.
Copyright (c) 1997-2012 University of Cambridge
Copyright (c) 1997-2013 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 PCRE_MAJOR 8
#define PCRE_MINOR 31
#define PCRE_MINOR 34
#define PCRE_PRERELEASE
#define PCRE_DATE 2012-07-06
#define PCRE_DATE 2013-12-15
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate
@@ -95,54 +95,80 @@ it is needed here for malloc. */
extern "C" {
#endif
/* Options. Some are compile-time only, some are run-time only, and some are
both, so we keep them all distinct. However, almost all the bits in the options
word are now used. In the long run, we may have to re-use some of the
compile-time only bits for runtime options, or vice versa. In the comments
below, "compile", "exec", and "DFA exec" mean that the option is permitted to
be set for those functions; "used in" means that an option may be set only for
compile, but is subsequently referenced in exec and/or DFA exec. Any of the
compile-time options may be inspected during studying (and therefore JIT
compiling). */
/* Public options. Some are compile-time only, some are run-time only, and some
are both. Most of the compile-time options are saved with the compiled regex so
that they can be inspected during studying (and therefore JIT compiling). Note
that pcre_study() has its own set of options. Originally, all the options
defined here used distinct bits. However, almost all the bits in a 32-bit word
are now used, so in order to conserve them, option bits that were previously
only recognized at matching time (i.e. by pcre_exec() or pcre_dfa_exec()) may
also be used for compile-time options that affect only compiling and are not
relevant for studying or JIT compiling.
#define PCRE_CASELESS 0x00000001 /* Compile */
#define PCRE_MULTILINE 0x00000002 /* Compile */
#define PCRE_DOTALL 0x00000004 /* Compile */
#define PCRE_EXTENDED 0x00000008 /* Compile */
#define PCRE_ANCHORED 0x00000010 /* Compile, exec, DFA exec */
#define PCRE_DOLLAR_ENDONLY 0x00000020 /* Compile, used in exec, DFA exec */
#define PCRE_EXTRA 0x00000040 /* Compile */
#define PCRE_NOTBOL 0x00000080 /* Exec, DFA exec */
#define PCRE_NOTEOL 0x00000100 /* Exec, DFA exec */
#define PCRE_UNGREEDY 0x00000200 /* Compile */
#define PCRE_NOTEMPTY 0x00000400 /* Exec, DFA exec */
/* The next two are also used in exec and DFA exec */
#define PCRE_UTF8 0x00000800 /* Compile (same as PCRE_UTF16) */
#define PCRE_UTF16 0x00000800 /* Compile (same as PCRE_UTF8) */
#define PCRE_NO_AUTO_CAPTURE 0x00001000 /* Compile */
/* The next two are also used in exec and DFA exec */
#define PCRE_NO_UTF8_CHECK 0x00002000 /* Compile (same as PCRE_NO_UTF16_CHECK) */
#define PCRE_NO_UTF16_CHECK 0x00002000 /* Compile (same as PCRE_NO_UTF8_CHECK) */
#define PCRE_AUTO_CALLOUT 0x00004000 /* Compile */
#define PCRE_PARTIAL_SOFT 0x00008000 /* Exec, DFA exec */
#define PCRE_PARTIAL 0x00008000 /* Backwards compatible synonym */
#define PCRE_DFA_SHORTEST 0x00010000 /* DFA exec */
#define PCRE_DFA_RESTART 0x00020000 /* DFA exec */
#define PCRE_FIRSTLINE 0x00040000 /* Compile, used in exec, DFA exec */
#define PCRE_DUPNAMES 0x00080000 /* Compile */
#define PCRE_NEWLINE_CR 0x00100000 /* Compile, exec, DFA exec */
#define PCRE_NEWLINE_LF 0x00200000 /* Compile, exec, DFA exec */
#define PCRE_NEWLINE_CRLF 0x00300000 /* Compile, exec, DFA exec */
#define PCRE_NEWLINE_ANY 0x00400000 /* Compile, exec, DFA exec */
#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* Compile, exec, DFA exec */
#define PCRE_BSR_ANYCRLF 0x00800000 /* Compile, exec, DFA exec */
#define PCRE_BSR_UNICODE 0x01000000 /* Compile, exec, DFA exec */
#define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* Compile, used in exec */
#define PCRE_NO_START_OPTIMIZE 0x04000000 /* Compile, exec, DFA exec */
#define PCRE_NO_START_OPTIMISE 0x04000000 /* Synonym */
#define PCRE_PARTIAL_HARD 0x08000000 /* Exec, DFA exec */
#define PCRE_NOTEMPTY_ATSTART 0x10000000 /* Exec, DFA exec */
#define PCRE_UCP 0x20000000 /* Compile, used in exec, DFA exec */
Some options for pcre_compile() change its behaviour but do not affect the
behaviour of the execution functions. Other options are passed through to the
execution functions and affect their behaviour, with or without affecting the
behaviour of pcre_compile().
Options that can be passed to pcre_compile() are tagged Cx below, with these
variants:
C1 Affects compile only
C2 Does not affect compile; affects exec, dfa_exec
C3 Affects compile, exec, dfa_exec
C4 Affects compile, exec, dfa_exec, study
C5 Affects compile, exec, study
Options that can be set for pcre_exec() and/or pcre_dfa_exec() are flagged with
E and D, respectively. They take precedence over C3, C4, and C5 settings passed
from pcre_compile(). Those that are compatible with JIT execution are flagged
with J. */
#define PCRE_CASELESS 0x00000001 /* C1 */
#define PCRE_MULTILINE 0x00000002 /* C1 */
#define PCRE_DOTALL 0x00000004 /* C1 */
#define PCRE_EXTENDED 0x00000008 /* C1 */
#define PCRE_ANCHORED 0x00000010 /* C4 E D */
#define PCRE_DOLLAR_ENDONLY 0x00000020 /* C2 */
#define PCRE_EXTRA 0x00000040 /* C1 */
#define PCRE_NOTBOL 0x00000080 /* E D J */
#define PCRE_NOTEOL 0x00000100 /* E D J */
#define PCRE_UNGREEDY 0x00000200 /* C1 */
#define PCRE_NOTEMPTY 0x00000400 /* E D J */
#define PCRE_UTF8 0x00000800 /* C4 ) */
#define PCRE_UTF16 0x00000800 /* C4 ) Synonyms */
#define PCRE_UTF32 0x00000800 /* C4 ) */
#define PCRE_NO_AUTO_CAPTURE 0x00001000 /* C1 */
#define PCRE_NO_UTF8_CHECK 0x00002000 /* C1 E D J ) */
#define PCRE_NO_UTF16_CHECK 0x00002000 /* C1 E D J ) Synonyms */
#define PCRE_NO_UTF32_CHECK 0x00002000 /* C1 E D J ) */
#define PCRE_AUTO_CALLOUT 0x00004000 /* C1 */
#define PCRE_PARTIAL_SOFT 0x00008000 /* E D J ) Synonyms */
#define PCRE_PARTIAL 0x00008000 /* E D J ) */
/* This pair use the same bit. */
#define PCRE_NEVER_UTF 0x00010000 /* C1 ) Overlaid */
#define PCRE_DFA_SHORTEST 0x00010000 /* D ) Overlaid */
/* This pair use the same bit. */
#define PCRE_NO_AUTO_POSSESS 0x00020000 /* C1 ) Overlaid */
#define PCRE_DFA_RESTART 0x00020000 /* D ) Overlaid */
#define PCRE_FIRSTLINE 0x00040000 /* C3 */
#define PCRE_DUPNAMES 0x00080000 /* C1 */
#define PCRE_NEWLINE_CR 0x00100000 /* C3 E D */
#define PCRE_NEWLINE_LF 0x00200000 /* C3 E D */
#define PCRE_NEWLINE_CRLF 0x00300000 /* C3 E D */
#define PCRE_NEWLINE_ANY 0x00400000 /* C3 E D */
#define PCRE_NEWLINE_ANYCRLF 0x00500000 /* C3 E D */
#define PCRE_BSR_ANYCRLF 0x00800000 /* C3 E D */
#define PCRE_BSR_UNICODE 0x01000000 /* C3 E D */
#define PCRE_JAVASCRIPT_COMPAT 0x02000000 /* C5 */
#define PCRE_NO_START_OPTIMIZE 0x04000000 /* C2 E D ) Synonyms */
#define PCRE_NO_START_OPTIMISE 0x04000000 /* C2 E D ) */
#define PCRE_PARTIAL_HARD 0x08000000 /* E D J */
#define PCRE_NOTEMPTY_ATSTART 0x10000000 /* E D J */
#define PCRE_UCP 0x20000000 /* C3 */
/* Exec-time and get/set-time error codes */
@@ -156,8 +182,9 @@ compiling). */
#define PCRE_ERROR_NOSUBSTRING (-7)
#define PCRE_ERROR_MATCHLIMIT (-8)
#define PCRE_ERROR_CALLOUT (-9) /* Never used by PCRE itself */
#define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16 */
#define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16 */
#define PCRE_ERROR_BADUTF8 (-10) /* Same for 8/16/32 */
#define PCRE_ERROR_BADUTF16 (-10) /* Same for 8/16/32 */
#define PCRE_ERROR_BADUTF32 (-10) /* Same for 8/16/32 */
#define PCRE_ERROR_BADUTF8_OFFSET (-11) /* Same for 8/16 */
#define PCRE_ERROR_BADUTF16_OFFSET (-11) /* Same for 8/16 */
#define PCRE_ERROR_PARTIAL (-12)
@@ -180,6 +207,9 @@ compiling). */
#define PCRE_ERROR_BADMODE (-28)
#define PCRE_ERROR_BADENDIANNESS (-29)
#define PCRE_ERROR_DFA_BADRESTART (-30)
#define PCRE_ERROR_JIT_BADOPTION (-31)
#define PCRE_ERROR_BADLENGTH (-32)
#define PCRE_ERROR_UNSET (-33)
/* Specific error codes for UTF-8 validity checks */
@@ -205,6 +235,7 @@ compiling). */
#define PCRE_UTF8_ERR19 19
#define PCRE_UTF8_ERR20 20
#define PCRE_UTF8_ERR21 21
#define PCRE_UTF8_ERR22 22 /* Unused (was non-character) */
/* Specific error codes for UTF-16 validity checks */
@@ -212,7 +243,14 @@ compiling). */
#define PCRE_UTF16_ERR1 1
#define PCRE_UTF16_ERR2 2
#define PCRE_UTF16_ERR3 3
#define PCRE_UTF16_ERR4 4
#define PCRE_UTF16_ERR4 4 /* Unused (was non-character) */
/* Specific error codes for UTF-32 validity checks */
#define PCRE_UTF32_ERR0 0
#define PCRE_UTF32_ERR1 1
#define PCRE_UTF32_ERR2 2 /* Unused (was non-character) */
#define PCRE_UTF32_ERR3 3
/* Request types for pcre_fullinfo() */
@@ -236,6 +274,13 @@ compiling). */
#define PCRE_INFO_JIT 16
#define PCRE_INFO_JITSIZE 17
#define PCRE_INFO_MAXLOOKBEHIND 18
#define PCRE_INFO_FIRSTCHARACTER 19
#define PCRE_INFO_FIRSTCHARACTERFLAGS 20
#define PCRE_INFO_REQUIREDCHAR 21
#define PCRE_INFO_REQUIREDCHARFLAGS 22
#define PCRE_INFO_MATCHLIMIT 23
#define PCRE_INFO_RECURSIONLIMIT 24
#define PCRE_INFO_MATCH_EMPTY 25
/* Request types for pcre_config(). Do not re-arrange, in order to remain
compatible. */
@@ -252,6 +297,8 @@ compatible. */
#define PCRE_CONFIG_JIT 9
#define PCRE_CONFIG_UTF16 10
#define PCRE_CONFIG_JITTARGET 11
#define PCRE_CONFIG_UTF32 12
#define PCRE_CONFIG_PARENS_LIMIT 13
/* Request types for pcre_study(). Do not re-arrange, in order to remain
compatible. */
@@ -259,8 +306,9 @@ compatible. */
#define PCRE_STUDY_JIT_COMPILE 0x0001
#define PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE 0x0002
#define PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE 0x0004
#define PCRE_STUDY_EXTRA_NEEDED 0x0008
/* Bit flags for the pcre[16]_extra structure. Do not re-arrange or redefine
/* Bit flags for the pcre[16|32]_extra structure. Do not re-arrange or redefine
these bits, just add new ones on the end, in order to remain compatible. */
#define PCRE_EXTRA_STUDY_DATA 0x0001
@@ -279,12 +327,18 @@ typedef struct real_pcre pcre;
struct real_pcre16; /* declaration; the definition is private */
typedef struct real_pcre16 pcre16;
struct real_pcre32; /* declaration; the definition is private */
typedef struct real_pcre32 pcre32;
struct real_pcre_jit_stack; /* declaration; the definition is private */
typedef struct real_pcre_jit_stack pcre_jit_stack;
struct real_pcre16_jit_stack; /* declaration; the definition is private */
typedef struct real_pcre16_jit_stack pcre16_jit_stack;
struct real_pcre32_jit_stack; /* declaration; the definition is private */
typedef struct real_pcre32_jit_stack pcre32_jit_stack;
/* If PCRE is compiled with 16 bit character support, PCRE_UCHAR16 must contain
a 16 bit wide signed data type. Otherwise it can be a dummy data type since
pcre16 functions are not implemented. There is a check for this in pcre_internal.h. */
@@ -296,6 +350,17 @@ pcre16 functions are not implemented. There is a check for this in pcre_internal
#define PCRE_SPTR16 const PCRE_UCHAR16 *
#endif
/* If PCRE is compiled with 32 bit character support, PCRE_UCHAR32 must contain
a 32 bit wide signed data type. Otherwise it can be a dummy data type since
pcre32 functions are not implemented. There is a check for this in pcre_internal.h. */
#ifndef PCRE_UCHAR32
#define PCRE_UCHAR32 unsigned int
#endif
#ifndef PCRE_SPTR32
#define PCRE_SPTR32 const PCRE_UCHAR32 *
#endif
/* When PCRE is compiled as a C++ library, the subject pointer type can be
replaced with a custom type. For conventional use, the public interface is a
const char *. */
@@ -332,6 +397,19 @@ typedef struct pcre16_extra {
void *executable_jit; /* Contains a pointer to a compiled jit code */
} pcre16_extra;
/* Same structure as above, but with 32 bit char pointers. */
typedef struct pcre32_extra {
unsigned long int flags; /* Bits for which fields are set */
void *study_data; /* Opaque data from pcre_study() */
unsigned long int match_limit; /* Maximum number of calls to match() */
void *callout_data; /* Data passed back in callouts */
const unsigned char *tables; /* Pointer to character tables */
unsigned long int match_limit_recursion; /* Max recursive calls to match() */
PCRE_UCHAR32 **mark; /* For passing back a mark pointer */
void *executable_jit; /* Contains a pointer to a compiled jit code */
} pcre32_extra;
/* The structure for passing out data via the pcre_callout_function. We use a
structure so that new fields can be added on the end in future versions,
without changing the API of the function, thereby allowing old clients to work
@@ -379,6 +457,28 @@ typedef struct pcre16_callout_block {
/* ------------------------------------------------------------------ */
} pcre16_callout_block;
/* Same structure as above, but with 32 bit char pointers. */
typedef struct pcre32_callout_block {
int version; /* Identifies version of block */
/* ------------------------ Version 0 ------------------------------- */
int callout_number; /* Number compiled into pattern */
int *offset_vector; /* The offset vector */
PCRE_SPTR32 subject; /* The subject being matched */
int subject_length; /* The length of the subject */
int start_match; /* Offset to start of this match attempt */
int current_position; /* Where we currently are in the subject */
int capture_top; /* Max current capture */
int capture_last; /* Most recently closed capture */
void *callout_data; /* Data passed in with the call */
/* ------------------- Added for Version 1 -------------------------- */
int pattern_position; /* Offset to next item in the pattern */
int next_item_length; /* Length of next item in the pattern */
/* ------------------- Added for Version 2 -------------------------- */
const PCRE_UCHAR32 *mark; /* Pointer to current mark or NULL */
/* ------------------------------------------------------------------ */
} pcre32_callout_block;
/* Indirection for store get and free functions. These can be set to
alternative malloc/free functions if required. Special ones are used in the
non-recursive case for "frames". There is also an optional callout function
@@ -397,6 +497,12 @@ PCRE_EXP_DECL void (*pcre16_free)(void *);
PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t);
PCRE_EXP_DECL void (*pcre16_stack_free)(void *);
PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *);
PCRE_EXP_DECL void *(*pcre32_malloc)(size_t);
PCRE_EXP_DECL void (*pcre32_free)(void *);
PCRE_EXP_DECL void *(*pcre32_stack_malloc)(size_t);
PCRE_EXP_DECL void (*pcre32_stack_free)(void *);
PCRE_EXP_DECL int (*pcre32_callout)(pcre32_callout_block *);
#else /* VPCOMPAT */
PCRE_EXP_DECL void *pcre_malloc(size_t);
PCRE_EXP_DECL void pcre_free(void *);
@@ -409,12 +515,19 @@ PCRE_EXP_DECL void pcre16_free(void *);
PCRE_EXP_DECL void *pcre16_stack_malloc(size_t);
PCRE_EXP_DECL void pcre16_stack_free(void *);
PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *);
PCRE_EXP_DECL void *pcre32_malloc(size_t);
PCRE_EXP_DECL void pcre32_free(void *);
PCRE_EXP_DECL void *pcre32_stack_malloc(size_t);
PCRE_EXP_DECL void pcre32_stack_free(void *);
PCRE_EXP_DECL int pcre32_callout(pcre32_callout_block *);
#endif /* VPCOMPAT */
/* User defined callback which provides a stack just before the match starts. */
typedef pcre_jit_stack *(*pcre_jit_callback)(void *);
typedef pcre16_jit_stack *(*pcre16_jit_callback)(void *);
typedef pcre32_jit_stack *(*pcre32_jit_callback)(void *);
/* Exported PCRE functions */
@@ -422,83 +535,134 @@ PCRE_EXP_DECL pcre *pcre_compile(const char *, int, const char **, int *,
const unsigned char *);
PCRE_EXP_DECL pcre16 *pcre16_compile(PCRE_SPTR16, int, const char **, int *,
const unsigned char *);
PCRE_EXP_DECL pcre32 *pcre32_compile(PCRE_SPTR32, int, const char **, int *,
const unsigned char *);
PCRE_EXP_DECL pcre *pcre_compile2(const char *, int, int *, const char **,
int *, const unsigned char *);
PCRE_EXP_DECL pcre16 *pcre16_compile2(PCRE_SPTR16, int, int *, const char **,
int *, const unsigned char *);
PCRE_EXP_DECL pcre32 *pcre32_compile2(PCRE_SPTR32, int, int *, const char **,
int *, const unsigned char *);
PCRE_EXP_DECL int pcre_config(int, void *);
PCRE_EXP_DECL int pcre16_config(int, void *);
PCRE_EXP_DECL int pcre32_config(int, void *);
PCRE_EXP_DECL int pcre_copy_named_substring(const pcre *, const char *,
int *, int, const char *, char *, int);
PCRE_EXP_DECL int pcre16_copy_named_substring(const pcre16 *, PCRE_SPTR16,
int *, int, PCRE_SPTR16, PCRE_UCHAR16 *, int);
PCRE_EXP_DECL int pcre32_copy_named_substring(const pcre32 *, PCRE_SPTR32,
int *, int, PCRE_SPTR32, PCRE_UCHAR32 *, int);
PCRE_EXP_DECL int pcre_copy_substring(const char *, int *, int, int,
char *, int);
PCRE_EXP_DECL int pcre16_copy_substring(PCRE_SPTR16, int *, int, int,
PCRE_UCHAR16 *, int);
PCRE_EXP_DECL int pcre32_copy_substring(PCRE_SPTR32, int *, int, int,
PCRE_UCHAR32 *, int);
PCRE_EXP_DECL int pcre_dfa_exec(const pcre *, const pcre_extra *,
const char *, int, int, int, int *, int , int *, int);
PCRE_EXP_DECL int pcre16_dfa_exec(const pcre16 *, const pcre16_extra *,
PCRE_SPTR16, int, int, int, int *, int , int *, int);
PCRE_EXP_DECL int pcre32_dfa_exec(const pcre32 *, const pcre32_extra *,
PCRE_SPTR32, int, int, int, int *, int , int *, int);
PCRE_EXP_DECL int pcre_exec(const pcre *, const pcre_extra *, PCRE_SPTR,
int, int, int, int *, int);
PCRE_EXP_DECL int pcre16_exec(const pcre16 *, const pcre16_extra *,
PCRE_SPTR16, int, int, int, int *, int);
PCRE_EXP_DECL int pcre32_exec(const pcre32 *, const pcre32_extra *,
PCRE_SPTR32, int, int, int, int *, int);
PCRE_EXP_DECL int pcre_jit_exec(const pcre *, const pcre_extra *,
PCRE_SPTR, int, int, int, int *, int,
pcre_jit_stack *);
PCRE_EXP_DECL int pcre16_jit_exec(const pcre16 *, const pcre16_extra *,
PCRE_SPTR16, int, int, int, int *, int,
pcre16_jit_stack *);
PCRE_EXP_DECL int pcre32_jit_exec(const pcre32 *, const pcre32_extra *,
PCRE_SPTR32, int, int, int, int *, int,
pcre32_jit_stack *);
PCRE_EXP_DECL void pcre_free_substring(const char *);
PCRE_EXP_DECL void pcre16_free_substring(PCRE_SPTR16);
PCRE_EXP_DECL void pcre32_free_substring(PCRE_SPTR32);
PCRE_EXP_DECL void pcre_free_substring_list(const char **);
PCRE_EXP_DECL void pcre16_free_substring_list(PCRE_SPTR16 *);
PCRE_EXP_DECL void pcre32_free_substring_list(PCRE_SPTR32 *);
PCRE_EXP_DECL int pcre_fullinfo(const pcre *, const pcre_extra *, int,
void *);
PCRE_EXP_DECL int pcre16_fullinfo(const pcre16 *, const pcre16_extra *, int,
void *);
PCRE_EXP_DECL int pcre32_fullinfo(const pcre32 *, const pcre32_extra *, int,
void *);
PCRE_EXP_DECL int pcre_get_named_substring(const pcre *, const char *,
int *, int, const char *, const char **);
PCRE_EXP_DECL int pcre16_get_named_substring(const pcre16 *, PCRE_SPTR16,
int *, int, PCRE_SPTR16, PCRE_SPTR16 *);
PCRE_EXP_DECL int pcre32_get_named_substring(const pcre32 *, PCRE_SPTR32,
int *, int, PCRE_SPTR32, PCRE_SPTR32 *);
PCRE_EXP_DECL int pcre_get_stringnumber(const pcre *, const char *);
PCRE_EXP_DECL int pcre16_get_stringnumber(const pcre16 *, PCRE_SPTR16);
PCRE_EXP_DECL int pcre32_get_stringnumber(const pcre32 *, PCRE_SPTR32);
PCRE_EXP_DECL int pcre_get_stringtable_entries(const pcre *, const char *,
char **, char **);
PCRE_EXP_DECL int pcre16_get_stringtable_entries(const pcre16 *, PCRE_SPTR16,
PCRE_UCHAR16 **, PCRE_UCHAR16 **);
PCRE_EXP_DECL int pcre32_get_stringtable_entries(const pcre32 *, PCRE_SPTR32,
PCRE_UCHAR32 **, PCRE_UCHAR32 **);
PCRE_EXP_DECL int pcre_get_substring(const char *, int *, int, int,
const char **);
PCRE_EXP_DECL int pcre16_get_substring(PCRE_SPTR16, int *, int, int,
PCRE_SPTR16 *);
PCRE_EXP_DECL int pcre32_get_substring(PCRE_SPTR32, int *, int, int,
PCRE_SPTR32 *);
PCRE_EXP_DECL int pcre_get_substring_list(const char *, int *, int,
const char ***);
PCRE_EXP_DECL int pcre16_get_substring_list(PCRE_SPTR16, int *, int,
PCRE_SPTR16 **);
PCRE_EXP_DECL int pcre32_get_substring_list(PCRE_SPTR32, int *, int,
PCRE_SPTR32 **);
PCRE_EXP_DECL const unsigned char *pcre_maketables(void);
PCRE_EXP_DECL const unsigned char *pcre16_maketables(void);
PCRE_EXP_DECL const unsigned char *pcre32_maketables(void);
PCRE_EXP_DECL int pcre_refcount(pcre *, int);
PCRE_EXP_DECL int pcre16_refcount(pcre16 *, int);
PCRE_EXP_DECL int pcre32_refcount(pcre32 *, int);
PCRE_EXP_DECL pcre_extra *pcre_study(const pcre *, int, const char **);
PCRE_EXP_DECL pcre16_extra *pcre16_study(const pcre16 *, int, const char **);
PCRE_EXP_DECL pcre32_extra *pcre32_study(const pcre32 *, int, const char **);
PCRE_EXP_DECL void pcre_free_study(pcre_extra *);
PCRE_EXP_DECL void pcre16_free_study(pcre16_extra *);
PCRE_EXP_DECL void pcre32_free_study(pcre32_extra *);
PCRE_EXP_DECL const char *pcre_version(void);
PCRE_EXP_DECL const char *pcre16_version(void);
PCRE_EXP_DECL const char *pcre32_version(void);
/* Utility functions for byte order swaps. */
PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *, pcre_extra *,
const unsigned char *);
PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *, pcre16_extra *,
const unsigned char *);
PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *, pcre32_extra *,
const unsigned char *);
PCRE_EXP_DECL int pcre16_utf16_to_host_byte_order(PCRE_UCHAR16 *,
PCRE_SPTR16, int, int *, int);
PCRE_EXP_DECL int pcre32_utf32_to_host_byte_order(PCRE_UCHAR32 *,
PCRE_SPTR32, int, int *, int);
/* JIT compiler related functions. */
PCRE_EXP_DECL pcre_jit_stack *pcre_jit_stack_alloc(int, int);
PCRE_EXP_DECL pcre16_jit_stack *pcre16_jit_stack_alloc(int, int);
PCRE_EXP_DECL pcre32_jit_stack *pcre32_jit_stack_alloc(int, int);
PCRE_EXP_DECL void pcre_jit_stack_free(pcre_jit_stack *);
PCRE_EXP_DECL void pcre16_jit_stack_free(pcre16_jit_stack *);
PCRE_EXP_DECL void pcre32_jit_stack_free(pcre32_jit_stack *);
PCRE_EXP_DECL void pcre_assign_jit_stack(pcre_extra *,
pcre_jit_callback, void *);
PCRE_EXP_DECL void pcre16_assign_jit_stack(pcre16_extra *,
pcre16_jit_callback, void *);
PCRE_EXP_DECL void pcre32_assign_jit_stack(pcre32_extra *,
pcre32_jit_callback, void *);
PCRE_EXP_DECL void pcre_jit_free_unused_memory(void);
PCRE_EXP_DECL void pcre16_jit_free_unused_memory(void);
PCRE_EXP_DECL void pcre32_jit_free_unused_memory(void);
#ifdef __cplusplus
} /* extern "C" */

View File

@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Copyright (c) 1997-2012 University of Cambridge
Copyright (c) 1997-2013 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -95,12 +95,15 @@ Arguments:
Returns: 0 if the swap is successful, negative on error
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DECL int pcre_pattern_to_host_byte_order(pcre *argument_re,
pcre_extra *extra_data, const unsigned char *tables)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DECL int pcre16_pattern_to_host_byte_order(pcre16 *argument_re,
pcre16_extra *extra_data, const unsigned char *tables)
#elif defined COMPILE_PCRE32
PCRE_EXP_DECL int pcre32_pattern_to_host_byte_order(pcre32 *argument_re,
pcre32_extra *extra_data, const unsigned char *tables)
#endif
{
REAL_PCRE *re = (REAL_PCRE *)argument_re;
@@ -108,10 +111,10 @@ pcre_study_data *study;
#ifndef COMPILE_PCRE8
pcre_uchar *ptr;
int length;
#ifdef SUPPORT_UTF
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
BOOL utf;
BOOL utf16_char;
#endif /* SUPPORT_UTF */
#endif /* SUPPORT_UTF && COMPILE_PCRE16 */
#endif /* !COMPILE_PCRE8 */
if (re == NULL) return PCRE_ERROR_NULL;
@@ -123,16 +126,26 @@ if (re->magic_number == MAGIC_NUMBER)
}
if (re->magic_number != REVERSED_MAGIC_NUMBER) return PCRE_ERROR_BADMAGIC;
if ((swap_uint16(re->flags) & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
if ((swap_uint32(re->flags) & PCRE_MODE) == 0) return PCRE_ERROR_BADMODE;
re->magic_number = MAGIC_NUMBER;
re->size = swap_uint32(re->size);
re->options = swap_uint32(re->options);
re->flags = swap_uint16(re->flags);
re->top_bracket = swap_uint16(re->top_bracket);
re->top_backref = swap_uint16(re->top_backref);
re->flags = swap_uint32(re->flags);
re->limit_match = swap_uint32(re->limit_match);
re->limit_recursion = swap_uint32(re->limit_recursion);
#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
re->first_char = swap_uint16(re->first_char);
re->req_char = swap_uint16(re->req_char);
#elif defined COMPILE_PCRE32
re->first_char = swap_uint32(re->first_char);
re->req_char = swap_uint32(re->req_char);
#endif
re->max_lookbehind = swap_uint16(re->max_lookbehind);
re->top_bracket = swap_uint16(re->top_bracket);
re->top_backref = swap_uint16(re->top_backref);
re->name_table_offset = swap_uint16(re->name_table_offset);
re->name_entry_size = swap_uint16(re->name_entry_size);
re->name_count = swap_uint16(re->name_count);
@@ -150,20 +163,24 @@ if (extra_data != NULL && (extra_data->flags & PCRE_EXTRA_STUDY_DATA) != 0)
#ifndef COMPILE_PCRE8
ptr = (pcre_uchar *)re + re->name_table_offset;
length = re->name_count * re->name_entry_size;
#ifdef SUPPORT_UTF
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
utf = (re->options & PCRE_UTF16) != 0;
utf16_char = FALSE;
#endif
#endif /* SUPPORT_UTF && COMPILE_PCRE16 */
while(TRUE)
{
/* Swap previous characters. */
while (length-- > 0)
{
#if defined COMPILE_PCRE16
*ptr = swap_uint16(*ptr);
#elif defined COMPILE_PCRE32
*ptr = swap_uint32(*ptr);
#endif
ptr++;
}
#ifdef SUPPORT_UTF
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
if (utf16_char)
{
if (HAS_EXTRALEN(ptr[-1]))
@@ -178,13 +195,17 @@ while(TRUE)
/* Get next opcode. */
length = 0;
#if defined COMPILE_PCRE16
*ptr = swap_uint16(*ptr);
#elif defined COMPILE_PCRE32
*ptr = swap_uint32(*ptr);
#endif
switch (*ptr)
{
case OP_END:
return 0;
#ifdef SUPPORT_UTF
#if defined SUPPORT_UTF && defined COMPILE_PCRE16
case OP_CHAR:
case OP_CHARI:
case OP_NOT:
@@ -259,16 +280,26 @@ while(TRUE)
case OP_XCLASS:
/* Reverse the size of the XCLASS instance. */
ptr++;
#if defined COMPILE_PCRE16
*ptr = swap_uint16(*ptr);
#elif defined COMPILE_PCRE32
*ptr = swap_uint32(*ptr);
#endif
#ifndef COMPILE_PCRE32
if (LINK_SIZE > 1)
{
/* LINK_SIZE can be 1 or 2 in 16 bit mode. */
ptr++;
*ptr = swap_uint16(*ptr);
}
#endif
ptr++;
length = (GET(ptr, -LINK_SIZE)) - (1 + LINK_SIZE + 1);
#if defined COMPILE_PCRE16
*ptr = swap_uint16(*ptr);
#elif defined COMPILE_PCRE32
*ptr = swap_uint32(*ptr);
#endif
if ((*ptr & XCL_MAP) != 0)
{
/* Skip the character bit map. */
@@ -279,7 +310,7 @@ while(TRUE)
}
ptr++;
}
/* Control should never reach here in 16 bit mode. */
/* Control should never reach here in 16/32 bit mode. */
#endif /* !COMPILE_PCRE8 */
return 0;

File diff suppressed because it is too large Load Diff

View File

@@ -65,18 +65,21 @@ Arguments:
Returns: 0 if data returned, negative on error
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_config(int what, void *where)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_config(int what, void *where)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_config(int what, void *where)
#endif
{
switch (what)
{
case PCRE_CONFIG_UTF8:
#if defined COMPILE_PCRE16
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
*((int *)where) = 0;
return PCRE_ERROR_BADOPTION;
#else
@@ -89,7 +92,20 @@ switch (what)
#endif
case PCRE_CONFIG_UTF16:
#if defined COMPILE_PCRE8
#if defined COMPILE_PCRE8 || defined COMPILE_PCRE32
*((int *)where) = 0;
return PCRE_ERROR_BADOPTION;
#else
#if defined SUPPORT_UTF
*((int *)where) = 1;
#else
*((int *)where) = 0;
#endif
break;
#endif
case PCRE_CONFIG_UTF32:
#if defined COMPILE_PCRE8 || defined COMPILE_PCRE16
*((int *)where) = 0;
return PCRE_ERROR_BADOPTION;
#else
@@ -145,6 +161,10 @@ switch (what)
*((int *)where) = POSIX_MALLOC_THRESHOLD;
break;
case PCRE_CONFIG_PARENS_LIMIT:
*((unsigned long int *)where) = PARENS_NEST_LIMIT;
break;
case PCRE_CONFIG_MATCH_LIMIT:
*((unsigned long int *)where) = MATCH_LIMIT;
break;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Copyright (c) 1997-2012 University of Cambridge
Copyright (c) 1997-2013 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -65,14 +65,18 @@ Arguments:
Returns: 0 if data returned, negative on error
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_fullinfo(const pcre *argument_re, const pcre_extra *extra_data,
int what, void *where)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_fullinfo(const pcre16 *argument_re, const pcre16_extra *extra_data,
int what, void *where)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_fullinfo(const pcre32 *argument_re, const pcre32_extra *extra_data,
int what, void *where)
#endif
{
const REAL_PCRE *re = (const REAL_PCRE *)argument_re;
@@ -132,10 +136,21 @@ switch (what)
case PCRE_INFO_FIRSTBYTE:
*((int *)where) =
((re->flags & PCRE_FIRSTSET) != 0)? re->first_char :
((re->flags & PCRE_FIRSTSET) != 0)? (int)re->first_char :
((re->flags & PCRE_STARTLINE) != 0)? -1 : -2;
break;
case PCRE_INFO_FIRSTCHARACTER:
*((pcre_uint32 *)where) =
(re->flags & PCRE_FIRSTSET) != 0 ? re->first_char : 0;
break;
case PCRE_INFO_FIRSTCHARACTERFLAGS:
*((int *)where) =
((re->flags & PCRE_FIRSTSET) != 0) ? 1 :
((re->flags & PCRE_STARTLINE) != 0) ? 2 : 0;
break;
/* Make sure we pass back the pointer to the bit vector in the external
block, not the internal copy (with flipped integer fields). */
@@ -159,9 +174,19 @@ switch (what)
case PCRE_INFO_LASTLITERAL:
*((int *)where) =
((re->flags & PCRE_REQCHSET) != 0)? re->req_char : -1;
((re->flags & PCRE_REQCHSET) != 0)? (int)re->req_char : -1;
break;
case PCRE_INFO_REQUIREDCHAR:
*((pcre_uint32 *)where) =
((re->flags & PCRE_REQCHSET) != 0) ? re->req_char : 0;
break;
case PCRE_INFO_REQUIREDCHARFLAGS:
*((int *)where) =
((re->flags & PCRE_REQCHSET) != 0);
break;
case PCRE_INFO_NAMEENTRYSIZE:
*((int *)where) = re->name_entry_size;
break;
@@ -197,6 +222,20 @@ switch (what)
*((int *)where) = re->max_lookbehind;
break;
case PCRE_INFO_MATCHLIMIT:
if ((re->flags & PCRE_MLSET) == 0) return PCRE_ERROR_UNSET;
*((pcre_uint32 *)where) = re->limit_match;
break;
case PCRE_INFO_RECURSIONLIMIT:
if ((re->flags & PCRE_RLSET) == 0) return PCRE_ERROR_UNSET;
*((pcre_uint32 *)where) = re->limit_recursion;
break;
case PCRE_INFO_MATCH_EMPTY:
*((int *)where) = (re->flags & PCRE_MATCH_EMPTY) != 0;
break;
default: return PCRE_ERROR_BADOPTION;
}

View File

@@ -65,12 +65,15 @@ Returns: the number of the named parentheses, or a negative number
(PCRE_ERROR_NOSUBSTRING) if not found
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_get_stringnumber(const pcre *code, const char *stringname)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_get_stringnumber(const pcre16 *code, PCRE_SPTR16 stringname)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_get_stringnumber(const pcre32 *code, PCRE_SPTR32 stringname)
#endif
{
int rc;
@@ -98,6 +101,16 @@ if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
return rc;
#endif
#ifdef COMPILE_PCRE32
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
return rc;
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
return rc;
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
return rc;
#endif
bot = 0;
while (top > bot)
@@ -132,14 +145,18 @@ Returns: the length of each entry, or a negative number
(PCRE_ERROR_NOSUBSTRING) if not found
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_get_stringtable_entries(const pcre *code, const char *stringname,
char **firstptr, char **lastptr)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_get_stringtable_entries(const pcre16 *code, PCRE_SPTR16 stringname,
PCRE_UCHAR16 **firstptr, PCRE_UCHAR16 **lastptr)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_get_stringtable_entries(const pcre32 *code, PCRE_SPTR32 stringname,
PCRE_UCHAR32 **firstptr, PCRE_UCHAR32 **lastptr)
#endif
{
int rc;
@@ -167,6 +184,16 @@ if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0
if ((rc = pcre16_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
return rc;
#endif
#ifdef COMPILE_PCRE32
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMECOUNT, &top)) != 0)
return rc;
if (top <= 0) return PCRE_ERROR_NOSUBSTRING;
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMEENTRYSIZE, &entrysize)) != 0)
return rc;
if ((rc = pcre32_fullinfo(code, NULL, PCRE_INFO_NAMETABLE, &nametable)) != 0)
return rc;
#endif
lastentry = nametable + entrysize * (top - 1);
bot = 0;
@@ -192,12 +219,15 @@ while (top > bot)
(pcre_uchar *)(last + entrysize + IMM2_SIZE)) != 0) break;
last += entrysize;
}
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
*firstptr = (char *)first;
*lastptr = (char *)last;
#else
#elif defined COMPILE_PCRE16
*firstptr = (PCRE_UCHAR16 *)first;
*lastptr = (PCRE_UCHAR16 *)last;
#elif defined COMPILE_PCRE32
*firstptr = (PCRE_UCHAR32 *)first;
*lastptr = (PCRE_UCHAR32 *)last;
#endif
return entrysize;
}
@@ -226,31 +256,40 @@ Returns: the number of the first that is set,
or a negative number on error
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
static int
get_first_set(const pcre *code, const char *stringname, int *ovector)
#else
#elif defined COMPILE_PCRE16
static int
get_first_set(const pcre16 *code, PCRE_SPTR16 stringname, int *ovector)
#elif defined COMPILE_PCRE32
static int
get_first_set(const pcre32 *code, PCRE_SPTR32 stringname, int *ovector)
#endif
{
const REAL_PCRE *re = (const REAL_PCRE *)code;
int entrysize;
pcre_uchar *entry;
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
char *first, *last;
#else
#elif defined COMPILE_PCRE16
PCRE_UCHAR16 *first, *last;
#elif defined COMPILE_PCRE32
PCRE_UCHAR32 *first, *last;
#endif
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
return pcre_get_stringnumber(code, stringname);
entrysize = pcre_get_stringtable_entries(code, stringname, &first, &last);
#else
#elif defined COMPILE_PCRE16
if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
return pcre16_get_stringnumber(code, stringname);
entrysize = pcre16_get_stringtable_entries(code, stringname, &first, &last);
#elif defined COMPILE_PCRE32
if ((re->options & PCRE_DUPNAMES) == 0 && (re->flags & PCRE_JCHANGED) == 0)
return pcre32_get_stringnumber(code, stringname);
entrysize = pcre32_get_stringtable_entries(code, stringname, &first, &last);
#endif
if (entrysize <= 0) return entrysize;
for (entry = (pcre_uchar *)first; entry <= (pcre_uchar *)last; entry += entrysize)
@@ -291,14 +330,18 @@ Returns: if successful:
PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_copy_substring(const char *subject, int *ovector, int stringcount,
int stringnumber, char *buffer, int size)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_copy_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
int stringnumber, PCRE_UCHAR16 *buffer, int size)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_copy_substring(PCRE_SPTR32 subject, int *ovector, int stringcount,
int stringnumber, PCRE_UCHAR32 *buffer, int size)
#endif
{
int yield;
@@ -342,24 +385,31 @@ Returns: if successful:
PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_copy_named_substring(const pcre *code, const char *subject,
int *ovector, int stringcount, const char *stringname,
char *buffer, int size)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_copy_named_substring(const pcre16 *code, PCRE_SPTR16 subject,
int *ovector, int stringcount, PCRE_SPTR16 stringname,
PCRE_UCHAR16 *buffer, int size)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_copy_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
int *ovector, int stringcount, PCRE_SPTR32 stringname,
PCRE_UCHAR32 *buffer, int size)
#endif
{
int n = get_first_set(code, stringname, ovector);
if (n <= 0) return n;
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
return pcre_copy_substring(subject, ovector, stringcount, n, buffer, size);
#else
#elif defined COMPILE_PCRE16
return pcre16_copy_substring(subject, ovector, stringcount, n, buffer, size);
#elif defined COMPILE_PCRE32
return pcre32_copy_substring(subject, ovector, stringcount, n, buffer, size);
#endif
}
@@ -386,14 +436,18 @@ Returns: if successful: 0
PCRE_ERROR_NOMEMORY (-6) failed to get store
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_get_substring_list(const char *subject, int *ovector, int stringcount,
const char ***listptr)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_get_substring_list(PCRE_SPTR16 subject, int *ovector, int stringcount,
PCRE_SPTR16 **listptr)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_get_substring_list(PCRE_SPTR32 subject, int *ovector, int stringcount,
PCRE_SPTR32 **listptr)
#endif
{
int i;
@@ -408,10 +462,12 @@ for (i = 0; i < double_count; i += 2)
stringlist = (pcre_uchar **)(PUBL(malloc))(size);
if (stringlist == NULL) return PCRE_ERROR_NOMEMORY;
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
*listptr = (const char **)stringlist;
#else
#elif defined COMPILE_PCRE16
*listptr = (PCRE_SPTR16 *)stringlist;
#elif defined COMPILE_PCRE32
*listptr = (PCRE_SPTR32 *)stringlist;
#endif
p = (pcre_uchar *)(stringlist + stringcount + 1);
@@ -442,12 +498,15 @@ Argument: the result of a previous pcre_get_substring_list()
Returns: nothing
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
pcre_free_substring_list(const char **pointer)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
pcre16_free_substring_list(PCRE_SPTR16 *pointer)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
pcre32_free_substring_list(PCRE_SPTR32 *pointer)
#endif
{
(PUBL(free))((void *)pointer);
@@ -480,14 +539,18 @@ Returns: if successful:
PCRE_ERROR_NOSUBSTRING (-7) substring not present
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_get_substring(const char *subject, int *ovector, int stringcount,
int stringnumber, const char **stringptr)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_get_substring(PCRE_SPTR16 subject, int *ovector, int stringcount,
int stringnumber, PCRE_SPTR16 *stringptr)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_get_substring(PCRE_SPTR32 subject, int *ovector, int stringcount,
int stringnumber, PCRE_SPTR32 *stringptr)
#endif
{
int yield;
@@ -500,10 +563,12 @@ substring = (pcre_uchar *)(PUBL(malloc))(IN_UCHARS(yield + 1));
if (substring == NULL) return PCRE_ERROR_NOMEMORY;
memcpy(substring, subject + ovector[stringnumber], IN_UCHARS(yield));
substring[yield] = 0;
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
*stringptr = (const char *)substring;
#else
#elif defined COMPILE_PCRE16
*stringptr = (PCRE_SPTR16)substring;
#elif defined COMPILE_PCRE32
*stringptr = (PCRE_SPTR32)substring;
#endif
return yield;
}
@@ -537,24 +602,31 @@ Returns: if successful:
PCRE_ERROR_NOSUBSTRING (-7) no such captured substring
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_get_named_substring(const pcre *code, const char *subject,
int *ovector, int stringcount, const char *stringname,
const char **stringptr)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_get_named_substring(const pcre16 *code, PCRE_SPTR16 subject,
int *ovector, int stringcount, PCRE_SPTR16 stringname,
PCRE_SPTR16 *stringptr)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_get_named_substring(const pcre32 *code, PCRE_SPTR32 subject,
int *ovector, int stringcount, PCRE_SPTR32 stringname,
PCRE_SPTR32 *stringptr)
#endif
{
int n = get_first_set(code, stringname, ovector);
if (n <= 0) return n;
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
return pcre_get_substring(subject, ovector, stringcount, n, stringptr);
#else
#elif defined COMPILE_PCRE16
return pcre16_get_substring(subject, ovector, stringcount, n, stringptr);
#elif defined COMPILE_PCRE32
return pcre32_get_substring(subject, ovector, stringcount, n, stringptr);
#endif
}
@@ -573,12 +645,15 @@ Argument: the result of a previous pcre_get_substring()
Returns: nothing
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
pcre_free_substring(const char *pointer)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
pcre16_free_substring(PCRE_SPTR16 pointer)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN void PCRE_CALL_CONVENTION
pcre32_free_substring(PCRE_SPTR32 pointer)
#endif
{
(PUBL(free))((void *)pointer);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -66,12 +66,15 @@ Arguments: none
Returns: pointer to the contiguous block of data
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
const unsigned char *
pcre_maketables(void)
#else
#elif defined COMPILE_PCRE16
const unsigned char *
pcre16_maketables(void)
#elif defined COMPILE_PCRE32
const unsigned char *
pcre32_maketables(void)
#endif
{
unsigned char *yield, *p;
@@ -95,13 +98,17 @@ for (i = 0; i < 256; i++) *p++ = tolower(i);
for (i = 0; i < 256; i++) *p++ = islower(i)? toupper(i) : tolower(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. Note that the table
for "space" includes everything "isspace" gives, including VT in the default
locale. This makes it work for the POSIX class [:space:]. Note also that it is
possible for a character to be alnum or alpha without being lower or upper,
such as "male and female ordinals" (\xAA and \xBA) in the fr_FR locale (at
least under Debian Linux's locales as of 12/2005). So we must test for alnum
specially. */
exclusive ones - in some locales things may be different.
Note that the table for "space" includes everything "isspace" gives, including
VT in the default locale. This makes it work for the POSIX class [:space:].
From release 8.34 is is also correct for Perl space, because Perl added VT at
release 5.18.
Note also that it is possible for a character to be alnum or alpha without
being lower or upper, such as "male and female ordinals" (\xAA and \xBA) in the
fr_FR locale (at least under Debian Linux's locales as of 12/2005). So we must
test for alnum specially. */
memset(p, 0, cbit_length);
for (i = 0; i < 256; i++)
@@ -120,14 +127,15 @@ for (i = 0; i < 256; i++)
}
p += cbit_length;
/* Finally, the character type table. In this, we exclude VT from the white
space chars, because Perl doesn't recognize it as such for \s and for comments
within regexes. */
/* Finally, the character type table. In this, we used to exclude VT from the
white space chars, because Perl didn't recognize it as such for \s and for
comments within regexes. However, Perl changed at release 5.18, so PCRE changed
at release 8.34. */
for (i = 0; i < 256; i++)
{
int x = 0;
if (i != 0x0b && isspace(i)) x += ctype_space;
if (isspace(i)) x += ctype_space;
if (isalpha(i)) x += ctype_letter;
if (isdigit(i)) x += ctype_digit;
if (isxdigit(i)) x += ctype_xdigit;

View File

@@ -76,7 +76,7 @@ BOOL
PRIV(is_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR endptr, int *lenptr,
BOOL utf)
{
int c;
pcre_uint32 c;
(void)utf;
#ifdef SUPPORT_UTF
if (utf)
@@ -87,11 +87,13 @@ else
#endif /* SUPPORT_UTF */
c = *ptr;
/* Note that this function is called only for ANY or ANYCRLF. */
if (type == NLTYPE_ANYCRLF) switch(c)
{
case 0x000a: *lenptr = 1; return TRUE; /* LF */
case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1;
return TRUE; /* CR */
case CHAR_LF: *lenptr = 1; return TRUE;
case CHAR_CR: *lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1;
return TRUE;
default: return FALSE;
}
@@ -99,20 +101,29 @@ if (type == NLTYPE_ANYCRLF) switch(c)
else switch(c)
{
case 0x000a: /* LF */
case 0x000b: /* VT */
case 0x000c: *lenptr = 1; return TRUE; /* FF */
case 0x000d: *lenptr = (ptr < endptr - 1 && ptr[1] == 0x0a)? 2 : 1;
return TRUE; /* CR */
#ifdef EBCDIC
case CHAR_NEL:
#endif
case CHAR_LF:
case CHAR_VT:
case CHAR_FF: *lenptr = 1; return TRUE;
case CHAR_CR:
*lenptr = (ptr < endptr - 1 && ptr[1] == CHAR_LF)? 2 : 1;
return TRUE;
#ifndef EBCDIC
#ifdef COMPILE_PCRE8
case 0x0085: *lenptr = utf? 2 : 1; return TRUE; /* NEL */
case CHAR_NEL: *lenptr = utf? 2 : 1; return TRUE;
case 0x2028: /* LS */
case 0x2029: *lenptr = 3; return TRUE; /* PS */
#else
case 0x0085: /* NEL */
#else /* COMPILE_PCRE16 || COMPILE_PCRE32 */
case CHAR_NEL:
case 0x2028: /* LS */
case 0x2029: *lenptr = 1; return TRUE; /* PS */
#endif /* COMPILE_PCRE8 */
#endif /* COMPILE_PCRE8 */
#endif /* Not EBCDIC */
default: return FALSE;
}
}
@@ -140,7 +151,7 @@ BOOL
PRIV(was_newline)(PCRE_PUCHAR ptr, int type, PCRE_PUCHAR startptr, int *lenptr,
BOOL utf)
{
int c;
pcre_uint32 c;
(void)utf;
ptr--;
#ifdef SUPPORT_UTF
@@ -153,30 +164,45 @@ else
#endif /* SUPPORT_UTF */
c = *ptr;
/* Note that this function is called only for ANY or ANYCRLF. */
if (type == NLTYPE_ANYCRLF) switch(c)
{
case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1;
return TRUE; /* LF */
case 0x000d: *lenptr = 1; return TRUE; /* CR */
case CHAR_LF:
*lenptr = (ptr > startptr && ptr[-1] == CHAR_CR)? 2 : 1;
return TRUE;
case CHAR_CR: *lenptr = 1; return TRUE;
default: return FALSE;
}
/* NLTYPE_ANY */
else switch(c)
{
case 0x000a: *lenptr = (ptr > startptr && ptr[-1] == 0x0d)? 2 : 1;
return TRUE; /* LF */
case 0x000b: /* VT */
case 0x000c: /* FF */
case 0x000d: *lenptr = 1; return TRUE; /* CR */
case CHAR_LF:
*lenptr = (ptr > startptr && ptr[-1] == CHAR_CR)? 2 : 1;
return TRUE;
#ifdef EBCDIC
case CHAR_NEL:
#endif
case CHAR_VT:
case CHAR_FF:
case CHAR_CR: *lenptr = 1; return TRUE;
#ifndef EBCDIC
#ifdef COMPILE_PCRE8
case 0x0085: *lenptr = utf? 2 : 1; return TRUE; /* NEL */
case 0x2028: /* LS */
case 0x2029: *lenptr = 3; return TRUE; /* PS */
#else
case 0x0085: /* NEL */
case CHAR_NEL: *lenptr = utf? 2 : 1; return TRUE;
case 0x2028: /* LS */
case 0x2029: *lenptr = 3; return TRUE; /* PS */
#else /* COMPILE_PCRE16 || COMPILE_PCRE32 */
case CHAR_NEL:
case 0x2028: /* LS */
case 0x2029: *lenptr = 1; return TRUE; /* PS */
#endif /* COMPILE_PCRE8 */
#endif /* COMPILE_PCRE8 */
#endif /* NotEBCDIC */
default: return FALSE;
}
}

View File

@@ -45,15 +45,16 @@ character value into a UTF8 string. */
#include "config.h"
#endif
#include "pcreinal.h"
#define COMPILE_PCRE8
#include "pcreinal.h"
/*************************************************
* Convert character value to UTF-8 *
*************************************************/
/* This function takes an integer value in the range 0 - 0x10ffff
and encodes it as a UTF-8 character in 1 to 6 pcre_uchars.
and encodes it as a UTF-8 character in 1 to 4 pcre_uchars.
Arguments:
cvalue the character value
@@ -62,6 +63,7 @@ Arguments:
Returns: number of characters placed in the buffer
*/
unsigned
int
PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
{
@@ -69,11 +71,6 @@ PRIV(ord2utf)(pcre_uint32 cvalue, pcre_uchar *buffer)
register int i, j;
/* Checking invalid cvalue character, encoded as invalid UTF-16 character.
Should never happen in practice. */
if ((cvalue & 0xf800) == 0xd800 || cvalue >= 0x110000)
cvalue = 0xfffe;
for (i = 0; i < PRIV(utf8_table1_size); i++)
if ((int)cvalue <= PRIV(utf8_table1)[i]) break;
buffer += i;

View File

@@ -78,10 +78,13 @@ having a separate .h file just for this. */
#ifdef PCRE_INCLUDED
static /* Keep the following function as private. */
#endif
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
void pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths);
#else
#elif defined COMPILE_PCRE16
void pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths);
#elif defined COMPILE_PCRE32
void pcre32_printint(pcre *external_re, FILE *f, BOOL print_lengths);
#endif
/* Macro that decides whether a character should be output as a literal or in
@@ -111,26 +114,28 @@ static const pcre_uint8 priv_OP_lengths[] = { OP_LENGTHS };
* Print single- or multi-byte character *
*************************************************/
static int
static unsigned int
print_char(FILE *f, pcre_uchar *ptr, BOOL utf)
{
int c = *ptr;
pcre_uint32 c = *ptr;
#ifndef SUPPORT_UTF
(void)utf; /* Avoid compiler warning */
if (PRINTABLE(c)) fprintf(f, "%c", c);
else if (c <= 0xff) fprintf(f, "\\x%02x", c);
if (PRINTABLE(c)) fprintf(f, "%c", (char)c);
else if (c <= 0x80) fprintf(f, "\\x%02x", c);
else fprintf(f, "\\x{%x}", c);
return 0;
#else
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
if (!utf || (c & 0xc0) != 0xc0)
{
if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02x", c);
if (PRINTABLE(c)) fprintf(f, "%c", (char)c);
else if (c < 0x80) fprintf(f, "\\x%02x", c);
else fprintf(f, "\\x{%02x}", c);
return 0;
}
else
@@ -160,15 +165,13 @@ else
return a;
}
#else
#ifdef COMPILE_PCRE16
#elif defined COMPILE_PCRE16
if (!utf || (c & 0xfc00) != 0xd800)
{
if (PRINTABLE(c)) fprintf(f, "%c", c);
else if (c <= 0xff) fprintf(f, "\\x%02x", c);
else fprintf(f, "\\x{%x}", c);
if (PRINTABLE(c)) fprintf(f, "%c", (char)c);
else if (c <= 0x80) fprintf(f, "\\x%02x", c);
else fprintf(f, "\\x{%02x}", c);
return 0;
}
else
@@ -188,9 +191,25 @@ else
return 1;
}
#endif /* COMPILE_PCRE16 */
#elif defined COMPILE_PCRE32
#endif /* COMPILE_PCRE8 */
if (!utf || (c & 0xfffff800u) != 0xd800u)
{
if (PRINTABLE(c)) fprintf(f, "%c", (char)c);
else if (c <= 0x80) fprintf(f, "\\x%02x", c);
else fprintf(f, "\\x{%x}", c);
return 0;
}
else
{
/* This is a check for malformed UTF-32; it should only occur if the sanity
check has been turned off. Rather than swallow a surrogate, just stop if
we hit one. Print it with \X instead of \x as an indication. */
fprintf(f, "\\X{%x}", c);
return 0;
}
#endif /* COMPILE_PCRE[8|16|32] */
#endif /* SUPPORT_UTF */
}
@@ -204,7 +223,7 @@ print_puchar(FILE *f, PCRE_PUCHAR ptr)
{
while (*ptr != '\0')
{
register int c = *ptr++;
register pcre_uint32 c = *ptr++;
if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);
}
}
@@ -214,7 +233,7 @@ while (*ptr != '\0')
*************************************************/
static const char *
get_ucpname(int ptype, int pvalue)
get_ucpname(unsigned int ptype, unsigned int pvalue)
{
#ifdef SUPPORT_UCP
int i;
@@ -231,6 +250,40 @@ return (ptype == pvalue)? "??" : "??";
}
/*************************************************
* Print Unicode property value *
*************************************************/
/* "Normal" properties can be printed from tables. The PT_CLIST property is a
pseudo-property that contains a pointer to a list of case-equivalent
characters. This is used only when UCP support is available and UTF mode is
selected. It should never occur otherwise, but just in case it does, have
something ready to print. */
static void
print_prop(FILE *f, pcre_uchar *code, const char *before, const char *after)
{
if (code[1] != PT_CLIST)
{
fprintf(f, "%s%s %s%s", before, priv_OP_names[*code], get_ucpname(code[1],
code[2]), after);
}
else
{
const char *not = (*code == OP_PROP)? "" : "not ";
#ifndef SUPPORT_UCP
fprintf(f, "%s%sclist %d%s", before, not, code[2], after);
#else
const pcre_uint32 *p = PRIV(ucd_caseless_sets) + code[2];
fprintf (f, "%s%sclist", before, not);
while (*p < NOTACHAR) fprintf(f, " %04x", *p++);
fprintf(f, "%s", after);
#endif
}
}
/*************************************************
* Print compiled regex *
@@ -245,12 +298,15 @@ written that do not depend on the value of LINK_SIZE. */
#ifdef PCRE_INCLUDED
static /* Keep the following function as private. */
#endif
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
void
pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths)
#else
#elif defined COMPILE_PCRE16
void
pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths)
#elif defined COMPILE_PCRE32
void
pcre32_printint(pcre *external_re, FILE *f, BOOL print_lengths)
#endif
{
REAL_PCRE *re = (REAL_PCRE *)external_re;
@@ -274,15 +330,15 @@ if (re->magic_number != MAGIC_NUMBER)
}
code = codestart = (pcre_uchar *)re + offset + count * size;
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
/* PCRE_UTF(16|32) have the same value as PCRE_UTF8. */
utf = (options & PCRE_UTF8) != 0;
for(;;)
{
pcre_uchar *ccode;
const char *flag = " ";
int c;
int extra = 0;
pcre_uint32 c;
unsigned int extra = 0;
if (print_lengths)
fprintf(f, "%3d ", (int)(code - codestart));
@@ -369,10 +425,19 @@ for(;;)
break;
case OP_CREF:
case OP_NCREF:
fprintf(f, "%3d %s", GET2(code,1), priv_OP_names[*code]);
break;
case OP_DNCREF:
{
pcre_uchar *entry = (pcre_uchar *)re + offset + (GET2(code, 1) * size) +
IMM2_SIZE;
fprintf(f, " %s Cond ref <", flag);
print_puchar(f, entry);
fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
}
break;
case OP_RREF:
c = GET2(code, 1);
if (c == RREF_ANY)
@@ -381,12 +446,14 @@ for(;;)
fprintf(f, " Cond recurse %d", c);
break;
case OP_NRREF:
c = GET2(code, 1);
if (c == RREF_ANY)
fprintf(f, " Cond nrecurse any");
else
fprintf(f, " Cond nrecurse %d", c);
case OP_DNRREF:
{
pcre_uchar *entry = (pcre_uchar *)re + offset + (GET2(code, 1) * size) +
IMM2_SIZE;
fprintf(f, " %s Cond recurse <", flag);
print_puchar(f, entry);
fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
}
break;
case OP_DEF:
@@ -425,12 +492,12 @@ for(;;)
fprintf(f, " %s ", flag);
if (*code >= OP_TYPESTAR)
{
fprintf(f, "%s", priv_OP_names[code[1]]);
if (code[1] == OP_PROP || code[1] == OP_NOTPROP)
{
fprintf(f, " %s ", get_ucpname(code[2], code[3]));
print_prop(f, code + 1, "", " ");
extra = 2;
}
else fprintf(f, "%s", priv_OP_names[code[1]]);
}
else extra = print_char(f, code+1, utf);
fprintf(f, "%s", priv_OP_names[*code]);
@@ -459,13 +526,12 @@ for(;;)
case OP_TYPEUPTO:
case OP_TYPEMINUPTO:
case OP_TYPEPOSUPTO:
fprintf(f, " %s", priv_OP_names[code[1 + IMM2_SIZE]]);
if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
{
fprintf(f, " %s ", get_ucpname(code[1 + IMM2_SIZE + 1],
code[1 + IMM2_SIZE + 2]));
print_prop(f, code + IMM2_SIZE + 1, " ", " ");
extra = 2;
}
else fprintf(f, " %s", priv_OP_names[code[1 + IMM2_SIZE]]);
fprintf(f, "{");
if (*code != OP_TYPEEXACT) fprintf(f, "0,");
fprintf(f, "%d}", GET2(code,1));
@@ -543,6 +609,20 @@ for(;;)
ccode = code + priv_OP_lengths[*code];
goto CLASS_REF_REPEAT;
case OP_DNREFI:
flag = "/i";
/* Fall through */
case OP_DNREF:
{
pcre_uchar *entry = (pcre_uchar *)re + offset + (GET2(code, 1) * size) +
IMM2_SIZE;
fprintf(f, " %s \\k<", flag);
print_puchar(f, entry);
fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
}
ccode = code + priv_OP_lengths[*code];
goto CLASS_REF_REPEAT;
case OP_CALLOUT:
fprintf(f, " %s %d %d %d", priv_OP_names[*code], code[1], GET(code,2),
GET(code, 2 + LINK_SIZE));
@@ -550,18 +630,19 @@ for(;;)
case OP_PROP:
case OP_NOTPROP:
fprintf(f, " %s %s", priv_OP_names[*code], get_ucpname(code[1], code[2]));
print_prop(f, code, " ", "");
break;
/* OP_XCLASS can only occur in UTF or PCRE16 modes. However, there's no
harm in having this code always here, and it makes it less messy without
all those #ifdefs. */
/* OP_XCLASS cannot occur in 8-bit, non-UTF mode. However, there's no harm
in having this code always here, and it makes it less messy without all
those #ifdefs. */
case OP_CLASS:
case OP_NCLASS:
case OP_XCLASS:
{
int i, min, max;
int i;
unsigned int min, max;
BOOL printmap;
pcre_uint8 *map;
@@ -612,29 +693,54 @@ for(;;)
if (*code == OP_XCLASS)
{
int ch;
pcre_uchar ch;
while ((ch = *ccode++) != XCL_END)
{
if (ch == XCL_PROP)
{
int ptype = *ccode++;
int pvalue = *ccode++;
fprintf(f, "\\p{%s}", get_ucpname(ptype, pvalue));
}
else if (ch == XCL_NOTPROP)
{
int ptype = *ccode++;
int pvalue = *ccode++;
fprintf(f, "\\P{%s}", get_ucpname(ptype, pvalue));
}
else
BOOL not = FALSE;
const char *notch = "";
switch(ch)
{
case XCL_NOTPROP:
not = TRUE;
notch = "^";
/* Fall through */
case XCL_PROP:
{
unsigned int ptype = *ccode++;
unsigned int pvalue = *ccode++;
switch(ptype)
{
case PT_PXGRAPH:
fprintf(f, "[:%sgraph:]", notch);
break;
case PT_PXPRINT:
fprintf(f, "[:%sprint:]", notch);
break;
case PT_PXPUNCT:
fprintf(f, "[:%spunct:]", notch);
break;
default:
fprintf(f, "\\%c{%s}", (not? 'P':'p'),
get_ucpname(ptype, pvalue));
break;
}
}
break;
default:
ccode += 1 + print_char(f, ccode, utf);
if (ch == XCL_RANGE)
{
fprintf(f, "-");
ccode += 1 + print_char(f, ccode, utf);
}
break;
}
}
}
@@ -654,17 +760,22 @@ for(;;)
case OP_CRMINPLUS:
case OP_CRQUERY:
case OP_CRMINQUERY:
case OP_CRPOSSTAR:
case OP_CRPOSPLUS:
case OP_CRPOSQUERY:
fprintf(f, "%s", priv_OP_names[*ccode]);
extra += priv_OP_lengths[*ccode];
break;
case OP_CRRANGE:
case OP_CRMINRANGE:
case OP_CRPOSRANGE:
min = GET2(ccode,1);
max = GET2(ccode,1 + IMM2_SIZE);
if (max == 0) fprintf(f, "{%d,}", min);
else fprintf(f, "{%d,%d}", min, max);
if (max == 0) fprintf(f, "{%u,}", min);
else fprintf(f, "{%u,%u}", min, max);
if (*ccode == OP_CRMINRANGE) fprintf(f, "?");
else if (*ccode == OP_CRPOSRANGE) fprintf(f, "+");
extra += priv_OP_lengths[*ccode];
break;

View File

@@ -68,12 +68,15 @@ Returns: the (possibly updated) count value (a non-negative number), or
a negative error number
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre_refcount(pcre *argument_re, int adjust)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre16_refcount(pcre16 *argument_re, int adjust)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN int PCRE_CALL_CONVENTION
pcre32_refcount(pcre32 *argument_re, int adjust)
#endif
{
REAL_PCRE *re = (REAL_PCRE *)argument_re;

View File

@@ -66,8 +66,9 @@ string of that length that matches. In UTF8 mode, the result is in characters
rather than bytes.
Arguments:
re compiled pattern block
code pointer to start of group (the bracket)
startcode pointer to start of the whole pattern
startcode pointer to start of the whole pattern's code
options the compiling options
int RECURSE depth
@@ -78,8 +79,8 @@ Returns: the minimum length
*/
static int
find_minlength(const pcre_uchar *code, const pcre_uchar *startcode, int options,
int recurse_depth)
find_minlength(const REAL_PCRE *re, const pcre_uchar *code,
const pcre_uchar *startcode, int options, int recurse_depth)
{
int length = -1;
/* PCRE_UTF16 has the same value as PCRE_UTF8. */
@@ -98,7 +99,7 @@ for (;;)
{
int d, min;
pcre_uchar *cs, *ce;
register int op = *cc;
register pcre_uchar op = *cc;
switch (op)
{
@@ -129,7 +130,7 @@ for (;;)
case OP_SBRAPOS:
case OP_ONCE:
case OP_ONCE_NC:
d = find_minlength(cc, startcode, options, recurse_depth);
d = find_minlength(re, cc, startcode, options, recurse_depth);
if (d < 0) return d;
branchlength += d;
do cc += GET(cc, 1); while (*cc == OP_ALT);
@@ -175,9 +176,9 @@ for (;;)
case OP_REVERSE:
case OP_CREF:
case OP_NCREF:
case OP_DNCREF:
case OP_RREF:
case OP_NRREF:
case OP_DNRREF:
case OP_DEF:
case OP_CALLOUT:
case OP_SOD:
@@ -323,20 +324,25 @@ for (;;)
/* Check a class for variable quantification */
#if defined SUPPORT_UTF || !defined COMPILE_PCRE8
case OP_XCLASS:
cc += GET(cc, 1) - PRIV(OP_lengths)[OP_CLASS];
/* Fall through */
#endif
case OP_CLASS:
case OP_NCLASS:
#if defined SUPPORT_UTF || defined COMPILE_PCRE16 || defined COMPILE_PCRE32
case OP_XCLASS:
/* The original code caused an unsigned overflow in 64 bit systems,
so now we use a conditional statement. */
if (op == OP_XCLASS)
cc += GET(cc, 1);
else
cc += PRIV(OP_lengths)[OP_CLASS];
#else
cc += PRIV(OP_lengths)[OP_CLASS];
#endif
switch (*cc)
{
case OP_CRPLUS:
case OP_CRMINPLUS:
case OP_CRPOSPLUS:
branchlength++;
/* Fall through */
@@ -344,11 +350,14 @@ for (;;)
case OP_CRMINSTAR:
case OP_CRQUERY:
case OP_CRMINQUERY:
case OP_CRPOSSTAR:
case OP_CRPOSQUERY:
cc++;
break;
case OP_CRRANGE:
case OP_CRMINRANGE:
case OP_CRPOSRANGE:
branchlength += GET2(cc,1);
cc += 1 + 2 * IMM2_SIZE;
break;
@@ -371,7 +380,38 @@ for (;;)
matches an empty string (by default it causes a matching failure), so in
that case we must set the minimum length to zero. */
case OP_REF:
case OP_DNREF: /* Duplicate named pattern back reference */
case OP_DNREFI:
if ((options & PCRE_JAVASCRIPT_COMPAT) == 0)
{
int count = GET2(cc, 1+IMM2_SIZE);
pcre_uchar *slot = (pcre_uchar *)re +
re->name_table_offset + GET2(cc, 1) * re->name_entry_size;
d = INT_MAX;
while (count-- > 0)
{
ce = cs = (pcre_uchar *)PRIV(find_bracket)(startcode, utf, GET2(slot, 0));
if (cs == NULL) return -2;
do ce += GET(ce, 1); while (*ce == OP_ALT);
if (cc > cs && cc < ce)
{
d = 0;
had_recurse = TRUE;
break;
}
else
{
int dd = find_minlength(re, cs, startcode, options, recurse_depth);
if (dd < d) d = dd;
}
slot += re->name_entry_size;
}
}
else d = 0;
cc += 1 + 2*IMM2_SIZE;
goto REPEAT_BACK_REFERENCE;
case OP_REF: /* Single back reference */
case OP_REFI:
if ((options & PCRE_JAVASCRIPT_COMPAT) == 0)
{
@@ -385,7 +425,7 @@ for (;;)
}
else
{
d = find_minlength(cs, startcode, options, recurse_depth);
d = find_minlength(re, cs, startcode, options, recurse_depth);
}
}
else d = 0;
@@ -393,24 +433,29 @@ for (;;)
/* Handle repeated back references */
REPEAT_BACK_REFERENCE:
switch (*cc)
{
case OP_CRSTAR:
case OP_CRMINSTAR:
case OP_CRQUERY:
case OP_CRMINQUERY:
case OP_CRPOSSTAR:
case OP_CRPOSQUERY:
min = 0;
cc++;
break;
case OP_CRPLUS:
case OP_CRMINPLUS:
case OP_CRPOSPLUS:
min = 1;
cc++;
break;
case OP_CRRANGE:
case OP_CRMINRANGE:
case OP_CRPOSRANGE:
min = GET2(cc, 1);
cc += 1 + 2 * IMM2_SIZE;
break;
@@ -433,7 +478,8 @@ for (;;)
had_recurse = TRUE;
else
{
branchlength += find_minlength(cs, startcode, options, recurse_depth + 1);
branchlength += find_minlength(re, cs, startcode, options,
recurse_depth + 1);
}
cc += 1 + LINK_SIZE;
break;
@@ -538,7 +584,7 @@ Arguments:
p points to the character
caseless the caseless flag
cd the block with char table pointers
utf TRUE for UTF-8 / UTF-16 mode
utf TRUE for UTF-8 / UTF-16 / UTF-32 mode
Returns: pointer after the character
*/
@@ -547,7 +593,7 @@ static const pcre_uchar *
set_table_bit(pcre_uint8 *start_bits, const pcre_uchar *p, BOOL caseless,
compile_data *cd, BOOL utf)
{
unsigned int c = *p;
pcre_uint32 c = *p;
#ifdef COMPILE_PCRE8
SET_BIT(c);
@@ -564,18 +610,20 @@ if (utf && c > 127)
(void)PRIV(ord2utf)(c, buff);
SET_BIT(buff[0]);
}
#endif
#endif /* Not SUPPORT_UCP */
return p;
}
#endif
#else /* Not SUPPORT_UTF */
(void)(utf); /* Stops warning for unused parameter */
#endif /* SUPPORT_UTF */
/* Not UTF-8 mode, or character is less than 127. */
if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
return p + 1;
#endif
#endif /* COMPILE_PCRE8 */
#ifdef COMPILE_PCRE16
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
if (c > 0xff)
{
c = 0xff;
@@ -595,10 +643,12 @@ if (utf && c > 127)
c = 0xff;
SET_BIT(c);
}
#endif
#endif /* SUPPORT_UCP */
return p;
}
#endif
#else /* Not SUPPORT_UTF */
(void)(utf); /* Stops warning for unused parameter */
#endif /* SUPPORT_UTF */
if (caseless && (cd->ctypes[c] & ctype_letter) != 0) SET_BIT(cd->fcc[c]);
return p + 1;
@@ -628,10 +678,10 @@ Returns: nothing
*/
static void
set_type_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit,
set_type_bits(pcre_uint8 *start_bits, int cbit_type, unsigned int table_limit,
compile_data *cd)
{
register int c;
register pcre_uint32 c;
for (c = 0; c < table_limit; c++) start_bits[c] |= cd->cbits[c+cbit_type];
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
if (table_limit == 32) return;
@@ -670,10 +720,10 @@ Returns: nothing
*/
static void
set_nottype_bits(pcre_uint8 *start_bits, int cbit_type, int table_limit,
set_nottype_bits(pcre_uint8 *start_bits, int cbit_type, unsigned int table_limit,
compile_data *cd)
{
register int c;
register pcre_uint32 c;
for (c = 0; c < table_limit; c++) start_bits[c] |= ~cd->cbits[c+cbit_type];
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
if (table_limit != 32) for (c = 24; c < 32; c++) start_bits[c] = 0xff;
@@ -697,7 +747,7 @@ function fails unless the result is SSB_DONE.
Arguments:
code points to an expression
start_bits points to a 32-byte table, initialized to 0
utf TRUE if in UTF-8 / UTF-16 mode
utf TRUE if in UTF-8 / UTF-16 / UTF-32 mode
cd the block with char table pointers
Returns: SSB_FAIL => Failed to find any starting bytes
@@ -710,7 +760,7 @@ static int
set_start_bits(const pcre_uchar *code, pcre_uint8 *start_bits, BOOL utf,
compile_data *cd)
{
register int c;
register pcre_uint32 c;
int yield = SSB_DONE;
#if defined SUPPORT_UTF && defined COMPILE_PCRE8
int table_limit = utf? 16:32;
@@ -770,6 +820,10 @@ do
case OP_COND:
case OP_CREF:
case OP_DEF:
case OP_DNCREF:
case OP_DNREF:
case OP_DNREFI:
case OP_DNRREF:
case OP_DOLL:
case OP_DOLLM:
case OP_END:
@@ -778,7 +832,6 @@ do
case OP_EXTUNI:
case OP_FAIL:
case OP_MARK:
case OP_NCREF:
case OP_NOT:
case OP_NOTEXACT:
case OP_NOTEXACTI:
@@ -810,7 +863,6 @@ do
case OP_NOTUPTOI:
case OP_NOT_HSPACE:
case OP_NOT_VSPACE:
case OP_NRREF:
case OP_PROP:
case OP_PRUNE:
case OP_PRUNE_ARG:
@@ -986,8 +1038,8 @@ do
identical. */
case OP_HSPACE:
SET_BIT(0x09);
SET_BIT(0x20);
SET_BIT(CHAR_HT);
SET_BIT(CHAR_SPACE);
#ifdef SUPPORT_UTF
if (utf)
{
@@ -996,46 +1048,46 @@ do
SET_BIT(0xE1); /* For U+1680, U+180E */
SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */
SET_BIT(0xE3); /* For U+3000 */
#endif
#ifdef COMPILE_PCRE16
#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
SET_BIT(0xA0);
SET_BIT(0xFF); /* For characters > 255 */
#endif
#endif /* COMPILE_PCRE[8|16|32] */
}
else
#endif /* SUPPORT_UTF */
{
#ifndef EBCDIC
SET_BIT(0xA0);
#ifdef COMPILE_PCRE16
#endif /* Not EBCDIC */
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
SET_BIT(0xFF); /* For characters > 255 */
#endif
#endif /* COMPILE_PCRE[16|32] */
}
try_next = FALSE;
break;
case OP_ANYNL:
case OP_VSPACE:
SET_BIT(0x0A);
SET_BIT(0x0B);
SET_BIT(0x0C);
SET_BIT(0x0D);
SET_BIT(CHAR_LF);
SET_BIT(CHAR_VT);
SET_BIT(CHAR_FF);
SET_BIT(CHAR_CR);
#ifdef SUPPORT_UTF
if (utf)
{
#ifdef COMPILE_PCRE8
SET_BIT(0xC2); /* For U+0085 */
SET_BIT(0xE2); /* For U+2028, U+2029 */
#endif
#ifdef COMPILE_PCRE16
SET_BIT(0x85);
#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
SET_BIT(CHAR_NEL);
SET_BIT(0xFF); /* For characters > 255 */
#endif
#endif /* COMPILE_PCRE[8|16|32] */
}
else
#endif /* SUPPORT_UTF */
{
SET_BIT(0x85);
#ifdef COMPILE_PCRE16
SET_BIT(CHAR_NEL);
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
SET_BIT(0xFF); /* For characters > 255 */
#endif
}
@@ -1058,7 +1110,8 @@ do
break;
/* The cbit_space table has vertical tab as whitespace; we have to
ensure it is set as not whitespace. */
ensure it is set as not whitespace. Luckily, the code value is the same
(0x0b) in ASCII and EBCDIC, so we can just adjust the appropriate bit. */
case OP_NOT_WHITESPACE:
set_nottype_bits(start_bits, cbit_space, table_limit, cd);
@@ -1066,8 +1119,9 @@ do
try_next = FALSE;
break;
/* The cbit_space table has vertical tab as whitespace; we have to
not set it from the table. */
/* The cbit_space table has vertical tab as whitespace; we have to not
set it from the table. Luckily, the code value is the same (0x0b) in
ASCII and EBCDIC, so we can just adjust the appropriate bit. */
case OP_WHITESPACE:
c = start_bits[1]; /* Save in case it was already set */
@@ -1121,8 +1175,8 @@ do
return SSB_FAIL;
case OP_HSPACE:
SET_BIT(0x09);
SET_BIT(0x20);
SET_BIT(CHAR_HT);
SET_BIT(CHAR_SPACE);
#ifdef SUPPORT_UTF
if (utf)
{
@@ -1131,38 +1185,38 @@ do
SET_BIT(0xE1); /* For U+1680, U+180E */
SET_BIT(0xE2); /* For U+2000 - U+200A, U+202F, U+205F */
SET_BIT(0xE3); /* For U+3000 */
#endif
#ifdef COMPILE_PCRE16
#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
SET_BIT(0xA0);
SET_BIT(0xFF); /* For characters > 255 */
#endif
#endif /* COMPILE_PCRE[8|16|32] */
}
else
#endif /* SUPPORT_UTF */
#ifndef EBCDIC
SET_BIT(0xA0);
#endif /* Not EBCDIC */
break;
case OP_ANYNL:
case OP_VSPACE:
SET_BIT(0x0A);
SET_BIT(0x0B);
SET_BIT(0x0C);
SET_BIT(0x0D);
SET_BIT(CHAR_LF);
SET_BIT(CHAR_VT);
SET_BIT(CHAR_FF);
SET_BIT(CHAR_CR);
#ifdef SUPPORT_UTF
if (utf)
{
#ifdef COMPILE_PCRE8
SET_BIT(0xC2); /* For U+0085 */
SET_BIT(0xE2); /* For U+2028, U+2029 */
#endif
#ifdef COMPILE_PCRE16
SET_BIT(0x85);
#elif defined COMPILE_PCRE16 || defined COMPILE_PCRE32
SET_BIT(CHAR_NEL);
SET_BIT(0xFF); /* For characters > 255 */
#endif
#endif /* COMPILE_PCRE16 */
}
else
#endif /* SUPPORT_UTF */
SET_BIT(0x85);
SET_BIT(CHAR_NEL);
break;
case OP_NOT_DIGIT:
@@ -1173,21 +1227,16 @@ do
set_type_bits(start_bits, cbit_digit, table_limit, cd);
break;
/* The cbit_space table has vertical tab as whitespace; we have to
ensure it gets set as not whitespace. */
/* The cbit_space table has vertical tab as whitespace; we no longer
have to play fancy tricks because Perl added VT to its whitespace at
release 5.18. PCRE added it at release 8.34. */
case OP_NOT_WHITESPACE:
set_nottype_bits(start_bits, cbit_space, table_limit, cd);
start_bits[1] |= 0x08;
break;
/* The cbit_space table has vertical tab as whitespace; we have to
avoid setting it. */
case OP_WHITESPACE:
c = start_bits[1]; /* Save in case it was already set */
set_type_bits(start_bits, cbit_space, table_limit, cd);
start_bits[1] = (start_bits[1] & ~0x08) | c;
break;
case OP_NOT_WORDCHAR:
@@ -1216,7 +1265,7 @@ do
memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */
}
#endif
#ifdef COMPILE_PCRE16
#if defined COMPILE_PCRE16 || defined COMPILE_PCRE32
SET_BIT(0xFF); /* For characters > 255 */
#endif
/* Fall through */
@@ -1264,11 +1313,14 @@ do
case OP_CRMINSTAR:
case OP_CRQUERY:
case OP_CRMINQUERY:
case OP_CRPOSSTAR:
case OP_CRPOSQUERY:
tcode++;
break;
case OP_CRRANGE:
case OP_CRMINRANGE:
case OP_CRPOSRANGE:
if (GET2(tcode, 1) == 0) tcode += 1 + 2 * IMM2_SIZE;
else try_next = FALSE;
break;
@@ -1312,12 +1364,15 @@ Returns: pointer to a pcre[16]_extra block, with study_data filled in and
NULL on error or if no optimization possible
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN pcre_extra * PCRE_CALL_CONVENTION
pcre_study(const pcre *external_re, int options, const char **errorptr)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN pcre16_extra * PCRE_CALL_CONVENTION
pcre16_study(const pcre16 *external_re, int options, const char **errorptr)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN pcre32_extra * PCRE_CALL_CONVENTION
pcre32_study(const pcre32 *external_re, int options, const char **errorptr)
#endif
{
int min;
@@ -1330,6 +1385,7 @@ pcre_uchar *code;
compile_data compile_block;
const REAL_PCRE *re = (const REAL_PCRE *)external_re;
*errorptr = NULL;
if (re == NULL || re->magic_number != MAGIC_NUMBER)
@@ -1340,10 +1396,12 @@ if (re == NULL || re->magic_number != MAGIC_NUMBER)
if ((re->flags & PCRE_MODE) == 0)
{
#ifdef COMPILE_PCRE8
*errorptr = "argument is compiled in 16 bit mode";
#else
*errorptr = "argument is compiled in 8 bit mode";
#if defined COMPILE_PCRE8
*errorptr = "argument not compiled in 8 bit mode";
#elif defined COMPILE_PCRE16
*errorptr = "argument not compiled in 16 bit mode";
#elif defined COMPILE_PCRE32
*errorptr = "argument not compiled in 32 bit mode";
#endif
return NULL;
}
@@ -1370,14 +1428,18 @@ if ((re->options & PCRE_ANCHORED) == 0 &&
tables = re->tables;
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
if (tables == NULL)
(void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
(void *)(&tables));
#else
#elif defined COMPILE_PCRE16
if (tables == NULL)
(void)pcre16_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
(void *)(&tables));
#elif defined COMPILE_PCRE32
if (tables == NULL)
(void)pcre32_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES,
(void *)(&tables));
#endif
compile_block.lcc = tables + lcc_offset;
@@ -1400,7 +1462,7 @@ if ((re->options & PCRE_ANCHORED) == 0 &&
/* Find the minimum length of subject string. */
switch(min = find_minlength(code, code, re->options, 0))
switch(min = find_minlength(re, code, code, re->options, 0))
{
case -2: *errorptr = "internal error: missing capturing bracket"; return NULL;
case -3: *errorptr = "internal error: opcode not recognized"; return NULL;
@@ -1408,20 +1470,20 @@ switch(min = find_minlength(code, code, re->options, 0))
}
/* If a set of starting bytes has been identified, or if the minimum length is
greater than zero, or if JIT optimization has been requested, get a
pcre[16]_extra block and a pcre_study_data block. The study data is put in the
latter, which is pointed to by the former, which may also get additional data
set later by the calling program. At the moment, the size of pcre_study_data
is fixed. We nevertheless save it in a field for returning via the
pcre_fullinfo() function so that if it becomes variable in the future,
we don't have to change that code. */
greater than zero, or if JIT optimization has been requested, or if
PCRE_STUDY_EXTRA_NEEDED is set, get a pcre[16]_extra block and a
pcre_study_data block. The study data is put in the latter, which is pointed to
by the former, which may also get additional data set later by the calling
program. At the moment, the size of pcre_study_data is fixed. We nevertheless
save it in a field for returning via the pcre_fullinfo() function so that if it
becomes variable in the future, we don't have to change that code. */
if (bits_set || min > 0
if (bits_set || min > 0 || (options & (
#ifdef SUPPORT_JIT
|| (options & (PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE
| PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE)) != 0
PCRE_STUDY_JIT_COMPILE | PCRE_STUDY_JIT_PARTIAL_SOFT_COMPILE |
PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE |
#endif
)
PCRE_STUDY_EXTRA_NEEDED)) != 0)
{
extra = (PUBL(extra) *)(PUBL(malloc))
(sizeof(PUBL(extra)) + sizeof(pcre_study_data));
@@ -1475,7 +1537,8 @@ if (bits_set || min > 0
/* If JIT support was compiled and requested, attempt the JIT compilation.
If no starting bytes were found, and the minimum length is zero, and JIT
compilation fails, abandon the extra block and return NULL. */
compilation fails, abandon the extra block and return NULL, unless
PCRE_STUDY_EXTRA_NEEDED is set. */
#ifdef SUPPORT_JIT
extra->executable_jit = NULL;
@@ -1486,13 +1549,15 @@ if (bits_set || min > 0
if ((options & PCRE_STUDY_JIT_PARTIAL_HARD_COMPILE) != 0)
PRIV(jit_compile)(re, extra, JIT_PARTIAL_HARD_COMPILE);
if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0)
if (study->flags == 0 && (extra->flags & PCRE_EXTRA_EXECUTABLE_JIT) == 0 &&
(options & PCRE_STUDY_EXTRA_NEEDED) == 0)
{
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
pcre_free_study(extra);
#endif
#ifdef COMPILE_PCRE16
#elif defined COMPILE_PCRE16
pcre16_free_study(extra);
#elif defined COMPILE_PCRE32
pcre32_free_study(extra);
#endif
extra = NULL;
}
@@ -1513,12 +1578,15 @@ Argument: a pointer to the pcre[16]_extra block
Returns: nothing
*/
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN void
pcre_free_study(pcre_extra *extra)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN void
pcre16_free_study(pcre16_extra *extra)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN void
pcre32_free_study(pcre32_extra *extra)
#endif
{
if (extra == NULL)

View File

@@ -58,6 +58,12 @@ the definition is next to the definition of the opcodes in pcre_internal.h. */
const pcre_uint8 PRIV(OP_lengths)[] = { OP_LENGTHS };
/* Tables of horizontal and vertical whitespace characters, suitable for
adding to classes. */
const pcre_uint32 PRIV(hspace_list)[] = { HSPACE_LIST };
const pcre_uint32 PRIV(vspace_list)[] = { VSPACE_LIST };
/*************************************************
@@ -68,9 +74,9 @@ const pcre_uint8 PRIV(OP_lengths)[] = { OP_LENGTHS };
character. */
#if (defined SUPPORT_UTF && defined COMPILE_PCRE8) \
|| (defined PCRE_INCLUDED && defined SUPPORT_PCRE16)
|| (defined PCRE_INCLUDED && (defined SUPPORT_PCRE16 || defined SUPPORT_PCRE32))
/* These tables are also required by pcretest in 16 bit mode. */
/* These tables are also required by pcretest in 16- or 32-bit mode. */
const int PRIV(utf8_table1)[] =
{ 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
@@ -92,13 +98,13 @@ const pcre_uint8 PRIV(utf8_table4)[] = {
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
#endif /* (SUPPORT_UTF && COMPILE_PCRE8) || (PCRE_INCLUDED && SUPPORT_PCRE16)*/
#endif /* (SUPPORT_UTF && COMPILE_PCRE8) || (PCRE_INCLUDED && SUPPORT_PCRE[16|32])*/
#ifdef SUPPORT_UTF
/* Table to translate from particular type value to the general value. */
const int PRIV(ucp_gentype)[] = {
const pcre_uint32 PRIV(ucp_gentype)[] = {
ucp_C, ucp_C, ucp_C, ucp_C, ucp_C, /* Cc, Cf, Cn, Co, Cs */
ucp_L, ucp_L, ucp_L, ucp_L, ucp_L, /* Ll, Lu, Lm, Lo, Lt */
ucp_M, ucp_M, ucp_M, /* Mc, Me, Mn */
@@ -109,6 +115,66 @@ const int PRIV(ucp_gentype)[] = {
ucp_Z, ucp_Z, ucp_Z /* Zl, Zp, Zs */
};
/* This table encodes the rules for finding the end of an extended grapheme
cluster. Every code point has a grapheme break property which is one of the
ucp_gbXX values defined in ucp.h. The 2-dimensional table is indexed by the
properties of two adjacent code points. The left property selects a word from
the table, and the right property selects a bit from that word like this:
ucp_gbtable[left-property] & (1 << right-property)
The value is non-zero if a grapheme break is NOT permitted between the relevant
two code points. The breaking rules are as follows:
1. Break at the start and end of text (pretty obviously).
2. Do not break between a CR and LF; otherwise, break before and after
controls.
3. Do not break Hangul syllable sequences, the rules for which are:
L may be followed by L, V, LV or LVT
LV or V may be followed by V or T
LVT or T may be followed by T
4. Do not break before extending characters.
The next two rules are only for extended grapheme clusters (but that's what we
are implementing).
5. Do not break before SpacingMarks.
6. Do not break after Prepend characters.
7. Otherwise, break everywhere.
*/
const pcre_uint32 PRIV(ucp_gbtable[]) = {
(1<<ucp_gbLF), /* 0 CR */
0, /* 1 LF */
0, /* 2 Control */
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark), /* 3 Extend */
(1<<ucp_gbExtend)|(1<<ucp_gbPrepend)| /* 4 Prepend */
(1<<ucp_gbSpacingMark)|(1<<ucp_gbL)|
(1<<ucp_gbV)|(1<<ucp_gbT)|(1<<ucp_gbLV)|
(1<<ucp_gbLVT)|(1<<ucp_gbOther),
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark), /* 5 SpacingMark */
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbL)| /* 6 L */
(1<<ucp_gbL)|(1<<ucp_gbV)|(1<<ucp_gbLV)|(1<<ucp_gbLVT),
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbV)| /* 7 V */
(1<<ucp_gbT),
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbT), /* 8 T */
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbV)| /* 9 LV */
(1<<ucp_gbT),
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark)|(1<<ucp_gbT), /* 10 LVT */
(1<<ucp_gbRegionalIndicator), /* 11 RegionalIndicator */
(1<<ucp_gbExtend)|(1<<ucp_gbSpacingMark) /* 12 Other */
};
#ifdef SUPPORT_JIT
/* This table reverses PRIV(ucp_gentype). We can save the cost
of a memory load. */
@@ -280,6 +346,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */
#define STRING_Xan0 STR_X STR_a STR_n "\0"
#define STRING_Xps0 STR_X STR_p STR_s "\0"
#define STRING_Xsp0 STR_X STR_s STR_p "\0"
#define STRING_Xuc0 STR_X STR_u STR_c "\0"
#define STRING_Xwd0 STR_X STR_w STR_d "\0"
#define STRING_Yi0 STR_Y STR_i "\0"
#define STRING_Z0 STR_Z "\0"
@@ -427,6 +494,7 @@ const char PRIV(utt_names)[] =
STRING_Xan0
STRING_Xps0
STRING_Xsp0
STRING_Xuc0
STRING_Xwd0
STRING_Yi0
STRING_Z0
@@ -574,12 +642,13 @@ const ucp_type_table PRIV(utt)[] = {
{ 1011, PT_ALNUM, 0 },
{ 1015, PT_PXSPACE, 0 },
{ 1019, PT_SPACE, 0 },
{ 1023, PT_WORD, 0 },
{ 1027, PT_SC, ucp_Yi },
{ 1030, PT_GC, ucp_Z },
{ 1032, PT_PC, ucp_Zl },
{ 1035, PT_PC, ucp_Zp },
{ 1038, PT_PC, ucp_Zs }
{ 1023, PT_UCNC, 0 },
{ 1027, PT_WORD, 0 },
{ 1031, PT_SC, ucp_Yi },
{ 1034, PT_GC, ucp_Z },
{ 1036, PT_PC, ucp_Zl },
{ 1039, PT_PC, ucp_Zp },
{ 1042, PT_PC, ucp_Zs }
};
const int PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);

File diff suppressed because it is too large Load Diff

View File

@@ -79,12 +79,15 @@ I could find no way of detecting that a macro is defined as an empty string at
pre-processor time. This hack uses a standard trick for avoiding calling
the STRING macro with an empty argument when doing the test. */
#ifdef COMPILE_PCRE8
#if defined COMPILE_PCRE8
PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
pcre_version(void)
#else
#elif defined COMPILE_PCRE16
PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
pcre16_version(void)
#elif defined COMPILE_PCRE32
PCRE_EXP_DEFN const char * PCRE_CALL_CONVENTION
pcre32_version(void)
#endif
{
return (XSTRING(Z PCRE_PRERELEASE)[1] == 0)?

View File

@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Copyright (c) 1997-2012 University of Cambridge
Copyright (c) 1997-2013 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -92,6 +92,7 @@ PCRE_UTF8_ERR18 Overlong 5-byte sequence (won't ever occur)
PCRE_UTF8_ERR19 Overlong 6-byte sequence (won't ever occur)
PCRE_UTF8_ERR20 Isolated 0x80 byte (not within UTF-8 character)
PCRE_UTF8_ERR21 Byte with the illegal value 0xfe or 0xff
PCRE_UTF8_ERR22 Unused (was non-character)
Arguments:
string points to the string
@@ -116,7 +117,7 @@ if (length < 0)
for (p = string; length-- > 0; p++)
{
register int ab, c, d;
register pcre_uchar ab, c, d;
c = *p;
if (c < 128) continue; /* ASCII character */
@@ -288,9 +289,10 @@ for (p = string; length-- > 0; p++)
}
}
#else /* SUPPORT_UTF */
#else /* Not SUPPORT_UTF */
(void)(string); /* Keep picky compilers happy */
(void)(length);
(void)(erroroffset);
#endif
return PCRE_UTF8_ERR0; /* This indicates success */

View File

@@ -6,7 +6,7 @@
and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Copyright (c) 1997-2012 University of Cambridge
Copyright (c) 1997-2013 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -64,9 +64,9 @@ Returns: TRUE if character matches, else FALSE
*/
BOOL
PRIV(xclass)(int c, const pcre_uchar *data, BOOL utf)
PRIV(xclass)(pcre_uint32 c, const pcre_uchar *data, BOOL utf)
{
int t;
pcre_uchar t;
BOOL negated = (*data & XCL_NOT) != 0;
(void)utf;
@@ -94,7 +94,7 @@ if ((*data++ & XCL_MAP) != 0) data += 32 / sizeof(pcre_uchar);
while ((t = *data++) != XCL_END)
{
int x, y;
pcre_uint32 x, y;
if (t == XCL_SINGLE)
{
#ifdef SUPPORT_UTF
@@ -128,55 +128,120 @@ while ((t = *data++) != XCL_END)
else /* XCL_PROP & XCL_NOTPROP */
{
const ucd_record *prop = GET_UCD(c);
BOOL isprop = t == XCL_PROP;
switch(*data)
{
case PT_ANY:
if (t == XCL_PROP) return !negated;
if (isprop) return !negated;
break;
case PT_LAMP:
if ((prop->chartype == ucp_Lu || prop->chartype == ucp_Ll ||
prop->chartype == ucp_Lt) == (t == XCL_PROP)) return !negated;
prop->chartype == ucp_Lt) == isprop) return !negated;
break;
case PT_GC:
if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == (t == XCL_PROP))
if ((data[1] == PRIV(ucp_gentype)[prop->chartype]) == isprop)
return !negated;
break;
case PT_PC:
if ((data[1] == prop->chartype) == (t == XCL_PROP)) return !negated;
if ((data[1] == prop->chartype) == isprop) return !negated;
break;
case PT_SC:
if ((data[1] == prop->script) == (t == XCL_PROP)) return !negated;
if ((data[1] == prop->script) == isprop) return !negated;
break;
case PT_ALNUM:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (t == XCL_PROP))
PRIV(ucp_gentype)[prop->chartype] == ucp_N) == isprop)
return !negated;
break;
/* Perl space used to exclude VT, but from Perl 5.18 it is included,
which means that Perl space and POSIX space are now identical. PCRE
was changed at release 8.34. */
case PT_SPACE: /* Perl space */
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
c == CHAR_HT || c == CHAR_NL || c == CHAR_FF || c == CHAR_CR)
== (t == XCL_PROP))
return !negated;
break;
case PT_PXSPACE: /* POSIX space */
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z ||
c == CHAR_HT || c == CHAR_NL || c == CHAR_VT ||
c == CHAR_FF || c == CHAR_CR) == (t == XCL_PROP))
return !negated;
switch(c)
{
HSPACE_CASES:
VSPACE_CASES:
if (isprop) return !negated;
break;
default:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == isprop)
return !negated;
break;
}
break;
case PT_WORD:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N || c == CHAR_UNDERSCORE)
== (t == XCL_PROP))
== isprop)
return !negated;
break;
case PT_UCNC:
if (c < 0xa0)
{
if ((c == CHAR_DOLLAR_SIGN || c == CHAR_COMMERCIAL_AT ||
c == CHAR_GRAVE_ACCENT) == isprop)
return !negated;
}
else
{
if ((c < 0xd800 || c > 0xdfff) == isprop)
return !negated;
}
break;
/* The following three properties can occur only in an XCLASS, as there
is no \p or \P coding for them. */
/* Graphic character. Implement this as not Z (space or separator) and
not C (other), except for Cf (format) with a few exceptions. This seems
to be what Perl does. The exceptional characters are:
U+061C Arabic Letter Mark
U+180E Mongolian Vowel Separator
U+2066 - U+2069 Various "isolate"s
*/
case PT_PXGRAPH:
if ((PRIV(ucp_gentype)[prop->chartype] != ucp_Z &&
(PRIV(ucp_gentype)[prop->chartype] != ucp_C ||
(prop->chartype == ucp_Cf &&
c != 0x061c && c != 0x180e && (c < 0x2066 || c > 0x2069))
)) == isprop)
return !negated;
break;
/* Printable character: same as graphic, with the addition of Zs, i.e.
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 &&
c != 0x061c && (c < 0x2066 || c > 0x2069))
)) == isprop)
return !negated;
break;
/* Punctuation: all Unicode punctuation, plus ASCII characters that
Unicode treats as symbols rather than punctuation, for Perl
compatibility (these are $+<=>^`|~). */
case PT_PXPUNCT:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_P ||
(c < 256 && PRIV(ucp_gentype)[prop->chartype] == ucp_S)) == isprop)
return !negated;
break;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -47,6 +47,8 @@
/* #define SLJIT_CONFIG_PPC_32 1 */
/* #define SLJIT_CONFIG_PPC_64 1 */
/* #define SLJIT_CONFIG_MIPS_32 1 */
/* #define SLJIT_CONFIG_SPARC_32 1 */
/* #define SLJIT_CONFIG_TILEGX 1 */
/* #define SLJIT_CONFIG_AUTO 1 */
/* #define SLJIT_CONFIG_UNSUPPORTED 1 */

View File

@@ -33,18 +33,23 @@
Feature detection (boolean) macros:
SLJIT_32BIT_ARCHITECTURE : 32 bit architecture
SLJIT_64BIT_ARCHITECTURE : 64 bit architecture
SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_w/sljit_uw array by index
SLJIT_FLOAT_SHIFT : the shift required to apply when accessing a double array by index
SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index
SLJIT_DOUBLE_SHIFT : the shift required to apply when accessing a double array by index
SLJIT_LITTLE_ENDIAN : little endian architecture
SLJIT_BIG_ENDIAN : big endian architecture
SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)
SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET() for more information
SLJIT_RETURN_ADDRESS_OFFSET : a return instruction always adds this offset to the return address
Types and useful macros:
sljit_b, sljit_ub : signed and unsigned 8 bit byte
sljit_h, sljit_uh : signed and unsigned 16 bit half-word (short) type
sljit_i, sljit_ui : signed and unsigned 32 bit integer type
sljit_w, sljit_uw : signed and unsigned machine word, enough to store a pointer (same as intptr_t)
sljit_sb, sljit_ub : signed and unsigned 8 bit byte
sljit_sh, sljit_uh : signed and unsigned 16 bit half-word (short) type
sljit_si, sljit_ui : signed and unsigned 32 bit integer type
sljit_sw, sljit_uw : signed and unsigned machine word, enough to store a pointer
sljit_p : unsgined pointer value (usually the same as sljit_uw, but
some 64 bit ABIs may use 32 bit pointers)
sljit_s : single precision floating point value
sljit_d : double precision floating point value
SLJIT_CALL : C calling convention define for both calling JIT form C and C callbacks for JIT
SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (compiler independent helper)
*/
@@ -57,6 +62,8 @@
|| (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_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
|| (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \
|| (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
|| (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED))
#error "An architecture must be selected"
@@ -70,7 +77,9 @@
+ (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \
+ (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
+ (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
+ (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \
+ (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
+ (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
+ (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \
+ (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2
#error "Multiple architectures are selected"
@@ -93,12 +102,16 @@
#else
#define SLJIT_CONFIG_ARM_V5 1
#endif
#elif defined(__ppc64__) || defined(__powerpc64__)
#elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_PPC64) || (defined(_POWER) && defined(__64BIT__))
#define SLJIT_CONFIG_PPC_64 1
#elif defined(__ppc__) || defined(__powerpc__)
#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__)
#elif defined(__mips__) && !defined(_LP64)
#define SLJIT_CONFIG_MIPS_32 1
#elif defined(__sparc__) || defined(__sparc)
#define SLJIT_CONFIG_SPARC_32 1
#elif defined(__tilegx__)
#define SLJIT_CONFIG_TILEGX 1
#else
/* Unsupported architecture */
#define SLJIT_CONFIG_UNSUPPORTED 1
@@ -164,9 +177,13 @@
#endif /* !defined(SLJIT_LIKELY) && !defined(SLJIT_UNLIKELY) */
#ifndef SLJIT_INLINE
/* Inline functions. */
/* Inline functions. Some old compilers do not support them. */
#if defined(__SUNPRO_C) && __SUNPRO_C <= 0x510
#define SLJIT_INLINE
#else
#define SLJIT_INLINE __inline
#endif
#endif /* !SLJIT_INLINE */
#ifndef SLJIT_CONST
/* Const variables. */
@@ -208,12 +225,25 @@
#define SLJIT_CACHE_FLUSH(from, to) \
sys_icache_invalidate((char*)(from), (char*)(to) - (char*)(from))
#elif defined __ANDROID__
/* Android lacks __clear_cache; instead, cacheflush should be used. */
#define SLJIT_CACHE_FLUSH(from, to) \
cacheflush((long)(from), (long)(to), 0)
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
/* The __clear_cache() implementation of GCC is a dummy function on PowerPC. */
#define SLJIT_CACHE_FLUSH(from, to) \
ppc_cache_flush((from), (to))
#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */
#define SLJIT_CACHE_FLUSH(from, to) \
sparc_cache_flush((from), (to))
#else
/* Calls __ARM_NR_cacheflush on ARM-Linux. */
@@ -226,15 +256,15 @@
/* 8 bit byte type. */
typedef unsigned char sljit_ub;
typedef signed char sljit_b;
typedef signed char sljit_sb;
/* 16 bit half-word type. */
typedef unsigned short int sljit_uh;
typedef signed short int sljit_h;
typedef signed short int sljit_sh;
/* 32 bit integer type. */
typedef unsigned int sljit_ui;
typedef signed int sljit_i;
typedef signed int sljit_si;
/* Machine word type. Can encapsulate a pointer.
32 bit for 32 bit machines.
@@ -243,26 +273,37 @@ typedef signed int sljit_i;
/* Just to have something. */
#define SLJIT_WORD_SHIFT 0
typedef unsigned long int sljit_uw;
typedef long int sljit_w;
#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
typedef long int sljit_sw;
#elif !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \
&& !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
&& !(defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
#define SLJIT_32BIT_ARCHITECTURE 1
#define SLJIT_WORD_SHIFT 2
typedef unsigned int sljit_uw;
typedef int sljit_w;
typedef int sljit_sw;
#else
#define SLJIT_64BIT_ARCHITECTURE 1
#define SLJIT_WORD_SHIFT 3
#ifdef _WIN32
typedef unsigned __int64 sljit_uw;
typedef __int64 sljit_w;
typedef __int64 sljit_sw;
#else
typedef unsigned long int sljit_uw;
typedef long int sljit_w;
typedef long int sljit_sw;
#endif
#endif
/* Double precision. */
#define SLJIT_FLOAT_SHIFT 3
typedef sljit_uw sljit_p;
/* Floating point types. */
typedef float sljit_s;
typedef double sljit_d;
/* Shift for pointer sized data. */
#define SLJIT_POINTER_SHIFT SLJIT_WORD_SHIFT
/* Shift for double precision sized data. */
#define SLJIT_DOUBLE_SHIFT 3
#ifndef SLJIT_W
@@ -280,7 +321,7 @@ typedef long int sljit_w;
/* ABI (Application Binary Interface) types. */
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
#if defined(__GNUC__)
#if defined(__GNUC__) && !defined(__APPLE__)
#if ( __GNUC__ > 3 ) || ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 4 ) )
#define SLJIT_CALL __attribute__ ((fastcall))
@@ -289,20 +330,24 @@ typedef long int sljit_w;
#define SLJIT_CALL
#endif
#elif defined(_WIN32)
#elif defined(_MSC_VER)
#ifdef __BORLANDC__
#define SLJIT_CALL __msfastcall
#else /* __BORLANDC__ */
#define SLJIT_CALL __fastcall
#endif /* __BORLANDC__ */
#define SLJIT_X86_32_FASTCALL 1
#else /* defined(_WIN32) */
#define SLJIT_CALL __stdcall
#elif defined(__BORLANDC__)
#define SLJIT_CALL __msfastcall
#define SLJIT_X86_32_FASTCALL 1
#else /* Unknown compiler. */
/* The cdecl attribute is the default. */
#define SLJIT_CALL
#endif
#else /* Other architectures. */
#else /* Non x86-32 architectures. */
#define SLJIT_CALL
@@ -313,7 +358,9 @@ typedef long int sljit_w;
#if !defined(SLJIT_BIG_ENDIAN) && !defined(SLJIT_LITTLE_ENDIAN)
/* These macros are useful for the application. */
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \
|| (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
#define SLJIT_BIG_ENDIAN 1
#elif (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
@@ -339,11 +386,21 @@ typedef long int sljit_w;
#error "Exactly one endianness must be selected"
#endif
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
/* It seems ppc64 compilers use an indirect addressing for functions.
It makes things really complicated. */
#ifndef SLJIT_INDIRECT_CALL
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32 && defined _AIX)
/* It seems certain ppc compilers use an indirect addressing for functions
which makes things complicated. */
#define SLJIT_INDIRECT_CALL 1
#endif
#endif /* SLJIT_INDIRECT_CALL */
#ifndef SLJIT_RETURN_ADDRESS_OFFSET
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
#define SLJIT_RETURN_ADDRESS_OFFSET 8
#else
#define SLJIT_RETURN_ADDRESS_OFFSET 0
#endif
#endif /* SLJIT_RETURN_ADDRESS_OFFSET */
#ifndef SLJIT_SSE2
@@ -377,21 +434,33 @@ typedef long int sljit_w;
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size);
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void);
#define SLJIT_MALLOC_EXEC(size) sljit_malloc_exec(size)
#define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr)
#endif
#if (defined SLJIT_DEBUG && SLJIT_DEBUG) || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
#include <stdio.h>
#endif
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
/* Feel free to redefine these two macros. */
#ifndef SLJIT_ASSERT
#if !defined(SLJIT_ASSERT) || !defined(SLJIT_ASSERT_STOP)
/* SLJIT_HALT_PROCESS must halt the process. */
#ifndef SLJIT_HALT_PROCESS
#include <stdlib.h>
#define SLJIT_HALT_PROCESS() \
*((int*)0) = 0
abort();
#endif /* !SLJIT_HALT_PROCESS */
#include <stdio.h>
#endif /* !SLJIT_ASSERT || !SLJIT_ASSERT_STOP */
/* Feel free to redefine these two macros. */
#ifndef SLJIT_ASSERT
#define SLJIT_ASSERT(x) \
do { \
@@ -415,6 +484,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr);
#else /* (defined SLJIT_DEBUG && SLJIT_DEBUG) */
/* Forcing empty, but valid statements. */
#undef SLJIT_ASSERT
#undef SLJIT_ASSERT_STOP

View File

@@ -52,7 +52,7 @@
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.
@@ -83,7 +83,7 @@
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
{
return VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
}
static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
@@ -94,11 +94,20 @@ static SLJIT_INLINE void free_chunk(void* chunk, sljit_uw size)
#else
#include <sys/mman.h>
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
{
void* retval = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
void* retval;
#ifdef MAP_ANON
retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
#else
if (dev_zero < 0) {
if (open_dev_zero())
return NULL;
}
retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, dev_zero, 0);
#endif
return (retval != MAP_FAILED) ? retval : NULL;
}
@@ -202,7 +211,10 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK;
header = (struct block_header*)alloc_chunk(chunk_size);
PTR_FAIL_IF(!header);
if (!header) {
allocator_release_lock();
return NULL;
}
chunk_size -= sizeof(struct block_header);
total_size += chunk_size;
@@ -237,14 +249,14 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
struct free_block* free_block;
allocator_grab_lock();
header = AS_BLOCK_HEADER(ptr, -(sljit_w)sizeof(struct block_header));
header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header));
allocated_size -= header->size;
/* 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_w)header->prev_size);
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);
@@ -275,3 +287,26 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr)
allocator_release_lock();
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
{
struct free_block* free_block;
struct free_block* next_free_block;
allocator_grab_lock();
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 + sizeof(struct block_header));
}
free_block = next_free_block;
}
SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks));
allocator_release_lock();
}

File diff suppressed because it is too large Load Diff

View File

@@ -34,12 +34,19 @@
Short description
Advantages:
- The execution can be continued from any LIR instruction
In other words, jump into and out of the code is safe
- Both target of (conditional) jump and call instructions
and constants can be dynamically modified during runtime
- The execution can be continued from any LIR instruction. In other
words, it is possible to jump to any label from anywhere, even from
a code fragment, which is compiled later, if both compiled code
shares the same context. See sljit_emit_enter for more details
- Supports self modifying code: target of (conditional) jump and call
instructions and some constant values can be dynamically modified
during runtime
- although it is not suggested to do it frequently
- very effective to cache an important value once
- can be used for inline caching: save an important value once
in the instruction stream
- since this feature limits the optimization possibilities, a
special flag must be passed at compile time when these
instructions are emitted
- A fixed stack space can be allocated for local variables
- The compiler is thread-safe
- The compiler is highly configurable through preprocessor macros.
@@ -47,19 +54,19 @@
threaded applications), and you can use your own system functions
(including memory allocators). See sljitConfig.h
Disadvantages:
- No automatic register allocation, and temporary results are
not stored on the stack. (hence the name comes)
- Limited number of registers (only 6+4 integer registers, max 3+2
temporary, max 3+2 saved and 4 floating point registers)
scratch, max 3+2 saved and 6 floating point registers)
In practice:
- This approach is very effective for interpreters
- One of the saved registers typically points to a stack interface
- It can jump to any exception handler anytime (even for another
function. It is safe for SLJIT.)
- Fast paths can be modified during runtime reflecting the changes
- It can jump to any exception handler anytime (even if it belongs
to another function)
- Hot paths can be modified during runtime reflecting the changes
of the fastest execution path of the dynamic language
- SLJIT supports complex memory addressing modes
- mainly position independent code
- Optimizations (perhaps later)
- Only for basic blocks (when no labels inserted between LIR instructions)
- mainly position and context independent code (except some cases)
For valgrind users:
- pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code"
@@ -70,7 +77,7 @@
#endif
/* The following header file defines useful macros for fine tuning
sljit based code generators. They are listed in the begining
sljit based code generators. They are listed in the beginning
of sljitConfigInternal.h */
#include "sjconfi.h"
@@ -99,12 +106,14 @@ of sljitConfigInternal.h */
#define SLJIT_UNUSED 0
/* Temporary (scratch) registers may not preserve their values across function calls. */
#define SLJIT_TEMPORARY_REG1 1
#define SLJIT_TEMPORARY_REG2 2
#define SLJIT_TEMPORARY_REG3 3
/* Note: Extra Registers cannot be used for memory addressing. */
/* Note: on x86-32, these registers are emulated (using stack loads & stores). */
/* Scratch (temporary) registers whose may not preserve their values
across function calls. */
#define SLJIT_SCRATCH_REG1 1
#define SLJIT_SCRATCH_REG2 2
#define SLJIT_SCRATCH_REG3 3
/* Note: extra registers cannot be used for memory addressing. */
/* Note: on x86-32, these registers are emulated (using stack
loads & stores). */
#define SLJIT_TEMPORARY_EREG1 4
#define SLJIT_TEMPORARY_EREG2 5
@@ -112,15 +121,17 @@ of sljitConfigInternal.h */
#define SLJIT_SAVED_REG1 6
#define SLJIT_SAVED_REG2 7
#define SLJIT_SAVED_REG3 8
/* Note: Extra Registers cannot be used for memory addressing. */
/* Note: on x86-32, these registers are emulated (using stack loads & stores). */
/* Note: extra registers cannot be used for memory addressing. */
/* Note: on x86-32, these registers are emulated (using stack
loads & stores). */
#define SLJIT_SAVED_EREG1 9
#define SLJIT_SAVED_EREG2 10
/* Read-only register (cannot be the destination of an operation).
Only SLJIT_MEM1(SLJIT_LOCALS_REG) addressing mode is allowed since
several ABIs has certain limitations about the stack layout. However
sljit_get_local_base() can be used to obtain the offset of a value. */
sljit_get_local_base() can be used to obtain the offset of a value
on the stack. */
#define SLJIT_LOCALS_REG 11
/* Number of registers. */
@@ -130,15 +141,15 @@ of sljitConfigInternal.h */
/* Return with machine word. */
#define SLJIT_RETURN_REG SLJIT_TEMPORARY_REG1
#define SLJIT_RETURN_REG SLJIT_SCRATCH_REG1
/* x86 prefers specific registers for special purposes. In case of shift
by register it supports only SLJIT_TEMPORARY_REG3 for shift argument
by register it supports only SLJIT_SCRATCH_REG3 for shift argument
(which is the src2 argument of sljit_emit_op2). If another register is
used, sljit must exchange data between registers which cause a minor
slowdown. Other architectures has no such limitation. */
#define SLJIT_PREF_SHIFT_REG SLJIT_TEMPORARY_REG3
#define SLJIT_PREF_SHIFT_REG SLJIT_SCRATCH_REG3
/* --------------------------------------------------------------------- */
/* Floating point registers */
@@ -147,12 +158,17 @@ of sljitConfigInternal.h */
/* Note: SLJIT_UNUSED as destination is not valid for floating point
operations, since they cannot be used for setting flags. */
/* Floating point operations are performed on double precision values. */
/* Floating point operations are performed on double or
single precision values. */
#define SLJIT_FLOAT_REG1 1
#define SLJIT_FLOAT_REG2 2
#define SLJIT_FLOAT_REG3 3
#define SLJIT_FLOAT_REG4 4
#define SLJIT_FLOAT_REG1 1
#define SLJIT_FLOAT_REG2 2
#define SLJIT_FLOAT_REG3 3
#define SLJIT_FLOAT_REG4 4
#define SLJIT_FLOAT_REG5 5
#define SLJIT_FLOAT_REG6 6
#define SLJIT_NO_FLOAT_REGISTERS 6
/* --------------------------------------------------------------------- */
/* Main structures and functions */
@@ -161,6 +177,7 @@ of sljitConfigInternal.h */
struct sljit_memory_fragment {
struct sljit_memory_fragment *next;
sljit_uw used_size;
/* Must be aligned to sljit_sw. */
sljit_ub memory[1];
};
@@ -174,7 +191,7 @@ struct sljit_label {
struct sljit_jump {
struct sljit_jump *next;
sljit_uw addr;
sljit_w flags;
sljit_sw flags;
union {
sljit_uw target;
struct sljit_label* label;
@@ -187,7 +204,7 @@ struct sljit_const {
};
struct sljit_compiler {
int error;
sljit_si error;
struct sljit_label *labels;
struct sljit_jump *jumps;
@@ -200,29 +217,29 @@ struct sljit_compiler {
struct sljit_memory_fragment *abuf;
/* Used local registers. */
int temporaries;
sljit_si scratches;
/* Used saved registers. */
int saveds;
sljit_si saveds;
/* Local stack size. */
int local_size;
sljit_si local_size;
/* Code size. */
sljit_uw size;
/* For statistical purposes. */
sljit_uw executable_size;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
int args;
int locals_offset;
int temporaries_start;
int saveds_start;
sljit_si args;
sljit_si locals_offset;
sljit_si scratches_start;
sljit_si saveds_start;
#endif
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
int mode32;
sljit_si mode32;
#endif
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
int flags_saved;
sljit_si flags_saved;
#endif
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
@@ -239,25 +256,36 @@ struct sljit_compiler {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
/* Temporary fields. */
sljit_uw shift_imm;
int cache_arg;
sljit_w cache_argw;
sljit_si cache_arg;
sljit_sw cache_argw;
#endif
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
int cache_arg;
sljit_w cache_argw;
sljit_si cache_arg;
sljit_sw cache_argw;
#endif
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
sljit_w imm;
int cache_arg;
sljit_w cache_argw;
sljit_sw imm;
sljit_si cache_arg;
sljit_sw cache_argw;
#endif
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
int delay_slot;
int cache_arg;
sljit_w cache_argw;
sljit_si delay_slot;
sljit_si cache_arg;
sljit_sw cache_argw;
#endif
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
sljit_si delay_slot;
sljit_si cache_arg;
sljit_sw cache_argw;
#endif
#if (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX)
sljit_si cache_arg;
sljit_sw cache_argw;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
@@ -266,11 +294,11 @@ struct sljit_compiler {
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
/* Local size passed to the functions. */
int logical_local_size;
sljit_si logical_local_size;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
int skip_checks;
sljit_si skip_checks;
#endif
};
@@ -281,22 +309,29 @@ struct sljit_compiler {
/* Creates an sljit compiler.
Returns NULL if failed. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void);
/* Free everything except the codes. */
/* Free everything except the compiled machine code. */
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler);
static SLJIT_INLINE int sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; }
/* Returns the current error code. If an error is occurred, future sljit
calls which uses the same compiler argument returns early with the same
error code. Thus there is no need for checking the error after every
call, it is enough to do it before the code is compiled. Removing
these checks increases the performance of the compiling process. */
static SLJIT_INLINE sljit_si sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; }
/*
Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit,
and <= 128 bytes on 64 bit architectures. The memory area is owned by the compiler,
and freed by sljit_free_compiler. The returned pointer is sizeof(sljit_w) aligned.
Excellent for allocating small blocks during the compiling, and no need to worry
about freeing them. The size is enough to contain at most 16 pointers.
If the size is outside of the range, the function will return with NULL,
but this return value does not indicate that there is no more memory (does
not set the compiler to out-of-memory status).
and <= 128 bytes on 64 bit architectures. The memory area is owned by the
compiler, and freed by sljit_free_compiler. The returned pointer is
sizeof(sljit_sw) aligned. Excellent for allocating small blocks during
the compiling, and no need to worry about freeing them. The size is
enough to contain at most 16 pointers. If the size is outside of the range,
the function will return with NULL. However, this return value does not
indicate that there is no more memory (does not set the current error code
of the compiler to out-of-memory status).
*/
SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, int size);
SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compiler, sljit_si size);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
/* Passing NULL disables verbose. */
@@ -307,15 +342,17 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code);
/*
After the code generation we can retrieve the allocated executable memory size,
although this area may not be fully filled with instructions depending on some
optimizations. This function is useful only for statistical purposes.
After the machine code generation is finished we can retrieve the allocated
executable memory size, although this area may not be fully filled with
instructions depending on some optimizations. This function is useful only
for statistical purposes.
Before a successful code generation, this function returns with 0.
*/
static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler *compiler) { return compiler->executable_size; }
/* Instruction generation. Returns with error code. */
/* Instruction generation. Returns with any error code. If there is no
error, they return with SLJIT_SUCCESS. */
/*
The executable code is basically a function call from the viewpoint of
@@ -326,8 +363,8 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
for the executable code and moves function arguments to the saved
registers. The number of arguments are specified in the "args"
parameter and the first argument goes to SLJIT_SAVED_REG1, the second
goes to SLJIT_SAVED_REG2 and so on. The number of temporary and
saved registers are passed in "temporaries" and "saveds" arguments
goes to SLJIT_SAVED_REG2 and so on. The number of scratch and
saved registers are passed in "scratches" and "saveds" arguments
respectively. Since the saved registers contains the arguments,
"args" must be less or equal than "saveds". The sljit_emit_enter
is also capable of allocating a stack space for local variables. The
@@ -338,54 +375,53 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler
SLJIT_LOCALS_REG + local_size (exclusive) can be modified freely
until the function returns. The stack space is uninitialized.
Note: every call of sljit_emit_enter and sljit_set_context overwrites
the previous context. */
Note: every call of sljit_emit_enter and sljit_set_context
overwrites the previous context. */
#define SLJIT_MAX_LOCAL_SIZE 65536
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler,
int args, int temporaries, int saveds, int local_size);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size);
/* The machine code has a context (which contains the local stack space size,
number of used registers, etc.) which initialized by sljit_emit_enter. Several
functions (like sljit_emit_return) requres this context to be able to generate
the appropriate code. However, some code fragments (like inline cache) may have
no normal entry point so their context is unknown for the compiler. Using the
function below we can specify thir context.
function below we can specify their context.
Note: every call of sljit_emit_enter and sljit_set_context overwrites
the previous context. */
/* Note: multiple calls of this function overwrites the previous call. */
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler,
int args, int temporaries, int saveds, int local_size);
sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size);
/* Return from machine code. The op argument can be SLJIT_UNUSED which means the
function does not return with anything or any opcode between SLJIT_MOV and
SLJIT_MOV_SI (see sljit_emit_op1). As for src and srcw they must be 0 if op
SLJIT_MOV_P (see sljit_emit_op1). As for src and srcw they must be 0 if op
is SLJIT_UNUSED, otherwise see below the description about source and
destination arguments. */
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op,
int src, sljit_w srcw);
/* Really fast calling method for utility functions inside sljit (see SLJIT_FAST_CALL).
All registers and even the stack frame is passed to the callee. The return address is
preserved in dst/dstw by sljit_emit_fast_enter, and sljit_emit_fast_return can
use this as a return value later. */
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op,
sljit_si src, sljit_sw srcw);
/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine instructions
are needed. Excellent for small uility functions, where saving registers and setting up
a new stack frame would cost too much performance. However, it is still possible to return
to the address of the caller (or anywhere else). */
/* Fast calling mechanism for utility functions (see SLJIT_FAST_CALL). All registers and
even the stack frame is passed to the callee. The return address is preserved in
dst/dstw by sljit_emit_fast_enter (the type of the value stored by this function
is sljit_p), and sljit_emit_fast_return can use this as a return value later. */
/* Note: only for sljit specific, non ABI compilant calls. Fast, since only a few machine
instructions are needed. Excellent for small uility functions, where saving registers
and setting up a new stack frame would cost too much performance. However, it is still
possible to return to the address of the caller (or anywhere else). */
/* Note: flags are not changed (unlike sljit_emit_enter / sljit_emit_return). */
/* Note: although sljit_emit_fast_return could be replaced by an ijump, it is not suggested,
since many architectures do clever branch prediction on call / return instruction pairs. */
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw);
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw);
/*
Source and destination values for arithmetical instructions
@@ -394,7 +430,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
[imm] - absolute immediate memory address
[reg+imm] - indirect memory address
[reg+(reg<<imm)] - indirect indexed memory address (shift must be between 0 and 3)
useful for (byte, half, int, sljit_w) array access
useful for (byte, half, int, sljit_sw) array access
(fully supported by both x86 and ARM architectures, and cheap operation on others)
*/
@@ -404,24 +440,40 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
length | alignment
---------+-----------
byte | 1 byte (not aligned)
half | 2 byte (real_address & 0x1 == 0)
int | 4 byte (real_address & 0x3 == 0)
sljit_w | 4 byte if SLJIT_32BIT_ARCHITECTURE is defined and its value is 1
byte | 1 byte (any physical_address is accepted)
half | 2 byte (physical_address & 0x1 == 0)
int | 4 byte (physical_address & 0x3 == 0)
word | 4 byte if SLJIT_32BIT_ARCHITECTURE is defined and its value is 1
| 8 byte if SLJIT_64BIT_ARCHITECTURE is defined and its value is 1
pointer | size of sljit_p type (4 byte on 32 bit machines, 4 or 8 byte
| on 64 bit machines)
Note: different architectures have different addressing limitations
Thus sljit may generate several instructions for other addressing modes
x86: all addressing modes supported, but write-back is not supported
(requires an extra instruction). On x86-64 only 32 bit signed
integers are supported by the architecture.
arm: [reg+imm] supported for small immediates (-4095 <= imm <= 4095
or -255 <= imm <= 255 for loading signed bytes, any halfs or doubles)
[reg+(reg<<imm)] are supported or requires only two instructions
Write back is limited to small immediates on thumb2
ppc: [reg+imm], -65535 <= imm <= 65535. 64 bit moves requires immediates
divisible by 4. [reg+reg] supported, write-back supported
[reg+(reg<<imm)] (imm != 0) is cheap (requires two instructions)
Note: Different architectures have different addressing limitations.
A single instruction is enough for the following addressing
modes. Other adrressing modes are emulated by instruction
sequences. This information could help to improve those code
generators which focuses only a few architectures.
x86: [reg+imm], -2^32+1 <= imm <= 2^32-1 (full address space on x86-32)
[reg+(reg<<imm)] is supported
[imm], -2^32+1 <= imm <= 2^32-1 is supported
Write-back is not supported
arm: [reg+imm], -4095 <= imm <= 4095 or -255 <= imm <= 255 for signed
bytes, any halfs or floating point values)
[reg+(reg<<imm)] is supported
Write-back is supported
arm-t2: [reg+imm], -255 <= imm <= 4095
[reg+(reg<<imm)] is supported
Write back is supported only for [reg+imm], where -255 <= imm <= 255
ppc: [reg+imm], -65536 <= imm <= 65535. 64 bit loads/stores and 32 bit
signed load on 64 bit requires immediates divisible by 4.
[reg+imm] is not supported for signed 8 bit values.
[reg+reg] is supported
Write-back is supported except for one instruction: 32 bit signed
load with [reg+imm] addressing mode on 64 bit.
mips: [reg+imm], -65536 <= imm <= 65535
sparc: [reg+imm], -4096 <= imm <= 4095
[reg+reg] is supported
*/
/* Register output: simply the name of the register.
@@ -433,12 +485,31 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
#define SLJIT_IMM 0x200
/* Set 32 bit operation mode (I) on 64 bit CPUs. The flag is totally ignored on
32 bit CPUs. The arithmetic instruction uses only the lower 32 bit of the
input register(s), and set the flags according to the 32 bit result. If the
destination is a register, the higher 32 bit of the result is undefined.
The addressing modes (SLJIT_MEM1/SLJIT_MEM2 macros) are unaffected by this flag. */
32 bit CPUs. If this flag is set for an arithmetic operation, it uses only the
lower 32 bit of the input register(s), and set the CPU status flags according
to the 32 bit result. The higher 32 bits are undefined for both the input and
output. However, the CPU might not ignore those higher 32 bits, like MIPS, which
expects it to be the sign extension of the lower 32 bit. All 32 bit operations
are undefined, if this condition is not fulfilled. Therefore, when SLJIT_INT_OP
is specified, all register arguments must be the result of other operations with
the same SLJIT_INT_OP flag. In other words, although a register can hold either
a 64 or 32 bit value, these values cannot be mixed. The only exceptions are
SLJIT_IMOV and SLJIT_IMOVU (SLJIT_MOV_SI/SLJIT_MOV_UI/SLJIT_MOVU_SI/SLJIT_MOV_UI
with SLJIT_INT_OP flag) which can convert any source argument to SLJIT_INT_OP
compatible result. This conversion might be unnecessary on some CPUs like x86-64,
since the upper 32 bit is always ignored. In this case SLJIT is clever enough
to not generate any instructions if the source and destination operands are the
same registers. Affects sljit_emit_op0, sljit_emit_op1 and sljit_emit_op2. */
#define SLJIT_INT_OP 0x100
/* Single precision mode (SP). This flag is similar to SLJIT_INT_OP, just
it applies to floating point registers (it is even the same bit). When
this flag is passed, the CPU performs single precision floating point
operations. Similar to SLJIT_INT_OP, all register arguments must be the
result of other floating point operations with this flag. Affects
sljit_emit_fop1, sljit_emit_fop2 and sljit_emit_fcmp. */
#define SLJIT_SINGLE_OP 0x100
/* Common CPU status flags for all architectures (x86, ARM, PPC)
- carry flag
- overflow flag
@@ -480,124 +551,169 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
Note: may or may not cause an extra cycle wait
it can even decrease the runtime in a few cases. */
#define SLJIT_NOP 1
/* Flags: may destroy flags
Unsigned multiplication of SLJIT_TEMPORARY_REG1 and SLJIT_TEMPORARY_REG2.
Result goes to SLJIT_TEMPORARY_REG2:SLJIT_TEMPORARY_REG1 (high:low) word */
/* Flags: - (may destroy flags)
Unsigned multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2.
Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */
#define SLJIT_UMUL 2
/* Flags: may destroy flags
Signed multiplication of SLJIT_TEMPORARY_REG1 and SLJIT_TEMPORARY_REG2.
Result goes to SLJIT_TEMPORARY_REG2:SLJIT_TEMPORARY_REG1 (high:low) word */
/* Flags: - (may destroy flags)
Signed multiplication of SLJIT_SCRATCH_REG1 and SLJIT_SCRATCH_REG2.
Result goes to SLJIT_SCRATCH_REG2:SLJIT_SCRATCH_REG1 (high:low) word */
#define SLJIT_SMUL 3
/* Flags: I | may destroy flags
Unsigned divide of the value in SLJIT_TEMPORARY_REG1 by the value in SLJIT_TEMPORARY_REG2.
The result is placed in SLJIT_TEMPORARY_REG1 and the remainder goes to SLJIT_TEMPORARY_REG2.
Note: if SLJIT_TEMPORARY_REG2 contains 0, the behaviour is undefined. */
/* Flags: I - (may destroy flags)
Unsigned divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2.
The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2.
Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */
#define SLJIT_UDIV 4
/* Flags: I | may destroy flags
Signed divide of the value in SLJIT_TEMPORARY_REG1 by the value in SLJIT_TEMPORARY_REG2.
The result is placed in SLJIT_TEMPORARY_REG1 and the remainder goes to SLJIT_TEMPORARY_REG2.
Note: if SLJIT_TEMPORARY_REG2 contains 0, the behaviour is undefined. */
#define SLJIT_IUDIV (SLJIT_UDIV | SLJIT_INT_OP)
/* Flags: I - (may destroy flags)
Signed divide of the value in SLJIT_SCRATCH_REG1 by the value in SLJIT_SCRATCH_REG2.
The result is placed in SLJIT_SCRATCH_REG1 and the remainder goes to SLJIT_SCRATCH_REG2.
Note: if SLJIT_SCRATCH_REG2 contains 0, the behaviour is undefined. */
#define SLJIT_SDIV 5
#define SLJIT_ISDIV (SLJIT_SDIV | SLJIT_INT_OP)
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op0(struct sljit_compiler *compiler, int op);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op);
/* Notes for MOV instructions:
U = Mov with update (post form). If source or destination defined as SLJIT_MEM1(r1)
or SLJIT_MEM2(r1, r2), r1 is increased by the sum of r2 and the constant argument
UB = unsigned byte (8 bit)
SB = signed byte (8 bit)
UH = unsgined half (16 bit)
SH = unsgined half (16 bit) */
UH = unsigned half (16 bit)
SH = signed half (16 bit)
UI = unsigned int (32 bit)
SI = signed int (32 bit)
P = pointer (sljit_p) size */
/* Flags: - (never set any flags) */
#define SLJIT_MOV 6
/* Flags: - (never set any flags) */
/* Flags: I - (never set any flags) */
#define SLJIT_MOV_UB 7
/* Flags: - (never set any flags) */
#define SLJIT_IMOV_UB (SLJIT_MOV_UB | SLJIT_INT_OP)
/* Flags: I - (never set any flags) */
#define SLJIT_MOV_SB 8
/* Flags: - (never set any flags) */
#define SLJIT_IMOV_SB (SLJIT_MOV_SB | SLJIT_INT_OP)
/* Flags: I - (never set any flags) */
#define SLJIT_MOV_UH 9
/* Flags: - (never set any flags) */
#define SLJIT_IMOV_UH (SLJIT_MOV_UH | SLJIT_INT_OP)
/* Flags: I - (never set any flags) */
#define SLJIT_MOV_SH 10
/* Flags: - (never set any flags) */
#define SLJIT_IMOV_SH (SLJIT_MOV_SH | SLJIT_INT_OP)
/* Flags: I - (never set any flags)
Note: see SLJIT_INT_OP for further details. */
#define SLJIT_MOV_UI 11
/* Flags: - (never set any flags) */
/* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */
/* Flags: I - (never set any flags)
Note: see SLJIT_INT_OP for further details. */
#define SLJIT_MOV_SI 12
#define SLJIT_IMOV (SLJIT_MOV_SI | SLJIT_INT_OP)
/* Flags: - (never set any flags) */
#define SLJIT_MOVU 13
#define SLJIT_MOV_P 13
/* Flags: - (never set any flags) */
#define SLJIT_MOVU_UB 14
#define SLJIT_MOVU 14
/* Flags: I - (never set any flags) */
#define SLJIT_MOVU_UB 15
#define SLJIT_IMOVU_UB (SLJIT_MOVU_UB | SLJIT_INT_OP)
/* Flags: I - (never set any flags) */
#define SLJIT_MOVU_SB 16
#define SLJIT_IMOVU_SB (SLJIT_MOVU_SB | SLJIT_INT_OP)
/* Flags: I - (never set any flags) */
#define SLJIT_MOVU_UH 17
#define SLJIT_IMOVU_UH (SLJIT_MOVU_UH | SLJIT_INT_OP)
/* Flags: I - (never set any flags) */
#define SLJIT_MOVU_SH 18
#define SLJIT_IMOVU_SH (SLJIT_MOVU_SH | SLJIT_INT_OP)
/* Flags: I - (never set any flags)
Note: see SLJIT_INT_OP for further details. */
#define SLJIT_MOVU_UI 19
/* No SLJIT_INT_OP form, since it the same as SLJIT_IMOVU. */
/* Flags: I - (never set any flags)
Note: see SLJIT_INT_OP for further details. */
#define SLJIT_MOVU_SI 20
#define SLJIT_IMOVU (SLJIT_MOVU_SI | SLJIT_INT_OP)
/* Flags: - (never set any flags) */
#define SLJIT_MOVU_SB 15
/* Flags: - (never set any flags) */
#define SLJIT_MOVU_UH 16
/* Flags: - (never set any flags) */
#define SLJIT_MOVU_SH 17
/* Flags: - (never set any flags) */
#define SLJIT_MOVU_UI 18
/* Flags: - (never set any flags) */
#define SLJIT_MOVU_SI 19
#define SLJIT_MOVU_P 21
/* Flags: I | E | K */
#define SLJIT_NOT 20
#define SLJIT_NOT 22
#define SLJIT_INOT (SLJIT_NOT | SLJIT_INT_OP)
/* Flags: I | E | O | K */
#define SLJIT_NEG 21
#define SLJIT_NEG 23
#define SLJIT_INEG (SLJIT_NEG | SLJIT_INT_OP)
/* Count leading zeroes
Flags: I | E | K */
#define SLJIT_CLZ 22
Flags: I | E | K
Important note! Sparc 32 does not support K flag, since
the required popc instruction is introduced only in sparc 64. */
#define SLJIT_CLZ 24
#define SLJIT_ICLZ (SLJIT_CLZ | SLJIT_INT_OP)
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op1(struct sljit_compiler *compiler, int op,
int dst, sljit_w dstw,
int src, sljit_w srcw);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op,
sljit_si dst, sljit_sw dstw,
sljit_si src, sljit_sw srcw);
/* Flags: I | E | O | C | K */
#define SLJIT_ADD 23
#define SLJIT_ADD 25
#define SLJIT_IADD (SLJIT_ADD | SLJIT_INT_OP)
/* Flags: I | C | K */
#define SLJIT_ADDC 24
#define SLJIT_ADDC 26
#define SLJIT_IADDC (SLJIT_ADDC | SLJIT_INT_OP)
/* Flags: I | E | S | U | O | C | K */
#define SLJIT_SUB 25
#define SLJIT_SUB 27
#define SLJIT_ISUB (SLJIT_SUB | SLJIT_INT_OP)
/* Flags: I | C | K */
#define SLJIT_SUBC 26
#define SLJIT_SUBC 28
#define SLJIT_ISUBC (SLJIT_SUBC | SLJIT_INT_OP)
/* Note: integer mul
Flags: I | O (see SLJIT_C_MUL_*) | K */
#define SLJIT_MUL 27
#define SLJIT_MUL 29
#define SLJIT_IMUL (SLJIT_MUL | SLJIT_INT_OP)
/* Flags: I | E | K */
#define SLJIT_AND 28
#define SLJIT_AND 30
#define SLJIT_IAND (SLJIT_AND | SLJIT_INT_OP)
/* Flags: I | E | K */
#define SLJIT_OR 29
#define SLJIT_OR 31
#define SLJIT_IOR (SLJIT_OR | SLJIT_INT_OP)
/* Flags: I | E | K */
#define SLJIT_XOR 30
#define SLJIT_XOR 32
#define SLJIT_IXOR (SLJIT_XOR | SLJIT_INT_OP)
/* Flags: I | E | K
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
to bit_length - 1, the operation is undefined. */
#define SLJIT_SHL 31
#define SLJIT_SHL 33
#define SLJIT_ISHL (SLJIT_SHL | SLJIT_INT_OP)
/* Flags: I | E | K
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
to bit_length - 1, the operation is undefined. */
#define SLJIT_LSHR 32
#define SLJIT_LSHR 34
#define SLJIT_ILSHR (SLJIT_LSHR | SLJIT_INT_OP)
/* Flags: I | E | K
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
to bit_length - 1, the operation is undefined. */
#define SLJIT_ASHR 33
#define SLJIT_ASHR 35
#define SLJIT_IASHR (SLJIT_ASHR | SLJIT_INT_OP)
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op2(struct sljit_compiler *compiler, int op,
int dst, sljit_w dstw,
int src1, sljit_w src1w,
int src2, sljit_w src2w);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op,
sljit_si dst, sljit_sw dstw,
sljit_si src1, sljit_sw src1w,
sljit_si src2, sljit_sw src2w);
/* The following function is a helper function for sljit_emit_op_custom.
It returns with the real machine register index of any SLJIT_TEMPORARY
It returns with the real machine register index of any SLJIT_SCRATCH
SLJIT_SAVED or SLJIT_LOCALS register.
Note: it returns with -1 for virtual registers (all EREGs on x86-32).
Note: register returned by SLJIT_LOCALS_REG is not necessary the real
stack pointer register of the target architecture. */
Note: it returns with -1 for virtual registers (all EREGs on x86-32). */
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg);
/* The following function is a helper function for sljit_emit_op_custom.
It returns with the real machine register index of any SLJIT_FLOAT register.
Note: the index is divided by 2 on ARM 32 bit architectures. */
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg);
/* Any instruction can be inserted into the instruction stream by
sljit_emit_op_custom. It has a similar purpose as inline assembly.
@@ -609,42 +725,50 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_get_register_index(int reg);
if size == 4, the instruction argument must be 4 byte aligned.
Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_op_custom(struct sljit_compiler *compiler,
void *instruction, int size);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler,
void *instruction, sljit_si size);
/* Returns with non-zero if fpu is available. */
SLJIT_API_FUNC_ATTRIBUTE int sljit_is_fpu_available(void);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void);
/* Note: dst is the left and src is the right operand for SLJIT_FCMP.
Note: NaN check is always performed. If SLJIT_C_FLOAT_NAN is set,
Note: NaN check is always performed. If SLJIT_C_FLOAT_UNORDERED is set,
the comparison result is unpredictable.
Flags: E | S (see SLJIT_C_FLOAT_*) */
#define SLJIT_FCMP 34
/* Flags: - (never set any flags) */
#define SLJIT_FMOV 35
/* Flags: - (never set any flags) */
#define SLJIT_FNEG 36
/* Flags: - (never set any flags) */
#define SLJIT_FABS 37
Flags: SP | E | S (see SLJIT_C_FLOAT_*) */
#define SLJIT_CMPD 36
#define SLJIT_CMPS (SLJIT_CMPD | SLJIT_SINGLE_OP)
/* Flags: SP - (never set any flags) */
#define SLJIT_MOVD 37
#define SLJIT_MOVS (SLJIT_MOVD | SLJIT_SINGLE_OP)
/* Flags: SP - (never set any flags) */
#define SLJIT_NEGD 38
#define SLJIT_NEGS (SLJIT_NEGD | SLJIT_SINGLE_OP)
/* Flags: SP - (never set any flags) */
#define SLJIT_ABSD 39
#define SLJIT_ABSS (SLJIT_ABSD | SLJIT_SINGLE_OP)
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop1(struct sljit_compiler *compiler, int op,
int dst, sljit_w dstw,
int src, sljit_w srcw);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop1(struct sljit_compiler *compiler, sljit_si op,
sljit_si dst, sljit_sw dstw,
sljit_si src, sljit_sw srcw);
/* Flags: - (never set any flags) */
#define SLJIT_FADD 38
/* Flags: - (never set any flags) */
#define SLJIT_FSUB 39
/* Flags: - (never set any flags) */
#define SLJIT_FMUL 40
/* Flags: - (never set any flags) */
#define SLJIT_FDIV 41
/* Flags: SP - (never set any flags) */
#define SLJIT_ADDD 40
#define SLJIT_ADDS (SLJIT_ADDD | SLJIT_SINGLE_OP)
/* Flags: SP - (never set any flags) */
#define SLJIT_SUBD 41
#define SLJIT_SUBS (SLJIT_SUBD | SLJIT_SINGLE_OP)
/* Flags: SP - (never set any flags) */
#define SLJIT_MULD 42
#define SLJIT_MULS (SLJIT_MULD | SLJIT_SINGLE_OP)
/* Flags: SP - (never set any flags) */
#define SLJIT_DIVD 43
#define SLJIT_DIVS (SLJIT_DIVD | SLJIT_SINGLE_OP)
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fop2(struct sljit_compiler *compiler, int op,
int dst, sljit_w dstw,
int src1, sljit_w src1w,
int src2, sljit_w src2w);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fop2(struct sljit_compiler *compiler, sljit_si op,
sljit_si dst, sljit_sw dstw,
sljit_si src1, sljit_sw src1w,
sljit_si src2, sljit_sw src2w);
/* Label and jump instructions. */
@@ -677,8 +801,8 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
#define SLJIT_C_FLOAT_GREATER_EQUAL 17
#define SLJIT_C_FLOAT_GREATER 18
#define SLJIT_C_FLOAT_LESS_EQUAL 19
#define SLJIT_C_FLOAT_NAN 20
#define SLJIT_C_FLOAT_NOT_NAN 21
#define SLJIT_C_FLOAT_UNORDERED 20
#define SLJIT_C_FLOAT_ORDERED 21
#define SLJIT_JUMP 22
#define SLJIT_FAST_CALL 23
@@ -697,7 +821,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
Flags: - (never set any flags) for both conditional and unconditional jumps.
Flags: destroy all flags for calls. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type);
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_si type);
/* Basic arithmetic comparison. In most architectures it is implemented as
an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting
@@ -707,23 +831,23 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
type must be between SLJIT_C_EQUAL and SLJIT_C_SIG_LESS_EQUAL
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP or SLJIT_INT_OP
Flags: destroy flags. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type,
int src1, sljit_w src1w,
int src2, sljit_w src2w);
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_si type,
sljit_si src1, sljit_sw src1w,
sljit_si src2, sljit_sw src2w);
/* Basic floating point comparison. In most architectures it is implemented as
an SLJIT_FCMP operation (setting appropriate flags) followed by a
sljit_emit_jump. However some architectures (i.e: MIPS) may employ
special optimizations here. It is suggested to use this comparison form
when appropriate.
type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_NOT_NAN
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_ORDERED
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and SLJIT_SINGLE_OP
Flags: destroy flags.
Note: if either operand is NaN, the behaviour is undefined for
type <= SLJIT_C_FLOAT_LESS_EQUAL. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
int src1, sljit_w src1w,
int src2, sljit_w src2w);
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_si type,
sljit_si src1, sljit_sw src1w,
sljit_si src2, sljit_sw src2w);
/* Set the destination of the jump to this label. */
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label);
@@ -737,29 +861,38 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
Indirect form: any other valid addressing mode
Flags: - (never set any flags) for unconditional jumps.
Flags: destroy all flags for calls. */
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compiler, sljit_si type, sljit_si src, sljit_sw srcw);
/* If op == SLJIT_MOV:
Set dst to 1 if condition is fulfilled, 0 otherwise
type must be between SLJIT_C_EQUAL and SLJIT_C_FLOAT_NOT_NAN
/* Perform the operation using the conditional flags as the second argument.
Type must always be between SLJIT_C_EQUAL and SLJIT_C_FLOAT_ORDERED. The
value represented by the type is 1, if the condition represented by the type
is fulfilled, and 0 otherwise.
If op == SLJIT_MOV, SLJIT_MOV_SI, SLJIT_MOV_UI:
Set dst to the value represented by the type (0 or 1).
Src must be SLJIT_UNUSED, and srcw must be 0
Flags: - (never set any flags)
If op == SLJIT_OR
Dst is used as src as well, and set its lowest bit to 1 if
the condition is fulfilled. Otherwise it does nothing.
Flags: E | K
Note: sljit_emit_cond_value does nothing, if dst is SLJIT_UNUSED (regardless of op). */
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_cond_value(struct sljit_compiler *compiler, int op, int dst, sljit_w dstw, int type);
If op == SLJIT_OR, op == SLJIT_AND, op == SLJIT_XOR
Performs the binary operation using src as the first, and the value
represented by type as the second argument.
Important note: only dst=src and dstw=srcw is supported at the moment!
Flags: I | E | K
Note: sljit_emit_op_flags does nothing, if dst is SLJIT_UNUSED (regardless of op). */
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_si op,
sljit_si dst, sljit_sw dstw,
sljit_si src, sljit_sw srcw,
sljit_si type);
/* Copies the base address of SLJIT_MEM1(SLJIT_LOCALS_REG)+offset to dst.
/* Copies the base address of SLJIT_LOCALS_REG+offset to dst.
Flags: - (never set any flags) */
SLJIT_API_FUNC_ATTRIBUTE int sljit_get_local_base(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w offset);
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset);
/* The constant can be changed runtime (see: sljit_set_const)
Flags: - (never set any flags) */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, int dst, sljit_w dstw, sljit_w init_value);
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value);
/* After the code generation the address for label, jump and const instructions
are computed. Since these structures are freed sljit_free_compiler, the
are computed. Since these structures are freed by sljit_free_compiler, the
addresses must be preserved by the user program elsewere. */
static SLJIT_INLINE sljit_uw sljit_get_label_addr(struct sljit_label *label) { return label->addr; }
static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; }
@@ -767,22 +900,22 @@ static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) {
/* Only the address is required to rewrite the code. */
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr);
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant);
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant);
/* --------------------------------------------------------------------- */
/* Miscellaneous utility functions */
/* --------------------------------------------------------------------- */
#define SLJIT_MAJOR_VERSION 0
#define SLJIT_MINOR_VERSION 88
#define SLJIT_MINOR_VERSION 91
/* Get the human readable name of the platfrom.
Can be useful for debugging on platforms like ARM, where ARM and
Thumb2 functions can be mixed. */
/* Get the human readable name of the platform. Can be useful on platforms
like ARM, where ARM and Thumb2 functions can be mixed, and
it is useful to know the type of the code generator. */
SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void);
/* Portble helper function to get an offset of a member. */
#define SLJIT_OFFSETOF(base, member) ((sljit_w)(&((base*)0x10)->member) - 0x10)
/* Portable helper function to get an offset of a member. */
#define SLJIT_OFFSETOF(base, member) ((sljit_sw)(&((base*)0x10)->member) - 0x10)
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
/* This global lock is useful to compile common functions. */
@@ -831,32 +964,32 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* st
since the growth ratio can be added to the current limit, and sljit_stack_resize
will do all the necessary checks. The fields of the stack are not changed if
sljit_stack_resize fails. */
SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit);
SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit);
#endif /* (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) */
#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
/* Get the entry address of a given function. */
#define SLJIT_FUNC_OFFSET(func_name) ((sljit_w)func_name)
#define SLJIT_FUNC_OFFSET(func_name) ((sljit_sw)func_name)
#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
/* All JIT related code should be placed in the same context (library, binary, etc.). */
#define SLJIT_FUNC_OFFSET(func_name) ((sljit_w)*(void**)func_name)
#define SLJIT_FUNC_OFFSET(func_name) (*(sljit_sw*)(void*)func_name)
/* For powerpc64, the function pointers point to a context descriptor. */
struct sljit_function_context {
sljit_w addr;
sljit_w r2;
sljit_w r11;
sljit_sw addr;
sljit_sw r2;
sljit_sw r11;
};
/* Fill the context arguments using the addr and the function.
If func_ptr is NULL, it will not be set to the address of context
If addr is NULL, the function address also comes from the func pointer. */
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_w addr, void* func);
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func);
#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */

View File

@@ -26,7 +26,7 @@
/* mips 32-bit arch dependent functions. */
static int load_immediate(struct sljit_compiler *compiler, int dst_ar, sljit_w imm)
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si dst_ar, sljit_sw imm)
{
if (!(imm & ~0xffff))
return push_inst(compiler, ORI | SA(0) | TA(dst_ar) | IMM(imm), dst_ar);
@@ -66,12 +66,92 @@ static int load_immediate(struct sljit_compiler *compiler, int dst_ar, sljit_w i
FAIL_IF(push_inst(compiler, op_norm | S(src2) | T(src1) | D(dst), DR(dst))); \
}
static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
int dst, int src1, sljit_w src2)
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
sljit_si dst, sljit_si src1, sljit_sw src2)
{
int overflow_ra = 0;
sljit_si overflow_ra = 0;
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
case SLJIT_MOV_UI:
case SLJIT_MOV_SI:
case SLJIT_MOV_P:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if (dst != src2)
return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
return SLJIT_SUCCESS;
case SLJIT_MOV_UB:
case SLJIT_MOV_SB:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SB) {
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
#else
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
#endif
}
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
}
else if (dst != src2)
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
case SLJIT_MOV_UH:
case SLJIT_MOV_SH:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SH) {
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
#else
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
#endif
}
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
}
else if (dst != src2)
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
case SLJIT_NOT:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if (op & SLJIT_SET_E)
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
return SLJIT_SUCCESS;
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
if (op & SLJIT_SET_E)
FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
#else
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
}
/* Nearly all instructions are unmovable in the following sequence. */
FAIL_IF(push_inst(compiler, ADDU_W | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
/* Check zero. */
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, ADDIU_W | SA(0) | T(dst) | IMM(-1), DR(dst)));
/* Loop for searching the highest bit. */
FAIL_IF(push_inst(compiler, ADDIU_W | S(dst) | T(dst) | IMM(1), DR(dst)));
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS));
if (op & SLJIT_SET_E)
return push_inst(compiler, ADDU_W | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
#endif
return SLJIT_SUCCESS;
case SLJIT_ADD:
if (flags & SRC2_IMM) {
if (op & SLJIT_SET_O) {
@@ -293,97 +373,16 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
case SLJIT_ASHR:
EMIT_SHIFT(SRA, SRAV);
return SLJIT_SUCCESS;
case SLJIT_MOV:
case SLJIT_MOV_UI:
case SLJIT_MOV_SI:
SLJIT_ASSERT(src1 == TMP_REG1);
if (dst != src2)
return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
return SLJIT_SUCCESS;
case SLJIT_MOV_UB:
case SLJIT_MOV_SB:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SB) {
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
#else
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
#endif
}
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
}
else if (dst != src2)
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
case SLJIT_MOV_UH:
case SLJIT_MOV_SH:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SH) {
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
#else
FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
#endif
}
return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
}
else if (dst != src2)
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
case SLJIT_NOT:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if (op & SLJIT_SET_E)
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG));
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(push_inst(compiler, NOR | S(src2) | T(src2) | D(dst), DR(dst)));
return SLJIT_SUCCESS;
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
#if (defined SLJIT_MIPS_32_64 && SLJIT_MIPS_32_64)
if (op & SLJIT_SET_E)
FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG));
if (CHECK_FLAGS(SLJIT_SET_E))
FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst)));
#else
if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) {
FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG));
return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG);
}
/* Nearly all instructions are unmovable in the following sequence. */
FAIL_IF(push_inst(compiler, ADDU_W | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
/* Check zero. */
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(6), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(32), UNMOVABLE_INS));
/* Check sign bit. */
FAIL_IF(push_inst(compiler, BLTZ | S(TMP_REG1) | IMM(4), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM(0), UNMOVABLE_INS));
/* Loop for searching the highest bit. */
FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), DR(TMP_REG1)));
FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, ADDIU_W | S(dst) | T(dst) | IMM(1), UNMOVABLE_INS));
if (op & SLJIT_SET_E)
return push_inst(compiler, ADDU_W | S(dst) | TA(0) | DA(EQUAL_FLAG), EQUAL_FLAG);
#endif
return SLJIT_SUCCESS;
}
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
}
static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw init_value)
{
FAIL_IF(push_inst(compiler, LUI | T(reg) | IMM(init_value >> 16), DR(reg)));
return push_inst(compiler, ORI | S(reg) | T(reg) | IMM(init_value), DR(reg));
FAIL_IF(push_inst(compiler, LUI | T(dst) | IMM(init_value >> 16), DR(dst)));
return push_inst(compiler, ORI | S(dst) | T(dst) | IMM(init_value), DR(dst));
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_addr)
@@ -395,7 +394,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
sljit_ins *inst = (sljit_ins*)addr;

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,7 @@
/* ppc 32-bit arch dependent functions. */
static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
{
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
return push_inst(compiler, ADDI | D(reg) | A(0) | IMM(imm));
@@ -41,10 +41,59 @@ static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
#define INS_CLEAR_LEFT(dst, src, from) \
(RLWINM | S(src) | A(dst) | ((from) << 6) | (31 << 1))
static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
int dst, int src1, int src2)
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
sljit_si dst, sljit_si src1, sljit_si src2)
{
switch (op) {
case SLJIT_MOV:
case SLJIT_MOV_UI:
case SLJIT_MOV_SI:
case SLJIT_MOV_P:
SLJIT_ASSERT(src1 == TMP_REG1);
if (dst != src2)
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
return SLJIT_SUCCESS;
case SLJIT_MOV_UB:
case SLJIT_MOV_SB:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SB)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
}
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
else {
SLJIT_ASSERT(dst == src2);
}
return SLJIT_SUCCESS;
case SLJIT_MOV_UH:
case SLJIT_MOV_SH:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SH)
return push_inst(compiler, EXTSH | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
}
else {
SLJIT_ASSERT(dst == src2);
}
return SLJIT_SUCCESS;
case SLJIT_NOT:
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
case SLJIT_NEG:
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
case SLJIT_ADD:
if (flags & ALT_FORM1) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
@@ -71,7 +120,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
case SLJIT_ADDC:
if (flags & ALT_FORM1) {
FAIL_IF(push_inst(compiler, MFXER | S(0)));
FAIL_IF(push_inst(compiler, MFXER | D(0)));
FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
return push_inst(compiler, MTXER | S(0));
}
@@ -106,7 +155,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
case SLJIT_SUBC:
if (flags & ALT_FORM1) {
FAIL_IF(push_inst(compiler, MFXER | S(0)));
FAIL_IF(push_inst(compiler, MFXER | D(0)));
FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
return push_inst(compiler, MTXER | S(0));
}
@@ -179,65 +228,23 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_ASHR:
if (flags & ALT_FORM3)
FAIL_IF(push_inst(compiler, MFXER | D(0)));
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
compiler->imm &= 0x1f;
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
}
return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_MOV:
case SLJIT_MOV_UI:
case SLJIT_MOV_SI:
SLJIT_ASSERT(src1 == TMP_REG1);
if (dst != src2)
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
return SLJIT_SUCCESS;
case SLJIT_MOV_UB:
case SLJIT_MOV_SB:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SB)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
}
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
else if (dst != src2)
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
case SLJIT_MOV_UH:
case SLJIT_MOV_SH:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SH)
return push_inst(compiler, EXTSH | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
}
else if (dst != src2)
SLJIT_ASSERT_STOP();
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_NEG:
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
else
FAIL_IF(push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2)));
return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
}
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
}
static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
{
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 16)));
return push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value));
@@ -252,7 +259,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
sljit_ins *inst = (sljit_ins*)addr;

View File

@@ -26,9 +26,11 @@
/* ppc 64-bit arch dependent functions. */
#ifdef __GNUC__
#if defined(__GNUC__) || (defined(__IBM_GCC_ASM) && __IBM_GCC_ASM)
#define ASM_SLJIT_CLZ(src, dst) \
asm volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
__asm__ volatile ( "cntlzd %0, %1" : "=r"(dst) : "r"(src) )
#elif defined(__xlc__)
#error "Please enable GCC syntax for inline assembly statements"
#else
#error "Must implement count leading zeroes"
#endif
@@ -39,7 +41,7 @@
#define PUSH_RLDICR(reg, shift) \
push_inst(compiler, RLDI(reg, reg, 63 - shift, shift, 1))
static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
static sljit_si load_immediate(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
{
sljit_uw tmp;
sljit_uw shift;
@@ -143,10 +145,74 @@ static int load_immediate(struct sljit_compiler *compiler, int reg, sljit_w imm)
src1 = TMP_REG1; \
}
static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op, int flags,
int dst, int src1, int src2)
static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, sljit_si op, sljit_si flags,
sljit_si dst, sljit_si src1, sljit_si src2)
{
switch (op) {
case SLJIT_MOV:
case SLJIT_MOV_P:
SLJIT_ASSERT(src1 == TMP_REG1);
if (dst != src2)
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
return SLJIT_SUCCESS;
case SLJIT_MOV_UI:
case SLJIT_MOV_SI:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SI)
return push_inst(compiler, EXTSW | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));
}
else {
SLJIT_ASSERT(dst == src2);
}
return SLJIT_SUCCESS;
case SLJIT_MOV_UB:
case SLJIT_MOV_SB:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SB)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
}
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
else {
SLJIT_ASSERT(dst == src2);
}
return SLJIT_SUCCESS;
case SLJIT_MOV_UH:
case SLJIT_MOV_SH:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SH)
return push_inst(compiler, EXTSH | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
}
else {
SLJIT_ASSERT(dst == src2);
}
return SLJIT_SUCCESS;
case SLJIT_NOT:
SLJIT_ASSERT(src1 == TMP_REG1);
UN_EXTS();
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
case SLJIT_NEG:
SLJIT_ASSERT(src1 == TMP_REG1);
UN_EXTS();
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
if (flags & ALT_FORM1)
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst));
case SLJIT_ADD:
if (flags & ALT_FORM1) {
/* Flags does not set: BIN_IMM_EXTS unnecessary. */
@@ -175,7 +241,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
case SLJIT_ADDC:
if (flags & ALT_FORM1) {
FAIL_IF(push_inst(compiler, MFXER | S(0)));
FAIL_IF(push_inst(compiler, MFXER | D(0)));
FAIL_IF(push_inst(compiler, ADDE | D(dst) | A(src1) | B(src2)));
return push_inst(compiler, MTXER | S(0));
}
@@ -212,7 +278,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
case SLJIT_SUBC:
if (flags & ALT_FORM1) {
FAIL_IF(push_inst(compiler, MFXER | S(0)));
FAIL_IF(push_inst(compiler, MFXER | D(0)));
FAIL_IF(push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1)));
return push_inst(compiler, MTXER | S(0));
}
@@ -284,9 +350,7 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
return push_inst(compiler, RLDI(dst, src1, compiler->imm, 63 - compiler->imm, 1) | RC(flags));
}
}
if (flags & ALT_FORM2)
return push_inst(compiler, SLW | RC(flags) | S(src1) | A(dst) | B(src2));
return push_inst(compiler, SLD | RC(flags) | S(src1) | A(dst) | B(src2));
return push_inst(compiler, ((flags & ALT_FORM2) ? SLW : SLD) | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_LSHR:
if (flags & ALT_FORM1) {
@@ -300,92 +364,32 @@ static SLJIT_INLINE int emit_single_op(struct sljit_compiler *compiler, int op,
return push_inst(compiler, RLDI(dst, src1, 64 - compiler->imm, compiler->imm, 0) | RC(flags));
}
}
if (flags & ALT_FORM2)
return push_inst(compiler, SRW | RC(flags) | S(src1) | A(dst) | B(src2));
return push_inst(compiler, SRD | RC(flags) | S(src1) | A(dst) | B(src2));
return push_inst(compiler, ((flags & ALT_FORM2) ? SRW : SRD) | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_ASHR:
if (flags & ALT_FORM3)
FAIL_IF(push_inst(compiler, MFXER | D(0)));
if (flags & ALT_FORM1) {
SLJIT_ASSERT(src2 == TMP_REG2);
if (flags & ALT_FORM2) {
compiler->imm &= 0x1f;
return push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11));
FAIL_IF(push_inst(compiler, SRAWI | RC(flags) | S(src1) | A(dst) | (compiler->imm << 11)));
}
else {
compiler->imm &= 0x3f;
return push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4));
FAIL_IF(push_inst(compiler, SRADI | RC(flags) | S(src1) | A(dst) | ((compiler->imm & 0x1f) << 11) | ((compiler->imm & 0x20) >> 4)));
}
}
if (flags & ALT_FORM2)
return push_inst(compiler, SRAW | RC(flags) | S(src1) | A(dst) | B(src2));
return push_inst(compiler, SRAD | RC(flags) | S(src1) | A(dst) | B(src2));
case SLJIT_MOV:
SLJIT_ASSERT(src1 == TMP_REG1);
if (dst != src2)
return push_inst(compiler, OR | S(src2) | A(dst) | B(src2));
return SLJIT_SUCCESS;
case SLJIT_MOV_UI:
case SLJIT_MOV_SI:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SI)
return push_inst(compiler, EXTSW | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 0));
}
else if (dst != src2)
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
case SLJIT_MOV_UB:
case SLJIT_MOV_SB:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SB)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 24));
}
else if ((flags & REG_DEST) && op == SLJIT_MOV_SB)
return push_inst(compiler, EXTSB | S(src2) | A(dst));
else if (dst != src2)
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
case SLJIT_MOV_UH:
case SLJIT_MOV_SH:
SLJIT_ASSERT(src1 == TMP_REG1);
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
if (op == SLJIT_MOV_SH)
return push_inst(compiler, EXTSH | S(src2) | A(dst));
return push_inst(compiler, INS_CLEAR_LEFT(dst, src2, 16));
}
else if (dst != src2)
SLJIT_ASSERT_STOP();
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_NEG:
SLJIT_ASSERT(src1 == TMP_REG1);
UN_EXTS();
return push_inst(compiler, NEG | OERC(flags) | D(dst) | A(src2));
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
if (flags & ALT_FORM1)
return push_inst(compiler, CNTLZW | RC(flags) | S(src2) | A(dst));
return push_inst(compiler, CNTLZD | RC(flags) | S(src2) | A(dst));
else
FAIL_IF(push_inst(compiler, ((flags & ALT_FORM2) ? SRAW : SRAD) | RC(flags) | S(src1) | A(dst) | B(src2)));
return (flags & ALT_FORM3) ? push_inst(compiler, MTXER | S(0)) : SLJIT_SUCCESS;
}
SLJIT_ASSERT_STOP();
return SLJIT_SUCCESS;
}
static SLJIT_INLINE int emit_const(struct sljit_compiler *compiler, int reg, sljit_w init_value)
static SLJIT_INLINE sljit_si emit_const(struct sljit_compiler *compiler, sljit_si reg, sljit_sw init_value)
{
FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(init_value >> 48)));
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(init_value >> 32)));
@@ -405,7 +409,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ad
SLJIT_CACHE_FLUSH(inst, inst + 5);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constant)
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant)
{
sljit_ins *inst = (sljit_ins*)addr;
@@ -415,14 +419,3 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_w new_constan
inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff);
SLJIT_CACHE_FLUSH(inst, inst + 5);
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_w addr, void* func)
{
sljit_w* ptrs;
if (func_ptr)
*func_ptr = (void*)context;
ptrs = (sljit_w*)func;
context->addr = addr ? addr : ptrs[0];
context->r2 = ptrs[1];
context->r11 = ptrs[2];
}

File diff suppressed because it is too large Load Diff

View File

@@ -106,10 +106,10 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
#else /* _WIN32 */
#include "pthread.h"
#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
#include <pthread.h>
static pthread_mutex_t allocator_mutex = PTHREAD_MUTEX_INITIALIZER;
static SLJIT_INLINE void allocator_grab_lock(void)
@@ -126,6 +126,8 @@ static SLJIT_INLINE void allocator_release_lock(void)
#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
#include <pthread.h>
static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_grab_lock(void)
@@ -146,17 +148,57 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_release_lock(void)
/* Stack */
/* ------------------------------------------------------------------------ */
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR)
#ifdef _WIN32
#include "windows.h"
#else
/* Provides mmap function. */
#include <sys/mman.h>
/* For detecting the page size. */
#include <unistd.h>
#ifndef MAP_ANON
#include <fcntl.h>
/* Some old systems does not have MAP_ANON. */
static sljit_si dev_zero = -1;
#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED)
static SLJIT_INLINE sljit_si open_dev_zero(void)
{
dev_zero = open("/dev/zero", O_RDWR);
return dev_zero < 0;
}
#else /* SLJIT_SINGLE_THREADED */
#include <pthread.h>
static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER;
static SLJIT_INLINE sljit_si open_dev_zero(void)
{
pthread_mutex_lock(&dev_zero_mutex);
dev_zero = open("/dev/zero", O_RDWR);
pthread_mutex_unlock(&dev_zero_mutex);
return dev_zero < 0;
}
#endif /* SLJIT_SINGLE_THREADED */
#endif
#endif
#endif /* SLJIT_UTIL_STACK || SLJIT_EXECUTABLE_ALLOCATOR */
#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK)
/* Planning to make it even more clever in the future. */
static sljit_w sljit_page_align = 0;
static sljit_sw sljit_page_align = 0;
SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(sljit_uw limit, sljit_uw max_limit)
{
@@ -195,7 +237,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
return NULL;
#ifdef _WIN32
base.ptr = VirtualAlloc(0, max_limit, MEM_RESERVE, PAGE_READWRITE);
base.ptr = VirtualAlloc(NULL, max_limit, MEM_RESERVE, PAGE_READWRITE);
if (!base.ptr) {
SLJIT_FREE(stack);
return NULL;
@@ -208,7 +250,17 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_CALL sljit_allocate_stack(slj
return NULL;
}
#else
base.ptr = mmap(0, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
#ifdef MAP_ANON
base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
#else
if (dev_zero < 0) {
if (open_dev_zero()) {
SLJIT_FREE(stack);
return NULL;
}
}
base.ptr = mmap(NULL, max_limit, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0);
#endif
if (base.ptr == MAP_FAILED) {
SLJIT_FREE(stack);
return NULL;
@@ -233,7 +285,7 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_CALL sljit_free_stack(struct sljit_stack* st
SLJIT_FREE(stack);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
SLJIT_API_FUNC_ATTRIBUTE sljit_sw SLJIT_CALL sljit_stack_resize(struct sljit_stack* stack, sljit_uw new_limit)
{
sljit_uw aligned_old_limit;
sljit_uw aligned_new_limit;
@@ -262,8 +314,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_w SLJIT_CALL sljit_stack_resize(struct sljit_stac
}
aligned_new_limit = (new_limit + sljit_page_align) & ~sljit_page_align;
aligned_old_limit = (stack->limit + sljit_page_align) & ~sljit_page_align;
/* If madvise is available, we release the unnecessary space. */
#if defined(MADV_DONTNEED)
if (aligned_new_limit < aligned_old_limit)
madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, MADV_DONTNEED);
#elif defined(POSIX_MADV_DONTNEED)
if (aligned_new_limit < aligned_old_limit)
posix_madvise((void*)aligned_new_limit, aligned_old_limit - aligned_new_limit, POSIX_MADV_DONTNEED);
#endif
stack->limit = new_limit;
return 0;
#endif

View File

@@ -26,30 +26,30 @@
/* x86 32-bit arch dependent functions. */
static int emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_w imm)
static sljit_si emit_do_imm(struct sljit_compiler *compiler, sljit_ub opcode, sljit_sw imm)
{
sljit_ub *buf;
sljit_ub *inst;
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_w));
FAIL_IF(!buf);
INC_SIZE(1 + sizeof(sljit_w));
*buf++ = opcode;
*(sljit_w*)buf = imm;
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_sw));
FAIL_IF(!inst);
INC_SIZE(1 + sizeof(sljit_sw));
*inst++ = opcode;
*(sljit_sw*)inst = imm;
return SLJIT_SUCCESS;
}
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type)
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
{
if (type == SLJIT_JUMP) {
*code_ptr++ = 0xe9;
*code_ptr++ = JMP_i32;
jump->addr++;
}
else if (type >= SLJIT_FAST_CALL) {
*code_ptr++ = 0xe8;
*code_ptr++ = CALL_i32;
jump->addr++;
}
else {
*code_ptr++ = 0x0f;
*code_ptr++ = GROUP_0F;
*code_ptr++ = get_jump_code(type);
jump->addr += 2;
}
@@ -57,22 +57,22 @@ static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_
if (jump->flags & JUMP_LABEL)
jump->flags |= PATCH_MW;
else
*(sljit_w*)code_ptr = jump->u.target - (jump->addr + 4);
*(sljit_sw*)code_ptr = jump->u.target - (jump->addr + 4);
code_ptr += 4;
return code_ptr;
}
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
int size;
int locals_offset;
sljit_ub *buf;
sljit_si size;
sljit_si locals_offset;
sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
compiler->temporaries = temporaries;
compiler->scratches = scratches;
compiler->saveds = saveds;
compiler->args = args;
compiler->flags_saved = 0;
@@ -85,15 +85,15 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
#else
size = 1 + (saveds <= 3 ? saveds : 3) + (args > 0 ? (2 + args * 3) : 0);
#endif
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
FAIL_IF(!inst);
INC_SIZE(size);
PUSH_REG(reg_map[TMP_REGISTER]);
#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
if (args > 0) {
*buf++ = 0x8b;
*buf++ = 0xc4 | (reg_map[TMP_REGISTER] << 3);
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (reg_map[TMP_REGISTER] << 3) | 0x4 /* esp */;
}
#endif
if (saveds > 2)
@@ -105,102 +105,125 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
if (args > 0) {
*buf++ = 0x8b;
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[SLJIT_TEMPORARY_REG3];
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[SLJIT_SCRATCH_REG3];
}
if (args > 1) {
*buf++ = 0x8b;
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[SLJIT_TEMPORARY_REG2];
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[SLJIT_SCRATCH_REG2];
}
if (args > 2) {
*buf++ = 0x8b;
*buf++ = 0x44 | (reg_map[SLJIT_SAVED_REG3] << 3);
*buf++ = 0x24;
*buf++ = sizeof(sljit_w) * (3 + 2); /* saveds >= 3 as well. */
*inst++ = MOV_r_rm;
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x4 /* esp */;
*inst++ = 0x24;
*inst++ = sizeof(sljit_sw) * (3 + 2); /* saveds >= 3 as well. */
}
#else
if (args > 0) {
*buf++ = 0x8b;
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER];
*buf++ = sizeof(sljit_w) * 2;
*inst++ = MOV_r_rm;
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG1] << 3) | reg_map[TMP_REGISTER];
*inst++ = sizeof(sljit_sw) * 2;
}
if (args > 1) {
*buf++ = 0x8b;
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER];
*buf++ = sizeof(sljit_w) * 3;
*inst++ = MOV_r_rm;
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG2] << 3) | reg_map[TMP_REGISTER];
*inst++ = sizeof(sljit_sw) * 3;
}
if (args > 2) {
*buf++ = 0x8b;
*buf++ = 0x40 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER];
*buf++ = sizeof(sljit_w) * 4;
*inst++ = MOV_r_rm;
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SAVED_REG3] << 3) | reg_map[TMP_REGISTER];
*inst++ = sizeof(sljit_sw) * 4;
}
#endif
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
locals_offset = 2 * sizeof(sljit_uw);
compiler->temporaries_start = locals_offset;
if (temporaries > 3)
locals_offset += (temporaries - 3) * sizeof(sljit_uw);
#else
SLJIT_COMPILE_ASSERT(FIXED_LOCALS_OFFSET >= 2 * sizeof(sljit_uw), require_at_least_two_words);
locals_offset = FIXED_LOCALS_OFFSET;
#endif
compiler->scratches_start = locals_offset;
if (scratches > 3)
locals_offset += (scratches - 3) * sizeof(sljit_uw);
compiler->saveds_start = locals_offset;
if (saveds > 3)
locals_offset += (saveds - 3) * sizeof(sljit_uw);
compiler->locals_offset = locals_offset;
#if defined(__APPLE__)
saveds = (2 + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
local_size = ((locals_offset + saveds + local_size + 15) & ~15) - saveds;
#else
local_size = locals_offset + ((local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1));
#endif
compiler->local_size = local_size;
#ifdef _WIN32
if (local_size > 1024) {
FAIL_IF(emit_do_imm(compiler, 0xb8 + reg_map[SLJIT_TEMPORARY_REG1], local_size));
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_SCRATCH_REG1], local_size));
#else
local_size -= FIXED_LOCALS_OFFSET;
FAIL_IF(emit_do_imm(compiler, MOV_r_i32 + reg_map[SLJIT_SCRATCH_REG1], local_size));
FAIL_IF(emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, FIXED_LOCALS_OFFSET));
#endif
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
}
#endif
compiler->local_size = local_size;
SLJIT_ASSERT(local_size > 0);
return emit_non_cum_binary(compiler, 0x2b, 0x29, 0x5 << 3, 0x2d,
return emit_non_cum_binary(compiler, SUB_r_rm, SUB_rm_r, SUB, SUB_EAX_i32,
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, local_size);
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
int locals_offset;
sljit_si locals_offset;
CHECK_ERROR_VOID();
check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
compiler->temporaries = temporaries;
compiler->scratches = scratches;
compiler->saveds = saveds;
compiler->args = args;
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
compiler->logical_local_size = local_size;
#endif
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
locals_offset = 2 * sizeof(sljit_uw);
compiler->temporaries_start = locals_offset;
if (temporaries > 3)
locals_offset += (temporaries - 3) * sizeof(sljit_uw);
#else
locals_offset = FIXED_LOCALS_OFFSET;
#endif
compiler->scratches_start = locals_offset;
if (scratches > 3)
locals_offset += (scratches - 3) * sizeof(sljit_uw);
compiler->saveds_start = locals_offset;
if (saveds > 3)
locals_offset += (saveds - 3) * sizeof(sljit_uw);
compiler->locals_offset = locals_offset;
#if defined(__APPLE__)
saveds = (2 + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
compiler->local_size = ((locals_offset + saveds + local_size + 15) & ~15) - saveds;
#else
compiler->local_size = locals_offset + ((local_size + sizeof(sljit_uw) - 1) & ~(sizeof(sljit_uw) - 1));
#endif
}
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
int size;
sljit_ub *buf;
sljit_si size;
sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_return(compiler, op, src, srcw);
SLJIT_ASSERT(compiler->args >= 0);
ADJUST_LOCAL_OFFSET(src, srcw);
compiler->flags_saved = 0;
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
SLJIT_ASSERT(compiler->local_size > 0);
FAIL_IF(emit_cum_binary(compiler, 0x03, 0x01, 0x0 << 3, 0x05,
FAIL_IF(emit_cum_binary(compiler, ADD_r_rm, ADD_rm_r, ADD, ADD_EAX_i32,
SLJIT_LOCALS_REG, 0, SLJIT_LOCALS_REG, 0, SLJIT_IMM, compiler->local_size));
size = 2 + (compiler->saveds <= 3 ? compiler->saveds : 3);
@@ -211,8 +234,8 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
if (compiler->args > 0)
size += 2;
#endif
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
FAIL_IF(!inst);
INC_SIZE(size);
@@ -225,14 +248,11 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
POP_REG(reg_map[TMP_REGISTER]);
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
if (compiler->args > 2)
RETN(sizeof(sljit_w));
RET_I16(sizeof(sljit_sw));
else
RET();
#else
if (compiler->args > 0)
RETN(compiler->args * sizeof(sljit_w));
else
RET();
RET();
#endif
return SLJIT_SUCCESS;
@@ -243,16 +263,16 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
/* --------------------------------------------------------------------- */
/* Size contains the flags as well. */
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
/* The register or immediate operand. */
int a, sljit_w imma,
sljit_si a, sljit_sw imma,
/* The general operand (not immediate). */
int b, sljit_w immb)
sljit_si b, sljit_sw immb)
{
sljit_ub *buf;
sljit_ub *inst;
sljit_ub *buf_ptr;
int flags = size & ~0xf;
int inst_size;
sljit_si flags = size & ~0xf;
sljit_si inst_size;
/* Both cannot be switched on. */
SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
@@ -263,13 +283,16 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
/* 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));
#endif
size &= 0xf;
inst_size = size;
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
if (flags & EX86_PREF_F2)
if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
inst_size++;
#endif
if (flags & EX86_PREF_66)
@@ -279,13 +302,13 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
inst_size += 1; /* mod r/m byte. */
if (b & SLJIT_MEM) {
if ((b & 0x0f) == SLJIT_UNUSED)
inst_size += sizeof(sljit_w);
inst_size += sizeof(sljit_sw);
else if (immb != 0 && !(b & 0xf0)) {
/* Immediate operand. */
if (immb <= 127 && immb >= -128)
inst_size += sizeof(sljit_b);
inst_size += sizeof(sljit_sb);
else
inst_size += sizeof(sljit_w);
inst_size += sizeof(sljit_sw);
}
if ((b & 0xf) == SLJIT_LOCALS_REG && !(b & 0xf0))
@@ -315,29 +338,31 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else if (flags & EX86_HALF_ARG)
inst_size += sizeof(short);
else
inst_size += sizeof(sljit_w);
inst_size += sizeof(sljit_sw);
}
else
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
PTR_FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
PTR_FAIL_IF(!inst);
/* Encoding the byte. */
INC_SIZE(inst_size);
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
if (flags & EX86_PREF_F2)
*buf++ = 0xf2;
*inst++ = 0xf2;
if (flags & EX86_PREF_F3)
*inst++ = 0xf3;
#endif
if (flags & EX86_PREF_66)
*buf++ = 0x66;
*inst++ = 0x66;
buf_ptr = buf + size;
buf_ptr = inst + size;
/* Encode mod/rm byte. */
if (!(flags & EX86_SHIFT_INS)) {
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
*buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81;
*inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
if ((a & SLJIT_IMM) || (a == 0))
*buf_ptr = 0;
@@ -354,19 +379,19 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else {
if (a & SLJIT_IMM) {
if (imma == 1)
*buf = 0xd1;
*inst = GROUP_SHIFT_1;
else
*buf = 0xc1;
*inst = GROUP_SHIFT_N;
} else
*buf = 0xd3;
*inst = GROUP_SHIFT_CL;
*buf_ptr = 0;
}
if (!(b & SLJIT_MEM))
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
*buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_map[b] : b);
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2)) ? reg_map[b] : b);
#else
*buf_ptr++ |= 0xc0 + reg_map[b];
*buf_ptr++ |= MOD_REG + reg_map[b];
#endif
else if ((b & 0x0f) != SLJIT_UNUSED) {
if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
@@ -388,8 +413,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
if (immb <= 127 && immb >= -128)
*buf_ptr++ = immb; /* 8 bit displacement. */
else {
*(sljit_w*)buf_ptr = immb; /* 32 bit displacement. */
buf_ptr += sizeof(sljit_w);
*(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
buf_ptr += sizeof(sljit_sw);
}
}
}
@@ -400,8 +425,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
}
else {
*buf_ptr++ |= 0x05;
*(sljit_w*)buf_ptr = immb; /* 32 bit displacement. */
buf_ptr += sizeof(sljit_w);
*(sljit_sw*)buf_ptr = immb; /* 32 bit displacement. */
buf_ptr += sizeof(sljit_sw);
}
if (a & SLJIT_IMM) {
@@ -410,45 +435,57 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else if (flags & EX86_HALF_ARG)
*(short*)buf_ptr = imma;
else if (!(flags & EX86_SHIFT_INS))
*(sljit_w*)buf_ptr = imma;
*(sljit_sw*)buf_ptr = imma;
}
return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
}
/* --------------------------------------------------------------------- */
/* Call / return instructions */
/* --------------------------------------------------------------------- */
static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
{
sljit_ub *buf;
sljit_ub *inst;
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
buf = (sljit_ub*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, type >= SLJIT_CALL3 ? 1 + 2 + 1 : 1 + 2);
FAIL_IF(!inst);
INC_SIZE(type >= SLJIT_CALL3 ? 2 + 1 : 2);
if (type >= SLJIT_CALL3)
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG3]);
*buf++ = 0x8b;
*buf++ = 0xc0 | (reg_map[SLJIT_TEMPORARY_REG3] << 3) | reg_map[SLJIT_TEMPORARY_REG1];
PUSH_REG(reg_map[SLJIT_SCRATCH_REG3]);
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (reg_map[SLJIT_SCRATCH_REG3] << 3) | reg_map[SLJIT_SCRATCH_REG1];
#else
buf = (sljit_ub*)ensure_buf(compiler, type - SLJIT_CALL0 + 1);
FAIL_IF(!buf);
INC_SIZE(type - SLJIT_CALL0);
if (type >= SLJIT_CALL3)
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG3]);
if (type >= SLJIT_CALL2)
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG2]);
PUSH_REG(reg_map[SLJIT_TEMPORARY_REG1]);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 * (type - SLJIT_CALL0));
FAIL_IF(!inst);
INC_SIZE(4 * (type - SLJIT_CALL0));
*inst++ = MOV_rm_r;
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG1] << 3) | 0x4 /* SIB */;
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
*inst++ = 0;
if (type >= SLJIT_CALL2) {
*inst++ = MOV_rm_r;
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG2] << 3) | 0x4 /* SIB */;
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
*inst++ = sizeof(sljit_sw);
}
if (type >= SLJIT_CALL3) {
*inst++ = MOV_rm_r;
*inst++ = MOD_DISP8 | (reg_map[SLJIT_SCRATCH_REG3] << 3) | 0x4 /* SIB */;
*inst++ = (0x4 /* none*/ << 3) | reg_map[SLJIT_LOCALS_REG];
*inst++ = 2 * sizeof(sljit_sw);
}
#endif
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
sljit_ub *buf;
sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_fast_enter(compiler, dst, dstw);
@@ -456,33 +493,30 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compil
CHECK_EXTRA_REGS(dst, dstw, (void)0);
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!buf);
/* For UNUSED dst. Uncommon, but possible. */
if (dst == SLJIT_UNUSED)
dst = TMP_REGISTER;
if (dst <= TMP_REGISTER) {
/* Unused dest is possible here. */
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
POP_REG(reg_map[dst]);
return SLJIT_SUCCESS;
}
else if (dst & SLJIT_MEM) {
buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
FAIL_IF(!buf);
*buf++ = 0x8f;
return SLJIT_SUCCESS;
}
/* For UNUSED dst. Uncommon, but possible. */
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!buf);
INC_SIZE(1);
POP_REG(reg_map[TMP_REGISTER]);
/* Memory. */
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
FAIL_IF(!inst);
*inst++ = POP_rm;
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
sljit_ub *buf;
sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_fast_return(compiler, src, srcw);
@@ -490,32 +524,32 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
CHECK_EXTRA_REGS(src, srcw, (void)0);
if (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_NO_REGISTERS) {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
FAIL_IF(!buf);
if (src <= TMP_REGISTER) {
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1 + 1);
PUSH_REG(reg_map[src]);
}
else if (src & SLJIT_MEM) {
buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
FAIL_IF(!buf);
*buf++ = 0xff;
*buf |= 6 << 3;
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = GROUP_FF;
*inst |= PUSH_rm;
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
}
else {
/* SLJIT_IMM. */
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
FAIL_IF(!inst);
INC_SIZE(5 + 1);
*buf++ = 0x68;
*(sljit_w*)buf = srcw;
buf += sizeof(sljit_w);
*inst++ = PUSH_i32;
*(sljit_sw*)inst = srcw;
inst += sizeof(sljit_sw);
}
RET();

View File

@@ -26,75 +26,76 @@
/* x86 64-bit arch dependent functions. */
static int emit_load_imm64(struct sljit_compiler *compiler, int reg, sljit_w imm)
static sljit_si emit_load_imm64(struct sljit_compiler *compiler, sljit_si reg, sljit_sw imm)
{
sljit_ub *buf;
sljit_ub *inst;
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_w));
FAIL_IF(!buf);
INC_SIZE(2 + sizeof(sljit_w));
*buf++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
*buf++ = 0xb8 + (reg_map[reg] & 0x7);
*(sljit_w*)buf = imm;
inst = (sljit_ub*)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++ = MOV_r_i32 + (reg_map[reg] & 0x7);
*(sljit_sw*)inst = imm;
return SLJIT_SUCCESS;
}
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, int type)
static sljit_ub* generate_far_jump_code(struct sljit_jump *jump, sljit_ub *code_ptr, sljit_si type)
{
if (type < SLJIT_JUMP) {
/* Invert type. */
*code_ptr++ = get_jump_code(type ^ 0x1) - 0x10;
*code_ptr++ = 10 + 3;
}
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_first);
*code_ptr++ = REX_W | REX_B;
*code_ptr++ = 0xb8 + 1;
*code_ptr++ = MOV_r_i32 + 1;
jump->addr = (sljit_uw)code_ptr;
if (jump->flags & JUMP_LABEL)
jump->flags |= PATCH_MD;
else
*(sljit_w*)code_ptr = jump->u.target;
*(sljit_sw*)code_ptr = jump->u.target;
code_ptr += sizeof(sljit_w);
code_ptr += sizeof(sljit_sw);
*code_ptr++ = REX_B;
*code_ptr++ = 0xff;
*code_ptr++ = (type >= SLJIT_FAST_CALL) ? 0xd1 /* call */ : 0xe1 /* jmp */;
*code_ptr++ = GROUP_FF;
*code_ptr++ = (type >= SLJIT_FAST_CALL) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
return code_ptr;
}
static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_w addr, int type)
static sljit_ub* generate_fixed_jump(sljit_ub *code_ptr, sljit_sw addr, sljit_si type)
{
sljit_w delta = addr - ((sljit_w)code_ptr + 1 + sizeof(sljit_hw));
sljit_sw delta = addr - ((sljit_sw)code_ptr + 1 + sizeof(sljit_si));
if (delta <= SLJIT_W(0x7fffffff) && delta >= SLJIT_W(-0x80000000)) {
*code_ptr++ = (type == 2) ? 0xe8 /* call */ : 0xe9 /* jmp */;
*(sljit_w*)code_ptr = delta;
*code_ptr++ = (type == 2) ? CALL_i32 : JMP_i32;
*(sljit_sw*)code_ptr = delta;
}
else {
SLJIT_COMPILE_ASSERT(reg_map[TMP_REG3] == 9, tmp3_is_9_second);
*code_ptr++ = REX_W | REX_B;
*code_ptr++ = 0xb8 + 1;
*(sljit_w*)code_ptr = addr;
code_ptr += sizeof(sljit_w);
*code_ptr++ = MOV_r_i32 + 1;
*(sljit_sw*)code_ptr = addr;
code_ptr += sizeof(sljit_sw);
*code_ptr++ = REX_B;
*code_ptr++ = 0xff;
*code_ptr++ = (type == 2) ? 0xd1 /* call */ : 0xe1 /* jmp */;
*code_ptr++ = GROUP_FF;
*code_ptr++ = (type == 2) ? (MOD_REG | CALL_rm | 1) : (MOD_REG | JMP_rm | 1);
}
return code_ptr;
}
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
int size, pushed_size;
sljit_ub *buf;
sljit_si size, pushed_size;
sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_enter(compiler, args, temporaries, saveds, local_size);
check_sljit_emit_enter(compiler, args, scratches, saveds, local_size);
compiler->temporaries = temporaries;
compiler->scratches = scratches;
compiler->saveds = saveds;
compiler->flags_saved = 0;
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
@@ -103,38 +104,38 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
size = saveds;
/* Including the return address saved by the call instruction. */
pushed_size = (saveds + 1) * sizeof(sljit_w);
pushed_size = (saveds + 1) * sizeof(sljit_sw);
#ifndef _WIN64
if (saveds >= 2)
size += saveds - 1;
#else
if (saveds >= 4)
size += saveds - 3;
if (temporaries >= 5) {
if (scratches >= 5) {
size += (5 - 4) * 2;
pushed_size += sizeof(sljit_w);
pushed_size += sizeof(sljit_sw);
}
#endif
size += args * 3;
if (size > 0) {
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
FAIL_IF(!inst);
INC_SIZE(size);
if (saveds >= 5) {
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG2] >= 8, saved_ereg2_is_hireg);
*buf++ = REX_B;
*inst++ = REX_B;
PUSH_REG(reg_lmap[SLJIT_SAVED_EREG2]);
}
if (saveds >= 4) {
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_EREG1] >= 8, saved_ereg1_is_hireg);
*buf++ = REX_B;
*inst++ = REX_B;
PUSH_REG(reg_lmap[SLJIT_SAVED_EREG1]);
}
if (saveds >= 3) {
#ifndef _WIN64
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] >= 8, saved_reg3_is_hireg);
*buf++ = REX_B;
*inst++ = REX_B;
#else
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG3] < 8, saved_reg3_is_loreg);
#endif
@@ -143,7 +144,7 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
if (saveds >= 2) {
#ifndef _WIN64
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] >= 8, saved_reg2_is_hireg);
*buf++ = REX_B;
*inst++ = REX_B;
#else
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SAVED_REG2] < 8, saved_reg2_is_loreg);
#endif
@@ -154,44 +155,44 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
PUSH_REG(reg_lmap[SLJIT_SAVED_REG1]);
}
#ifdef _WIN64
if (temporaries >= 5) {
if (scratches >= 5) {
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_EREG2] >= 8, temporary_ereg2_is_hireg);
*buf++ = REX_B;
*inst++ = REX_B;
PUSH_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
}
#endif
#ifndef _WIN64
if (args > 0) {
*buf++ = REX_W;
*buf++ = 0x8b;
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x7;
*inst++ = REX_W;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x7 /* rdi */;
}
if (args > 1) {
*buf++ = REX_W | REX_R;
*buf++ = 0x8b;
*buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6;
*inst++ = REX_W | REX_R;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (reg_lmap[SLJIT_SAVED_REG2] << 3) | 0x6 /* rsi */;
}
if (args > 2) {
*buf++ = REX_W | REX_R;
*buf++ = 0x8b;
*buf++ = 0xc0 | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2;
*inst++ = REX_W | REX_R;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (reg_lmap[SLJIT_SAVED_REG3] << 3) | 0x2 /* rdx */;
}
#else
if (args > 0) {
*buf++ = REX_W;
*buf++ = 0x8b;
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1;
*inst++ = REX_W;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG1] << 3) | 0x1 /* rcx */;
}
if (args > 1) {
*buf++ = REX_W;
*buf++ = 0x8b;
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2;
*inst++ = REX_W;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG2] << 3) | 0x2 /* rdx */;
}
if (args > 2) {
*buf++ = REX_W | REX_B;
*buf++ = 0x8b;
*buf++ = 0xc0 | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0;
*inst++ = REX_W | REX_B;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (reg_map[SLJIT_SAVED_REG3] << 3) | 0x0 /* r8 */;
}
#endif
}
@@ -201,101 +202,124 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_enter(struct sljit_compiler *compiler, i
#ifdef _WIN64
if (local_size > 1024) {
/* Allocate stack for the callback, which grows the stack. */
buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!buf);
INC_SIZE(4);
*buf++ = REX_W;
*buf++ = 0x83;
*buf++ = 0xc0 | (5 << 3) | 4;
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4 + (3 + sizeof(sljit_si)));
FAIL_IF(!inst);
INC_SIZE(4 + (3 + sizeof(sljit_si)));
*inst++ = REX_W;
*inst++ = GROUP_BINARY_83;
*inst++ = MOD_REG | SUB | 4;
/* Pushed size must be divisible by 8. */
SLJIT_ASSERT(!(pushed_size & 0x7));
if (pushed_size & 0x8) {
*buf++ = 5 * sizeof(sljit_w);
local_size -= 5 * sizeof(sljit_w);
*inst++ = 5 * sizeof(sljit_sw);
local_size -= 5 * sizeof(sljit_sw);
} else {
*buf++ = 4 * sizeof(sljit_w);
local_size -= 4 * sizeof(sljit_w);
*inst++ = 4 * sizeof(sljit_sw);
local_size -= 4 * sizeof(sljit_sw);
}
FAIL_IF(emit_load_imm64(compiler, SLJIT_TEMPORARY_REG1, local_size));
/* Second instruction */
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG1] < 8, temporary_reg1_is_loreg);
*inst++ = REX_W;
*inst++ = MOV_rm_i32;
*inst++ = MOD_REG | reg_lmap[SLJIT_SCRATCH_REG1];
*(sljit_si*)inst = local_size;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
compiler->skip_checks = 1;
#endif
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_CALL1, SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_grow_stack)));
}
#endif
SLJIT_ASSERT(local_size > 0);
if (local_size <= 127) {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!inst);
INC_SIZE(4);
*buf++ = REX_W;
*buf++ = 0x83;
*buf++ = 0xc0 | (5 << 3) | 4;
*buf++ = local_size;
*inst++ = REX_W;
*inst++ = GROUP_BINARY_83;
*inst++ = MOD_REG | SUB | 4;
*inst++ = local_size;
}
else {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
FAIL_IF(!inst);
INC_SIZE(7);
*buf++ = REX_W;
*buf++ = 0x81;
*buf++ = 0xc0 | (5 << 3) | 4;
*(sljit_hw*)buf = local_size;
buf += sizeof(sljit_hw);
*inst++ = REX_W;
*inst++ = GROUP_BINARY_81;
*inst++ = MOD_REG | SUB | 4;
*(sljit_si*)inst = local_size;
inst += sizeof(sljit_si);
}
#ifdef _WIN64
/* Save xmm6 with MOVAPS instruction. */
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
FAIL_IF(!inst);
INC_SIZE(5);
*inst++ = GROUP_0F;
*(sljit_si*)inst = 0x20247429;
#endif
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, int args, int temporaries, int saveds, int local_size)
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si local_size)
{
int pushed_size;
sljit_si pushed_size;
CHECK_ERROR_VOID();
check_sljit_set_context(compiler, args, temporaries, saveds, local_size);
check_sljit_set_context(compiler, args, scratches, saveds, local_size);
compiler->temporaries = temporaries;
compiler->scratches = scratches;
compiler->saveds = saveds;
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
compiler->logical_local_size = local_size;
#endif
/* Including the return address saved by the call instruction. */
pushed_size = (saveds + 1) * sizeof(sljit_w);
pushed_size = (saveds + 1) * sizeof(sljit_sw);
#ifdef _WIN64
if (temporaries >= 5)
pushed_size += sizeof(sljit_w);
if (scratches >= 5)
pushed_size += sizeof(sljit_sw);
#endif
compiler->local_size = ((local_size + FIXED_LOCALS_OFFSET + pushed_size + 16 - 1) & ~(16 - 1)) - pushed_size;
}
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler, int op, int src, sljit_w srcw)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw)
{
int size;
sljit_ub *buf;
sljit_si size;
sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_return(compiler, op, src, srcw);
ADJUST_LOCAL_OFFSET(src, srcw);
compiler->flags_saved = 0;
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
#ifdef _WIN64
/* Restore xmm6 with MOVAPS instruction. */
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5);
FAIL_IF(!inst);
INC_SIZE(5);
*inst++ = GROUP_0F;
*(sljit_si*)inst = 0x20247428;
#endif
SLJIT_ASSERT(compiler->local_size > 0);
if (compiler->local_size <= 127) {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 4);
FAIL_IF(!inst);
INC_SIZE(4);
*buf++ = REX_W;
*buf++ = 0x83;
*buf++ = 0xc0 | (0 << 3) | 4;
*buf = compiler->local_size;
*inst++ = REX_W;
*inst++ = GROUP_BINARY_83;
*inst++ = MOD_REG | ADD | 4;
*inst = compiler->local_size;
}
else {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 7);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 7);
FAIL_IF(!inst);
INC_SIZE(7);
*buf++ = REX_W;
*buf++ = 0x81;
*buf++ = 0xc0 | (0 << 3) | 4;
*(sljit_hw*)buf = compiler->local_size;
*inst++ = REX_W;
*inst++ = GROUP_BINARY_81;
*inst++ = MOD_REG | ADD | 4;
*(sljit_si*)inst = compiler->local_size;
}
size = 1 + compiler->saveds;
@@ -305,17 +329,17 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
#else
if (compiler->saveds >= 4)
size += compiler->saveds - 3;
if (compiler->temporaries >= 5)
if (compiler->scratches >= 5)
size += (5 - 4) * 2;
#endif
buf = (sljit_ub*)ensure_buf(compiler, 1 + size);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + size);
FAIL_IF(!inst);
INC_SIZE(size);
#ifdef _WIN64
if (compiler->temporaries >= 5) {
*buf++ = REX_B;
if (compiler->scratches >= 5) {
*inst++ = REX_B;
POP_REG(reg_lmap[SLJIT_TEMPORARY_EREG2]);
}
#endif
@@ -323,22 +347,22 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
POP_REG(reg_map[SLJIT_SAVED_REG1]);
if (compiler->saveds >= 2) {
#ifndef _WIN64
*buf++ = REX_B;
*inst++ = REX_B;
#endif
POP_REG(reg_lmap[SLJIT_SAVED_REG2]);
}
if (compiler->saveds >= 3) {
#ifndef _WIN64
*buf++ = REX_B;
*inst++ = REX_B;
#endif
POP_REG(reg_lmap[SLJIT_SAVED_REG3]);
}
if (compiler->saveds >= 4) {
*buf++ = REX_B;
*inst++ = REX_B;
POP_REG(reg_lmap[SLJIT_SAVED_EREG1]);
}
if (compiler->saveds >= 5) {
*buf++ = REX_B;
*inst++ = REX_B;
POP_REG(reg_lmap[SLJIT_SAVED_EREG2]);
}
@@ -350,39 +374,32 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_return(struct sljit_compiler *compiler,
/* Operators */
/* --------------------------------------------------------------------- */
static int emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_w imm)
static sljit_si emit_do_imm32(struct sljit_compiler *compiler, sljit_ub rex, sljit_ub opcode, sljit_sw imm)
{
sljit_ub *buf;
sljit_ub *inst;
sljit_si length = 1 + (rex ? 1 : 0) + sizeof(sljit_si);
if (rex != 0) {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + sizeof(sljit_hw));
FAIL_IF(!buf);
INC_SIZE(2 + sizeof(sljit_hw));
*buf++ = rex;
*buf++ = opcode;
*(sljit_hw*)buf = imm;
}
else {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + sizeof(sljit_hw));
FAIL_IF(!buf);
INC_SIZE(1 + sizeof(sljit_hw));
*buf++ = opcode;
*(sljit_hw*)buf = imm;
}
inst = (sljit_ub*)ensure_buf(compiler, 1 + length);
FAIL_IF(!inst);
INC_SIZE(length);
if (rex)
*inst++ = rex;
*inst++ = opcode;
*(sljit_si*)inst = imm;
return SLJIT_SUCCESS;
}
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, sljit_si size,
/* The register or immediate operand. */
int a, sljit_w imma,
sljit_si a, sljit_sw imma,
/* The general operand (not immediate). */
int b, sljit_w immb)
sljit_si b, sljit_sw immb)
{
sljit_ub *buf;
sljit_ub *inst;
sljit_ub *buf_ptr;
sljit_ub rex = 0;
int flags = size & ~0xf;
int inst_size;
sljit_si flags = size & ~0xf;
sljit_si inst_size;
/* The immediate operand must be 32 bit. */
SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
@@ -395,6 +412,9 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
/* 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));
#endif
size &= 0xf;
@@ -416,7 +436,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
rex |= REX;
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
if (flags & EX86_PREF_F2)
if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
inst_size++;
#endif
if (flags & EX86_PREF_66)
@@ -426,16 +446,16 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
inst_size += 1; /* mod r/m byte. */
if (b & SLJIT_MEM) {
if ((b & 0x0f) == SLJIT_UNUSED)
inst_size += 1 + sizeof(sljit_hw); /* SIB byte required to avoid RIP based addressing. */
inst_size += 1 + sizeof(sljit_si); /* SIB byte required to avoid RIP based addressing. */
else {
if (reg_map[b & 0x0f] >= 8)
rex |= REX_B;
if (immb != 0 && !(b & 0xf0)) {
/* Immediate operand. */
if (immb <= 127 && immb >= -128)
inst_size += sizeof(sljit_b);
inst_size += sizeof(sljit_sb);
else
inst_size += sizeof(sljit_hw);
inst_size += sizeof(sljit_si);
}
}
@@ -475,7 +495,7 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else if (flags & EX86_HALF_ARG)
inst_size += sizeof(short);
else
inst_size += sizeof(sljit_hw);
inst_size += sizeof(sljit_si);
}
else {
SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
@@ -492,25 +512,27 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
if (rex)
inst_size++;
buf = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
PTR_FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + inst_size);
PTR_FAIL_IF(!inst);
/* Encoding the byte. */
INC_SIZE(inst_size);
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
if (flags & EX86_PREF_F2)
*buf++ = 0xf2;
*inst++ = 0xf2;
if (flags & EX86_PREF_F3)
*inst++ = 0xf3;
#endif
if (flags & EX86_PREF_66)
*buf++ = 0x66;
*inst++ = 0x66;
if (rex)
*buf++ = rex;
buf_ptr = buf + size;
*inst++ = rex;
buf_ptr = inst + size;
/* Encode mod/rm byte. */
if (!(flags & EX86_SHIFT_INS)) {
if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
*buf = (flags & EX86_BYTE_ARG) ? 0x83 : 0x81;
*inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
if ((a & SLJIT_IMM) || (a == 0))
*buf_ptr = 0;
@@ -527,19 +549,19 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else {
if (a & SLJIT_IMM) {
if (imma == 1)
*buf = 0xd1;
*inst = GROUP_SHIFT_1;
else
*buf = 0xc1;
*inst = GROUP_SHIFT_N;
} else
*buf = 0xd3;
*inst = GROUP_SHIFT_CL;
*buf_ptr = 0;
}
if (!(b & SLJIT_MEM))
#if (defined SLJIT_SSE2 && SLJIT_SSE2)
*buf_ptr++ |= 0xc0 + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b);
*buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2)) ? reg_lmap[b] : b);
#else
*buf_ptr++ |= 0xc0 + reg_lmap[b];
*buf_ptr++ |= MOD_REG + reg_lmap[b];
#endif
else if ((b & 0x0f) != SLJIT_UNUSED) {
if ((b & 0xf0) == SLJIT_UNUSED || (b & 0xf0) == (SLJIT_LOCALS_REG << 4)) {
@@ -561,8 +583,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
if (immb <= 127 && immb >= -128)
*buf_ptr++ = immb; /* 8 bit displacement. */
else {
*(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
buf_ptr += sizeof(sljit_hw);
*(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
buf_ptr += sizeof(sljit_si);
}
}
}
@@ -574,8 +596,8 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else {
*buf_ptr++ |= 0x04;
*buf_ptr++ = 0x25;
*(sljit_hw*)buf_ptr = immb; /* 32 bit displacement. */
buf_ptr += sizeof(sljit_hw);
*(sljit_si*)buf_ptr = immb; /* 32 bit displacement. */
buf_ptr += sizeof(sljit_si);
}
if (a & SLJIT_IMM) {
@@ -584,55 +606,55 @@ static sljit_ub* emit_x86_instruction(struct sljit_compiler *compiler, int size,
else if (flags & EX86_HALF_ARG)
*(short*)buf_ptr = imma;
else if (!(flags & EX86_SHIFT_INS))
*(sljit_hw*)buf_ptr = imma;
*(sljit_si*)buf_ptr = imma;
}
return !(flags & EX86_SHIFT_INS) ? buf : (buf + 1);
return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
}
/* --------------------------------------------------------------------- */
/* Call / return instructions */
/* --------------------------------------------------------------------- */
static SLJIT_INLINE int call_with_args(struct sljit_compiler *compiler, int type)
static SLJIT_INLINE sljit_si call_with_args(struct sljit_compiler *compiler, sljit_si type)
{
sljit_ub *buf;
sljit_ub *inst;
#ifndef _WIN64
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 6 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG2] == 6 && reg_map[SLJIT_SCRATCH_REG1] < 8 && reg_map[SLJIT_SCRATCH_REG3] < 8, args_registers);
buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
FAIL_IF(!inst);
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
if (type >= SLJIT_CALL3) {
*buf++ = REX_W;
*buf++ = 0x8b;
*buf++ = 0xc0 | (0x2 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
*inst++ = REX_W;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (0x2 /* rdx */ << 3) | reg_lmap[SLJIT_SCRATCH_REG3];
}
*buf++ = REX_W;
*buf++ = 0x8b;
*buf++ = 0xc0 | (0x7 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
*inst++ = REX_W;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (0x7 /* rdi */ << 3) | reg_lmap[SLJIT_SCRATCH_REG1];
#else
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_TEMPORARY_REG2] == 2 && reg_map[SLJIT_TEMPORARY_REG1] < 8 && reg_map[SLJIT_TEMPORARY_REG3] < 8, args_registers);
SLJIT_COMPILE_ASSERT(reg_map[SLJIT_SCRATCH_REG2] == 2 && reg_map[SLJIT_SCRATCH_REG1] < 8 && reg_map[SLJIT_SCRATCH_REG3] < 8, args_registers);
buf = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + ((type < SLJIT_CALL3) ? 3 : 6));
FAIL_IF(!inst);
INC_SIZE((type < SLJIT_CALL3) ? 3 : 6);
if (type >= SLJIT_CALL3) {
*buf++ = REX_W | REX_R;
*buf++ = 0x8b;
*buf++ = 0xc0 | (0x0 << 3) | reg_lmap[SLJIT_TEMPORARY_REG3];
*inst++ = REX_W | REX_R;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (0x0 /* r8 */ << 3) | reg_lmap[SLJIT_SCRATCH_REG3];
}
*buf++ = REX_W;
*buf++ = 0x8b;
*buf++ = 0xc0 | (0x1 << 3) | reg_lmap[SLJIT_TEMPORARY_REG1];
*inst++ = REX_W;
*inst++ = MOV_r_rm;
*inst++ = MOD_REG | (0x1 /* rcx */ << 3) | reg_lmap[SLJIT_SCRATCH_REG1];
#endif
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compiler, int dst, sljit_w dstw)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw)
{
sljit_ub *buf;
sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_fast_enter(compiler, dst, dstw);
@@ -642,36 +664,34 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_enter(struct sljit_compiler *compil
if (dst == SLJIT_UNUSED)
dst = TMP_REGISTER;
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= TMP_REGISTER) {
if (dst <= TMP_REGISTER) {
if (reg_map[dst] < 8) {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
POP_REG(reg_lmap[dst]);
return SLJIT_SUCCESS;
}
else {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!buf);
INC_SIZE(2);
*buf++ = REX_B;
POP_REG(reg_lmap[dst]);
}
}
else if (dst & SLJIT_MEM) {
/* REX_W is not necessary (src is not immediate). */
compiler->mode32 = 1;
buf = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
FAIL_IF(!buf);
*buf++ = 0x8f;
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
INC_SIZE(2);
*inst++ = REX_B;
POP_REG(reg_lmap[dst]);
return SLJIT_SUCCESS;
}
/* REX_W is not necessary (src is not immediate). */
compiler->mode32 = 1;
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, dstw);
FAIL_IF(!inst);
*inst++ = POP_rm;
return SLJIT_SUCCESS;
}
SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compiler, int src, sljit_w srcw)
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw)
{
sljit_ub *buf;
sljit_ub *inst;
CHECK_ERROR();
check_sljit_emit_fast_return(compiler, src, srcw);
@@ -682,45 +702,45 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
src = TMP_REGISTER;
}
if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REGISTER) {
if (src <= TMP_REGISTER) {
if (reg_map[src] < 8) {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1 + 1);
PUSH_REG(reg_lmap[src]);
}
else {
buf = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 2 + 1);
FAIL_IF(!inst);
INC_SIZE(2 + 1);
*buf++ = REX_B;
*inst++ = REX_B;
PUSH_REG(reg_lmap[src]);
}
}
else if (src & SLJIT_MEM) {
/* REX_W is not necessary (src is not immediate). */
compiler->mode32 = 1;
buf = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
FAIL_IF(!buf);
*buf++ = 0xff;
*buf |= 6 << 3;
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = GROUP_FF;
*inst |= PUSH_rm;
buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
}
else {
SLJIT_ASSERT(IS_HALFWORD(srcw));
/* SLJIT_IMM. */
buf = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
FAIL_IF(!buf);
inst = (sljit_ub*)ensure_buf(compiler, 1 + 5 + 1);
FAIL_IF(!inst);
INC_SIZE(5 + 1);
*buf++ = 0x68;
*(sljit_hw*)buf = srcw;
buf += sizeof(sljit_hw);
*inst++ = PUSH_i32;
*(sljit_si*)inst = srcw;
inst += sizeof(sljit_si);
}
RET();
@@ -732,12 +752,12 @@ SLJIT_API_FUNC_ATTRIBUTE int sljit_emit_fast_return(struct sljit_compiler *compi
/* Extend input */
/* --------------------------------------------------------------------- */
static int emit_mov_int(struct sljit_compiler *compiler, int sign,
int dst, sljit_w dstw,
int src, sljit_w srcw)
static sljit_si emit_mov_int(struct sljit_compiler *compiler, sljit_si sign,
sljit_si dst, sljit_sw dstw,
sljit_si src, sljit_sw srcw)
{
sljit_ub* code;
int dst_r;
sljit_ub* inst;
sljit_si dst_r;
compiler->mode32 = 0;
@@ -745,32 +765,32 @@ static int emit_mov_int(struct sljit_compiler *compiler, int sign,
return SLJIT_SUCCESS; /* Empty instruction. */
if (src & SLJIT_IMM) {
if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
if (dst <= TMP_REGISTER) {
if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
FAIL_IF(!code);
*code = 0xc7;
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
FAIL_IF(!inst);
*inst = MOV_rm_i32;
return SLJIT_SUCCESS;
}
return emit_load_imm64(compiler, dst, srcw);
}
compiler->mode32 = 1;
code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
FAIL_IF(!code);
*code = 0xc7;
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_sw)(sljit_si)srcw, dst, dstw);
FAIL_IF(!inst);
*inst = MOV_rm_i32;
compiler->mode32 = 0;
return SLJIT_SUCCESS;
}
dst_r = (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_SAVED_REG3) ? dst : TMP_REGISTER;
dst_r = (dst <= TMP_REGISTER) ? dst : TMP_REGISTER;
if ((dst & SLJIT_MEM) && (src >= SLJIT_TEMPORARY_REG1 && src <= SLJIT_SAVED_REG3))
if ((dst & SLJIT_MEM) && (src <= TMP_REGISTER))
dst_r = src;
else {
if (sign) {
code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
FAIL_IF(!code);
*code++ = 0x63;
inst = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = MOVSXD_r_rm;
} else {
compiler->mode32 = 1;
FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));
@@ -780,9 +800,9 @@ static int emit_mov_int(struct sljit_compiler *compiler, int sign,
if (dst & SLJIT_MEM) {
compiler->mode32 = 1;
code = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
FAIL_IF(!code);
*code = 0x89;
inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
FAIL_IF(!inst);
*inst = MOV_rm_r;
compiler->mode32 = 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,14 @@
/* This file contains definitions of the property values that are returned by
the UCD access macros. New values that are added for new releases of Unicode
should always be at the end of each enum, for backwards compatibility. */
should always be at the end of each enum, for backwards compatibility.
IMPORTANT: Note also that the specific numeric values of the enums have to be
the same as the values that are generated by the maint/MultiStage2.py script,
where the equivalent property descriptive names are listed in vectors.
ALSO: The specific values of the first two enums are assumed for the table
called catposstab in pcre_compile.c. */
/* These are the general character categories. */
@@ -21,7 +28,7 @@ enum {
ucp_Z /* Separator */
};
/* These are the particular character types. */
/* These are the particular character categories. */
enum {
ucp_Cc, /* Control */
@@ -56,6 +63,26 @@ enum {
ucp_Zs /* Space separator */
};
/* These are grapheme break properties. Note that the code for processing them
assumes that the values are less than 16. If more values are added that take
the number to 16 or more, the code will have to be rewritten. */
enum {
ucp_gbCR, /* 0 */
ucp_gbLF, /* 1 */
ucp_gbControl, /* 2 */
ucp_gbExtend, /* 3 */
ucp_gbPrepend, /* 4 */
ucp_gbSpacingMark, /* 5 */
ucp_gbL, /* 6 Hangul syllable type L */
ucp_gbV, /* 7 Hangul syllable type V */
ucp_gbT, /* 8 Hangul syllable type T */
ucp_gbLV, /* 9 Hangul syllable type LV */
ucp_gbLVT, /* 10 Hangul syllable type LVT */
ucp_gbRegionalIndicator, /* 11 */
ucp_gbOther /* 12 */
};
/* These are the script identifications. */
enum {