summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmake/QtTargetHelpers.cmake19
-rw-r--r--cmake/configure-cmake-mapping.md1
-rw-r--r--config_help.txt2
-rw-r--r--src/3rdparty/pcre2/AUTHORS.md16
-rw-r--r--src/3rdparty/pcre2/CMakeLists.txt1
-rw-r--r--src/3rdparty/pcre2/LICENCE.md9
-rw-r--r--src/3rdparty/pcre2/LICENSE-SLJIT (renamed from src/3rdparty/pcre2/LICENCE-SLJIT)0
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c48
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitConfigInternal.h68
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitLir.c427
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitLir.h249
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_32.c286
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_64.c298
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_T2_32.c293
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c293
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_32.c9
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_64.c13
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c294
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_32.c4
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_64.c8
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_common.c326
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_32.c34
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_64.c167
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_common.c1716
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeS390X.c602
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_32.c62
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_64.c31
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_common.c360
-rw-r--r--src/3rdparty/pcre2/deps/sljit/sljit_src/sljitSerialize.c89
-rwxr-xr-xsrc/3rdparty/pcre2/import_from_pcre2_tarball.sh9
-rw-r--r--src/3rdparty/pcre2/qt_attribution.json19
-rw-r--r--src/3rdparty/pcre2/src/pcre2.h52
-rw-r--r--src/3rdparty/pcre2/src/pcre2_auto_possess.c20
-rw-r--r--src/3rdparty/pcre2/src/pcre2_chartables.c4
-rw-r--r--src/3rdparty/pcre2/src/pcre2_chkdint.c8
-rw-r--r--src/3rdparty/pcre2/src/pcre2_compile.c1360
-rw-r--r--src/3rdparty/pcre2/src/pcre2_compile.h116
-rw-r--r--src/3rdparty/pcre2/src/pcre2_compile_cgroup.c632
-rw-r--r--src/3rdparty/pcre2/src/pcre2_compile_class.c60
-rw-r--r--src/3rdparty/pcre2/src/pcre2_config.c28
-rw-r--r--src/3rdparty/pcre2/src/pcre2_context.c23
-rw-r--r--src/3rdparty/pcre2/src/pcre2_dfa_match.c114
-rw-r--r--src/3rdparty/pcre2/src/pcre2_error.c45
-rw-r--r--src/3rdparty/pcre2/src/pcre2_extuni.c7
-rw-r--r--src/3rdparty/pcre2/src/pcre2_find_bracket.c5
-rw-r--r--src/3rdparty/pcre2/src/pcre2_internal.h434
-rw-r--r--src/3rdparty/pcre2/src/pcre2_intmodedep.h119
-rw-r--r--src/3rdparty/pcre2/src/pcre2_jit_char_inc.h26
-rw-r--r--src/3rdparty/pcre2/src/pcre2_jit_compile.c411
-rw-r--r--src/3rdparty/pcre2/src/pcre2_jit_match_inc.h (renamed from src/3rdparty/pcre2/src/pcre2_jit_match.c)12
-rw-r--r--src/3rdparty/pcre2/src/pcre2_jit_misc_inc.h (renamed from src/3rdparty/pcre2/src/pcre2_jit_misc.c)2
-rw-r--r--src/3rdparty/pcre2/src/pcre2_jit_neon_inc.h354
-rw-r--r--src/3rdparty/pcre2/src/pcre2_jit_simd_inc.h808
-rw-r--r--src/3rdparty/pcre2/src/pcre2_maketables.c62
-rw-r--r--src/3rdparty/pcre2/src/pcre2_match.c293
-rw-r--r--src/3rdparty/pcre2/src/pcre2_match_data.c5
-rw-r--r--src/3rdparty/pcre2/src/pcre2_newline.c4
-rw-r--r--src/3rdparty/pcre2/src/pcre2_ord2utf.c12
-rw-r--r--src/3rdparty/pcre2/src/pcre2_pattern_info.c8
-rw-r--r--src/3rdparty/pcre2/src/pcre2_script_run.c5
-rw-r--r--src/3rdparty/pcre2/src/pcre2_serialize.c6
-rw-r--r--src/3rdparty/pcre2/src/pcre2_string_utils.c40
-rw-r--r--src/3rdparty/pcre2/src/pcre2_study.c89
-rw-r--r--src/3rdparty/pcre2/src/pcre2_substitute.c246
-rw-r--r--src/3rdparty/pcre2/src/pcre2_substring.c17
-rw-r--r--src/3rdparty/pcre2/src/pcre2_tables.c112
-rw-r--r--src/3rdparty/pcre2/src/pcre2_ucd.c7
-rw-r--r--src/3rdparty/pcre2/src/pcre2_ucptables_inc.h (renamed from src/3rdparty/pcre2/src/pcre2_ucptables.c)2
-rw-r--r--src/3rdparty/pcre2/src/pcre2_util.h51
-rw-r--r--src/3rdparty/pcre2/src/pcre2_valid_utf.c5
-rw-r--r--src/3rdparty/pcre2/src/pcre2_xclass.c10
-rw-r--r--src/3rdparty/sha3/qt_attribution.json2
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java23
-rw-r--r--src/corelib/Qt6AndroidMacros.cmake183
-rw-r--r--src/corelib/io/qlockfile.cpp5
-rw-r--r--src/corelib/itemmodels/qrangemodel.cpp2
-rw-r--r--src/corelib/kernel/qassociativeiterable.cpp10
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp2
-rw-r--r--src/corelib/kernel/qcoreapplication.h2
-rw-r--r--src/corelib/kernel/qpermissions.cpp4
-rw-r--r--src/corelib/kernel/qsequentialiterable.cpp10
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp19
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h2
-rw-r--r--src/corelib/plugin/qlibrary.h1
-rw-r--r--src/corelib/plugin/qlibrary_p.h7
-rw-r--r--src/corelib/serialization/qdatastream.cpp88
-rw-r--r--src/corelib/text/qstring.cpp6
-rw-r--r--src/corelib/text/qunicodetools.cpp55
-rw-r--r--src/corelib/time/qdatetime.cpp186
-rw-r--r--src/dbus/qt_attribution.json2
-rw-r--r--src/gui/accessible/linux/atspiadaptor.cpp4
-rw-r--r--src/gui/accessible/qaccessible.cpp75
-rw-r--r--src/gui/accessible/qaccessiblehelper.cpp77
-rw-r--r--src/gui/accessible/qaccessiblehelper_p.h18
-rw-r--r--src/gui/text/qfont_p.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm19
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.cpp19
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.h1
-rw-r--r--src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgtopleveliconv1.cpp1
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputdevice.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp5
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp15
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp1
-rw-r--r--src/plugins/platforms/xcb/qxcbatom.cpp1
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style.cpp120
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style_p.h2
-rw-r--r--src/plugins/styles/modernwindows/qwindowsvistastyle.cpp14
-rw-r--r--src/tools/bootstrap/CMakeLists.txt1
-rw-r--r--src/widgets/CMakeLists.txt1
-rw-r--r--src/widgets/accessible/qaccessiblewidgets.cpp46
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp133
-rw-r--r--src/widgets/dialogs/qcolorwell_p.h142
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp1
-rw-r--r--src/widgets/dialogs/qfiledialog_p.h5
-rw-r--r--src/widgets/styles/qwindowsstyle.cpp13
-rw-r--r--tests/auto/corelib/animation/qparallelanimationgroup/tst_qparallelanimationgroup.cpp13
-rw-r--r--tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp6
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp25
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h7
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp10
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp27
-rw-r--r--tests/auto/corelib/plugin/CMakeLists.txt4
-rw-r--r--tests/auto/corelib/plugin/qlibrary/tst/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp8
-rw-r--r--tests/auto/corelib/tools/collections/tst_collections.cpp4
-rw-r--r--tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp6
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp20
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp1
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp9
130 files changed, 9119 insertions, 3722 deletions
diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake
index 632fb5b5644..7b2d51d69a7 100644
--- a/cmake/QtTargetHelpers.cmake
+++ b/cmake/QtTargetHelpers.cmake
@@ -841,13 +841,12 @@ function(qt_internal_export_additional_targets_file)
qt_internal_append_export_additional_targets()
- set_property(GLOBAL APPEND PROPERTY _qt_export_additional_targets_ids "${id}")
set_property(GLOBAL APPEND
PROPERTY _qt_export_additional_targets_export_name_prefix_${id} "${arg_EXPORT_NAME_PREFIX}")
set_property(GLOBAL APPEND
PROPERTY _qt_export_additional_targets_config_install_dir_${id} "${arg_CONFIG_INSTALL_DIR}")
- qt_add_list_file_finalizer(qt_internal_export_additional_targets_file_finalizer)
+ qt_add_list_file_finalizer(qt_internal_export_additional_targets_file_finalizer "${id}")
endfunction()
function(qt_internal_get_export_additional_targets_id export_name out_var)
@@ -913,19 +912,9 @@ function(qt_internal_validate_export_additional_targets)
set(arg_TARGET_EXPORT_NAMES "${arg_TARGET_EXPORT_NAMES}" PARENT_SCOPE)
endfunction()
-# The finalizer might be called multiple times in the same scope, but only the first one will
-# process all the ids.
-function(qt_internal_export_additional_targets_file_finalizer)
- get_property(ids GLOBAL PROPERTY _qt_export_additional_targets_ids)
-
- foreach(id ${ids})
- qt_internal_export_additional_targets_file_handler("${id}")
- endforeach()
-
- set_property(GLOBAL PROPERTY _qt_export_additional_targets_ids "")
-endfunction()
-
-function(qt_internal_export_additional_targets_file_handler id)
+# The finalizer might be called multiple times in the same directory scope, but it will only process
+# one specific id.
+function(qt_internal_export_additional_targets_file_finalizer id)
get_property(arg_EXPORT_NAME_PREFIX GLOBAL PROPERTY
_qt_export_additional_targets_export_name_prefix_${id})
get_property(arg_CONFIG_INSTALL_DIR GLOBAL PROPERTY
diff --git a/cmake/configure-cmake-mapping.md b/cmake/configure-cmake-mapping.md
index 95b1215ddce..fadc03c831b 100644
--- a/cmake/configure-cmake-mapping.md
+++ b/cmake/configure-cmake-mapping.md
@@ -128,7 +128,6 @@ The following table describes the mapping of configure options to CMake argument
| -glib | -DFEATURE_glib=ON | |
| -inotify | -DFEATURE_inotify=ON | |
| -icu | -DFEATURE_icu=ON | |
-| -pcre | -DFEATURE_pcre2=ON | |
| -pcre [system/qt] | -DFEATURE_system_pcre2=ON/OFF | |
| -pps | n/a | QNX feature. Not available for 6.0. |
| -zlib [system/qt] | -DFEATURE_system_zlib=ON/OFF | |
diff --git a/config_help.txt b/config_help.txt
index 27b80654fab..dcd57bdfbc0 100644
--- a/config_help.txt
+++ b/config_help.txt
@@ -274,7 +274,7 @@ Core options:
-inotify ............. Enable inotify support
-icu ................. Enable ICU support [auto]
-jemalloc ............ Enable jemalloc support and cooperation [no]
- -pcre ................ Select used libpcre2 [system/qt/no]
+ -pcre ................ Select used libpcre2 [system/qt]
-zlib ................ Select used zlib [system/qt]
Logging backends:
diff --git a/src/3rdparty/pcre2/AUTHORS.md b/src/3rdparty/pcre2/AUTHORS.md
index 708fc2325ce..ced81e68adc 100644
--- a/src/3rdparty/pcre2/AUTHORS.md
+++ b/src/3rdparty/pcre2/AUTHORS.md
@@ -1,14 +1,14 @@
PCRE2 Authorship and Contributors
=================================
-COPYRIGHT
+Copyright
---------
Please see the file [LICENCE](./LICENCE.md) in the PCRE2 distribution for
copyright details.
-MAINTAINERS
+Maintainers
-----------
The PCRE and PCRE2 libraries were authored and maintained by Philip Hazel.
@@ -62,7 +62,7 @@ Both administrators are volunteers acting in a personal capacity.
</table>
-CONTRIBUTORS
+Contributors
------------
Many others have participated and contributed to PCRE2 over its history.
@@ -77,7 +77,7 @@ All names listed alphabetically.
### Contributors to PCRE2
-This list includes names up until the PCRE2 10.44 release. New names will be
+This list includes names up until the PCRE2 10.47 release. New names will be
added from the Git history on each release.
Scott Bell
@@ -93,13 +93,16 @@ added from the Git history on each release.
Addison Crump
Alex Dowad
Daniel Engberg
+ Marco Feuerstein
Daniel Richard G
+ Isaac Oscar Gariano
David Gaussmann
Andrey Gorbachev
Jordan Griege
Jason Hood
Bumsu Hyeon
Roy Ivy
+ Nobuhiro Iwamatsu
Martin Joerg
Guillem Jover
Ralf Junker
@@ -114,13 +117,17 @@ added from the Git history on each release.
Kai Lu
Behzod Mansurov
B. Scott Michel
+ Greg Minshall
Nathan Moinvaziri
Mike Munday
Marc Mutz
Fabio Pagani
Christian Persch
+ Alex Reinking
+ Joshua Rogers
Tristan Ross
William A Rowe Jr
+ Rocco Ruscitti
David Seifert
Yaakov Selkowitz
Rich Siegel
@@ -131,6 +138,7 @@ added from the Git history on each release.
Greg Thain
Lucas Trzesniewski
Theodore Tsirpanis
+ Aaron M. Ucko
Matthew Vernon
Rémi Verschelde
Thomas Voss
diff --git a/src/3rdparty/pcre2/CMakeLists.txt b/src/3rdparty/pcre2/CMakeLists.txt
index 6b4cd1b1cc3..3f4a4677787 100644
--- a/src/3rdparty/pcre2/CMakeLists.txt
+++ b/src/3rdparty/pcre2/CMakeLists.txt
@@ -15,6 +15,7 @@ qt_internal_add_3rdparty_library(BundledPcre2
src/pcre2_chartables.c
src/pcre2_chkdint.c
src/pcre2_compile.c
+ src/pcre2_compile_cgroup.c
src/pcre2_compile_class.c
src/pcre2_config.c
src/pcre2_context.c
diff --git a/src/3rdparty/pcre2/LICENCE.md b/src/3rdparty/pcre2/LICENCE.md
index f58ceb75a63..f6fba35db25 100644
--- a/src/3rdparty/pcre2/LICENCE.md
+++ b/src/3rdparty/pcre2/LICENCE.md
@@ -1,4 +1,4 @@
-PCRE2 License
+PCRE2 Licence
=============
| SPDX-License-Identifier: | BSD-3-Clause WITH PCRE2-exception |
@@ -16,7 +16,8 @@ testdata directory is not copyrighted and is in the public domain.
The basic library functions are written in C and are freestanding. Also
included in the distribution is a just-in-time compiler that can be used to
optimize pattern matching. This is an optional feature that can be omitted when
-the library is built.
+the library is built. The just-in-time compiler is separately licensed under the
+"2-clause BSD" licence.
COPYRIGHT
@@ -53,6 +54,8 @@ COPYRIGHT
Copyright (c) 2009-2024 Zoltan Herczeg
All rights reserved.
+The code in the `deps/sljit` directory has its own LICENSE file.
+
### All other contributions
Many other contributors have participated in the authorship of PCRE2. As PCRE2
@@ -99,5 +102,3 @@ not apply all the way down a chain of software. If binary package A includes
PCRE2, it must respect the condition, but if package B is software that
includes package A, the condition is not imposed on package B unless it uses
PCRE2 independently.
-
-End
diff --git a/src/3rdparty/pcre2/LICENCE-SLJIT b/src/3rdparty/pcre2/LICENSE-SLJIT
index 0aaecaaa286..0aaecaaa286 100644
--- a/src/3rdparty/pcre2/LICENCE-SLJIT
+++ b/src/3rdparty/pcre2/LICENSE-SLJIT
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c
index 4e1119bc40c..314483c7ae7 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/allocator_src/sljitExecAllocatorCore.c
@@ -49,9 +49,9 @@
n - The size of the previous block.
Using these size values we can go forward or backward on the block chain.
- The unused blocks are stored in a chain list pointed by free_blocks. This
- list is useful if we need to find a suitable memory area when the allocator
- is called.
+ The unused blocks are stored in a chain list pointed by sljit_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.
@@ -115,20 +115,20 @@ struct free_block {
#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7u) & ~(sljit_uw)7)
#define CHUNK_EXTRA_SIZE (sizeof(struct block_header) + CHUNK_HEADER_SIZE)
-static struct free_block* free_blocks;
-static sljit_uw allocated_size;
-static sljit_uw total_size;
+static struct free_block* sljit_free_blocks;
+static sljit_uw sljit_allocated_size;
+static sljit_uw sljit_total_size;
static SLJIT_INLINE void sljit_insert_free_block(struct free_block *free_block, sljit_uw size)
{
free_block->header.size = 0;
free_block->size = size;
- free_block->next = free_blocks;
+ free_block->next = sljit_free_blocks;
free_block->prev = NULL;
- if (free_blocks)
- free_blocks->prev = free_block;
- free_blocks = free_block;
+ if (sljit_free_blocks)
+ sljit_free_blocks->prev = free_block;
+ sljit_free_blocks = free_block;
}
static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)
@@ -139,8 +139,8 @@ static SLJIT_INLINE void sljit_remove_free_block(struct free_block *free_block)
if (free_block->prev)
free_block->prev->next = free_block->next;
else {
- SLJIT_ASSERT(free_blocks == free_block);
- free_blocks = free_block->next;
+ SLJIT_ASSERT(sljit_free_blocks == free_block);
+ sljit_free_blocks = free_block->next;
}
}
@@ -166,7 +166,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
size = ALIGN_SIZE(size);
SLJIT_ALLOCATOR_LOCK();
- free_block = free_blocks;
+ free_block = sljit_free_blocks;
while (free_block) {
if (free_block->size >= size) {
chunk_size = free_block->size;
@@ -186,7 +186,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
header = (struct block_header*)free_block;
size = chunk_size;
}
- allocated_size += size;
+ sljit_allocated_size += size;
header->size = size;
SLJIT_ALLOCATOR_UNLOCK();
return MEM_START(header);
@@ -207,7 +207,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
chunk_size -= CHUNK_EXTRA_SIZE;
- total_size += chunk_size;
+ sljit_total_size += chunk_size;
header = (struct block_header*)(((sljit_u8*)chunk_header) + CHUNK_HEADER_SIZE);
@@ -218,7 +218,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
if (chunk_size > size + 64) {
/* Cut the allocated space into a free and a used block. */
- allocated_size += size;
+ sljit_allocated_size += size;
header->size = size;
chunk_size -= size;
@@ -231,7 +231,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size)
next_header = AS_BLOCK_HEADER(free_block, chunk_size);
} else {
/* All space belongs to this allocation. */
- allocated_size += chunk_size;
+ sljit_allocated_size += chunk_size;
header->size = chunk_size;
next_header = AS_BLOCK_HEADER(header, chunk_size);
}
@@ -254,7 +254,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void *ptr)
#ifdef SLJIT_HAS_EXECUTABLE_OFFSET
header = AS_BLOCK_HEADER(header, -header->executable_offset);
#endif /* SLJIT_HAS_EXECUTABLE_OFFSET */
- allocated_size -= header->size;
+ sljit_allocated_size -= header->size;
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
@@ -282,9 +282,9 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void *ptr)
/* The whole chunk is free. */
if (SLJIT_UNLIKELY(!free_block->header.prev_size && header->size == 1)) {
- /* If this block is freed, we still have (allocated_size / 2) free space. */
- if (total_size - free_block->size > (allocated_size * 3 / 2)) {
- total_size -= free_block->size;
+ /* If this block is freed, we still have (sljit_allocated_size / 2) free space. */
+ if (sljit_total_size - free_block->size > (sljit_allocated_size * 3 / 2)) {
+ sljit_total_size -= free_block->size;
sljit_remove_free_block(free_block);
free_chunk(free_block, free_block->size + CHUNK_EXTRA_SIZE);
}
@@ -302,19 +302,19 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void)
SLJIT_ALLOCATOR_LOCK();
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 0);
- free_block = free_blocks;
+ free_block = sljit_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_total_size -= free_block->size;
sljit_remove_free_block(free_block);
free_chunk(free_block, free_block->size + CHUNK_EXTRA_SIZE);
}
free_block = next_free_block;
}
- SLJIT_ASSERT(total_size || (!total_size && !free_blocks));
+ SLJIT_ASSERT(sljit_total_size || (!sljit_total_size && !sljit_free_blocks));
SLJIT_UPDATE_WX_FLAGS(NULL, NULL, 1);
SLJIT_ALLOCATOR_UNLOCK();
}
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitConfigInternal.h b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitConfigInternal.h
index 3ae944efb81..c052434d2f5 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitConfigInternal.h
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitConfigInternal.h
@@ -71,6 +71,7 @@
SLJIT_SEPARATE_VECTOR_REGISTERS : if this macro is defined, the vector registers do not
overlap with floating point registers
SLJIT_WORD_SHIFT : the shift required to apply when accessing a sljit_sw/sljit_uw array by index
+ SLJIT_POINTER_SHIFT : the shift required to apply when accessing a sljit_sp/sljit_up array by index
SLJIT_F32_SHIFT : the shift required to apply when accessing
a single precision floating point array by index
SLJIT_F64_SHIFT : the shift required to apply when accessing
@@ -96,15 +97,21 @@
SLJIT_TMP_FR(i) : accessing temporary floating point registers
SLJIT_TMP_VR0 .. VR9 : accessing temporary vector registers
SLJIT_TMP_VR(i) : accessing temporary vector registers
- SLJIT_TMP_DEST_REG : a temporary register for results
- SLJIT_TMP_MEM_REG : a temporary base register for accessing memory
- (can be the same as SLJIT_TMP_DEST_REG)
- SLJIT_TMP_DEST_FREG : a temporary register for float results
- SLJIT_TMP_DEST_VREG : a temporary register for vector results
+ SLJIT_TMP_DEST_REG : a temporary register for results, see the rules below
+ SLJIT_TMP_DEST_FREG : a temporary register for float results, see the rules below
+ SLJIT_TMP_DEST_VREG : a temporary register for vector results, see the rules below
+ SLJIT_TMP_OPT_REG : a temporary register which might not be defined, see the rules below
SLJIT_FUNC : calling convention attribute for both calling JIT from C and C calling back from JIT
SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (platform independent helper)
SLJIT_F64_SECOND(reg) : provides the register index of the second 32 bit part of a 64 bit
floating point register when SLJIT_HAS_F64_AS_F32_PAIR returns non-zero
+
+ Temporary register rules (e.g. SLJIT_TMP_DEST_REG / SLJIT_TMP_OPT_REG):
+ Sljit tries to emit instructions without using any temporary registers whenever it is possible.
+ When a single temporary register is needed, it is always the "OPT" register. When two temporary
+ registers are needed, both the "DEST" and "OPT" are used. The x86-32 does not define an "OPT"
+ register, and handles all cases without an "OPT" register which requires an "OPT" register
+ on other architectures.
*/
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
@@ -602,7 +609,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0
-#define SLJIT_TMP_MEM_REG SLJIT_TMP_R0
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
#define SLJIT_LOCALS_OFFSET_BASE (8 * (sljit_s32)sizeof(sljit_sw))
#define SLJIT_PREF_SHIFT_REG SLJIT_R2
@@ -627,7 +633,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))
#endif /* !_WIN64 */
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0
-#define SLJIT_TMP_MEM_REG SLJIT_TMP_R0
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R1
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
#define SLJIT_PREF_SHIFT_REG SLJIT_R3
#define SLJIT_MASKED_SHIFT 1
@@ -644,7 +650,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
-#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
#define SLJIT_LOCALS_OFFSET_BASE 0
@@ -657,7 +663,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0
-#define SLJIT_TMP_MEM_REG SLJIT_TMP_R0
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R1
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
#define SLJIT_LOCALS_OFFSET_BASE (2 * (sljit_s32)sizeof(sljit_sw))
#define SLJIT_MASKED_SHIFT 1
@@ -674,7 +680,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 18
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
-#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX)
#define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * (sljit_s32)sizeof(sljit_sw))
@@ -702,7 +708,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
#define SLJIT_NUMBER_OF_TEMPORARY_REGISTERS 5
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 3
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
-#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
#define SLJIT_MASKED_SHIFT 1
#define SLJIT_MASKED_SHIFT32 1
@@ -721,7 +727,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
#define SLJIT_NUMBER_OF_SAVED_VECTOR_REGISTERS 0
#define SLJIT_NUMBER_OF_TEMPORARY_VECTOR_REGISTERS 2
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
-#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
#define SLJIT_TMP_DEST_VREG SLJIT_TMP_VR0
#define SLJIT_LOCALS_OFFSET_BASE 0
@@ -759,8 +765,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 1
-#define SLJIT_TMP_DEST_REG SLJIT_TMP_R0
-#define SLJIT_TMP_MEM_REG SLJIT_TMP_R2
+#define SLJIT_TMP_DEST_REG SLJIT_TMP_R2
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R1
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
#define SLJIT_LOCALS_OFFSET_BASE SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE
#define SLJIT_MASKED_SHIFT 1
@@ -776,7 +782,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 12
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 2
#define SLJIT_TMP_DEST_REG SLJIT_TMP_R1
-#define SLJIT_TMP_MEM_REG SLJIT_TMP_R1
+#define SLJIT_TMP_OPT_REG SLJIT_TMP_R0
#define SLJIT_TMP_DEST_FREG SLJIT_TMP_FR0
#define SLJIT_LOCALS_OFFSET_BASE 0
#define SLJIT_MASKED_SHIFT 1
@@ -793,7 +799,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
#define SLJIT_NUMBER_OF_TEMPORARY_FLOAT_REGISTERS 0
#define SLJIT_TMP_DEST_REG 0
-#define SLJIT_TMP_MEM_REG 0
#define SLJIT_TMP_DEST_FREG 0
#define SLJIT_LOCALS_OFFSET_BASE 0
@@ -965,6 +970,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void *code);
#endif /* !SLJIT_COMPILE_ASSERT */
+#ifndef SLJIT_FALLTHROUGH
+
+#if defined(__cplusplus) && __cplusplus >= 202002L && \
+ defined(__has_cpp_attribute)
+/* Standards-compatible C++ variant. */
+#if __has_cpp_attribute(fallthrough)
+#define SLJIT_FALLTHROUGH [[fallthrough]];
+#endif
+#elif !defined(__cplusplus) && \
+ defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L && \
+ defined(__has_c_attribute)
+/* Standards-compatible C variant. */
+#if __has_c_attribute(fallthrough)
+#define SLJIT_FALLTHROUGH [[fallthrough]];
+#endif
+#elif ((defined(__clang__) && __clang_major__ >= 10) || \
+ (defined(__GNUC__) && __GNUC__ >= 7)) && \
+ defined(__has_attribute)
+/* Clang and GCC syntax. Rule out old versions because apparently Clang at
+ least has a broken implementation of __has_attribute. */
+#if __has_attribute(fallthrough)
+#define SLJIT_FALLTHROUGH __attribute__((fallthrough));
+#endif
+#endif
+
+#ifndef SLJIT_FALLTHROUGH
+#define SLJIT_FALLTHROUGH
+#endif
+
+#endif /* !SLJIT_FALLTHROUGH */
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitLir.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitLir.c
index 6b2d5564c75..633e794b3bf 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitLir.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitLir.c
@@ -95,17 +95,12 @@
#define VARIABLE_FLAG_SHIFT (10)
/* All variable flags are even. */
#define VARIABLE_FLAG_MASK (0x3e << VARIABLE_FLAG_SHIFT)
+#define ALL_STATUS_FLAGS_MASK (VARIABLE_FLAG_MASK | SLJIT_SET_Z)
#define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT)
#define GET_FLAG_TYPE_MASK(op) (((op) >> VARIABLE_FLAG_SHIFT) & 0x3e)
-
-#define GET_OPCODE(op) \
- ((op) & 0xff)
-
-#define HAS_FLAGS(op) \
- ((op) & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))
-
-#define GET_ALL_FLAGS(op) \
- ((op) & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK))
+#define GET_OPCODE(op) ((op) & 0xff)
+#define HAS_FLAGS(op) ((op) & ALL_STATUS_FLAGS_MASK)
+#define GET_ALL_FLAGS(op) ((op) & (SLJIT_32 | ALL_STATUS_FLAGS_MASK))
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
#define TYPE_CAST_NEEDED(op) \
@@ -155,10 +150,22 @@
#define SLJIT_SIMD_TYPE_MASK(m) ((sljit_s32)0xff000fff & ~(SLJIT_SIMD_FLOAT | SLJIT_SIMD_TEST | (m)))
#define SLJIT_SIMD_TYPE_MASK2(m) ((sljit_s32)0xc0000fff & ~(SLJIT_SIMD_FLOAT | SLJIT_SIMD_TEST | (m)))
-/* Jump flags. */
+/* Label definitions. */
+
+#define SLJIT_LABEL_ALIGNED ((~(sljit_uw)0) - 1)
+
+struct sljit_extended_label {
+ struct sljit_label label;
+ sljit_uw index;
+ sljit_uw data;
+};
+
+/* Jump definitions. */
+
+/* Jump flag bits. */
#define JUMP_ADDR 0x1
#define JUMP_MOV_ADDR 0x2
-/* SLJIT_REWRITABLE_JUMP is 0x1000. */
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
# define PATCH_MB 0x04
@@ -172,14 +179,15 @@
# define JUMP_MAX_SIZE ((sljit_uw)5)
# define CJUMP_MAX_SIZE ((sljit_uw)6)
#endif /* SLJIT_CONFIG_X86_64 */
-# define TYPE_SHIFT 13
+# define TYPE_SHIFT 17
#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
-/* Bits 7..12 is for debug jump size, SLJIT_REWRITABLE_JUMP is 0x1000 */
-# define JUMP_SIZE_SHIFT 7
+/* Bits 7..15 is for debug jump size, SLJIT_REWRITABLE_JUMP is 0x10000 */
+# define JUMP_SIZE_SHIFT 8
#endif /* SLJIT_DEBUG */
#endif /* SLJIT_CONFIG_X86 */
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
# define IS_BL 0x04
# define PATCH_B 0x08
#endif /* SLJIT_CONFIG_ARM_V6 || SLJIT_CONFIG_ARM_V7 */
@@ -194,8 +202,11 @@
#endif /* SLJIT_CONFIG_ARM_V7 */
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
# define IS_COND 0x04
# define IS_BL 0x08
+ /* mov_addr does not use IS_BL */
+# define IS_ABS IS_BL
/* conditional + imm8 */
# define PATCH_TYPE1 0x10
/* conditional + imm20 */
@@ -214,6 +225,7 @@
#endif /* SLJIT_CONFIG_ARM_THUMB2 */
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
# define IS_COND 0x004
# define IS_CBZ 0x008
# define IS_BL 0x010
@@ -227,6 +239,7 @@
#endif /* SLJIT_CONFIG_ARM_64 */
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
# define IS_COND 0x004
# define IS_CALL 0x008
# define PATCH_B 0x010
@@ -243,6 +256,7 @@
#endif /* SLJIT_CONFIG_PPC */
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
# define IS_MOVABLE 0x004
# define IS_JAL 0x008
# define IS_CALL 0x010
@@ -270,26 +284,36 @@
#endif /* SLJIT_CONFIG_MIPS */
#if (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
-# define IS_COND 0x004
-# define IS_CALL 0x008
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
+# define IS_COND 0x0004
+# define IS_CALL 0x0008
-# define PATCH_B 0x010
-# define PATCH_J 0x020
+# define IS_COND16 0x0010
+# define PATCH_B 0x0020
+# define PATCH_J 0x0040
+# define PATCH_16 0x0080
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
-# define PATCH_REL32 0x040
-# define PATCH_ABS32 0x080
-# define PATCH_ABS44 0x100
-# define PATCH_ABS52 0x200
+# define PATCH_REL32 0x0100
+# define PATCH_ABS32 0x0200
+# define PATCH_ABS44 0x0400
+# define PATCH_ABS52 0x0800
# define JUMP_SIZE_SHIFT 58
-# define JUMP_MAX_SIZE ((sljit_uw)6)
+# define JUMP_MAX_SIZE ((sljit_uw)12)
#else /* !SLJIT_CONFIG_RISCV_64 */
# define JUMP_SIZE_SHIFT 26
-# define JUMP_MAX_SIZE ((sljit_uw)2)
+# define JUMP_MAX_SIZE ((sljit_uw)4)
#endif /* SLJIT_CONFIG_RISCV_64 */
#endif /* SLJIT_CONFIG_RISCV */
+#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
+# define PATCH_POOL 0x004
+# define PATCH_IMM32 0x008
+#endif /* SLJIT_CONFIG_S390X */
+
#if (defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+/* SLJIT_REWRITABLE_JUMP is 0x10000. */
# define IS_COND 0x004
# define IS_CALL 0x008
@@ -303,6 +327,7 @@
# define JUMP_MAX_SIZE ((sljit_uw)4)
#endif /* SLJIT_CONFIG_LOONGARCH */
+
/* Stack management. */
#define GET_SAVED_REGISTERS_SIZE(scratches, saveds, extra) \
@@ -451,12 +476,12 @@
/* Public functions */
/* --------------------------------------------------------------------- */
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
#define SLJIT_NEEDS_COMPILER_INIT 1
static sljit_s32 compiler_initialized = 0;
/* A thread safe initialization. */
static void init_compiler(void);
-#endif /* SLJIT_CONFIG_X86 */
+#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_RISCV */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data)
{
@@ -475,8 +500,12 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo
&& (sizeof(sljit_sw) == 4 || sizeof(sljit_sw) == 8)
&& (sizeof(sljit_uw) == sizeof(sljit_sw)),
invalid_integer_types);
- SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_32,
- rewritable_jump_and_single_op_must_not_be_the_same);
+ SLJIT_COMPILE_ASSERT((SLJIT_REWRITABLE_JUMP & SLJIT_32) == 0
+ && (ALL_STATUS_FLAGS_MASK & SLJIT_32) == 0
+ && (SLJIT_REWRITABLE_JUMP & ALL_STATUS_FLAGS_MASK) == 0,
+ rewritable_jump_and_status_flag_bits_and_sljit_32_must_not_have_common_bits);
+ SLJIT_COMPILE_ASSERT((VARIABLE_FLAG_MASK & SLJIT_SET_Z) == 0,
+ rewritable_jump_and_status_flag_bits_must_not_have_common_bits);
SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_F_EQUAL & 0x1) && !(SLJIT_JUMP & 0x1),
conditional_flags_must_be_even_numbers);
@@ -615,8 +644,8 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw
}
}
-#define SLJIT_CURRENT_FLAGS_ALL \
- (SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE)
+#define SLJIT_CURRENT_FLAGS_ALL (SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_ADD \
+ | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE | SLJIT_CURRENT_FLAGS_OP2CMPZ)
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
{
@@ -624,12 +653,18 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *com
SLJIT_UNUSED_ARG(current_flags);
#if (defined SLJIT_HAS_STATUS_FLAGS_STATE && SLJIT_HAS_STATUS_FLAGS_STATE)
+#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
+ if (current_flags & SLJIT_CURRENT_FLAGS_OP2CMPZ) {
+ current_flags |= SLJIT_SET_Z;
+ }
+#endif /* SLJIT_CONFIG_S390X */
+
compiler->status_flags_state = current_flags;
#endif /* SLJIT_HAS_STATUS_FLAGS_STATE */
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->last_flags = 0;
- if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_ALL)) == 0) {
+ if ((current_flags & ~(ALL_STATUS_FLAGS_MASK | SLJIT_CURRENT_FLAGS_ALL)) == 0) {
compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_32 | SLJIT_SET_Z));
}
#endif /* SLJIT_ARGUMENT_CHECKS */
@@ -826,22 +861,34 @@ static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compi
label->next = NULL;
label->u.index = compiler->label_count++;
label->size = compiler->size;
+
if (compiler->last_label != NULL)
compiler->last_label->next = label;
else
compiler->labels = label;
+
compiler->last_label = label;
}
+static SLJIT_INLINE void set_extended_label(struct sljit_extended_label *ext_label, struct sljit_compiler *compiler, sljit_uw type, sljit_uw data)
+{
+ set_label(&ext_label->label, compiler);
+ ext_label->index = ext_label->label.u.index;
+ ext_label->label.u.index = type;
+ ext_label->data = data;
+}
+
static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_u32 flags)
{
jump->next = NULL;
jump->flags = flags;
jump->u.label = NULL;
+
if (compiler->last_jump != NULL)
compiler->last_jump->next = jump;
else
compiler->jumps = jump;
+
compiler->last_jump = jump;
}
@@ -1318,6 +1365,10 @@ static const char* call_arg_names[] = {
"void", "w", "32", "p", "f64", "f32"
};
+static const char* op_addr_types[] = {
+ "mov_addr", "mov_abs_addr", "add_abs_addr"
+};
+
#endif /* SLJIT_VERBOSE */
/* --------------------------------------------------------------------- */
@@ -1328,18 +1379,21 @@ static const char* call_arg_names[] = {
|| (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
#define SLJIT_SKIP_CHECKS(compiler) (compiler)->skip_checks = 1
-#define SLJIT_CHECK_OPCODE(op, flags) ((op) & ~(SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK | (flags)))
+#define SLJIT_CHECK_OPCODE(op, flags) ((op) & ~(SLJIT_32 | ALL_STATUS_FLAGS_MASK | (flags)))
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
struct sljit_jump *jump;
#endif /* SLJIT_ARGUMENT_CHECKS */
SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(options);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(compiler->size > 0);
+ CHECK_ARGUMENT((options & ~(SLJIT_GENERATE_CODE_BUFFER | SLJIT_GENERATE_CODE_NO_CONTEXT)) == 0);
+
jump = compiler->jumps;
while (jump) {
/* All jumps have target. */
@@ -1643,11 +1697,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
case SLJIT_REV_U32:
case SLJIT_REV_S32:
/* Nothing allowed */
- CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+ CHECK_ARGUMENT(!(op & (SLJIT_32 | ALL_STATUS_FLAGS_MASK)));
break;
default:
/* Only SLJIT_32 is allowed. */
- CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
break;
}
@@ -1679,8 +1733,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_load(struct sljit_
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_ATOMIC));
- CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z | VARIABLE_FLAG_MASK) >= SLJIT_MOV
- && SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | SLJIT_SET_Z | VARIABLE_FLAG_MASK) <= SLJIT_MOV_P);
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | ALL_STATUS_FLAGS_MASK) >= SLJIT_MOV
+ && SLJIT_CHECK_OPCODE(op, SLJIT_ATOMIC_TEST | SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS | ALL_STATUS_FLAGS_MASK) <= SLJIT_MOV_P);
CHECK_ARGUMENT((op & (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS)) != (SLJIT_ATOMIC_USE_CAS | SLJIT_ATOMIC_USE_LS));
/* All arguments must be valid registers. */
@@ -1778,19 +1832,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_atomic_store(struct sljit
CHECK_RETURN_OK;
}
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 unset,
- sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src1, sljit_sw src1w,
- sljit_s32 src2, sljit_sw src2w)
-{
- if (SLJIT_UNLIKELY(compiler->skip_checks)) {
- compiler->skip_checks = 0;
- CHECK_RETURN_OK;
- }
-
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_ADD && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_ROTR);
+static sljit_s32 check_sljit_emit_op2_operation(struct sljit_compiler *compiler, sljit_s32 op)
+{
switch (GET_OPCODE(op)) {
case SLJIT_AND:
case SLJIT_OR:
@@ -1801,39 +1846,49 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler
case SLJIT_MLSHR:
case SLJIT_ASHR:
case SLJIT_MASHR:
- CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
- break;
+ return !(op & VARIABLE_FLAG_MASK);
case SLJIT_MUL:
- CHECK_ARGUMENT(!(op & SLJIT_SET_Z));
- CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
- || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
- break;
+ return !(op & SLJIT_SET_Z) && (!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
case SLJIT_ADD:
- CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+ return !(op & VARIABLE_FLAG_MASK)
|| GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)
- || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
- break;
+ || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
case SLJIT_SUB:
- CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
+ return !(op & VARIABLE_FLAG_MASK)
|| (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_OVERFLOW)
- || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
- break;
+ || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY);
case SLJIT_ADDC:
case SLJIT_SUBC:
- CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
- || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
- CHECK_ARGUMENT((compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
- CHECK_ARGUMENT((op & SLJIT_32) == (compiler->last_flags & SLJIT_32));
+ return (!(op & VARIABLE_FLAG_MASK) || GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY))
+ && (compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY)
+ && (op & SLJIT_32) == (compiler->last_flags & SLJIT_32);
break;
case SLJIT_ROTL:
case SLJIT_ROTR:
- CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
- break;
- default:
- SLJIT_UNREACHABLE();
- break;
+ return !(op & ALL_STATUS_FLAGS_MASK);
}
+ /* Operation type should be checked earlier. */
+ SLJIT_UNREACHABLE();
+ return 1;
+}
+
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 unset,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_ADD && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_ROTR);
+ CHECK_ARGUMENT(check_sljit_emit_op2_operation(compiler, op));
+
if (unset) {
CHECK_ARGUMENT(HAS_FLAGS(op));
} else {
@@ -1923,6 +1978,36 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_shift_into(struct sljit_c
CHECK_RETURN_OK;
}
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ SLJIT_UNUSED_ARG(shift_arg);
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT((op & ~SLJIT_SRC2_UNDEFINED) == (SLJIT_ADD | SLJIT_SHL_IMM));
+ FUNCTION_CHECK_DST(dst, dstw);
+ FUNCTION_CHECK_SRC(src1, src1w);
+ FUNCTION_CHECK_SRC(src2, src2w);
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " %s.shl_imm%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],
+ (op & SLJIT_SRC2_UNDEFINED) ? ".src2und" : "");
+
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src2, src2w);
+ fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", shift_arg);
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -2005,12 +2090,12 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_co
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
CHECK_ARGUMENT(size > 0 && size < 16);
-#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) || (defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV)
CHECK_ARGUMENT((size == 2 && (((sljit_sw)instruction) & 0x1) == 0)
|| (size == 4 && (((sljit_sw)instruction) & 0x3) == 0));
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
CHECK_ARGUMENT(size == 2 || size == 4 || size == 6);
-#else /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM_THUMB2 && !SLJIT_CONFIG_S390X */
+#else /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM_THUMB2 && !SLJIT_CONFIG_RISCV && !SLJIT_CONFIG_S390X */
CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0);
#endif /* SLJIT_CONFIG_X86 */
@@ -2039,7 +2124,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compile
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_MOV_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_ABS_F64);
- CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
FUNCTION_FCHECK(src, srcw, op & SLJIT_32);
FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);
#endif /* SLJIT_ARGUMENT_CHECKS */
@@ -2110,7 +2195,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(str
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
- CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
FUNCTION_FCHECK(src, srcw, op & SLJIT_32);
FUNCTION_CHECK_DST(dst, dstw);
#endif /* SLJIT_ARGUMENT_CHECKS */
@@ -2139,7 +2224,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_w(stru
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
- CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
FUNCTION_CHECK_SRC(src, srcw);
FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);
#endif /* SLJIT_ARGUMENT_CHECKS */
@@ -2170,7 +2255,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compile
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_ADD_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_DIV_F64);
- CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
FUNCTION_FCHECK(src1, src1w, op & SLJIT_32);
FUNCTION_FCHECK(src2, src2w, op & SLJIT_32);
FUNCTION_FCHECK(dst, dstw, op & SLJIT_32);
@@ -2269,7 +2354,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcopy(struct sljit_compil
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, 0) >= SLJIT_COPY_TO_F64 && SLJIT_CHECK_OPCODE(op, 0) <= SLJIT_COPY_FROM_F64);
- CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+ CHECK_ARGUMENT(!(op & ALL_STATUS_FLAGS_MASK));
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg, op & SLJIT_32));
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
@@ -2341,6 +2426,37 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_label(struct sljit_compil
CHECK_RETURN_OK;
}
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(buffers);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(alignment >= SLJIT_LABEL_ALIGN_1 && alignment <= SLJIT_LABEL_ALIGN_16);
+ compiler->last_flags = 0;
+#endif /* SLJIT_ARGUMENT_CHECKS */
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, "label.al%d:%s", 1 << alignment, buffers == NULL ? "\n" : " [");
+
+ if (buffers != NULL) {
+ fprintf(compiler->verbose, "%ld", (long int)buffers->size);
+ buffers = buffers->next;
+
+ while (buffers != NULL) {
+ fprintf(compiler->verbose, ", %ld", (long int)buffers->size);
+ buffers = buffers->next;
+ }
+
+ fprintf(compiler->verbose, "]\n");
+ }
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|| (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)
@@ -2427,6 +2543,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_SIG_LESS_EQUAL);
@@ -2472,6 +2593,40 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile
CHECK_RETURN_OK;
}
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2cmpz(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ SLJIT_COMPILE_ASSERT((SLJIT_JUMP_IF_ZERO == SLJIT_SET_Z) && (SLJIT_JUMP_IF_NON_ZERO == 0),
+ incorrect_values_for_sljit_jump_zero_or_non_zero);
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(SLJIT_CHECK_OPCODE(op, SLJIT_REWRITABLE_JUMP) >= SLJIT_ADD && SLJIT_CHECK_OPCODE(op, SLJIT_REWRITABLE_JUMP) <= SLJIT_ROTR);
+ /* Not all opcodes allow setting zero flags. */
+ CHECK_ARGUMENT(check_sljit_emit_op2_operation(compiler, ((op | SLJIT_SET_Z) & ~SLJIT_REWRITABLE_JUMP)));
+ FUNCTION_CHECK_DST(dst, dstw);
+ FUNCTION_CHECK_SRC(src1, src1w);
+ FUNCTION_CHECK_SRC(src2, src2w);
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & SLJIT_32);
+#endif /* SLJIT_ARGUMENT_CHECKS */
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " cmp%sz.%s%s%s%s%s ", (op & SLJIT_JUMP_IF_ZERO) ? "" : "n",
+ op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",
+ !(op & VARIABLE_FLAG_MASK) ? "" : ".", !(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op & ~SLJIT_REWRITABLE_JUMP)],
+ !(op & SLJIT_REWRITABLE_JUMP) ? "" : ".r");
+ sljit_verbose_param(compiler, dst, dstw);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src1, src1w);
+ fprintf(compiler->verbose, ", ");
+ sljit_verbose_param(compiler, src2, src2w);
+ fprintf(compiler->verbose, "\n");
+ }
+#endif /* SLJIT_VERBOSE */
+ CHECK_RETURN_OK;
+}
+
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 src, sljit_sw srcw)
{
@@ -2578,27 +2733,30 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_select(struct sljit_compi
sljit_s32 src2_reg)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- sljit_s32 cond = type & ~SLJIT_32;
-
- CHECK_ARGUMENT(cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL);
-
+ sljit_s32 cond = type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
+ CHECK_ARGUMENT((type & SLJIT_COMPARE_SELECT) ? (cond >= SLJIT_LESS && cond <= SLJIT_SET_SIG_LESS_EQUAL)
+ : (cond >= SLJIT_EQUAL && cond <= SLJIT_ORDERED_LESS_EQUAL));
CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg));
FUNCTION_CHECK_SRC(src1, src1w);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src2_reg));
- if (cond <= SLJIT_NOT_ZERO)
- CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
- else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {
- CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);
- compiler->last_flags = 0;
+ if (!(type & SLJIT_COMPARE_SELECT)) {
+ if (cond <= SLJIT_NOT_ZERO)
+ CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
+ else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {
+ CHECK_ARGUMENT((type & 0xfe) == SLJIT_CARRY);
+ compiler->last_flags = 0;
+ } else
+ CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff)
+ || CHECK_UNORDERED(cond, compiler->last_flags));
} else
- CHECK_ARGUMENT((cond & 0xfe) == (compiler->last_flags & 0xff)
- || CHECK_UNORDERED(cond, compiler->last_flags));
+ compiler->last_flags = 0;
#endif /* SLJIT_ARGUMENT_CHECKS */
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " select%s %s, ",
+ fprintf(compiler->verbose, " %sselect%s %s, ",
+ !(type & SLJIT_COMPARE_SELECT) ? "" : "cmp_",
!(type & SLJIT_32) ? "" : "32",
jump_names[type & ~SLJIT_32]);
sljit_verbose_reg(compiler, dst_reg);
@@ -2680,7 +2838,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler
case SLJIT_MOV_P:
case SLJIT_MOV:
allowed_flags |= SLJIT_MEM_ALIGNED_32;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
case SLJIT_MOV32:
@@ -2714,11 +2872,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler
!(type & SLJIT_32) ? "" : "32", op1_types[(type & 0xff) - SLJIT_OP1_BASE]);
if (type & SLJIT_MEM_UNALIGNED)
- printf(".unal");
+ fprintf(compiler->verbose, ".unal");
else if (type & SLJIT_MEM_ALIGNED_16)
- printf(".al16");
+ fprintf(compiler->verbose, ".al16");
else if (type & SLJIT_MEM_ALIGNED_32)
- printf(".al32");
+ fprintf(compiler->verbose, ".al32");
if (reg & REG_PAIR_MASK) {
fprintf(compiler->verbose, " {");
@@ -3176,16 +3334,21 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_co
CHECK_RETURN_OK;
}
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
{
SLJIT_UNUSED_ARG(init_value);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV_S32
+ || op == SLJIT_MOV32 || (op | SLJIT_32) == SLJIT_MOV32_U8);
FUNCTION_CHECK_DST(dst, dstw);
#endif /* SLJIT_ARGUMENT_CHECKS */
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " const ");
+ fprintf(compiler->verbose, " const%s%s ",
+ !(op & SLJIT_32) ? "" : "32", op1_types[GET_OPCODE(op) - SLJIT_OP1_BASE]);
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, ", #%" SLJIT_PRINT_D "d\n", init_value);
}
@@ -3193,14 +3356,16 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil
CHECK_RETURN_OK;
}
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(op == SLJIT_MOV_ADDR || op == SLJIT_MOV_ABS_ADDR || op == SLJIT_ADD_ABS_ADDR);
FUNCTION_CHECK_DST(dst, dstw);
#endif /* SLJIT_ARGUMENT_CHECKS */
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " mov_addr ");
+ fprintf(compiler->verbose, " %s ", op_addr_types[op]);
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, "\n");
}
@@ -3276,6 +3441,14 @@ static sljit_s32 sljit_emit_fmem_unaligned(struct sljit_compiler *compiler, slji
#endif /* (!SLJIT_CONFIG_MIPS || SLJIT_MIPS_REV >= 6) && !SLJIT_CONFIG_ARM */
+static void sljit_reset_read_only_buffers(struct sljit_read_only_buffer *buffers)
+{
+ while (buffers != NULL) {
+ buffers->u.label = NULL;
+ buffers = buffers->next;
+ }
+}
+
/* CPU description section */
#if (defined SLJIT_32BIT_ARCHITECTURE && SLJIT_32BIT_ARCHITECTURE)
@@ -3501,6 +3674,49 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
return sljit_emit_jump(compiler, type);
}
+#if !(defined SLJIT_CONFIG_RISCV && SLJIT_CONFIG_RISCV) \
+ && !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
+ && !(defined SLJIT_CONFIG_LOONGARCH && SLJIT_CONFIG_LOONGARCH)
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op2cmpz(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op2cmpz(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ PTR_FAIL_IF(sljit_emit_op2(compiler, ((op | SLJIT_SET_Z) & ~SLJIT_REWRITABLE_JUMP), dst, dstw, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_jump(compiler, ((op & SLJIT_JUMP_IF_ZERO) ? SLJIT_ZERO : SLJIT_NOT_ZERO) | (op & SLJIT_REWRITABLE_JUMP));
+}
+
+#else /* SLJIT_CONFIG_RISCV || SLJIT_CONFIG_MIPS || SLJIT_CONFIG_LOONGARCH */
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op2cmpz(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 reg;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_op2cmpz(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+
+ SLJIT_SKIP_CHECKS(compiler);
+ PTR_FAIL_IF(sljit_emit_op2(compiler, (op & ~(SLJIT_SET_Z | SLJIT_REWRITABLE_JUMP)), dst, dstw, src1, src1w, src2, src2w));
+
+ /* When dst is a memory operand, its value is stored in SLJIT_TMP_DEST_FREG. */
+ reg = FAST_IS_REG(dst) ? dst : SLJIT_TMP_DEST_REG;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_cmp(compiler, ((op & SLJIT_JUMP_IF_ZERO) ? SLJIT_ZERO : SLJIT_NOT_ZERO) | (op & (SLJIT_32 | SLJIT_REWRITABLE_JUMP)), reg, 0, SLJIT_IMM, 0);
+}
+
+#endif /* !SLJIT_CONFIG_RISCV && !SLJIT_CONFIG_MIPS && !SLJIT_CONFIG_LOONGARCH */
+
#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
&& !(defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
@@ -3687,4 +3903,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_ARM_64 */
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_read_only_buffer_start_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset)
+{
+ SLJIT_UNUSED_ARG(size);
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + size), 0);
+ return SLJIT_ADD_EXEC_OFFSET(addr, -executable_offset);
+}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_read_only_buffer_end_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset)
+{
+ SLJIT_UNUSED_ARG(addr);
+ SLJIT_UNUSED_ARG(size);
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + size), 1);
+ SLJIT_CACHE_FLUSH((void*)addr, (void*)(addr + size));
+}
+
#endif /* !SLJIT_CONFIG_UNSUPPORTED */
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitLir.h b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitLir.h
index 60d34f15430..c5bf1287c39 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitLir.h
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitLir.h
@@ -503,6 +503,16 @@ struct sljit_generate_code_buffer {
sljit_sw executable_offset;
};
+struct sljit_read_only_buffer {
+ struct sljit_read_only_buffer *next;
+ sljit_uw size;
+ /* Label can be replaced by address after sljit_generate_code. */
+ union {
+ struct sljit_label *label;
+ sljit_uw addr;
+ } u;
+};
+
struct sljit_compiler {
sljit_s32 error;
sljit_s32 options;
@@ -705,6 +715,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp
buffer which type is sljit_generate_code_buffer. */
#define SLJIT_GENERATE_CODE_BUFFER 0x1
+/* When SLJIT_INDIRECT_CALL is defined, no function context is
+created for the generated code (see sljit_set_function_context),
+so the returned pointer cannot be directly called from C code.
+The flag is ignored when SLJIT_INDIRECT_CALL is not defined. */
+#define SLJIT_GENERATE_CODE_NO_CONTEXT 0x2
+
/* Create executable code from the instruction stream. This is the final step
of the code generation, and no more instructions can be emitted after this call.
@@ -1450,6 +1466,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *
sljit_s32 src2_reg,
sljit_s32 src3, sljit_sw src3w);
+/* The following options are used by sljit_emit_op2_shift. */
+
+/* The src2 argument is shifted left by an immedate value. */
+#define SLJIT_SHL_IMM (1 << 9)
+/* When src2 argument is a register, its value is undefined after the operation. */
+#define SLJIT_SRC2_UNDEFINED (1 << 10)
+
+/* Emits an addition operation, where the second argument is shifted by a value.
+
+ op must be SLJIT_ADD | SLJIT_SHL_IMM, where the immedate value is stored in shift_arg
+
+ Flags: - (may destroy flags) */
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg);
+
/* Starting index of opcodes for sljit_emit_op_src
and sljit_emit_op_dst. */
#define SLJIT_OP_SRC_DST_BASE 112
@@ -1629,8 +1663,53 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fcopy(struct sljit_compiler *compi
/* Label and jump instructions. */
+/* Emits a label which can be the target of jump / mov_addr instructions. */
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler);
+/* Alignment values for sljit_emit_aligned_label. */
+
+#define SLJIT_LABEL_ALIGN_1 0
+#define SLJIT_LABEL_ALIGN_2 1
+#define SLJIT_LABEL_ALIGN_4 2
+#define SLJIT_LABEL_ALIGN_8 3
+#define SLJIT_LABEL_ALIGN_16 4
+#define SLJIT_LABEL_ALIGN_W SLJIT_WORD_SHIFT
+#define SLJIT_LABEL_ALIGN_P SLJIT_POINTER_SHIFT
+
+/* Emits a label which address is aligned to a power of 2 value. When some
+ extra space needs to be added to align the label, that space is filled
+ with SLJIT_NOP instructions. These labels usually represent the end of a
+ compilation block, and a new function or some read-only data (e.g. a
+ jump table) follows it. In these typical cases the SLJIT_NOPs are never
+ executed.
+
+ Optionally, buffers for storing read-only data or code can be allocated
+ by this operation. The buffers are passed as a chain list, and a separate
+ memory area is allocated for each item in the list. All buffers are aligned
+ to SLJIT_NOP instruction size, and their starting address is returned as
+ as a label. The sljit_get_label_abs_addr function or the SLJIT_MOV_ABS_ADDR
+ operation can be used to get the real address. The label of the first buffer
+ is always the same as the returned label. The buffers are initially
+ initialized with SLJIT_NOP instructions. The alignment of the buffers can
+ be controlled by their starting address and sizes. If the starting address
+ is aligned to N, and size is also divisible by N, the next buffer is aligned
+ to N. I.e. if a buffer is 16 byte aligned, and its size is divisible by 4,
+ the next buffer is 4 byte aligned. Note: if a buffer is N (>=2) byte aligned,
+ it is also N/2 byte aligned.
+
+ align represents the alignment, and its value can
+ be specified by SLJIT_LABEL_* constants
+
+ buffers is a list of read-only buffers stored in a chain list.
+ After calling sljit_generate_code, these buffers can be
+ modified by sljit_read_only_buffer_start_writing() /
+ sljit_read_only_buffer_end_writing() functions
+
+ Note: the constant pool (if present) may be stored before the label. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers);
+
/* The SLJIT_FAST_CALL is a calling method for creating lightweight function
calls. This type of calls preserve the values of all registers and stack
frame. Unlike normal function calls, the enter and return operations must
@@ -1757,16 +1836,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
#define SLJIT_CALL_REG_ARG 39
/* The target can be changed during runtime (see: sljit_set_jump_addr). */
-#define SLJIT_REWRITABLE_JUMP 0x1000
+#define SLJIT_REWRITABLE_JUMP 0x10000
/* When this flag is passed, the execution of the current function ends and
the called function returns to the caller of the current function. The
stack usage is reduced before the call, but it is not necessarily reduced
to zero. In the latter case the compiler needs to allocate space for some
arguments and the return address must be stored on the stack as well. */
-#define SLJIT_CALL_RETURN 0x2000
+#define SLJIT_CALL_RETURN 0x20000
/* Emit a jump instruction. The destination is not set, only the type of the jump.
- type must be between SLJIT_EQUAL and SLJIT_FAST_CALL
+ type must be between SLJIT_JUMP and SLJIT_FAST_CALL
type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
Flags: does not modify flags. */
@@ -1780,31 +1859,56 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
Flags: destroy all flags. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types);
-/* Basic arithmetic comparison. In most architectures it is implemented as
- a compare operation followed by a sljit_emit_jump. However some
- architectures (i.e: ARM64 or MIPS) may employ special optimizations
- here. It is suggested to use this comparison form when appropriate.
+/* Integer comparison operation. In most architectures it is implemented
+ as a compare (sljit_emit_op2u with SLJIT_SUB) operation followed by
+ an sljit_emit_jump. However, some architectures (e.g: ARM64 or RISCV)
+ may optimize the generated code further. It is suggested to use this
+ comparison form when appropriate.
type must be between SLJIT_EQUAL and SLJIT_SIG_LESS_EQUAL
- type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
+ type can be combined (or'ed) with SLJIT_32 or SLJIT_REWRITABLE_JUMP
Flags: may destroy flags. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w);
-/* Basic floating point comparison. In most architectures it is implemented as
- a SLJIT_CMP_F32/64 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.
+/* Floating point comparison operation. In most architectures it is
+ implemented as a SLJIT_CMP_F32/64 operation (setting appropriate
+ flags) followed by a sljit_emit_jump. However, some architectures
+ (e.g: MIPS) may optimize the generated code further. It is suggested
+ to use this comparison form when appropriate.
type must be between SLJIT_F_EQUAL and SLJIT_ORDERED_LESS_EQUAL
- type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
+ type can be combined (or'ed) with SLJIT_32 or SLJIT_REWRITABLE_JUMP
+
Flags: destroy flags.
- Note: when an operand is NaN the behaviour depends on the comparison type. */
+ Note: when any operand is NaN the behaviour depends on the comparison type. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w);
+/* The following flags are used by sljit_emit_op2cmpz(). */
+#define SLJIT_JUMP_IF_NON_ZERO 0
+#define SLJIT_JUMP_IF_ZERO SLJIT_SET_Z
+
+/* Perform an integer arithmetic operation, then its result is compared to
+ zero. In most architectures it is implemented as an sljit_emit_op2
+ followed by an sljit_emit_jump. However, some architectures (e.g: RISCV)
+ may optimize the generated code further. It is suggested to use this
+ operation form when appropriate (e.g. for loops with counters).
+
+ op must be an sljit_emit_op2 operation where zero flag can be set,
+ op can be combined with SLJIT_SET_* status flag setters except
+ SLJIT_SET_Z, SLJIT_REWRITABLE_JUMP or SLJIT_JUMP_IF_* option bits.
+
+ Note: SLJIT_JUMP_IF_NON_ZERO is the default operation if neither
+ SLJIT_JUMP_IF_ZERO or SLJIT_JUMP_IF_NON_ZERO is specified.
+ Flags: sets the variable flag depending on op argument, the
+ zero flag is undefined. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op2cmpz(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 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);
/* Set the destination address of the jump to this label. */
@@ -1831,7 +1935,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
/* Perform an operation using the conditional flags as the second argument.
Type must always be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL.
The value represented by the type is 1, if the condition represented
- by the type is fulfilled, and 0 otherwise.
+ by type is fulfilled, and 0 otherwise.
When op is SLJIT_MOV or SLJIT_MOV32:
Set dst to the value represented by the type (0 or 1).
@@ -1844,27 +1948,55 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
sljit_s32 dst, sljit_sw dstw,
sljit_s32 type);
+/* The following flags are used by sljit_emit_select(). */
+
+/* Compare src1 and src2_reg operands before executing select
+ (i.e. converts the select operation to a min/max operation). */
+#define SLJIT_COMPARE_SELECT SLJIT_SET_Z
+
/* Emit a conditional select instruction which moves src1 to dst_reg,
- if the condition is satisfied, or src2_reg to dst_reg otherwise.
+ if the conditional flag is set, or src2_reg to dst_reg otherwise.
+ The conditional flag should be set before executing the select
+ instruction unless SLJIT_COMPARE_SELECT is specified.
type must be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL
+ when SLJIT_COMPARE_SELECT option is NOT specified
+ type must be between SLJIT_LESS and SLJIT_SET_SIG_LESS_EQUAL
+ when SLJIT_COMPARE_SELECT option is specified
type can be combined (or'ed) with SLJIT_32 to move 32 bit
register values instead of word sized ones
+ type can be combined (or'ed) with SLJIT_COMPARE_SELECT
+ which compares src1 and src2_reg before executing the select
dst_reg and src2_reg must be valid registers
src1 must be valid operand
Note: if src1 is a memory operand, its value
- might be loaded even if the condition is false.
-
- Flags: - (does not modify flags) */
+ might be loaded even if the condition is false
+
+ Note: when SLJIT_COMPARE_SELECT is specified, the status flag
+ bits might not represent the result of a normal compare
+ operation, hence flags are not specified after the operation
+
+ Note: if sljit_has_cpu_feature(SLJIT_HAS_CMOV) returns with a non-zero value:
+ (a) conditional register move (dst_reg==src2_reg, src1 is register)
+ can be performed using a single instruction, except on RISCV,
+ where three instructions are needed
+ (b) conditional clearing (dst_reg==src2_reg, src1==SLJIT_IMM,
+ src1w==0) can be performed using a single instruction,
+ except on x86, where two instructions are needed
+
+ Flags:
+ When SLJIT_COMPARE_SELECT is NOT specified: - (does not modify flags)
+ When SLJIT_COMPARE_SELECT is specified: - (may destroy flags) */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 dst_reg,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2_reg);
/* Emit a conditional floating point select instruction which moves
- src1 to dst_reg, if the condition is satisfied, or src2_reg to
- dst_reg otherwise.
+ src1 to dst_reg, if the conditional flag is set, or src2_reg to
+ dst_reg otherwise. The conditional flag should be set before
+ executing the select instruction.
type must be between SLJIT_EQUAL and SLJIT_ORDERED_LESS_EQUAL
type can be combined (or'ed) with SLJIT_32 to move 32 bit
@@ -2301,26 +2433,66 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler
Flags: - (may destroy flags) */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset);
-/* Store a value that can be changed runtime (see: sljit_get_const_addr / sljit_set_const)
+/* Store a value that can be changed at runtime. The constant
+ can be managed by sljit_get_const_addr and sljit_set_const.
+
+ op must be SLJIT_MOV, SLJIT_MOV32, SLJIT_MOV_S32,
+ SLJIT_MOV_U8, SLJIT_MOV32_U8
+
+ Note: when SLJIT_MOV_U8 is used, and dst is a register,
+ init_value supports a 9 bit signed value between [-256..255]
+
Flags: - (does not modify flags) */
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value);
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value);
+
+/* Opcodes for sljit_emit_mov_addr. */
+
+/* The address is suitable for jump/call target. */
+#define SLJIT_MOV_ADDR 0
+/* The address is suitable for reading memory. */
+#define SLJIT_MOV_ABS_ADDR 1
+/* Add absolute address. */
+#define SLJIT_ADD_ABS_ADDR 2
/* Store the value of a label (see: sljit_set_label / sljit_set_target)
Flags: - (does not modify flags) */
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw);
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw);
+
+/* Returns the address of a label after sljit_generate_code is called, and
+ before the compiler is freed by sljit_free_compiler. It is recommended
+ to save these addresses elsewhere before sljit_free_compiler is called.
+
+ The address returned by sljit_get_label_addr is suitable for a jump/call
+ target, and the address returned by sljit_get_label_abs_addr is suitable
+ for reading memory. */
-/* Provides the address of label, jump and const instructions after sljit_generate_code
- is called. The returned value is unspecified before the sljit_generate_code call.
- 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->u.addr; }
+#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
+static SLJIT_INLINE sljit_uw sljit_get_label_abs_addr(struct sljit_label *label) { return label->u.addr & ~(sljit_uw)1; }
+#else /* !SLJIT_CONFIG_ARM_THUMB2 */
+static SLJIT_INLINE sljit_uw sljit_get_label_abs_addr(struct sljit_label *label) { return label->u.addr; }
+#endif /* SLJIT_CONFIG_ARM_THUMB2 */
+
+/* Returns the address of jump and const instructions after sljit_generate_code
+ is called, and before the compiler is freed by sljit_free_compiler. It is
+ recommended to save these addresses elsewhere before sljit_free_compiler is called. */
+
static SLJIT_INLINE sljit_uw sljit_get_jump_addr(struct sljit_jump *jump) { return jump->addr; }
static SLJIT_INLINE sljit_uw sljit_get_const_addr(struct sljit_const *const_) { return const_->addr; }
/* Only the address and executable offset are required to perform dynamic
code modifications. See sljit_get_executable_offset function. */
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset);
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset);
+/* The op opcode must be set to the same value that was passed to sljit_emit_const. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset);
+
+/* Only a single buffer is writable at a time, so sljit_read_only_buffer_end_writing()
+ must be called before sljit_read_only_buffer_start_writing() is called again. */
+SLJIT_API_FUNC_ATTRIBUTE void* sljit_read_only_buffer_start_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset);
+SLJIT_API_FUNC_ATTRIBUTE void sljit_read_only_buffer_end_writing(sljit_uw addr, sljit_uw size, sljit_sw executable_offset);
/* --------------------------------------------------------------------- */
/* CPU specific functions */
@@ -2369,13 +2541,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Flags were set by an ADD or ADDC operations. */
#define SLJIT_CURRENT_FLAGS_ADD 0x01
-/* Flags were set by a SUB, SUBC, or NEG operation. */
+/* Flags were set by a SUB or SUBC operation. */
#define SLJIT_CURRENT_FLAGS_SUB 0x02
/* Flags were set by sljit_emit_op2u with SLJIT_SUB opcode.
Must be combined with SLJIT_CURRENT_FLAGS_SUB. */
#define SLJIT_CURRENT_FLAGS_COMPARE 0x04
+/* Flags were set by sljit_emit_op2cmpz operation. */
+#define SLJIT_CURRENT_FLAGS_OP2CMPZ 0x08
+
/* Define the currently available CPU status flags. It is usually used after
an sljit_emit_label or sljit_emit_op_custom operations to define which CPU
status flags are available.
@@ -2405,10 +2580,14 @@ static SLJIT_INLINE struct sljit_const *sljit_get_next_const(struct sljit_const
/* A number starting from 0 is assigned to each label, which
represents its creation index. The first label created by the
-compiler has index 0, the second has index 1, the third has
-index 2, and so on. The returned value is unspecified after
-sljit_generate_code() is called. */
-static SLJIT_INLINE sljit_uw sljit_get_label_index(struct sljit_label *label) { return label->u.index; }
+compiler has index 0, the second one has index 1, the third one
+has index 2, and so on. The returned value is unspecified after
+sljit_generate_code() is called.
+
+It is recommended to use this function to get the creation index
+of a label, since sljit_emit_label() may return with the last label,
+if no code is generated since the last sljit_emit_label() call. */
+SLJIT_API_FUNC_ATTRIBUTE sljit_uw sljit_get_label_index(struct sljit_label *label);
/* The sljit_jump_has_label() and sljit_jump_has_target() functions
returns non-zero value if a label or target is set for the jump
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_32.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_32.c
index 327dc824efc..16ef39940c5 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_32.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_32.c
@@ -93,7 +93,7 @@ static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1)
#define VN(vn) (((sljit_ins)freg_map[vn] << 16) | ((sljit_ins)freg_ebit_map[vn] << 7))
/* --------------------------------------------------------------------- */
-/* Instrucion forms */
+/* Instruction forms */
/* --------------------------------------------------------------------- */
/* The instruction includes the AL condition.
@@ -771,6 +771,12 @@ static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_
#endif /* SLJIT_CONFIG_ARM_V6 */
}
+static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
static void reduce_code_size(struct sljit_compiler *compiler)
@@ -882,7 +888,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_const *const_;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_generate_code(compiler));
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
/* Second code generation pass. */
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
@@ -945,6 +951,11 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!const_ || const_->addr >= word_count);
if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -1011,6 +1022,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} while (buf);
if (label && label->size == word_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -1111,17 +1125,23 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
const_ = compiler->consts;
while (const_) {
buf_ptr = (sljit_ins*)const_->addr;
- const_->addr = (sljit_uw)code_ptr;
- code_ptr[0] = (sljit_ins)buf_ptr;
- code_ptr[1] = *buf_ptr;
- if (*buf_ptr & (1 << 23))
- buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
- else
- buf_ptr += 1;
- /* Set the value again (can be a simple constant). */
- set_const_value((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0);
- code_ptr += 2;
+ /* Note: MVN = (MOV ^ 0x400000) */
+ SLJIT_ASSERT((*buf_ptr & 0xfdb00000) == MOV || (*buf_ptr & 0xfd100000) == LDR);
+
+ if ((*buf_ptr & 0x4000000) != 0) {
+ const_->addr = (sljit_uw)code_ptr;
+
+ code_ptr[0] = (sljit_ins)buf_ptr;
+ code_ptr[1] = *buf_ptr;
+ if (*buf_ptr & (1 << 23))
+ buf_ptr += ((*buf_ptr & 0xfff) >> 2) + 2;
+ else
+ buf_ptr += 1;
+ /* Set the value again (can be a simple constant). */
+ set_const_value((sljit_uw)code_ptr, executable_offset, *buf_ptr, 0);
+ code_ptr += 2;
+ }
const_ = const_->next;
}
@@ -1800,7 +1820,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
src2 = TMP_REG2;
} else
compiler->shift_imm = (sljit_uw)(-(sljit_sw)compiler->shift_imm) & 0x1f;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_ROTR:
shift_type = 3;
@@ -2613,6 +2633,54 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *
return push_inst(compiler, ORR | RD(dst_reg) | RN(dst_reg) | RM8(TMP_REG2) | ((sljit_ins)(is_left ? 1 : 0) << 5) | 0x10 | RM(TMP_REG1));
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= 0x1f;
+
+ if (src2 == SLJIT_IMM) {
+ src2w = src2w << shift_arg;
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
+ src1 = TMP_REG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, tmp_r, src2, src2w, tmp_r));
+ src2 = tmp_r;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(src1) | RM(src2) | ((sljit_ins)shift_arg << 7)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_SIZE, dst_r, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -2624,9 +2692,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp
case SLJIT_FAST_RETURN:
SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
- if (FAST_IS_REG(src))
- FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src)));
- else
+ if (FAST_IS_REG(src)) {
+ if (src != TMP_REG2)
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src)));
+ } else
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1));
return push_inst(compiler, BX | RM(TMP_REG2));
@@ -2656,8 +2725,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp
case SLJIT_FAST_ENTER:
SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
- if (FAST_IS_REG(dst))
+ if (FAST_IS_REG(dst)) {
+ if (dst == TMP_REG2)
+ return SLJIT_SUCCESS;
return push_inst(compiler, MOV | RD(dst) | RM(TMP_REG2));
+ }
break;
case SLJIT_GET_RETURN_ADDRESS:
size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0);
@@ -3065,7 +3137,7 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_CARRY:
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
return 0x20000000;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_LESS:
return 0x30000000;
@@ -3073,7 +3145,7 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_NOT_CARRY:
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
return 0x30000000;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_GREATER_EQUAL:
return 0x20000000;
@@ -3108,7 +3180,7 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_OVERFLOW:
if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x10000000;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_UNORDERED:
return 0x60000000;
@@ -3116,7 +3188,7 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_NOT_OVERFLOW:
if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x00000000;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_ORDERED:
return 0x70000000;
@@ -3150,6 +3222,65 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
+ if (SLJIT_UNLIKELY(compiler->cpool_diff != CONST_POOL_EMPTY))
+ PTR_FAIL_IF(push_cpool(compiler));
+#endif /* SLJIT_CONFIG_ARM_V6 */
+
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
{
struct sljit_jump *jump;
@@ -3604,7 +3735,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2_reg)
{
- sljit_ins cc, tmp;
+ sljit_ins cc, tmp, tmp2;
CHECK_ERROR();
CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
@@ -3615,7 +3746,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
src1 = src2_reg;
src1w = 0;
src2_reg = dst_reg;
- type ^= 0x1;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
}
if (src1 & SLJIT_MEM) {
@@ -3624,7 +3756,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
if (src2_reg != dst_reg) {
src1 = src2_reg;
src1w = 0;
- type ^= 0x1;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
} else {
src1 = TMP_REG1;
src1w = 0;
@@ -3632,29 +3765,48 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
} else if (dst_reg != src2_reg)
FAIL_IF(push_inst(compiler, MOV | RD(dst_reg) | RM(src2_reg)));
- cc = get_cc(compiler, type & ~SLJIT_32);
+ if (type & SLJIT_COMPARE_SELECT)
+ type ^= 0x1;
+
+ cc = get_cc(compiler, type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT));
if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {
tmp = get_imm((sljit_uw)src1w);
- if (tmp)
+ if (tmp) {
+ if (type & SLJIT_COMPARE_SELECT)
+ FAIL_IF(push_inst(compiler, (CMP | SET_FLAGS | RN(dst_reg) | tmp)));
return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc);
+ }
tmp = get_imm(~(sljit_uw)src1w);
+ if (tmp && (type & SLJIT_COMPARE_SELECT)) {
+ tmp2 = get_imm((sljit_uw)-src1w);
+ if (tmp2)
+ FAIL_IF(push_inst(compiler, (CMN | SET_FLAGS | RN(dst_reg) | tmp2)));
+ else
+ tmp = 0;
+ }
+
if (tmp)
return push_inst(compiler, ((MVN | RD(dst_reg) | tmp) & ~COND_MASK) | cc);
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
- tmp = (sljit_ins)src1w;
- FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff)));
- if (tmp <= 0xffff)
- return SLJIT_SUCCESS;
- return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff));
-#else /* !SLJIT_CONFIG_ARM_V7 */
+ if (!(type & SLJIT_COMPARE_SELECT)) {
+ tmp = (sljit_ins)src1w;
+ FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff)));
+ if (tmp <= 0xffff)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff));
+ }
+#endif /* SLJIT_CONFIG_ARM_V7 */
+
FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
src1 = TMP_REG1;
-#endif /* SLJIT_CONFIG_ARM_V7 */
}
+ if (type & SLJIT_COMPARE_SELECT)
+ FAIL_IF(push_inst(compiler, (CMP | SET_FLAGS | RN(dst_reg) | RM(src1))));
+
return push_inst(compiler, ((MOV | RD(dst_reg) | RM(src1)) & ~COND_MASK) | cc);
}
@@ -4688,13 +4840,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
+#define SLJIT_EMIT_CONST_U8(c) \
+ (((c) & 0x100) != 0 ? (MVN | SRC2_IMM | (~(c) & 0xff)) : (MOV | SRC2_IMM | ((c) & 0xff)))
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
{
struct sljit_const *const_;
sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_SIZE;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
@@ -4703,35 +4861,52 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ if (GET_OPCODE(op) == SLJIT_MOV_U8) {
+ PTR_FAIL_IF(push_inst(compiler, SLJIT_EMIT_CONST_U8(init_value) | RD(dst_r)));
+ mem_flags = BYTE_SIZE;
+ } else {
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
- PTR_FAIL_IF(push_inst_with_unique_literal(compiler,
- EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), (sljit_ins)init_value));
- compiler->patches++;
+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler,
+ EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), (sljit_ins)init_value));
+ compiler->patches++;
#else /* !SLJIT_CONFIG_ARM_V6 */
- PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));
+ PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));
#endif /* SLJIT_CONFIG_ARM_V6 */
+ }
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, dst, dstw, TMP_REG1));
+
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
{
struct sljit_jump *jump;
- sljit_s32 dst_r;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, dst, dstw, TMP_REG1));
+ }
+
#if (defined SLJIT_CONFIG_ARM_V6 && SLJIT_CONFIG_ARM_V6)
- PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0));
+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, target_r, TMP_PC, 0), 0));
compiler->patches++;
#else /* !SLJIT_CONFIG_ARM_V6 */
- PTR_FAIL_IF(push_inst(compiler, RD(dst_r)));
+ PTR_FAIL_IF(push_inst(compiler, RD(target_r)));
#endif /* SLJIT_CONFIG_ARM_V6 */
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
@@ -4742,6 +4917,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_com
compiler->size += 1;
#endif /* SLJIT_CONFIG_ARM_V7 */
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(dst_r) | RM(TMP_REG1)));
+
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1));
return jump;
@@ -4752,7 +4930,21 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
set_jump_addr(addr, executable_offset, new_target, 1);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
{
- set_const_value(addr, executable_offset, (sljit_uw)new_constant, 1);
+ sljit_ins *inst;
+
+ if (GET_OPCODE(op) != SLJIT_MOV_U8) {
+ set_const_value(addr, executable_offset, (sljit_uw)new_constant, 1);
+ return;
+ }
+
+ inst = (sljit_ins*)addr;
+ SLJIT_ASSERT((inst[0] & 0xfff00000) == (MOV | SRC2_IMM) || (inst[0] & 0xfff00000) == (MVN | SRC2_IMM));
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ *inst = SLJIT_EMIT_CONST_U8(new_constant) | (*inst & 0xf000);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
}
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_64.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_64.c
index d80c9e546ee..dabbd3b0792 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_64.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_64.c
@@ -24,9 +24,15 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef __ARM_FEATURE_ATOMICS
+#define ARM_ATOMIC_INFO " (LSE)"
+#else
+#define ARM_ATOMIC_INFO ""
+#endif
+
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
{
- return "ARM-64" SLJIT_CPUINFO;
+ return "ARM-64" ARM_ATOMIC_INFO SLJIT_CPUINFO;
}
/* Length of an instruction word */
@@ -64,7 +70,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define VM(vm) ((sljit_ins)freg_map[vm] << 16)
/* --------------------------------------------------------------------- */
-/* Instrucion forms */
+/* Instruction forms */
/* --------------------------------------------------------------------- */
#define ADC 0x9a000000
@@ -91,6 +97,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define CLZ 0xdac01000
#define CSEL 0x9a800000
#define CSINC 0x9a800400
+#define CSINV 0xda800000
#define DMB_SY 0xd5033fbf
#define DUP_e 0x0e000400
#define DUP_g 0x0e000c00
@@ -385,6 +392,12 @@ static SLJIT_INLINE void generate_jump_or_mov_addr(struct sljit_jump *jump, slji
buf_ptr[3] = MOVK | ((sljit_ins)((sljit_uw)addr >> 48) << 5) | (3 << 21) | dst;
}
+static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
static void reduce_code_size(struct sljit_compiler *compiler)
{
struct sljit_label *label;
@@ -499,7 +512,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_const *const_;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_generate_code(compiler));
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
reduce_code_size(compiler);
@@ -529,6 +542,11 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* These structures are ordered by their address. */
if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -565,6 +583,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} while (buf);
if (label && label->size == word_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -884,7 +905,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
if (flags & ARG1_IMM)
break;
imm = -imm;
- /* Fall through. */
+ SLJIT_FALLTHROUGH
case SLJIT_ADD:
if (op != SLJIT_SUB)
compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
@@ -930,7 +951,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(reg)));
goto set_flags;
}
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_OR:
inst_bits = logical_imm(imm, LOGICAL_IMM_CHECK | ((flags & INT_OP) ? 16 : 32));
if (!inst_bits)
@@ -1039,7 +1060,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
if (dst == arg2)
return SLJIT_SUCCESS;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_MOV_U32:
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
return push_inst(compiler, (MOV ^ W_OP) | RD(dst) | RM(arg2));
@@ -1124,7 +1145,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
case SLJIT_ROTL:
FAIL_IF(push_inst(compiler, (SUB ^ inv_bits) | RD(TMP_REG2) | RN(TMP_ZERO) | RM(arg2)));
arg2 = TMP_REG2;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_ROTR:
return push_inst(compiler, (RORV ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
case SLJIT_MULADD:
@@ -1855,6 +1876,54 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *
return push_inst(compiler, (ORR ^ inv_bits) | RD(dst_reg) | RN(dst_reg) | RM(TMP_REG1));
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= 0x3f;
+
+ if (src2 == SLJIT_IMM) {
+ src2w = src2w << shift_arg;
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, src1w));
+ src1 = TMP_REG2;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src1, src1w, TMP_REG2));
+ src1 = TMP_REG2;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ tmp_r = (src1 == TMP_REG2) ? TMP_REG1 : TMP_REG2;
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, tmp_r, src2, src2w, tmp_r));
+ src2 = tmp_r;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(src1) | RM(src2) | ((sljit_ins)shift_arg << 10)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2);
+ return SLJIT_SUCCESS;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -1864,9 +1933,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp
switch (op) {
case SLJIT_FAST_RETURN:
- if (FAST_IS_REG(src))
- FAIL_IF(push_inst(compiler, MOV | RD(TMP_LR) | RM(src)));
- else
+ if (FAST_IS_REG(src)) {
+ if (src != TMP_LR)
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_LR) | RM(src)));
+ } else
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1));
return push_inst(compiler, RET | RN(TMP_LR));
@@ -1906,8 +1976,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp
switch (op) {
case SLJIT_FAST_ENTER:
- if (FAST_IS_REG(dst))
+ if (FAST_IS_REG(dst)) {
+ if (dst == TMP_LR)
+ return SLJIT_SUCCESS;
return push_inst(compiler, MOV | RD(dst) | RM(TMP_LR));
+ }
break;
case SLJIT_GET_RETURN_ADDRESS:
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
@@ -2291,7 +2364,7 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_CARRY:
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
return 0x3;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_LESS:
return 0x2;
@@ -2299,7 +2372,7 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_NOT_CARRY:
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
return 0x2;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_GREATER_EQUAL:
return 0x3;
@@ -2334,7 +2407,7 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_OVERFLOW:
if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x0;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_UNORDERED:
return 0x7;
@@ -2342,7 +2415,7 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_NOT_OVERFLOW:
if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x1;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_ORDERED:
return 0x6;
@@ -2376,6 +2449,60 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
{
struct sljit_jump *jump;
@@ -2565,6 +2692,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
sljit_s32 src2_reg)
{
sljit_ins inv_bits = (type & SLJIT_32) ? W_OP : 0;
+ sljit_ins op = CSEL;
+ sljit_ins cmp = 0;
sljit_ins cc;
CHECK_ERROR();
@@ -2575,15 +2704,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
if (src1 == SLJIT_IMM) {
if (type & SLJIT_32)
src1w = (sljit_s32)src1w;
- FAIL_IF(load_immediate(compiler, TMP_REG2, src1w));
- src1 = TMP_REG2;
+
+ if (src1w <= 1 && src1w >= -1) {
+ src1 = TMP_ZERO;
+ cmp = (SUBI ^ inv_bits) | (1 << 29) | RD(TMP_ZERO);
+
+ if (src1w == 1) {
+ op = CSINC;
+ cmp = (SUBI ^ inv_bits) | (1 << 29) | RD(TMP_ZERO) | (1 << 10);
+ } else if (src1w == -1) {
+ op = CSINV;
+ cmp = (ADDI ^ inv_bits) | (1 << 29) | RD(TMP_ZERO) | (1 << 10);
+ }
+
+ src1w = 0;
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, src1w));
+ src1 = TMP_REG2;
+ }
} else if (src1 & SLJIT_MEM) {
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src1, src1w, TMP_REG2));
src1 = TMP_REG2;
}
- cc = get_cc(compiler, type & ~SLJIT_32);
- return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(src2_reg) | RM(src1));
+ if (type & SLJIT_COMPARE_SELECT) {
+ type ^= 0x1;
+ if (cmp == 0)
+ cmp = (SUB ^ inv_bits) | (1 << 29) | RD(TMP_ZERO) | RM(src1);
+ FAIL_IF(push_inst(compiler, cmp | RN(src2_reg)));
+ }
+
+ cc = get_cc(compiler, type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT));
+ return push_inst(compiler, (op ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(src2_reg) | RM(src1));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *compiler, sljit_s32 type,
@@ -2701,19 +2853,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem_update(struct sljit_compiler *
break;
case SLJIT_MOV_S8:
sign = 1;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_MOV_U8:
inst = STURBI | (MEM_SIZE_SHIFT(BYTE_SIZE) << 30) | 0x400;
break;
case SLJIT_MOV_S16:
sign = 1;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_MOV_U16:
inst = STURBI | (MEM_SIZE_SHIFT(HALF_SIZE) << 30) | 0x400;
break;
case SLJIT_MOV_S32:
sign = 1;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_MOV_U32:
case SLJIT_MOV32:
inst = STURBI | (MEM_SIZE_SHIFT(INT_SIZE) << 30) | 0x400;
@@ -3378,6 +3530,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler
{
sljit_ins ins;
sljit_ins cmp = 0;
+ SLJIT_UNUSED_ARG(temp_reg); /* !__ARM_FEATURE_ATOMICS */
CHECK_ERROR();
CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
@@ -3467,6 +3620,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
CHECK_ERROR();
CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
@@ -3500,13 +3654,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
+#define SLJIT_EMIT_CONST_U8(c) \
+ (((c) & 0x100) != 0 ? (MOVN | (sljit_ins)((~(c) & 0xff) << 5)) : (MOVZ | (sljit_ins)(((c) & 0xff) << 5)))
+#define SLJIT_EMIT_CONST_S32(c) \
+ (((c) < 0) ? (MOVN | (sljit_ins)((~(c) & 0xffff) << 5)) : (MOVZ | (sljit_ins)(((c) & 0xffff) << 5)))
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
{
struct sljit_const *const_;
sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_SIZE | STORE;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
@@ -3514,24 +3676,58 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
set_const(const_, compiler);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
- PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, (sljit_uw)init_value));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ PTR_FAIL_IF(push_inst(compiler, SLJIT_EMIT_CONST_U8(init_value) | RD(dst_r)));
+ mem_flags = BYTE_SIZE | STORE;
+ break;
+
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ if (GET_OPCODE(op) == SLJIT_MOV32) {
+ init_value = (sljit_u32)init_value;
+ mem_flags = INT_SIZE | STORE;
+ } else
+ init_value = (sljit_s32)init_value;
+
+ PTR_FAIL_IF(push_inst(compiler, SLJIT_EMIT_CONST_S32(init_value) | RD(dst_r)));
+ PTR_FAIL_IF(push_inst(compiler, MOVK | (1 << 21) | (sljit_ins)((init_value >> 11) & 0x1fffe0) | RD(dst_r)));
+ break;
+
+ default:
+ PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, (sljit_uw)init_value));
+ break;
+ }
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, dst, dstw, TMP_REG2));
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
{
struct sljit_jump *jump;
- sljit_s32 dst_r;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
- PTR_FAIL_IF(push_inst(compiler, RD(dst_r)));
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG2;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, dst, dstw, TMP_REG2));
+ }
+
+ PTR_FAIL_IF(push_inst(compiler, RD(target_r)));
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
@@ -3539,6 +3735,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_com
compiler->size += 3;
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RN(dst_r) | RM(TMP_REG2)));
+
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
@@ -3565,7 +3764,42 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_CACHE_FLUSH(inst, inst + 4);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ sljit_ins* inst;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ inst = (sljit_ins*)addr;
+ SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ || (inst[0] & 0xffe00000) == MOVN);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ inst[0] = SLJIT_EMIT_CONST_U8(new_constant) | (inst[0] & 0x1f);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ return;
+
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ if (GET_OPCODE(op) == SLJIT_MOV32)
+ new_constant = (sljit_u32)new_constant;
+ else
+ new_constant = (sljit_s32)new_constant;
+
+ inst = (sljit_ins*)addr;
+ SLJIT_ASSERT(((inst[0] & 0xffe00000) == MOVZ || (inst[0] & 0xffe00000) == MOVN) && (inst[1] & 0xffe00000) == (MOVK | (1 << 21)));
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[0] = SLJIT_EMIT_CONST_S32(new_constant) | (inst[0] & 0x1f);
+ inst[1] = MOVK | (1 << 21) | (sljit_ins)((new_constant >> 11) & 0x1fffe0) | (inst[1] & 0x1f);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+
+ default:
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
}
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_T2_32.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_T2_32.c
index d8058ab6ea4..eab9ec1ff05 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_T2_32.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeARM_T2_32.c
@@ -102,7 +102,7 @@ static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1)
(COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | ((sljit_ins)imm & 0xff))
/* --------------------------------------------------------------------- */
-/* Instrucion forms */
+/* Instruction forms */
/* --------------------------------------------------------------------- */
/* dot '.' changed to _
@@ -160,6 +160,7 @@ static const sljit_u8 freg_ebit_map[((SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2) << 1)
#define LSR_WI 0xea4f0010
#define MLA 0xfb000000
#define MOV 0x4600
+#define MOVI 0x2000
#define MOVS 0x0000
#define MOVSI 0x2000
#define MOVT 0xf2c00000
@@ -444,6 +445,9 @@ static SLJIT_INLINE void generate_jump_or_mov_addr(struct sljit_jump *jump, slji
diff = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr);
+ if ((jump->flags & (JUMP_MOV_ADDR | IS_ABS)) == (JUMP_MOV_ADDR | IS_ABS))
+ diff &= ~(sljit_sw)1;
+
if (SLJIT_UNLIKELY(type == 0)) {
ins = (jump->flags & JUMP_MOV_ADDR) ? *jump_inst : RDN3(TMP_REG1);
set_imm32_const((sljit_u16*)jump->addr, ins, (sljit_uw)diff);
@@ -506,6 +510,12 @@ static SLJIT_INLINE void generate_jump_or_mov_addr(struct sljit_jump *jump, slji
jump_inst[1] |= 0xd000;
}
+static SLJIT_INLINE sljit_u16 *process_extended_label(sljit_u16 *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_u16*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
static void reduce_code_size(struct sljit_compiler *compiler)
{
struct sljit_label *label;
@@ -615,7 +625,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_const *const_;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_generate_code(compiler));
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
reduce_code_size(compiler);
@@ -645,6 +655,11 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* These structures are ordered by their address. */
if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
label->u.addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -682,6 +697,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} while (buf);
if (label && label->size == half_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
label->u.addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -1025,7 +1043,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
return push_inst32(compiler, ASR_WI | (flags & SET_FLAGS) | RD4(dst) | RM4(reg) | IMM5(imm));
case SLJIT_ROTL:
imm = (imm ^ 0x1f) + 1;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
default: /* SLJIT_ROTR */
return push_inst32(compiler, ROR_WI | RD4(dst) | RM4(reg) | IMM5(imm));
}
@@ -1161,7 +1179,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;
FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f));
arg2 = (sljit_uw)reg;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_SHL:
if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2));
@@ -1170,7 +1188,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;
FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f));
arg2 = (sljit_uw)reg;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_LSHR:
if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2));
@@ -1179,7 +1197,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;
FAIL_IF(push_inst32(compiler, ANDI | RD4(reg) | RN4(arg2) | 0x1f));
arg2 = (sljit_uw)reg;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_ASHR:
if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2));
@@ -1188,7 +1206,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
reg = (arg2 == TMP_REG1) ? TMP_REG1 : TMP_REG2;
FAIL_IF(push_inst32(compiler, RSB_WI | RD4(reg) | RN4(arg2) | 0));
arg2 = (sljit_uw)reg;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_ROTR:
if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, RORS | RD3(dst) | RN3(arg2));
@@ -2182,6 +2200,54 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *
return push_inst32(compiler, ORR_W | RD4(dst_reg) | RN4(dst_reg) | RM4(TMP_REG1));
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= 0x1f;
+
+ if (src2 == SLJIT_IMM) {
+ src2w = src2w << shift_arg;
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src1, src1w, TMP_REG1));
+ src1 = TMP_REG1;
+ }
+
+ if (src2 & SLJIT_MEM) {
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, tmp_r, src2, src2w, tmp_r));
+ src2 = tmp_r;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(dst_r) | RN4(src1) | RM4(src2) | ((sljit_ins)(shift_arg & 0x3) << 6) | ((sljit_ins)(shift_arg & 0x1c) << 10)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -2193,9 +2259,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp
case SLJIT_FAST_RETURN:
SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
- if (FAST_IS_REG(src))
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));
- else
+ if (FAST_IS_REG(src)) {
+ if (src != TMP_REG2)
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src)));
+ } else
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2));
return push_inst16(compiler, BX | RN3(TMP_REG2));
@@ -2224,8 +2291,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp
case SLJIT_FAST_ENTER:
SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
- if (FAST_IS_REG(dst))
+ if (FAST_IS_REG(dst)) {
+ if (dst == TMP_REG2)
+ return SLJIT_SUCCESS;
return push_inst16(compiler, MOV | SET_REGS44(dst, TMP_REG2));
+ }
break;
case SLJIT_GET_RETURN_ADDRESS:
size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds - SLJIT_KEPT_SAVEDS_COUNT(compiler->options), 0);
@@ -2632,7 +2702,7 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_CARRY:
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
return 0x2;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_LESS:
return 0x3;
@@ -2640,7 +2710,7 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_NOT_CARRY:
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
return 0x3;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_GREATER_EQUAL:
return 0x2;
@@ -2675,7 +2745,7 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_OVERFLOW:
if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x1;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_UNORDERED:
return 0x6;
@@ -2683,7 +2753,7 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_NOT_OVERFLOW:
if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x0;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_ORDERED:
return 0x7;
@@ -2717,6 +2787,60 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_2) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_u16);
+
+ for (i = (mask >> 1); i != 0; i--)
+ PTR_FAIL_IF(push_inst16(compiler, NOP));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 1) >> 1; i > 0; i--)
+ PTR_FAIL_IF(push_inst16(compiler, NOP));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
{
struct sljit_jump *jump;
@@ -3166,7 +3290,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2_reg)
{
- sljit_uw cc, tmp;
+ sljit_uw cc, tmp, tmp2;
CHECK_ERROR();
CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
@@ -3177,7 +3301,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
src1 = src2_reg;
src1w = 0;
src2_reg = dst_reg;
- type ^= 0x1;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
}
if (src1 & SLJIT_MEM) {
@@ -3186,7 +3311,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
if (src2_reg != dst_reg) {
src1 = src2_reg;
src1w = 0;
- type ^= 0x1;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
} else {
src1 = TMP_REG1;
src1w = 0;
@@ -3194,9 +3320,55 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
} else if (dst_reg != src2_reg)
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(dst_reg, src2_reg)));
- cc = get_cc(compiler, type & ~SLJIT_32);
+ if ((type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
+ cc = get_cc(compiler, type & ~(SLJIT_32 | SLJIT_COMPARE_SELECT));
+
+ if (src1 == SLJIT_IMM && (type & SLJIT_COMPARE_SELECT)) {
+ tmp = (sljit_uw)src1w;
+ if (tmp <= 0xff && reg_map[dst_reg] <= 7) {
+ if (type & SLJIT_COMPARE_SELECT)
+ FAIL_IF(push_inst16(compiler, CMPI | IMM8(tmp) | RDN3(dst_reg)));
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst16(compiler, MOVI | IMM8(tmp) | RDN3(dst_reg));
+ }
+
+ tmp = get_imm((sljit_uw)src1w);
+ if (tmp != INVALID_IMM) {
+ if (type & SLJIT_COMPARE_SELECT)
+ FAIL_IF(push_inst32(compiler, CMPI_W | RN4(dst_reg) | tmp));
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp);
+ }
+
+ tmp = get_imm(~(sljit_uw)src1w);
+ if (tmp != INVALID_IMM && (type & SLJIT_COMPARE_SELECT)) {
+ tmp2 = get_imm(NEGATE(src1w));
+ if (tmp2 != INVALID_IMM)
+ FAIL_IF(push_inst32(compiler, CMNI_W | RN4(dst_reg) | tmp2));
+ else
+ tmp = INVALID_IMM;
+ }
+
+ if (tmp != INVALID_IMM) {
+ FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
+ return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp);
+ }
+
+ if (type & SLJIT_COMPARE_SELECT) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
+ src1 = TMP_REG1;
+ }
+ }
if (src1 != SLJIT_IMM) {
+ if (type & SLJIT_COMPARE_SELECT) {
+ if (IS_2_LO_REGS(dst_reg, src1))
+ FAIL_IF(push_inst16(compiler, CMP | RD3(dst_reg) | RN3(src1)));
+ else
+ FAIL_IF(push_inst16(compiler, CMP_X | SET_REGS44(dst_reg, src1)));
+ }
+
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
return push_inst16(compiler, MOV | SET_REGS44(dst_reg, src1));
}
@@ -3210,18 +3382,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
| COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff));
}
- tmp = get_imm((sljit_uw)src1w);
- if (tmp != INVALID_IMM) {
- FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
- return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp);
- }
-
- tmp = get_imm(~(sljit_uw)src1w);
- if (tmp != INVALID_IMM) {
- FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
- return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp);
- }
-
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | ((cc & 0x1) << 3) | 0x4));
tmp = (sljit_uw)src1w;
@@ -4357,13 +4517,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
{
struct sljit_const *const_;
sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_SIZE | STORE;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
@@ -4371,32 +4534,55 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
set_const(const_, compiler);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
- PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, (sljit_uw)init_value));
+
+ if (GET_OPCODE(op) == SLJIT_MOV_U8) {
+ PTR_FAIL_IF(push_inst32(compiler,
+ ((init_value & 0x100) != 0 ? (MVN_WI | (~init_value & 0xff)) : (MOV_WI | (init_value & 0xff))) | RD4(dst_r)));
+ mem_flags = BYTE_SIZE | STORE;
+ } else
+ PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, (sljit_uw)init_value));
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, dst, dstw, TMP_REG2));
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
{
struct sljit_jump *jump;
- sljit_s32 dst_r;
+ sljit_s32 dst_r, target_r;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE, dst_r, dst, dstw, TMP_REG1));
+ }
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
set_mov_addr(jump, compiler, 0);
- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
- PTR_FAIL_IF(push_inst16(compiler, RDN3(dst_r)));
+ if (op != SLJIT_MOV_ADDR)
+ jump->flags |= IS_ABS;
+
+ PTR_FAIL_IF(push_inst16(compiler, RDN3(target_r)));
compiler->size += 3;
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(dst_r, TMP_REG1)));
+
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG1));
return jump;
}
@@ -4412,7 +4598,28 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_CACHE_FLUSH(inst, inst + 4);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ sljit_u16 *inst;
+
+ if (GET_OPCODE(op) != SLJIT_MOV_U8) {
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
+
+ inst = (sljit_u16*)addr;
+ SLJIT_ASSERT(inst[0] == (MOV_WI >> 16) || inst[0] == (MVN_WI >> 16));
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+
+ if ((new_constant & 0x100) != 0) {
+ inst[0] = (sljit_u16)(MVN_WI >> 16);
+ new_constant = ~new_constant;
+ } else
+ inst[0] = (sljit_u16)(MOV_WI >> 16);
+
+ inst[1] = (sljit_u16)((new_constant & 0xff) | (inst[1] & 0xf00));
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst + 1, inst + 2);
}
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c
index 73868ca186a..13319669a55 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeLOONGARCH_64.c
@@ -53,7 +53,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
};
/* --------------------------------------------------------------------- */
-/* Instrucion forms */
+/* Instruction forms */
/* --------------------------------------------------------------------- */
/*
@@ -256,6 +256,7 @@ lower parts in the instruction word, denoted by the “L” and “H” suffixes
/* Other instructions */
#define BREAK OPC_3R(0x54)
#define DBGCALL OPC_3R(0x55)
+#define NOP ANDI
#define SYSCALL OPC_3R(0x56)
/* Basic Floating-Point Instructions */
@@ -580,6 +581,12 @@ static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw exec
ins[1] = ORI | RD(reg) | RJ(reg) | IMM_I12(addr);
}
+static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
static void reduce_code_size(struct sljit_compiler *compiler)
{
struct sljit_label *label;
@@ -694,7 +701,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_const *const_;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_generate_code(compiler));
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
reduce_code_size(compiler);
@@ -724,6 +731,11 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* These structures are ordered by their address. */
if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -759,6 +771,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} while (buf);
if (label && label->size == word_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
label->u.addr = (sljit_uw)code_ptr;
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -893,14 +908,18 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r
if (imm <= 0x7fffffffl && imm >= -0x80000000l) {
FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5)));
- return push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm));
+ if (IMM_I12(imm) != 0)
+ return push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm));
+ return SLJIT_SUCCESS;
} else if (imm <= 0x7ffffffffffffl && imm >= -0x8000000000000l) {
FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5)));
- FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm)));
+ if (IMM_I12(imm) != 0)
+ FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm)));
return push_inst(compiler, LU32I_D | RD(dst_r) | (sljit_ins)(((imm >> 32) & 0xfffff) << 5));
}
FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)(((imm & 0xffffffff) >> 12) << 5)));
- FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm)));
+ if (IMM_I12(imm) != 0)
+ FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(imm)));
FAIL_IF(push_inst(compiler, LU32I_D | RD(dst_r) | (sljit_ins)(((imm >> 32) & 0xfffff) << 5)));
return push_inst(compiler, LU52I_D | RD(dst_r) | RJ(dst_r) | IMM_I12(imm >> 52));
}
@@ -1596,7 +1615,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
if (src2 >= 0)
FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(0)));
else {
- FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(src1) | IMM_I12(-1)));
+ FAIL_IF(push_inst(compiler, INST(ADDI, op) | RD(EQUAL_FLAG) | RJ(TMP_ZERO) | IMM_I12(-1)));
FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RJ(src1) | RK(EQUAL_FLAG)));
}
} else if (op & SLJIT_SET_Z)
@@ -1897,7 +1916,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
case SLJIT_BREAKPOINT:
return push_inst(compiler, BREAK);
case SLJIT_NOP:
- return push_inst(compiler, ANDI | RD(TMP_ZERO) | RJ(TMP_ZERO) | IMM_I12(0));
+ return push_inst(compiler, NOP);
case SLJIT_LMUL_UW:
FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(SLJIT_R1) | IMM_I12(0)));
FAIL_IF(push_inst(compiler, MULH_DU | RD(SLJIT_R1) | RJ(SLJIT_R0) | RK(SLJIT_R1)));
@@ -2155,6 +2174,55 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *
return push_inst(compiler, OR | RD(dst_reg) | RJ(dst_reg) | RK(TMP_REG1));
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);
+
+ if (src2 == SLJIT_IMM) {
+ src2w = src2w << shift_arg;
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
+ src2 = TMP_REG2;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ src1 = TMP_REG1;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(push_inst(compiler, SLLI_D | RD(tmp_r) | RJ(src2) | IMM_I12(shift_arg)));
+ FAIL_IF(push_inst(compiler, ADD_D | RD(dst_r) | RJ(src1) | RK(tmp_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, WORD_DATA, dst_r, dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -2166,9 +2234,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp
switch (op) {
case SLJIT_FAST_RETURN:
- if (FAST_IS_REG(src))
- FAIL_IF(push_inst(compiler, ADDI_D | RD(RETURN_ADDR_REG) | RJ(src) | IMM_I12(0)));
- else
+ if (FAST_IS_REG(src)) {
+ if (src != RETURN_ADDR_REG)
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(RETURN_ADDR_REG) | RJ(src) | IMM_I12(0)));
+ } else
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
return push_inst(compiler, JIRL | RD(TMP_ZERO) | RJ(RETURN_ADDR_REG) | IMM_I12(0));
@@ -2207,8 +2276,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp
switch (op) {
case SLJIT_FAST_ENTER:
- if (FAST_IS_REG(dst))
+ if (FAST_IS_REG(dst)) {
+ if (dst == RETURN_ADDR_REG)
+ return SLJIT_SUCCESS;
return push_inst(compiler, ADDI_D | RD(dst) | RJ(RETURN_ADDR_REG) | IMM_I12(0));
+ }
SLJIT_ASSERT(RETURN_ADDR_REG == TMP_REG2);
break;
@@ -2676,6 +2748,60 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
static sljit_ins get_jump_instruction(sljit_s32 type)
{
switch (type) {
@@ -3032,19 +3158,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
{
sljit_ins *ptr;
sljit_uw size;
+ sljit_s32 is_compare = (type & SLJIT_COMPARE_SELECT);
sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
CHECK_ERROR();
CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
ADJUST_LOCAL_OFFSET(src1, src1w);
+ if (src1 == SLJIT_IMM && type & SLJIT_32)
+ src1w = (sljit_s32)src1w;
+
+ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
+
if (dst_reg != src2_reg) {
if (dst_reg == src1) {
src1 = src2_reg;
src1w = 0;
- type ^= 0x1;
+ if (!is_compare)
+ type ^= 0x1;
} else {
if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
+ SLJIT_ASSERT(!(type & SLJIT_COMPARE_SELECT));
FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG1) | RJ(dst_reg) | IMM_I12(0)));
if ((src1 & REG_MASK) == dst_reg)
@@ -3058,6 +3192,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
}
}
+ if (is_compare) {
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG3, src1, src1w));
+ } else if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG3, src1w));
+ } else
+ FAIL_IF(push_inst(compiler, ADDI_D | RD(TMP_REG3) | RJ(src1) | IMM_I12(0)));
+ }
+
size = compiler->size;
ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
@@ -3067,13 +3210,35 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
if (src1 & SLJIT_MEM) {
FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w));
} else if (src1 == SLJIT_IMM) {
- if (type & SLJIT_32)
- src1w = (sljit_s32)src1w;
FAIL_IF(load_immediate(compiler, dst_reg, src1w));
} else
FAIL_IF(push_inst(compiler, ADDI_D | RD(dst_reg) | RJ(src1) | IMM_I12(0)));
- *ptr = get_jump_instruction(type & ~SLJIT_32) | IMM_I16(compiler->size - size);
+ if (is_compare) {
+ switch (type) {
+ case SLJIT_LESS:
+ case SLJIT_LESS_EQUAL:
+ *ptr = BGEU;
+ break;
+ case SLJIT_GREATER:
+ case SLJIT_GREATER_EQUAL:
+ *ptr = BLTU;
+ break;
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_LESS_EQUAL:
+ *ptr = BGE;
+ break;
+ default:
+ *ptr = BLT;
+ break;
+ }
+
+ *ptr |= RJ(TMP_REG3) | RD(dst_reg);
+ } else {
+ *ptr = get_jump_instruction(type);
+ }
+
+ *ptr |= IMM_I16(compiler->size - size);
return SLJIT_SUCCESS;
}
@@ -3830,13 +3995,16 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_CACHE_FLUSH(inst, inst + 4);
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
{
struct sljit_const *const_;
sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_DATA;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
@@ -3844,39 +4012,112 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
set_const(const_, compiler);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
- PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, 0));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ if (init_value & 0x100)
+ init_value |= 0xf00;
+ else
+ init_value &= 0xff;
+
+ PTR_FAIL_IF(push_inst(compiler, ADDI_D | RD(dst_r) | RJ(TMP_ZERO) | IMM_I12(init_value)));
+ mem_flags = BYTE_DATA;
+ break;
+
+ case SLJIT_MOV32:
+ mem_flags = INT_DATA;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_S32:
+ PTR_FAIL_IF(push_inst(compiler, LU12I_W | RD(dst_r) | (sljit_ins)((init_value >> 7) & 0x1ffffe0)));
+ PTR_FAIL_IF(push_inst(compiler, ORI | RD(dst_r) | RJ(dst_r) | IMM_I12(init_value)));
+ break;
+
+ default:
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, 0));
+ break;
+ }
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, dst, dstw));
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
{
struct sljit_jump *jump;
- sljit_s32 dst_r;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, dst, dstw));
+ }
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
set_mov_addr(jump, compiler, 0);
- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
- PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));
+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)target_r));
compiler->size += JUMP_MAX_SIZE - 1;
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, ADD_D | RD(dst_r) | RJ(dst_r) | RK(TMP_REG1)));
+
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
return jump;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ sljit_ins* inst;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ inst = (sljit_ins*)addr;
+ SLJIT_ASSERT((inst[0] & OPC_2RI12(0xb)) == ADDI_D);
+
+ if (new_constant & 0x100)
+ new_constant |= 0xf00;
+ else
+ new_constant &= 0xff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ inst[0] = (inst[0] & 0xffc003ff) | (sljit_ins)((new_constant & 0xfff) << 10);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ return;
+
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & OPC_1RI20(0xa)) == LU12I_W && (inst[1] & OPC_2RI12(0xe)) == ORI);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[0] = (inst[0] & (OPC_1RI20(0xa) | 0x1f)) | (sljit_ins)((new_constant >> 7) & 0x1ffffe0);
+ inst[1] = (inst[1] & (OPC_2RI12(0xe) | 0x3ff)) | (sljit_ins)((new_constant & 0xfff) << 10);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+
+ default:
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
}
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_32.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_32.c
index 91153e5f258..83979617d37 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_32.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_32.c
@@ -196,18 +196,13 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
- inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
- inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_target >> 16);
+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_target);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
-{
- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
-}
-
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr, sljit_u32 *extra_space)
{
sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_64.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_64.c
index b9f03a7bd24..965931b8c9a 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_64.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_64.c
@@ -202,20 +202,15 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_UNUSED_ARG(executable_offset);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 0);
- inst[0] = (inst[0] & 0xffff0000) | ((sljit_ins)(new_target >> 48) & 0xffff);
- inst[1] = (inst[1] & 0xffff0000) | ((sljit_ins)(new_target >> 32) & 0xffff);
- inst[3] = (inst[3] & 0xffff0000) | ((sljit_ins)(new_target >> 16) & 0xffff);
- inst[5] = (inst[5] & 0xffff0000) | ((sljit_ins)new_target & 0xffff);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_target >> 48);
+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_target >> 32);
+ inst[3] = (inst[3] & 0xffff0000) | IMM(new_target >> 16);
+ inst[5] = (inst[5] & 0xffff0000) | IMM(new_target);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 6);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
-{
- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
-}
-
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
{
sljit_s32 arg_count = 0;
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c
index 1b951fe1834..771abfec247 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeMIPS_common.c
@@ -121,7 +121,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#endif /* SLJIT_CONFIG_MIPS_32 */
/* --------------------------------------------------------------------- */
-/* Instrucion forms */
+/* Instruction forms */
/* --------------------------------------------------------------------- */
#define S(s) ((sljit_ins)reg_map[s] << 21)
@@ -709,6 +709,12 @@ static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump)
ins[1] = ORI | S(reg) | T(reg) | IMM(addr & 0xffff);
}
+static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
{
struct sljit_memory_fragment *buf;
@@ -725,7 +731,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_const *const_;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_generate_code(compiler));
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
reverse_buf(compiler);
code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
@@ -752,6 +758,11 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* These structures are ordered by their address. */
if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -796,6 +807,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} while (buf);
if (label && label->size == word_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
label->u.addr = (sljit_uw)code_ptr;
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -1532,11 +1546,11 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar) | IMM(argw), delay_slot);
}
-static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
+static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
{
- if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
+ if (getput_arg_fast(compiler, flags, reg_ar, arg1, arg1w))
return compiler->error;
- return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
+ return getput_arg(compiler, flags, reg_ar, arg1, arg1w, arg2, arg2w);
}
#define EMIT_LOGICAL(op_imm, op_reg) \
@@ -2167,7 +2181,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
FAIL_IF(push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(0) | T(src2) | D(TMP_REG2), DR(TMP_REG2)));
src2 = TMP_REG2;
}
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_ROTR:
EMIT_SHIFT(DROTR, DROTR32, ROTR, DROTRV, ROTRV);
@@ -2634,7 +2648,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
if ((src1 == SLJIT_IMM && src1w == -1) || (src2 == SLJIT_IMM && src2w == -1)) {
return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
}
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_AND:
case SLJIT_OR:
return emit_op(compiler, op, flags | CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
@@ -2780,6 +2794,59 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *
return push_inst(compiler, OR | S(dst_reg) | T(TMP_REG1) | D(dst_reg), DR(dst_reg));
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);
+
+ if (src2 == SLJIT_IMM) {
+ src2w = src2w << shift_arg;
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), src2, src2w, src1, src1w));
+ src2 = TMP_REG2;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG1), src1, src1w, dst, dstw));
+ src1 = TMP_REG1;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ FAIL_IF(push_inst(compiler, (shift_arg >= 32 ? DSLL32 : DSLL) | T(src2) | D(tmp_r) | SH_IMM(shift_arg & 0x1f), DR(tmp_r)));
+#else /* !SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(tmp_r) | SH_IMM(shift_arg), DR(tmp_r)));
+#endif /* SLJIT_CONFIG_MIPS_64 */
+ FAIL_IF(push_inst(compiler, ADDU_W | S(src1) | T(tmp_r) | D(dst_r), DR(dst_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, WORD_DATA, DR(dst_r), dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
#undef SELECT_OP3
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
@@ -2791,9 +2858,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp
switch (op) {
case SLJIT_FAST_RETURN:
- if (FAST_IS_REG(src))
- FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
- else
+ if (FAST_IS_REG(src)) {
+ if (DR(src) != RETURN_ADDR_REG)
+ FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG));
+ } else
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
@@ -2825,8 +2893,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp
switch (op) {
case SLJIT_FAST_ENTER:
- if (FAST_IS_REG(dst))
+ if (FAST_IS_REG(dst)) {
+ if (DR(dst) == RETURN_ADDR_REG)
+ return SLJIT_SUCCESS;
return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS);
+ }
break;
case SLJIT_GET_RETURN_ADDRESS:
dst_ar = DR(FAST_IS_REG(dst) ? dst : TMP_REG2);
@@ -3278,6 +3349,60 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#define BRANCH_LENGTH 4
#else
@@ -3718,7 +3843,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
static sljit_ins get_select_cc(sljit_s32 type, sljit_s32 is_float)
{
- switch (type & ~SLJIT_32) {
+ switch (type) {
case SLJIT_EQUAL:
return (is_float ? MOVZ_S : MOVZ) | TA(EQUAL_FLAG);
case SLJIT_NOT_EQUAL:
@@ -3789,15 +3914,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
ADJUST_LOCAL_OFFSET(src1, src1w);
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
+ if (src1 == SLJIT_IMM && (type & SLJIT_32))
+ src1w = (sljit_s32)src1w;
+#endif
+
+ type &= ~SLJIT_32;
+
+ if (type & SLJIT_COMPARE_SELECT) {
+ type ^= SLJIT_COMPARE_SELECT;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG1), src1, src1w));
+ src1 = TMP_REG1;
+ } else if (src1 == SLJIT_IMM) {
+ if (src1w == 0) {
+ src1 = 0;
+ } else {
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
+ src1 = TMP_REG1;
+ }
+ }
+
+ src1w = 0;
+ FAIL_IF(emit_op(compiler, SLJIT_SUB | SLJIT_SET(type & ~0x1), IMM_OP, 0, 0, src1, 0, src2_reg, 0));
+ }
+
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)
if (src1 & SLJIT_MEM) {
FAIL_IF(emit_op_mem(compiler, inp_flags, DR(TMP_REG1), src1, src1w));
src1 = TMP_REG1;
} else if (src1 == SLJIT_IMM) {
-#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
- if (type & SLJIT_32)
- src1w = (sljit_s32)src1w;
-#endif
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), src1w));
src1 = TMP_REG1;
}
@@ -3834,16 +3981,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
}
SLJIT_SKIP_CHECKS(compiler);
- jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);
+ jump = sljit_emit_jump(compiler, type ^ 0x1);
FAIL_IF(!jump);
if (src1 & SLJIT_MEM) {
FAIL_IF(emit_op_mem(compiler, inp_flags, DR(dst_reg), src1, src1w));
} else if (src1 == SLJIT_IMM) {
-#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
- if (type & SLJIT_32)
- src1w = (sljit_s32)src1w;
-#endif /* SLJIT_CONFIG_MIPS_64 */
FAIL_IF(load_immediate(compiler, DR(dst_reg), src1w));
} else
FAIL_IF(push_inst(compiler, mov_ins | S(src1) | TA(0) | D(dst_reg), DR(dst_reg)));
@@ -3887,11 +4030,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *com
src1 = TMP_FREG2;
}
- return push_inst(compiler, get_select_cc(type, 1) | FMT(type) | FS(src1) | FD(dst_freg), MOVABLE_INS);
+ return push_inst(compiler, get_select_cc(type & ~SLJIT_32, 1) | FMT(type) | FS(src1) | FD(dst_freg), MOVABLE_INS);
#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */
SLJIT_SKIP_CHECKS(compiler);
- jump = sljit_emit_jump(compiler, (type & ~SLJIT_32) ^ 0x1);
+ jump = sljit_emit_jump(compiler, type ^ 0x1);
FAIL_IF(!jump);
if (src1 & SLJIT_MEM)
@@ -4301,7 +4444,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
ins = SCD;
break;
-#endif /* SLJIT_CONFIG_RISCV_64 */
+#endif /* SLJIT_CONFIG_MIPS_64 */
case SLJIT_MOV_S32:
case SLJIT_MOV32:
op |= SLJIT_32;
@@ -4319,13 +4462,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler
return push_inst(compiler, ins | TA(OTHER_FLAG) | S(mem_reg), OTHER_FLAG);
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
{
struct sljit_const *const_;
sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_DATA;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
@@ -4333,37 +4479,119 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
set_const(const_, compiler);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
- PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ if (init_value & 0x100)
+ init_value |= 0xff00;
+ else
+ init_value &= 0xff;
+
+ PTR_FAIL_IF(push_inst(compiler, ADDIU | SA(0) | T(dst_r) | IMM(init_value), DR(dst_r)));
+ mem_flags = BYTE_DATA;
+ break;
+
+#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64)
+ case SLJIT_MOV32:
+ mem_flags = INT_DATA;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_S32:
+ PTR_FAIL_IF(push_inst(compiler, LUI | T(dst_r) | IMM(init_value >> 16), DR(dst_r)));
+ PTR_FAIL_IF(push_inst(compiler, ORI | S(dst_r) | T(dst_r) | IMM(init_value), DR(dst_r)));
+ break;
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ default:
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
+ break;
+ }
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, DR(TMP_REG2), dst, dstw));
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
{
struct sljit_jump *jump;
- sljit_s32 dst_r;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(TMP_REG2), dst, dstw));
+ }
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
set_mov_addr(jump, compiler, 0);
- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
- PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS));
+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)target_r, UNMOVABLE_INS));
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
compiler->size += 1;
#else
compiler->size += 5;
#endif
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, ADDU_W | S(dst_r) | T(TMP_REG1) | D(dst_r), DR(dst_r)));
+
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, DR(TMP_REG2), dst, dstw));
return jump;
}
+
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
+{
+ sljit_ins *inst;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xfc000000) == ADDIU);
+
+ if (new_constant & 0x100)
+ new_constant |= 0xff00;
+ else
+ new_constant &= 0xff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ return;
+
+#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64)
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant >> 16);
+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_constant);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+#endif /* SLJIT_CONFIG_MIPS_64 */
+
+ default:
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
+}
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_32.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_32.c
index 2352fad5d47..c07f4b48e04 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_32.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_32.c
@@ -477,8 +477,8 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
- inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff);
- inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_target >> 16);
+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_target);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 2);
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_64.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_64.c
index b3cf9d074d5..2b07fcba47f 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_64.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_64.c
@@ -709,10 +709,10 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_UNUSED_ARG(executable_offset);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
- inst[0] = (inst[0] & 0xffff0000u) | ((sljit_ins)(new_target >> 48) & 0xffff);
- inst[1] = (inst[1] & 0xffff0000u) | ((sljit_ins)(new_target >> 32) & 0xffff);
- inst[3] = (inst[3] & 0xffff0000u) | ((sljit_ins)(new_target >> 16) & 0xffff);
- inst[4] = (inst[4] & 0xffff0000u) | ((sljit_ins)new_target & 0xffff);
+ inst[0] = (inst[0] & 0xffff0000u) | IMM(new_target >> 48);
+ inst[1] = (inst[1] & 0xffff0000u) | IMM(new_target >> 32);
+ inst[3] = (inst[3] & 0xffff0000u) | IMM(new_target >> 16);
+ inst[4] = (inst[4] & 0xffff0000u) | IMM(new_target);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 5);
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_common.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_common.c
index 3d2268e896b..07df86f3156 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_common.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativePPC_common.c
@@ -113,7 +113,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
};
/* --------------------------------------------------------------------- */
-/* Instrucion forms */
+/* Instruction forms */
/* --------------------------------------------------------------------- */
#define D(d) ((sljit_ins)reg_map[d] << 21)
#define S(s) ((sljit_ins)reg_map[s] << 21)
@@ -504,6 +504,12 @@ static void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executab
#endif /* SLJIT_CONFIG_PPC_32 */
}
+static SLJIT_INLINE sljit_ins *process_extended_label(sljit_ins *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_ins*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
static void reduce_code_size(struct sljit_compiler *compiler)
{
struct sljit_label *label;
@@ -619,18 +625,20 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_const *const_;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_generate_code(compiler));
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
reduce_code_size(compiler);
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+ if (!(options & SLJIT_GENERATE_CODE_NO_CONTEXT)) {
/* add to compiler->size additional instruction space to hold the trampoline and padding */
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
-#else
- compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
-#endif
-#endif
+ compiler->size += (compiler->size & 0x1) + (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
+#else /* !SLJIT_CONFIG_PPC_64 */
+ compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins));
+#endif /* SLJIT_CONFIG_PPC_64 */
+ }
+#endif /* SLJIT_INDIRECT_CALL */
code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
PTR_FAIL_WITH_EXEC_IF(code);
@@ -657,6 +665,11 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* These structures are ordered by their address. */
if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
/* Just recording the address. */
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = (sljit_uw)(code_ptr - code);
@@ -700,6 +713,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} while (buf);
if (label && label->size == word_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -710,7 +726,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!const_);
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
- SLJIT_ASSERT(code_ptr - code <= (sljit_sw)(compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins))));
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)(compiler->size -
+ ((options & SLJIT_GENERATE_CODE_NO_CONTEXT) ? 0 : (sizeof(struct sljit_function_context) / sizeof(sljit_ins)))));
#else
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
#endif
@@ -727,12 +744,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
+ if (!(options & SLJIT_GENERATE_CODE_NO_CONTEXT)) {
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if (((sljit_sw)code_ptr) & 0x4)
- code_ptr++;
-#endif
- sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_uw)code, (void*)sljit_generate_code);
-#endif
+ if (((sljit_sw)code_ptr) & 0x4)
+ code_ptr++;
+#endif /* SLJIT_CONFIG_PPC_64 */
+ sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_uw)code, (void*)sljit_generate_code);
+ }
+#endif /* SLJIT_INDIRECT_CALL */
code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
@@ -740,12 +759,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
- compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins) + sizeof(struct sljit_function_context);
- return code_ptr;
-#else
+ if (!(options & SLJIT_GENERATE_CODE_NO_CONTEXT)) {
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins) + sizeof(struct sljit_function_context);
+ return code_ptr;
+ }
+#endif /* SLJIT_INDIRECT_CALL */
+
compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
return code;
-#endif
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
@@ -1683,7 +1704,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
op |= SLJIT_32;
#endif /* SLJIT_CONFIG_PPC_64 */
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_REV:
case SLJIT_REV_U16:
case SLJIT_REV_S16:
@@ -1925,7 +1946,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
if (src1 == SLJIT_IMM && src1w == -1) {
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM4, dst, dstw, TMP_REG1, 0, src2, src2w);
}
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_AND:
case SLJIT_OR:
/* Commutative unsigned operations. */
@@ -2103,6 +2124,56 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *
return push_inst(compiler, OR | S(dst_reg) | A(dst_reg) | B(TMP_REG1));
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);
+
+ if (src2 == SLJIT_IMM) {
+ src2w = src2w << shift_arg;
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
+ src1 = TMP_REG1;
+ }
+
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, tmp_r, src2, src2w, tmp_r));
+ src2 = tmp_r;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ FAIL_IF(push_inst(compiler, SLWI_W(shift_arg) | S(src2) | A(tmp_r)));
+ FAIL_IF(push_inst(compiler, ADD | D(dst_r) | A(src1) | B(tmp_r)));
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1);
+ return SLJIT_SUCCESS;
+}
+
static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
sljit_s32 src, sljit_sw srcw)
{
@@ -2322,7 +2393,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
break;
}
- /* Fall through. */
+ SLJIT_FALLTHROUGH
case SLJIT_MOV_F64:
if (src != dst_r) {
if (!(dst & SLJIT_MEM))
@@ -2447,13 +2518,67 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type)
{
switch (type) {
case SLJIT_NOT_CARRY:
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
return (4 << 21) | (2 << 16);
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_EQUAL:
case SLJIT_ATOMIC_STORED:
@@ -2462,7 +2587,7 @@ static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type
case SLJIT_CARRY:
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
return (12 << 21) | (2 << 16);
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_NOT_EQUAL:
case SLJIT_ATOMIC_NOT_STORED:
@@ -2835,6 +2960,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
{
sljit_ins *ptr;
sljit_uw size;
+ sljit_s32 is_compare = (type & SLJIT_COMPARE_SELECT);
+ sljit_ins ins;
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
#else /* !SLJIT_CONFIG_PPC_64 */
@@ -2846,6 +2973,45 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
ADJUST_LOCAL_OFFSET(src1, src1w);
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (src1 == SLJIT_IMM && (type & SLJIT_32))
+ src1w = (sljit_s32)src1w;
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
+
+ if (is_compare) {
+ ins = 0;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src1, src1w, TMP_REG1));
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ if (type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL && src1w >= 0 && src1w <= UIMM_MAX)
+ ins = CMPLI | CRD(0) | IMM(src1w);
+ else if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL && src1w >= SIMM_MIN && src1w <= SIMM_MAX)
+ ins = CMPI | CRD(0) | IMM(src1w);
+ else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+ }
+
+ if (ins == 0)
+ ins = ((type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL) ? CMPL : CMP) | CRD(0) | B(src1);
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ if (inp_flags == (WORD_DATA | LOAD_DATA))
+ ins |= CRD(1);
+#endif /* SLJIT_CONFIG_PPC_64 */
+ FAIL_IF(push_inst(compiler, ins | A(src2_reg)));
+ type ^= 0x1;
+ }
+
if (dst_reg != src2_reg) {
if (dst_reg == src1) {
src1 = src2_reg;
@@ -2866,7 +3032,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
}
}
- if (((type & ~SLJIT_32) | 0x1) == SLJIT_NOT_CARRY)
+ if ((type | 0x1) == SLJIT_NOT_CARRY)
FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));
size = compiler->size;
@@ -2878,15 +3044,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
if (src1 & SLJIT_MEM) {
FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w, TMP_REG1));
} else if (src1 == SLJIT_IMM) {
-#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
- if (type & SLJIT_32)
- src1w = (sljit_s32)src1w;
-#endif /* SLJIT_CONFIG_RISCV_64 */
FAIL_IF(load_immediate(compiler, dst_reg, src1w));
} else
FAIL_IF(push_inst(compiler, OR | S(src1) | A(dst_reg) | B(src1)));
- *ptr = BCx | get_bo_bi_flags(compiler, (type ^ 0x1) & ~SLJIT_32) | (sljit_ins)((compiler->size - size) << 2);
+ *ptr = BCx | get_bo_bi_flags(compiler, type ^ 0x1) | (sljit_ins)((compiler->size - size) << 2);
return SLJIT_SUCCESS;
}
@@ -3162,7 +3324,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
ins = LDARX;
break;
-#endif /* SLJIT_CONFIG_RISCV_64 */
+#endif /* SLJIT_CONFIG_PPC_64 */
case SLJIT_MOV_U32:
case SLJIT_MOV32:
ins = LWARX;
@@ -3200,7 +3362,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
ins = STDCX | 0x1;
break;
-#endif /* SLJIT_CONFIG_RISCV_64 */
+#endif /* SLJIT_CONFIG_PPC_64 */
case SLJIT_MOV_U32:
case SLJIT_MOV32:
ins = STWCX | 0x1;
@@ -3216,13 +3378,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler
return push_inst(compiler, ins | D(src_reg) | B(mem_reg));
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
{
struct sljit_const *const_;
sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_DATA;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
@@ -3230,42 +3395,119 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
set_const(const_, compiler);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
- PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ if (init_value & 0x100)
+ init_value |= 0xff00;
+ else
+ init_value &= 0xff;
+
+ PTR_FAIL_IF(push_inst(compiler, ADDI | D(dst_r) | A(0) | IMM(init_value)));
+ mem_flags = BYTE_DATA;
+ break;
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ case SLJIT_MOV32:
+ mem_flags = INT_DATA;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_S32:
+ PTR_FAIL_IF(push_inst(compiler, ADDIS | D(dst_r) | A(0) | IMM(init_value >> 16)));
+ PTR_FAIL_IF(push_inst(compiler, ORI | S(dst_r) | A(dst_r) | IMM(init_value)));
+ break;
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ default:
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value));
+ break;
+ }
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1));
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, dst_r, dst, dstw, TMP_REG1));
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
{
struct sljit_jump *jump;
- sljit_s32 dst_r;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, dst_r, dst, dstw, TMP_REG1));
+ }
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
set_mov_addr(jump, compiler, 0);
- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
- PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));
+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)target_r));
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
compiler->size++;
#else
compiler->size += 4;
#endif
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, ADD | D(dst_r) | A(dst_r) | B(TMP_REG1)));
+
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0));
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, dst_r, dst, dstw, TMP_REG1));
return jump;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ sljit_ins *inst;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDI);
+
+ if (new_constant & 0x100)
+ new_constant |= 0xff00;
+ else
+ new_constant &= 0xff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 1);
+ return;
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ inst = (sljit_ins *)addr;
+ SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[0] = (inst[0] & 0xffff0000) | IMM(new_constant >> 16);
+ inst[1] = (inst[1] & 0xffff0000) | IMM(new_constant);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+#endif /* SLJIT_CONFIG_PPC_64 */
+
+ default:
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
}
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_32.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_32.c
index 396c956c197..e2dfb01cd07 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_32.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_32.c
@@ -28,17 +28,28 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r
{
SLJIT_UNUSED_ARG(tmp_r);
+ if (RISCV_HAS_COMPRESSED(200) && imm <= SIMM16_MAX && imm >= SIMM16_MIN)
+ return push_inst16(compiler, C_LI | C_RD(dst_r) | C_IMM_I(imm));
+
if (imm <= SIMM_MAX && imm >= SIMM_MIN)
return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));
if (imm & 0x800)
imm += 0x1000;
- FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));
+ if (RISCV_HAS_COMPRESSED(200) && imm <= 0x1ffff && imm >= -0x20000)
+ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | ((sljit_u16)(((imm) & 0x1f000) >> 10) | ((imm) & 0x20000) >> 5)));
+ else
+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~(sljit_sw)0xfff)));
+
+ imm &= 0xfff;
- if ((imm & 0xfff) == 0)
+ if (imm == 0)
return SLJIT_SUCCESS;
+ if (RISCV_HAS_COMPRESSED(200) && (imm <= 0x1f || imm >= 0xfe0))
+ return push_inst16(compiler, C_ADDI | C_RD(dst_r) | C_IMM_I(imm));
+
return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
}
@@ -123,20 +134,21 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
- sljit_ins *inst = (sljit_ins*)addr;
+ sljit_u16 *inst = (sljit_u16*)addr;
SLJIT_UNUSED_ARG(executable_offset);
if ((new_target & 0x800) != 0)
new_target += 0x1000;
- SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);
SLJIT_ASSERT((inst[0] & 0x7f) == LUI);
- inst[0] = (inst[0] & 0xfff) | (sljit_ins)((sljit_sw)new_target & ~0xfff);
- SLJIT_ASSERT((inst[1] & 0x707f) == ADDI || (inst[1] & 0x707f) == JALR);
- inst[1] = (inst[1] & 0xfffff) | IMM_I(new_target);
-
- SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
- inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
- SLJIT_CACHE_FLUSH(inst, inst + 5);
+ inst[0] = (sljit_u16)((inst[0] & 0xfff) | (new_target & 0xf000));
+ inst[1] = (sljit_u16)(new_target >> 16);
+ SLJIT_ASSERT((inst[2] & 0x707f) == ADDI || (inst[2] & 0x707f) == JALR);
+ inst[3] = (sljit_u16)((inst[3] & 0xf) | (new_target << 4));
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
}
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_64.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_64.c
index 7fcf2c52730..113d1f88702 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_64.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_64.c
@@ -24,29 +24,88 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r)
+static sljit_s32 load_immediate32(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm)
{
- sljit_sw high;
+ SLJIT_ASSERT((imm <= 0x7fffffffl && imm > SIMM_MAX) || (imm >= S32_MIN && imm < SIMM_MIN));
- if (imm <= SIMM_MAX && imm >= SIMM_MIN)
- return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));
+ if (imm > S32_MAX) {
+ SLJIT_ASSERT((imm & 0x800) != 0);
+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));
+ return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
+ }
- if (imm <= 0x7fffffffl && imm >= S32_MIN) {
- if (imm > S32_MAX) {
+ if (RISCV_HAS_COMPRESSED(200) && imm <= 0x1ffff && imm >= -0x20000) {
+ if (imm > 0x1f7ff) {
SLJIT_ASSERT((imm & 0x800) != 0);
- FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));
+ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | (sljit_u16)0x1000));
return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
}
if ((imm & 0x800) != 0)
imm += 0x1000;
- FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));
+ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | ((sljit_u16)(((imm) & 0x1f000) >> 10) | ((imm) & 0x20000) >> 5)));
+ } else {
+ if ((imm & 0x800) != 0)
+ imm += 0x1000;
+
+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~(sljit_sw)0xfff)));
+ }
+
+ imm &= 0xfff;
+
+ if (imm == 0)
+ return SLJIT_SUCCESS;
+
+ if (RISCV_HAS_COMPRESSED(200) && (imm <= 0x1f || imm >= 0xfe0))
+ return push_inst16(compiler, C_ADDI | C_RD(dst_r) | C_IMM_I(imm));
+
+ return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
+}
+
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r, sljit_sw imm, sljit_s32 tmp_r)
+{
+ sljit_sw high, shift;
+
+ if (RISCV_HAS_COMPRESSED(200) && imm <= SIMM16_MAX && imm >= SIMM16_MIN)
+ return push_inst16(compiler, C_LI | C_RD(dst_r) | C_IMM_I(imm));
- if ((imm & 0xfff) == 0)
- return SLJIT_SUCCESS;
+ if (imm <= SIMM_MAX && imm >= SIMM_MIN)
+ return push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm));
+
+ if (imm <= 0x7fffffffl && imm >= S32_MIN)
+ return load_immediate32(compiler, dst_r, imm);
+
+ /* Shifted small immediates. */
+
+ high = imm;
+ shift = 0;
+ while ((high & 0xff) == 0) {
+ high >>= 8;
+ shift += 8;
+ }
+
+ if ((high & 0xf) == 0) {
+ high >>= 4;
+ shift += 4;
+ }
+
+ if ((high & 0x3) == 0) {
+ high >>= 2;
+ shift += 2;
+ }
+
+ if ((high & 0x1) == 0) {
+ high >>= 1;
+ shift += 1;
+ }
+
+ if (high <= 0x7fffffffl && high >= S32_MIN) {
+ load_immediate(compiler, dst_r, high, tmp_r);
- return push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
+ if (RISCV_HAS_COMPRESSED(200))
+ return push_inst16(compiler, C_SLLI | C_RD(dst_r) | C_IMM_I(shift));
+ return push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(shift));
}
/* Trailing zeroes could be used to produce shifted immediates. */
@@ -57,26 +116,15 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r
if (imm & 0x800)
high = ~high;
- if (high > S32_MAX) {
- SLJIT_ASSERT((high & 0x800) != 0);
- FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)0x80000000u));
- FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(high)));
- } else {
- if ((high & 0x800) != 0)
- high += 0x1000;
-
- FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(high & ~0xfff)));
+ FAIL_IF(load_immediate32(compiler, dst_r, high));
- if ((high & 0xfff) != 0)
- FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(high)));
- }
-
- FAIL_IF(push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(12)));
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_SLLI | C_RD(dst_r) | (sljit_u16)(12 << 2)));
+ else
+ FAIL_IF(push_inst(compiler, SLLI | RD(dst_r) | RS1(dst_r) | IMM_I(12)));
- if ((imm & 0xfff) != 0)
- return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
-
- return SLJIT_SUCCESS;
+ SLJIT_ASSERT((imm & 0xfff) != 0);
+ return push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm));
}
SLJIT_ASSERT(dst_r != tmp_r);
@@ -99,7 +147,10 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r
}
if (imm <= SIMM_MAX && imm >= SIMM_MIN) {
- FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)));
+ if (RISCV_HAS_COMPRESSED(200) && imm <= 0x1f && imm >= -0x20)
+ FAIL_IF(push_inst16(compiler, C_LI | C_RD(dst_r) | C_IMM_I(imm)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(TMP_ZERO) | IMM_I(imm)));
imm = 0;
} else if (imm > S32_MAX) {
SLJIT_ASSERT((imm & 0x800) != 0);
@@ -110,19 +161,35 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_r
if ((imm & 0x800) != 0)
imm += 0x1000;
- FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));
+ if (RISCV_HAS_COMPRESSED(200) && imm <= 0x1ffff && imm >= -0x20000)
+ FAIL_IF(push_inst16(compiler, C_LUI | C_RD(dst_r) | ((sljit_u16)(((imm) & 0x1f000) >> 10) | ((imm) & 0x20000) >> 5)));
+ else
+ FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(imm & ~0xfff)));
imm &= 0xfff;
}
- if ((high & 0xfff) != 0)
- FAIL_IF(push_inst(compiler, ADDI | RD(tmp_r) | RS1(tmp_r) | IMM_I(high)));
+ if ((high & 0xfff) != 0) {
+ SLJIT_ASSERT(high <= 0xfff);
+ if (RISCV_HAS_COMPRESSED(200) && (high <= 0x1f || high >= 0xfe0))
+ FAIL_IF(push_inst16(compiler, C_ADDI | C_RD(tmp_r) | C_IMM_I(high)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(tmp_r) | RS1(tmp_r) | IMM_I(high)));
+ }
if (imm & 0x1000)
FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));
- else if (imm != 0)
- FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));
+ else if (imm != 0) {
+ SLJIT_ASSERT(imm <= 0xfff);
+ if (RISCV_HAS_COMPRESSED(200) && (imm <= 0x1f || imm >= 0xfe0))
+ FAIL_IF(push_inst16(compiler, C_ADDI | C_RD(dst_r) | C_IMM_I(imm)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | RS1(dst_r) | IMM_I(imm)));
+ }
- FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(tmp_r) | IMM_I((high & 0x1000) ? 20 : 32)));
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_SLLI | C_RD(tmp_r) | (sljit_u16)((high & 0x1000) ? (20 << 2) : (1 << 12))));
+ else
+ FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(tmp_r) | IMM_I((high & 0x1000) ? 20 : 32)));
return push_inst(compiler, XOR | RD(dst_r) | RS1(dst_r) | RS2(tmp_r));
}
@@ -190,7 +257,7 @@ static SLJIT_INLINE sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
- sljit_ins *inst = (sljit_ins*)addr;
+ sljit_u16 *inst = (sljit_u16*)addr;
sljit_sw high;
SLJIT_UNUSED_ARG(executable_offset);
@@ -205,18 +272,20 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
if ((high & 0x800) != 0)
high += 0x1000;
- SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 12, 0);
SLJIT_ASSERT((inst[0] & 0x7f) == LUI);
- inst[0] = (inst[0] & 0xfff) | (sljit_ins)(high & ~0xfff);
- SLJIT_ASSERT((inst[1] & 0x707f) == ADDI);
- inst[1] = (inst[1] & 0xfffff) | IMM_I(high);
- SLJIT_ASSERT((inst[2] & 0x7f) == LUI);
- inst[2] = (inst[2] & 0xfff) | (sljit_ins)((sljit_sw)new_target & ~0xfff);
- SLJIT_ASSERT((inst[5] & 0x707f) == ADDI || (inst[5] & 0x707f) == JALR);
- inst[5] = (inst[5] & 0xfffff) | IMM_I(new_target);
- SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
-
- inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
- SLJIT_CACHE_FLUSH(inst, inst + 5);
+ inst[0] = (sljit_u16)((inst[0] & 0xfff) | (high & 0xf000));
+ inst[1] = (sljit_u16)(high >> 16);
+ SLJIT_ASSERT((inst[2] & 0x707f) == ADDI);
+ inst[3] = (sljit_u16)((inst[3] & 0xf) | (high << 4));
+ SLJIT_ASSERT((inst[4] & 0x7f) == LUI);
+ inst[4] = (sljit_u16)((inst[4] & 0xfff) | (new_target & 0xf000));
+ inst[5] = (sljit_u16)(new_target >> 16);
+ SLJIT_ASSERT((inst[10] & 0x707f) == ADDI || (inst[10] & 0x707f) == JALR);
+ inst[11] = (sljit_u16)((inst[11] & 0xf) | (new_target << 4));
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 12, 1);
+
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 12);
}
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_common.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_common.c
index d3ba46dba8b..dec12c9a67f 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_common.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeRISCV_common.c
@@ -24,17 +24,148 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#if !(defined SLJIT_CONFIG_RISCV_ATOMIC) && defined(__riscv_atomic)
+/* Auto detect atomic instruction support. */
+#define SLJIT_CONFIG_RISCV_ATOMIC 200
+#endif /* !SLJIT_CONFIG_RISCV_ATOMIC && __riscv_atomic */
+
+/* SLJIT_CONFIG_RISCV_ATOMIC enables/disables atomic instruction
+ support. Non-zero values represents the highest version of the feature
+ that is supported by the CPU.
+ Allowed values: 0 - disabled, 200 - 2.00 */
+#if (defined SLJIT_CONFIG_RISCV_ATOMIC && SLJIT_CONFIG_RISCV_ATOMIC != 0)
+#if SLJIT_CONFIG_RISCV_ATOMIC != 200
+#error "Unsupported value for SLJIT_CONFIG_RISCV_ATOMIC"
+#endif
+#define RISCV_HAS_ATOMIC(x) ((SLJIT_CONFIG_RISCV_ATOMIC) >= (x))
+#define RISCV_ATOMIC_INFO "a"
+#else /* !SLJIT_CONFIG_RISCV_ATOMIC || SLJIT_CONFIG_RISCV_ATOMIC == 0 */
+#define RISCV_HAS_ATOMIC(x) 0
+#define RISCV_ATOMIC_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_ATOMIC && SLJIT_CONFIG_RISCV_ATOMIC != 0 */
+
+#if !(defined SLJIT_CONFIG_RISCV_COMPRESSED) && defined(__riscv_compressed)
+/* Auto detect compressed instruction support. */
+#define SLJIT_CONFIG_RISCV_COMPRESSED 200
+#endif /* !SLJIT_CONFIG_RISCV_COMPRESSED && __riscv_compressed */
+
+/* SLJIT_CONFIG_RISCV_COMPRESSED enables/disables compressed instruction
+ support. Non-zero values represents the highest version of the feature
+ that is supported by the CPU.
+ Allowed values: 0 - disabled, 200 - 2.00 */
+#if (defined SLJIT_CONFIG_RISCV_COMPRESSED && SLJIT_CONFIG_RISCV_COMPRESSED != 0)
+#if SLJIT_CONFIG_RISCV_COMPRESSED != 200
+#error "Unsupported value for SLJIT_CONFIG_RISCV_COMPRESSED"
+#endif
+#define RISCV_HAS_COMPRESSED(x) ((SLJIT_CONFIG_RISCV_COMPRESSED) >= (x))
+#define RISCV_COMPRESSED_CHECK(x) (x)
+#define RISCV_COMPRESSED_INFO "c"
+#else /* !SLJIT_CONFIG_RISCV_COMPRESSED || SLJIT_CONFIG_RISCV_COMPRESSED == 0 */
+#define RISCV_HAS_COMPRESSED(x) 0
+#define RISCV_COMPRESSED_CHECK(x) 0
+#define RISCV_COMPRESSED_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_COMPRESSED && SLJIT_CONFIG_RISCV_COMPRESSED != 0 */
+
+#if !(defined SLJIT_CONFIG_RISCV_VECTOR) && defined(__riscv_vector)
+/* Auto detect vector instruction support. */
+#define SLJIT_CONFIG_RISCV_VECTOR 100
+#endif /* !SLJIT_CONFIG_RISCV_VECTOR && __riscv_vector */
+
+/* SLJIT_CONFIG_RISCV_VECTOR enables/disables vector instruction
+ support. Non-zero values represents the highest version of the feature
+ that is supported by the CPU.
+ Allowed values: 0 - disabled, 100 - 1.00 */
+#if (defined SLJIT_CONFIG_RISCV_VECTOR && SLJIT_CONFIG_RISCV_VECTOR != 0)
+#if SLJIT_CONFIG_RISCV_VECTOR != 100
+#error "Unsupported value for SLJIT_CONFIG_RISCV_VECTOR"
+#endif
+#define RISCV_HAS_VECTOR(x) ((SLJIT_CONFIG_RISCV_VECTOR) >= (x))
+#define RISCV_VECTOR_INFO "v"
+#else /* !SLJIT_CONFIG_RISCV_VECTOR || SLJIT_CONFIG_RISCV_VECTOR == 0 */
+#define RISCV_HAS_VECTOR(x) 0
+#define RISCV_VECTOR_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_VECTOR && SLJIT_CONFIG_RISCV_VECTOR != 0 */
+
+#if !(defined SLJIT_CONFIG_RISCV_BITMANIP_A) && defined(__riscv_zba)
+/* Auto detect bit manipulation extension A instruction support. */
+#define SLJIT_CONFIG_RISCV_BITMANIP_A 93
+#endif /* !SLJIT_CONFIG_RISCV_BITMANIP_A && __riscv_zba */
+
+/* SLJIT_CONFIG_RISCV_BITMANIP_A enables/disables bit manipulation extension A
+ instruction support. Non-zero values represents the highest version of the
+ feature that is supported by the CPU.
+ Allowed values: 0 - disabled, 93 - 0.93 */
+#if (defined SLJIT_CONFIG_RISCV_BITMANIP_A && SLJIT_CONFIG_RISCV_BITMANIP_A != 0)
+#if SLJIT_CONFIG_RISCV_BITMANIP_A != 93
+#error "Unsupported value for SLJIT_CONFIG_RISCV_BITMANIP_A"
+#endif
+#define RISCV_HAS_BITMANIP_A(x) ((SLJIT_CONFIG_RISCV_BITMANIP_A) >= (x))
+#define RISCV_BITMANIP_A_INFO "_zba"
+#else /* !SLJIT_CONFIG_RISCV_BITMANIP_A || SLJIT_CONFIG_RISCV_BITMANIP_A == 0 */
+#define RISCV_HAS_BITMANIP_A(x) 0
+#define RISCV_BITMANIP_A_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_BITMANIP_A && SLJIT_CONFIG_RISCV_BITMANIP_A != 0 */
+
+#if !(defined SLJIT_CONFIG_RISCV_BITMANIP_B) && defined(__riscv_zbb)
+/* Auto detect bit manipulation extension B instruction support. */
+#define SLJIT_CONFIG_RISCV_BITMANIP_B 93
+#endif /* !SLJIT_CONFIG_RISCV_BITMANIP_B && __riscv_zbb */
+
+/* SLJIT_CONFIG_RISCV_BITMANIP_B enables/disables bit manipulation extension B
+ instruction support. Non-zero values represents the highest version of the
+ feature that is supported by the CPU.
+ Allowed values: 0 - disabled, 93 - 0.93 */
+#if (defined SLJIT_CONFIG_RISCV_BITMANIP_B && SLJIT_CONFIG_RISCV_BITMANIP_B != 0)
+#if SLJIT_CONFIG_RISCV_BITMANIP_B != 93
+#error "Unsupported value for SLJIT_CONFIG_RISCV_BITMANIP_B"
+#endif
+#define RISCV_HAS_BITMANIP_B(x) ((SLJIT_CONFIG_RISCV_BITMANIP_B) >= (x))
+#define RISCV_BITMANIP_B_INFO "_zbb"
+#else /* !SLJIT_CONFIG_RISCV_BITMANIP_B || SLJIT_CONFIG_RISCV_BITMANIP_B == 0 */
+#define RISCV_HAS_BITMANIP_B(x) 0
+#define RISCV_BITMANIP_B_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_BITMANIP_B && SLJIT_CONFIG_RISCV_BITMANIP_B != 0 */
+
+#if !(defined SLJIT_CONFIG_RISCV_ICOND) && defined(__riscv_zicond)
+/* Auto detect integer conditional instruction support. */
+#define SLJIT_CONFIG_RISCV_ICOND 100
+#endif /* !SLJIT_CONFIG_RISCV_ICOND && __riscv_zicond */
+
+/* SLJIT_CONFIG_RISCV_ICOND enables/disables integer conditional
+ instruction support. Non-zero values represents the highest version of the
+ feature that is supported by the CPU.
+ Allowed values: 0 - disabled, 100 - 1.00 */
+#if (defined SLJIT_CONFIG_RISCV_ICOND && SLJIT_CONFIG_RISCV_ICOND != 0)
+#if SLJIT_CONFIG_RISCV_ICOND != 100
+#error "Unsupported value for SLJIT_CONFIG_RISCV_ICOND"
+#endif
+#define RISCV_HAS_ICOND(x) ((SLJIT_CONFIG_RISCV_ICOND) >= (x))
+#define RISCV_ICOND_INFO "_zicond"
+#else /* !SLJIT_CONFIG_RISCV_ICOND || SLJIT_CONFIG_RISCV_ICOND == 0 */
+#define RISCV_HAS_ICOND(x) 0
+#define RISCV_ICOND_INFO ""
+#endif /* SLJIT_CONFIG_RISCV_ICOND && SLJIT_CONFIG_RISCV_ICOND != 0 */
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+#define RISCV_CHECK_COMPRESSED_JUMP(jump, diff, unit) \
+ (!((jump)->flags & IS_CALL) && (diff) >= (JUMP16_MIN / SSIZE_OF(unit)) && (diff) <= (JUMP16_MAX / SSIZE_OF(unit)))
+#else /* !SLJIT_CONFIG_RISCV_64 */
+#define RISCV_CHECK_COMPRESSED_JUMP(jump, diff, unit) \
+ ((diff) >= (JUMP16_MIN / SSIZE_OF(unit)) && (diff) <= (JUMP16_MAX / SSIZE_OF(unit)))
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
{
+ /* The arch string is not entirely correct since 'g' contains 'a'. */
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
- return "RISC-V-32" SLJIT_CPUINFO;
+ return "RISC-V-32 (rv32g" RISCV_ATOMIC_INFO RISCV_COMPRESSED_INFO RISCV_VECTOR_INFO RISCV_BITMANIP_A_INFO RISCV_BITMANIP_B_INFO RISCV_ICOND_INFO ")" SLJIT_CPUINFO;
#else /* !SLJIT_CONFIG_RISCV_32 */
- return "RISC-V-64" SLJIT_CPUINFO;
+ return "RISC-V-64 (rv64g" RISCV_ATOMIC_INFO RISCV_COMPRESSED_INFO RISCV_VECTOR_INFO RISCV_BITMANIP_A_INFO RISCV_BITMANIP_B_INFO RISCV_ICOND_INFO ")" SLJIT_CPUINFO;
#endif /* SLJIT_CONFIG_RISCV_32 */
}
-/* Length of an instruction word
- Both for riscv-32 and riscv-64 */
+/* Most instructions are 32 bit long on RISCV.
+ Code is processed as 16 bit units. */
typedef sljit_u32 sljit_ins;
#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
@@ -66,7 +197,7 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = {
};
/* --------------------------------------------------------------------- */
-/* Instrucion forms */
+/* Instruction forms */
/* --------------------------------------------------------------------- */
#define RD(rd) ((sljit_ins)reg_map[rd] << 7)
@@ -80,9 +211,28 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = {
#define VRS2(rs2) ((sljit_ins)vreg_map[rs2] << 20)
#define IMM_I(imm) ((sljit_ins)(imm) << 20)
#define IMM_S(imm) ((((sljit_ins)(imm) & 0xfe0) << 20) | (((sljit_ins)(imm) & 0x1f) << 7))
+#define C_RD(rd) ((sljit_u16)((sljit_u16)reg_map[rd] << 7))
+#define C_RS2(rd) ((sljit_u16)((sljit_u16)reg_map[rd] << 2))
+#define C_FRD(rd) ((sljit_u16)((sljit_u16)freg_map[rd] << 7))
+#define C_FRS2(rd) ((sljit_u16)((sljit_u16)freg_map[rd] << 2))
+#define C_RS1_R3(rs1) ((sljit_u16)((sljit_u16)(reg_map[rs1] & 0x7) << 7))
+#define C_RS2_R3(rs2) ((sljit_u16)((sljit_u16)(reg_map[rs2] & 0x7) << 2))
+#define C_FRS2_R3(rs2) ((sljit_u16)((sljit_u16)(freg_map[rs2] & 0x7) << 2))
+#define C_IS_R3(r) ((reg_map[r] & 0x18) == 0x08)
+#define C_IS_FR3(r) ((freg_map[r] & 0x18) == 0x08)
+#define C_IMM_I(imm) ((sljit_u16)((((imm) & 0x1f) << 2) | (((imm) & 0x20) << 7)))
+#define C_LD32_SP(imm) ((sljit_u16)((((imm) & 0x1c) << 2) | (((imm) & 0x20) << 7) | (((imm) & 0xc0) >> 4)))
+#define C_ST32_SP(imm) ((sljit_u16)((((imm) & 0x3c) << 7) | (((imm) & 0xc0) << 1)))
+#define C_LD64_SP(imm) ((sljit_u16)((((imm) & 0x18) << 2) | (((imm) & 0x20) << 7) | (((imm) & 0x1c0) >> 4)))
+#define C_ST64_SP(imm) ((sljit_u16)((((imm) & 0x38) << 7) | (((imm) & 0x1c0) << 1)))
+#define C_MEM32(imm) ((sljit_u16)((((imm) & 0x4) << 4) | (((imm) & 0x38) << 7) | (((imm) & 0x40) >> 1)))
+#define C_MEM64(imm) ((sljit_u16)((((imm) & 0x38) << 7) | (((imm) & 0xc0) >> 1)))
+#define C_BRN16(imm) ((sljit_u16)((((imm) & 0x6) << 2) | (((imm) & 0x18) << 7) | (((imm) & 0x20) >> 3) | (((imm) & 0xc0) >> 1) | (((imm) & 0x100) << 4)))
+#define C_JMP16(imm) ((sljit_u16)((((imm) & 0xb40) << 1) | (((imm) & 0xe) << 2) | (((imm) & 0x10) << 7) | (((imm) & 0x20) >> 3) | (((imm) & 0x80) >> 1) | (((imm) & 0x400) >> 2)))
/* Represents funct(i) parts of the instructions. */
#define OPC(o) ((sljit_ins)(o))
+#define C_OPC(o1, o2) ((sljit_u16)((o1) | ((o2) << 13)))
#define F3(f) ((sljit_ins)(f) << 12)
#define F12(f) ((sljit_ins)(f) << 20)
#define F7(f) ((sljit_ins)(f) << 25)
@@ -107,10 +257,50 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = {
#define BGE (F3(0x5) | OPC(0x63))
#define BLTU (F3(0x6) | OPC(0x63))
#define BGEU (F3(0x7) | OPC(0x63))
-#if defined __riscv_zbb
+/* C_*: compressed */
+#define C_ADD (C_OPC(0x2, 0x4) | (sljit_u16)(1 << 12))
+#define C_ADDI (C_OPC(0x1, 0x0))
+#define C_ADDIW (C_OPC(0x1, 0x1))
+#define C_ADDW (C_OPC(0x1, 0x4) | (sljit_u16)(7 << 10) | (sljit_u16)(1 << 5))
+#define C_ADDI16SP (C_OPC(0x1, 0x3) | (sljit_u16)(2 << 7))
+#define C_AND (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(3 << 5))
+#define C_ANDI (C_OPC(0x1, 0x4) | (sljit_u16)(2 << 10))
+#define C_BEQZ (C_OPC(0x1, 0x6))
+#define C_BNEZ (C_OPC(0x1, 0x7))
+#define C_EBREAK (C_OPC(0x2, 0x4) | (sljit_u16)(1 << 12))
+#define C_FLDSP (C_OPC(0x2, 0x1))
+#define C_FLWSP (C_OPC(0x2, 0x3))
+#define C_FSD (C_OPC(0x0, 0x5))
+#define C_FSDSP (C_OPC(0x2, 0x5))
+#define C_FSW (C_OPC(0x0, 0x7))
+#define C_FSWSP (C_OPC(0x2, 0x7))
+#define C_J (C_OPC(0x1, 0x5))
+#define C_JR (C_OPC(0x2, 0x4))
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+#define C_JAL (C_OPC(0x1, 0x1))
+#endif
+#define C_JALR (C_OPC(0x2, 0x4) | (sljit_u16)(1 << 12))
+#define C_LI (C_OPC(0x1, 0x2))
+#define C_LUI (C_OPC(0x1, 0x3))
+#define C_LDSP (C_OPC(0x2, 0x3))
+#define C_LWSP (C_OPC(0x2, 0x2))
+#define C_MV (C_OPC(0x2, 0x4))
+#define C_NOP (C_OPC(0x1, 0x0))
+#define C_SD (C_OPC(0x0, 0x7))
+#define C_SDSP (C_OPC(0x2, 0x7))
+#define C_SLLI (C_OPC(0x2, 0x0))
+#define C_OR (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(2 << 5))
+#define C_SRAI (C_OPC(0x1, 0x4) | (sljit_u16)(1 << 10))
+#define C_SRLI (C_OPC(0x1, 0x4) | (sljit_u16)(0 << 10))
+#define C_SUB (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(0 << 5))
+#define C_SW (C_OPC(0x0, 0x6))
+#define C_SWSP (C_OPC(0x2, 0x6))
+#define C_XOR (C_OPC(0x1, 0x4) | (sljit_u16)(3 << 10) | (sljit_u16)(1 << 5))
+/* CLZ / CTZ: zbb */
#define CLZ (F7(0x30) | F3(0x1) | OPC(0x13))
#define CTZ (F7(0x30) | F12(0x1) | F3(0x1) | OPC(0x13))
-#endif /* __riscv_zbb */
+#define CZERO_EQZ (F7(0x7) | F3(0x5) | OPC(0x33))
+#define CZERO_NEZ (F7(0x7) | F3(0x7) | OPC(0x33))
#define DIV (F7(0x1) | F3(0x4) | OPC(0x33))
#define DIVU (F7(0x1) | F3(0x5) | OPC(0x33))
#define EBREAK (F12(0x1) | F3(0x0) | OPC(0x73))
@@ -140,35 +330,39 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = {
#define LD (F3(0x3) | OPC(0x3))
#define LUI (OPC(0x37))
#define LW (F3(0x2) | OPC(0x3))
+/* LR: atomic */
#define LR (F7(0x8) | OPC(0x2f))
+#define MAX (F7(0x5) | F3(0x6) | OPC(0x33))
+#define MAXU (F7(0x5) | F3(0x7) | OPC(0x33))
+#define MIN (F7(0x5) | F3(0x4) | OPC(0x33))
+#define MINU (F7(0x5) | F3(0x5) | OPC(0x33))
#define MUL (F7(0x1) | F3(0x0) | OPC(0x33))
#define MULH (F7(0x1) | F3(0x1) | OPC(0x33))
#define MULHU (F7(0x1) | F3(0x3) | OPC(0x33))
+#define NOP ADDI
#define OR (F7(0x0) | F3(0x6) | OPC(0x33))
#define ORI (F3(0x6) | OPC(0x13))
#define REM (F7(0x1) | F3(0x6) | OPC(0x33))
#define REMU (F7(0x1) | F3(0x7) | OPC(0x33))
-#if defined __riscv_zbb
-#if defined SLJIT_CONFIG_RISCV_32
+/* REV8 / ROL / ROR / RORI: zbb */
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
#define REV8 (F12(0x698) | F3(0x5) | OPC(0x13))
-#elif defined SLJIT_CONFIG_RISCV_64
+#elif (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
#define REV8 (F12(0x6b8) | F3(0x5) | OPC(0x13))
#endif /* SLJIT_CONFIG_RISCV_32 */
#define ROL (F7(0x30) | F3(0x1) | OPC(0x33))
#define ROR (F7(0x30) | F3(0x5) | OPC(0x33))
#define RORI (F7(0x30) | F3(0x5) | OPC(0x13))
-#endif /* __riscv_zbb */
+/* SC: atomic */
#define SC (F7(0xc) | OPC(0x2f))
#define SD (F3(0x3) | OPC(0x23))
-#if defined __riscv_zbb
+/* SEXTB / SEXTH: zbb */
#define SEXTB (F7(0x30) | F12(0x4) | F3(0x1) | OPC(0x13))
#define SEXTH (F7(0x30) | F12(0x5) | F3(0x1) | OPC(0x13))
-#endif /* __riscv_zbb */
-#if defined __riscv_zba
+/* SH1ADD / SH2ADD / SH3ADD: zba */
#define SH1ADD (F7(0x10) | F3(0x2) | OPC(0x33))
#define SH2ADD (F7(0x10) | F3(0x4) | OPC(0x33))
#define SH3ADD (F7(0x10) | F3(0x6) | OPC(0x33))
-#endif /* __riscv_zba */
#define SLL (F7(0x0) | F3(0x1) | OPC(0x33))
#define SLLI (F3(0x1) | OPC(0x13))
#define SLT (F7(0x0) | F3(0x2) | OPC(0x33))
@@ -181,6 +375,7 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = {
#define SRAI (F7(0x20) | F3(0x5) | OPC(0x13))
#define SUB (F7(0x20) | F3(0x0) | OPC(0x33))
#define SW (F3(0x2) | OPC(0x23))
+/* V*: vector */
#define VAND_VV (F7(0x13) | OPIVV)
#define VFMV_FS (F7(0x21) | OPFVV)
#define VFMV_SF (F7(0x21) | OPFVF)
@@ -194,6 +389,7 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = {
#define VMV_VX (F7(0x2f) | OPIVX)
#define VMV_XS (F7(0x21) | OPMVV)
#define VOR_VV (F7(0x15) | OPIVV)
+#define VSETVLI (F7(0x0) | F3(0x7) | OPC(0x57))
#define VSETIVLI (F7(0x60) | F3(0x7) | OPC(0x57))
#define VS (F7(0x1) | OPC(0x27))
#define VSLIDEDOWN_VX (F7(0x1f) | OPIVX)
@@ -208,20 +404,25 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = {
#define VZEXT_VF8 (F7(0x25) | (0x2 << 15) | OPMVV)
#define XOR (F7(0x0) | F3(0x4) | OPC(0x33))
#define XORI (F3(0x4) | OPC(0x13))
-#if defined __riscv_zbb
-#if defined SLJIT_CONFIG_RISCV_32
+/* ZEXTH: zbb */
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
#define ZEXTH (F7(0x4) | F3(0x4) | OPC(0x33))
-#elif defined SLJIT_CONFIG_RISCV_64
+#else /* SLJIT_CONFIG_RISCV_64 */
#define ZEXTH (F7(0x4) | F3(0x4) | OPC(0x3B))
#endif /* SLJIT_CONFIG_RISCV_32 */
-#endif /* __riscv_zbb */
#define SIMM_MAX (0x7ff)
#define SIMM_MIN (-0x800)
+#define SIMM16_MAX (0x1f)
+#define SIMM16_MIN (-0x20)
#define BRANCH_MAX (0xfff)
#define BRANCH_MIN (-0x1000)
+#define BRANCH16_MAX (0xff)
+#define BRANCH16_MIN (-0x100)
#define JUMP_MAX (0xfffff)
#define JUMP_MIN (-0x100000)
+#define JUMP16_MAX SIMM_MAX
+#define JUMP16_MIN SIMM_MIN
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
#define S32_MAX (0x7ffff7ffl)
@@ -230,9 +431,30 @@ static const sljit_u8 vreg_map[SLJIT_NUMBER_OF_VECTOR_REGISTERS + 3] = {
#define S52_MAX (0x7ffffffffffffl)
#endif /* SLJIT_CONFIG_RISCV_64 */
+#define C_ADDI_W(word) (C_ADDI | (sljit_u16)((word) << 10))
+#define C_SUB_W(word) (C_SUB | (sljit_u16)((word) << 9))
+
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+#define BRANCH_LENGTH ((sljit_ins)(3 * sizeof(sljit_ins)) << 7)
+#define BRANCH16_LENGTH C_BRN16(5 * sizeof(sljit_u16))
+#else /* !SLJIT_CONFIG_RISCV_32 */
+#define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7)
+#define BRANCH16_LENGTH C_BRN16(13 * sizeof(sljit_u16))
+#endif /* SLJIT_CONFIG_RISCV_32 */
+
static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
{
- sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_ins));
+ FAIL_IF(!ptr);
+ ptr[0] = (sljit_u16)ins;
+ ptr[1] = (sljit_u16)(ins >> 16);
+ compiler->size += 2;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_u16 ins)
+{
+ sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_u16));
FAIL_IF(!ptr);
*ptr = ins;
compiler->size++;
@@ -244,12 +466,16 @@ static sljit_s32 push_imm_s_inst(struct sljit_compiler *compiler, sljit_ins ins,
return push_inst(compiler, ins | IMM_S(imm));
}
-static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
+static SLJIT_INLINE sljit_u16* detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)
{
- sljit_sw diff;
+ sljit_sw diff, cond_diff;
sljit_uw target_addr;
sljit_uw jump_addr = (sljit_uw)code_ptr;
sljit_uw orig_addr = jump->addr;
+ sljit_ins ins;
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ sljit_s32 jalr_offset = JUMP_MAX_SIZE - 1;
+#endif /* SLJIT_CONFIG_RISCV_64 */
SLJIT_UNUSED_ARG(executable_offset);
jump->addr = jump_addr;
@@ -269,90 +495,131 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
diff = (sljit_sw)target_addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);
if (jump->flags & IS_COND) {
- diff += SSIZE_OF(ins);
+ cond_diff = diff + SSIZE_OF(ins);
+
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16))) {
+ SLJIT_ASSERT((code_ptr[-1] & 0xe003) == C_BEQZ || (code_ptr[-1] & 0xe003) == C_BNEZ);
+
+ cond_diff = diff + SSIZE_OF(u16);
+
+ if (diff >= BRANCH16_MIN && diff <= BRANCH16_MAX) {
+ code_ptr--;
+ code_ptr[0] = (sljit_u16)((code_ptr[0] & 0xe383) ^ 0x2000);
+ jump->flags |= PATCH_B | PATCH_16;
+ jump->addr = (sljit_uw)code_ptr;
+ return code_ptr;
+ }
+ }
+
+ if (cond_diff >= BRANCH_MIN && cond_diff <= BRANCH_MAX) {
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16))) {
+ /* Converting 16 bit branch to 32 bit branch. */
+ code_ptr--;
+ code_ptr[1] = (sljit_u16)(((code_ptr[0] & 0x300) >> 8) | 0x4);
+ code_ptr[0] = (sljit_u16)((BNE ^ ((code_ptr[0] & 0x2000) >> 1)) | ((code_ptr[0] & 0x80) << 8));
+ } else {
+ code_ptr -= 2;
+ code_ptr[0] = (sljit_u16)((code_ptr[0] & 0xf07f) ^ 0x1000);
+ code_ptr[1] = (sljit_u16)(code_ptr[1] & 0x1ff);
+ }
- if (diff >= BRANCH_MIN && diff <= BRANCH_MAX) {
- code_ptr--;
- code_ptr[0] = (code_ptr[0] & 0x1fff07f) ^ 0x1000;
jump->flags |= PATCH_B;
jump->addr = (sljit_uw)code_ptr;
- return code_ptr;
+ return code_ptr + 1;
}
+ }
- diff -= SSIZE_OF(ins);
+ if (RISCV_HAS_COMPRESSED(200) && RISCV_CHECK_COMPRESSED_JUMP(jump, diff, u8)) {
+ /* A conditional instruction has larger max offset
+ than a 16 bit jump instruction. */
+ SLJIT_ASSERT(!(jump->flags & IS_COND));
+ jump->flags |= PATCH_J | PATCH_16;
+ return code_ptr;
}
if (diff >= JUMP_MIN && diff <= JUMP_MAX) {
if (jump->flags & IS_COND) {
-#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
- code_ptr[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7;
-#else /* !SLJIT_CONFIG_RISCV_32 */
- code_ptr[-1] -= (sljit_ins)(5 * sizeof(sljit_ins)) << 7;
-#endif /* SLJIT_CONFIG_RISCV_32 */
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))
+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(3 * sizeof(sljit_u16)));
+ else
+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (2 * sizeof(sljit_ins) << 7));
}
jump->flags |= PATCH_J;
- return code_ptr;
+ return code_ptr + 1;
}
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
if (diff >= S32_MIN && diff <= S32_MAX) {
- if (jump->flags & IS_COND)
- code_ptr[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7;
+ if (jump->flags & IS_COND) {
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))
+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(5 * sizeof(sljit_u16)));
+ else
+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (3 * sizeof(sljit_ins) << 7));
+ }
jump->flags |= PATCH_REL32;
- code_ptr[1] = code_ptr[0];
- return code_ptr + 1;
- }
-
- if (target_addr <= (sljit_uw)S32_MAX) {
- if (jump->flags & IS_COND)
- code_ptr[-1] -= (sljit_ins)(4 * sizeof(sljit_ins)) << 7;
+ jalr_offset = 3;
+ } else if (target_addr <= (sljit_uw)S32_MAX) {
+ if (jump->flags & IS_COND) {
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))
+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(5 * sizeof(sljit_u16)));
+ else
+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (3 * sizeof(sljit_ins) << 7));
+ }
jump->flags |= PATCH_ABS32;
- code_ptr[1] = code_ptr[0];
- return code_ptr + 1;
- }
-
- if (target_addr <= S44_MAX) {
- if (jump->flags & IS_COND)
- code_ptr[-1] -= (sljit_ins)(2 * sizeof(sljit_ins)) << 7;
+ jalr_offset = 3;
+ } else if (target_addr <= S44_MAX) {
+ if (jump->flags & IS_COND) {
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))
+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(9 * sizeof(sljit_u16)));
+ else
+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (5 * sizeof(sljit_ins) << 7));
+ }
jump->flags |= PATCH_ABS44;
- code_ptr[3] = code_ptr[0];
- return code_ptr + 3;
- }
-
- if (target_addr <= S52_MAX) {
- if (jump->flags & IS_COND)
- code_ptr[-1] -= (sljit_ins)(1 * sizeof(sljit_ins)) << 7;
+ jalr_offset = 7;
+ } else if (target_addr <= S52_MAX) {
+ if (jump->flags & IS_COND) {
+ if (RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16)))
+ code_ptr[-1] ^= (sljit_u16)(BRANCH16_LENGTH ^ C_BRN16(11 * sizeof(sljit_u16)));
+ else
+ code_ptr[-2] ^= (sljit_u16)(BRANCH_LENGTH ^ (6 * sizeof(sljit_ins) << 7));
+ }
jump->flags |= PATCH_ABS52;
- code_ptr[4] = code_ptr[0];
- return code_ptr + 4;
+ jalr_offset = 9;
}
#endif /* SLJIT_CONFIG_RISCV_64 */
exit:
+ ins = JALR | RS1(TMP_REG1) | IMM_I(0);
+ if (jump->flags & IS_CALL)
+ ins |= RD(RETURN_ADDR_REG);
+
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
- code_ptr[1] = code_ptr[0];
- return code_ptr + 1;
+ code_ptr[2] = (sljit_u16)ins;
+ code_ptr[3] = (sljit_u16)(ins >> 16);
+ return code_ptr + 3;
#else /* !SLJIT_CONFIG_RISCV_32 */
- code_ptr[5] = code_ptr[0];
- return code_ptr + 5;
+ code_ptr += jalr_offset;
+ code_ptr[-1] = (sljit_u16)ins;
+ code_ptr[0] = (sljit_u16)(ins >> 16);
+ return code_ptr;
#endif /* SLJIT_CONFIG_RISCV_32 */
}
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
-static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
+static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)
{
sljit_uw addr;
sljit_uw jump_addr = (sljit_uw)code_ptr;
sljit_sw diff;
SLJIT_UNUSED_ARG(executable_offset);
- SLJIT_ASSERT(jump->flags < ((sljit_uw)6 << JUMP_SIZE_SHIFT));
+ SLJIT_ASSERT(jump->flags < (JUMP_MAX_SIZE << JUMP_SIZE_SHIFT));
if (jump->flags & JUMP_ADDR)
addr = jump->u.target;
else {
@@ -365,31 +632,31 @@ static SLJIT_INLINE sljit_sw mov_addr_get_length(struct sljit_jump *jump, sljit_
diff = (sljit_sw)addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(jump_addr, executable_offset);
if (diff >= S32_MIN && diff <= S32_MAX) {
- SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
jump->flags |= PATCH_REL32;
- return 1;
+ return 3;
}
if (addr <= S32_MAX) {
- SLJIT_ASSERT(jump->flags >= ((sljit_uw)1 << JUMP_SIZE_SHIFT));
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
jump->flags |= PATCH_ABS32;
- return 1;
+ return 3;
}
if (addr <= S44_MAX) {
- SLJIT_ASSERT(jump->flags >= ((sljit_uw)3 << JUMP_SIZE_SHIFT));
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)7 << JUMP_SIZE_SHIFT));
jump->flags |= PATCH_ABS44;
- return 3;
+ return 7;
}
if (addr <= S52_MAX) {
- SLJIT_ASSERT(jump->flags >= ((sljit_uw)4 << JUMP_SIZE_SHIFT));
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)9 << JUMP_SIZE_SHIFT));
jump->flags |= PATCH_ABS52;
- return 4;
+ return 9;
}
- SLJIT_ASSERT(jump->flags >= ((sljit_uw)5 << JUMP_SIZE_SHIFT));
- return 5;
+ SLJIT_ASSERT(jump->flags >= ((sljit_uw)11 << JUMP_SIZE_SHIFT));
+ return 11;
}
#endif /* SLJIT_CONFIG_RISCV_64 */
@@ -398,8 +665,9 @@ static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw exec
{
sljit_uw flags = jump->flags;
sljit_uw addr = (flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
- sljit_ins *ins = (sljit_ins*)jump->addr;
- sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *ins : TMP_REG1;
+ sljit_ins ins;
+ sljit_u16 *buf = (sljit_u16 *)jump->addr;
+ sljit_u32 reg = (flags & JUMP_MOV_ADDR) ? *buf : TMP_REG1;
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
sljit_sw high;
#endif /* SLJIT_CONFIG_RISCV_64 */
@@ -407,20 +675,26 @@ static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw exec
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
if (flags & PATCH_REL32) {
- addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(ins, executable_offset);
+ addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf, executable_offset);
SLJIT_ASSERT((sljit_sw)addr >= S32_MIN && (sljit_sw)addr <= S32_MAX);
if ((addr & 0x800) != 0)
addr += 0x1000;
- ins[0] = AUIPC | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
+ ins = AUIPC | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
if (!(flags & JUMP_MOV_ADDR)) {
- SLJIT_ASSERT((ins[1] & 0x707f) == JALR);
- ins[1] = (ins[1] & 0xfffff) | IMM_I(addr);
+ ins = JALR | RS1(reg) | IMM_I(addr);
+ if (jump->flags & IS_CALL)
+ ins |= RD(RETURN_ADDR_REG);
} else
- ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);
+ ins = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);
+
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
return;
}
#endif /* SLJIT_CONFIG_RISCV_64 */
@@ -429,30 +703,44 @@ static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw exec
addr += 0x1000;
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
- ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
+ ins = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
#else /* !SLJIT_CONFIG_RISCV_32 */
if (flags & PATCH_ABS32) {
SLJIT_ASSERT(addr <= S32_MAX);
- ins[0] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
+ ins = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
} else if (flags & PATCH_ABS44) {
high = (sljit_sw)addr >> 12;
SLJIT_ASSERT((sljit_uw)high <= 0x7fffffff);
if (high > S32_MAX) {
SLJIT_ASSERT((high & 0x800) != 0);
- ins[0] = LUI | RD(reg) | (sljit_ins)0x80000000u;
- ins[1] = XORI | RD(reg) | RS1(reg) | IMM_I(high);
+ ins = LUI | RD(reg) | (sljit_ins)0x80000000u;
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
+ ins = XORI | RD(reg) | RS1(reg) | IMM_I(high);
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
} else {
if ((high & 0x800) != 0)
high += 0x1000;
- ins[0] = LUI | RD(reg) | (sljit_ins)(high & ~0xfff);
- ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(high);
+ ins = LUI | RD(reg) | (sljit_ins)(high & ~0xfff);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
+ ins = ADDI | RD(reg) | RS1(reg) | IMM_I(high);
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
}
- ins[2] = SLLI | RD(reg) | RS1(reg) | IMM_I(12);
- ins += 2;
+ ins = SLLI | RD(reg) | RS1(reg) | IMM_I(12);
+ buf[4] = (sljit_u16)ins;
+ buf[5] = (sljit_u16)(ins >> 16);
+ buf += 4;
} else {
high = (sljit_sw)addr >> 32;
@@ -461,27 +749,49 @@ static SLJIT_INLINE void load_addr_to_reg(struct sljit_jump *jump, sljit_sw exec
if (flags & PATCH_ABS52) {
SLJIT_ASSERT(addr <= S52_MAX);
- ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12);
+ ins = LUI | RD(TMP_REG3) | (sljit_ins)(high << 12);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
} else {
if ((high & 0x800) != 0)
high += 0x1000;
- ins[0] = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff);
- ins[1] = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high);
- ins++;
+ ins = LUI | RD(TMP_REG3) | (sljit_ins)(high & ~0xfff);
+ buf[0] = (sljit_u16)ins;
+ buf[1] = (sljit_u16)(ins >> 16);
+ ins = ADDI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I(high);
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
+ buf += 2;
}
- ins[1] = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
- ins[2] = SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I((flags & PATCH_ABS52) ? 20 : 32);
- ins[3] = XOR | RD(reg) | RS1(reg) | RS2(TMP_REG3);
- ins += 3;
+ ins = LUI | RD(reg) | (sljit_ins)((sljit_sw)addr & ~0xfff);
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
+ ins = SLLI | RD(TMP_REG3) | RS1(TMP_REG3) | IMM_I((flags & PATCH_ABS52) ? 20 : 32);
+ buf[4] = (sljit_u16)ins;
+ buf[5] = (sljit_u16)(ins >> 16);
+ ins = XOR | RD(reg) | RS1(reg) | RS2(TMP_REG3);
+ buf[6] = (sljit_u16)ins;
+ buf[7] = (sljit_u16)(ins >> 16);
+ buf += 6;
}
#endif /* !SLJIT_CONFIG_RISCV_32 */
if (!(flags & JUMP_MOV_ADDR)) {
- SLJIT_ASSERT((ins[1] & 0x707f) == JALR);
- ins[1] = (ins[1] & 0xfffff) | IMM_I(addr);
+ ins = JALR | RS1(reg) | IMM_I(addr);
+ if (jump->flags & IS_CALL)
+ ins |= RD(RETURN_ADDR_REG);
} else
- ins[1] = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);
+ ins = ADDI | RD(reg) | RS1(reg) | IMM_I(addr);
+
+ buf[2] = (sljit_u16)ins;
+ buf[3] = (sljit_u16)(ins >> 16);
+}
+
+static SLJIT_INLINE sljit_u16 *process_extended_label(sljit_u16 *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_u16*)((sljit_uw)code_ptr & ~(ext_label->data));
}
static void reduce_code_size(struct sljit_compiler *compiler)
@@ -492,7 +802,7 @@ static void reduce_code_size(struct sljit_compiler *compiler)
SLJIT_NEXT_DEFINE_TYPES;
sljit_uw total_size;
sljit_uw size_reduce = 0;
- sljit_sw diff;
+ sljit_sw diff, cond_size, cond_diff;
label = compiler->labels;
jump = compiler->jumps;
@@ -530,11 +840,11 @@ static void reduce_code_size(struct sljit_compiler *compiler)
if (jump->flags & JUMP_ADDR) {
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
if (jump->u.target <= S32_MAX)
- total_size = 2;
- else if (jump->u.target <= S44_MAX)
total_size = 4;
+ else if (jump->u.target <= S44_MAX)
+ total_size = 8;
else if (jump->u.target <= S52_MAX)
- total_size = 5;
+ total_size = 10;
#endif /* SLJIT_CONFIG_RISCV_64 */
} else {
/* Unit size: instruction. */
@@ -544,13 +854,20 @@ static void reduce_code_size(struct sljit_compiler *compiler)
diff -= (sljit_sw)size_reduce;
}
- if ((jump->flags & IS_COND) && (diff + 1) <= (BRANCH_MAX / SSIZE_OF(ins)) && (diff + 1) >= (BRANCH_MIN / SSIZE_OF(ins)))
+ cond_size = RISCV_COMPRESSED_CHECK((jump->flags & IS_COND16) != 0);
+ cond_diff = diff + 2 - cond_size;
+
+ if (RISCV_COMPRESSED_CHECK(cond_size) && diff >= (BRANCH16_MIN / SSIZE_OF(u16)) && diff <= (BRANCH16_MAX / SSIZE_OF(u16)))
total_size = 0;
- else if (diff >= (JUMP_MIN / SSIZE_OF(ins)) && diff <= (JUMP_MAX / SSIZE_OF(ins)))
+ else if ((jump->flags & IS_COND) && cond_diff <= (BRANCH_MAX / SSIZE_OF(u16)) && cond_diff >= (BRANCH_MIN / SSIZE_OF(u16)))
+ total_size = (sljit_uw)cond_size;
+ else if (RISCV_HAS_COMPRESSED(200) && RISCV_CHECK_COMPRESSED_JUMP(jump, diff, u16))
total_size = 1;
-#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
- else if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))
+ else if (diff >= (JUMP_MIN / SSIZE_OF(u16)) && diff <= (JUMP_MAX / SSIZE_OF(u16)))
total_size = 2;
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ else if (diff >= (S32_MIN / SSIZE_OF(u16)) && diff <= (S32_MAX / SSIZE_OF(u16)))
+ total_size = 4;
#endif /* SLJIT_CONFIG_RISCV_64 */
}
}
@@ -559,26 +876,26 @@ static void reduce_code_size(struct sljit_compiler *compiler)
jump->flags |= total_size << JUMP_SIZE_SHIFT;
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
} else {
- total_size = 5;
+ total_size = 11;
if (!(jump->flags & JUMP_ADDR)) {
- /* Real size minus 1. Unit size: instruction. */
+ /* Real size minus 1. Unit size: 16 bit. */
diff = (sljit_sw)jump->u.label->size - (sljit_sw)jump->addr;
if (jump->u.label->size > jump->addr) {
SLJIT_ASSERT(jump->u.label->size - size_reduce >= jump->addr);
diff -= (sljit_sw)size_reduce;
}
- if (diff >= (S32_MIN / SSIZE_OF(ins)) && diff <= (S32_MAX / SSIZE_OF(ins)))
- total_size = 1;
+ if (diff >= (S32_MIN / SSIZE_OF(u16)) && diff <= (S32_MAX / SSIZE_OF(u16)))
+ total_size = 3;
} else if (jump->u.target < S32_MAX)
- total_size = 1;
- else if (jump->u.target < S44_MAX)
total_size = 3;
+ else if (jump->u.target < S44_MAX)
+ total_size = 7;
else if (jump->u.target <= S52_MAX)
- total_size = 4;
+ total_size = 9;
- size_reduce += 5 - total_size;
+ size_reduce += 11 - total_size;
jump->flags |= total_size << JUMP_SIZE_SHIFT;
#endif /* !SLJIT_CONFIG_RISCV_64 */
}
@@ -593,32 +910,33 @@ static void reduce_code_size(struct sljit_compiler *compiler)
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
{
struct sljit_memory_fragment *buf;
- sljit_ins *code;
- sljit_ins *code_ptr;
- sljit_ins *buf_ptr;
- sljit_ins *buf_end;
- sljit_uw word_count;
+ sljit_u16 *code;
+ sljit_u16 *code_ptr;
+ sljit_u16 *buf_ptr;
+ sljit_u16 *buf_end;
+ sljit_uw half_count;
SLJIT_NEXT_DEFINE_TYPES;
sljit_sw executable_offset;
sljit_uw addr;
+ sljit_ins ins;
struct sljit_label *label;
struct sljit_jump *jump;
struct sljit_const *const_;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_generate_code(compiler));
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
reduce_code_size(compiler);
- code = (sljit_ins*)allocate_executable_memory(compiler->size * sizeof(sljit_ins), options, exec_allocator_data, &executable_offset);
+ code = (sljit_u16 *)allocate_executable_memory(compiler->size * sizeof(sljit_u16), options, exec_allocator_data, &executable_offset);
PTR_FAIL_WITH_EXEC_IF(code);
reverse_buf(compiler);
buf = compiler->buf;
code_ptr = code;
- word_count = 0;
+ half_count = 0;
label = compiler->labels;
jump = compiler->jumps;
const_ = compiler->consts;
@@ -626,17 +944,22 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_GET_NEXT_MIN();
do {
- buf_ptr = (sljit_ins*)buf->memory;
- buf_end = buf_ptr + (buf->used_size >> 2);
+ buf_ptr = (sljit_u16*)buf->memory;
+ buf_end = buf_ptr + (buf->used_size >> 1);
do {
*code_ptr = *buf_ptr++;
- if (next_min_addr == word_count) {
- SLJIT_ASSERT(!label || label->size >= word_count);
- SLJIT_ASSERT(!jump || jump->addr >= word_count);
- SLJIT_ASSERT(!const_ || const_->addr >= word_count);
+ if (next_min_addr == half_count) {
+ SLJIT_ASSERT(!label || label->size >= half_count);
+ SLJIT_ASSERT(!jump || jump->addr >= half_count);
+ SLJIT_ASSERT(!const_ || const_->addr >= half_count);
/* These structures are ordered by their address. */
if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+ *code_ptr = buf_ptr[-1];
+ }
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -645,16 +968,16 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (next_min_addr == next_jump_addr) {
if (!(jump->flags & JUMP_MOV_ADDR)) {
- word_count = word_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);
+ half_count = half_count - 1 + (jump->flags >> JUMP_SIZE_SHIFT);
code_ptr = detect_jump_type(jump, code_ptr, code, executable_offset);
SLJIT_ASSERT((jump->flags & PATCH_B) || ((sljit_uw)code_ptr - jump->addr < (jump->flags >> JUMP_SIZE_SHIFT) * sizeof(sljit_ins)));
} else {
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
- word_count += 1;
+ half_count += 3;
jump->addr = (sljit_uw)code_ptr;
- code_ptr += 1;
+ code_ptr += 3;
#else /* !SLJIT_CONFIG_RISCV_32 */
- word_count += jump->flags >> JUMP_SIZE_SHIFT;
+ half_count += jump->flags >> JUMP_SIZE_SHIFT;
addr = (sljit_uw)code_ptr;
code_ptr += mov_addr_get_length(jump, code_ptr, code, executable_offset);
jump->addr = addr;
@@ -671,13 +994,16 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_GET_NEXT_MIN();
}
code_ptr++;
- word_count++;
+ half_count++;
} while (buf_ptr < buf_end);
buf = buf->next;
} while (buf);
- if (label && label->size == word_count) {
+ if (label && label->size == half_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
label->u.addr = (sljit_uw)code_ptr;
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -697,19 +1023,41 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
}
addr = (jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr;
- buf_ptr = (sljit_ins *)jump->addr;
+ buf_ptr = (sljit_u16 *)jump->addr;
addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
if (jump->flags & PATCH_B) {
+ SLJIT_ASSERT(RISCV_HAS_COMPRESSED(200) || !(jump->flags & PATCH_16));
SLJIT_ASSERT((sljit_sw)addr >= BRANCH_MIN && (sljit_sw)addr <= BRANCH_MAX);
- addr = ((addr & 0x800) >> 4) | ((addr & 0x1e) << 7) | ((addr & 0x7e0) << 20) | ((addr & 0x1000) << 19);
- buf_ptr[0] |= (sljit_ins)addr;
+
+ if (RISCV_COMPRESSED_CHECK(jump->flags & PATCH_16)) {
+ buf_ptr[0] |= C_BRN16(addr);
+ break;
+ }
+
+ buf_ptr[0] |= (sljit_u16)(((addr & 0x800) >> 4) | ((addr & 0x1e) << 7));
+ buf_ptr[1] |= (sljit_u16)(((addr & 0x7e0) << 4) | ((addr & 0x1000) << 3));
+ break;
+ }
+
+ SLJIT_ASSERT(RISCV_HAS_COMPRESSED(200) || !(jump->flags & PATCH_16));
+ if (RISCV_COMPRESSED_CHECK(jump->flags & PATCH_16)) {
+ SLJIT_ASSERT((sljit_sw)addr >= JUMP16_MIN && (sljit_sw)addr <= JUMP16_MAX);
+#if defined SLJIT_CONFIG_RISCV_32
+ ins = ((jump->flags & IS_CALL) ? C_JAL : C_J) | C_JMP16(addr);
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ SLJIT_ASSERT(!(jump->flags & IS_CALL));
+ ins = C_J | C_JMP16(addr);
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ buf_ptr[0] = (sljit_u16)ins;
break;
}
SLJIT_ASSERT((sljit_sw)addr >= JUMP_MIN && (sljit_sw)addr <= JUMP_MAX);
addr = (addr & 0xff000) | ((addr & 0x800) << 9) | ((addr & 0x7fe) << 20) | ((addr & 0x100000) << 11);
- buf_ptr[0] = JAL | RD((jump->flags & IS_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | (sljit_ins)addr;
+ ins = JAL | RD((jump->flags & IS_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | (sljit_ins)addr;
+ buf_ptr[0] = (sljit_u16)ins;
+ buf_ptr[1] = (sljit_u16)(ins >> 16);
} while (0);
jump = jump->next;
@@ -719,8 +1067,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
compiler->executable_offset = executable_offset;
compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
- code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
- code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ code = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
+ code_ptr = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
SLJIT_CACHE_FLUSH(code, code_ptr);
SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1);
@@ -744,18 +1092,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
case SLJIT_HAS_COPY_F64:
#endif /* !SLJIT_CONFIG_RISCV_64 */
case SLJIT_HAS_ATOMIC:
+ return RISCV_HAS_ATOMIC(200) ? 1 : 0;
case SLJIT_HAS_MEMORY_BARRIER:
-#ifdef __riscv_vector
- case SLJIT_HAS_SIMD:
-#endif /* __riscv_vector */
return 1;
-#ifdef __riscv_zbb
case SLJIT_HAS_CLZ:
case SLJIT_HAS_CTZ:
case SLJIT_HAS_REV:
case SLJIT_HAS_ROT:
- return 1;
-#endif /* __riscv_zbb */
+ return RISCV_HAS_BITMANIP_B(93) ? 1 : 0;
+ case SLJIT_HAS_CMOV:
+ return RISCV_HAS_ICOND(100) ? 2 : 0;
+ case SLJIT_HAS_SIMD:
+ return RISCV_HAS_VECTOR(100) ? 1 : 0;
default:
return 0;
}
@@ -813,9 +1161,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_cmp_info(sljit_s32 type)
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
#define STACK_STORE SW
#define STACK_LOAD LW
+#define C_STACK_OFFSET_CHECK(offset) ((offset) <= 0xfc)
+#define C_STACK_LOAD(offset) (C_LWSP | C_LD32_SP(offset))
+#define C_STACK_STORE(offset) (C_SWSP | C_ST32_SP(offset))
#else /* !SLJIT_CONFIG_RISCV_32 */
#define STACK_STORE SD
#define STACK_LOAD LD
+#define C_STACK_OFFSET_CHECK(offset) ((offset) <= 0x1f8)
+#define C_STACK_LOAD(offset) (C_LDSP | C_LD64_SP(offset))
+#define C_STACK_STORE(offset) (C_SDSP | C_ST64_SP(offset))
#endif /* SLJIT_CONFIG_RISCV_32 */
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
@@ -858,8 +1212,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
if (local_size <= STACK_MAX_DISTANCE) {
/* Frequent case. */
- FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(-local_size)));
offset = local_size - SSIZE_OF(sw);
+ local_size = -local_size;
+ if (RISCV_HAS_COMPRESSED(200) && local_size >= -0x200) {
+ SLJIT_ASSERT((local_size & 0x200) != 0 && (local_size & 0xf) == 0);
+ FAIL_IF(push_inst16(compiler, C_ADDI16SP | (sljit_u16)(((local_size & 0x10) << 2) | ((local_size & 0x20) >> 3) | ((local_size & 0x40) >> 1) | ((local_size & 0x180) >> 4) | (1 << 12))));
+ } else
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size)));
local_size = 0;
} else {
FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(STACK_MAX_DISTANCE)));
@@ -870,17 +1229,26 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
offset = STACK_MAX_DISTANCE - SSIZE_OF(sw);
}
- FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(RETURN_ADDR_REG), offset));
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_STORE(offset) | C_RS2(RETURN_ADDR_REG)));
+ else
+ FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(RETURN_ADDR_REG), offset));
tmp = SLJIT_S0 - saveds;
for (i = SLJIT_S0 - saved_arg_count; i > tmp; i--) {
offset -= SSIZE_OF(sw);
- FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_STORE(offset) | C_RS2(i)));
+ else
+ FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));
}
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
offset -= SSIZE_OF(sw);
- FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_STORE(offset) | C_RS2(i)));
+ else
+ FAIL_IF(push_imm_s_inst(compiler, STACK_STORE | RS1(SLJIT_SP) | RS2(i), offset));
}
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
@@ -892,12 +1260,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
tmp = SLJIT_FS0 - fsaveds;
for (i = SLJIT_FS0; i > tmp; i--) {
offset -= SSIZE_OF(f64);
- FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));
+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)
+ FAIL_IF(push_inst16(compiler, C_FSDSP | C_FRS2(i) | C_ST64_SP(offset)));
+ else
+ FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));
}
for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
offset -= SSIZE_OF(f64);
- FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));
+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)
+ FAIL_IF(push_inst16(compiler, C_FSDSP | C_FRS2(i) | C_ST64_SP(offset)));
+ else
+ FAIL_IF(push_imm_s_inst(compiler, FSD | RS1(SLJIT_SP) | FRS2(i), offset));
}
if (local_size > STACK_MAX_DISTANCE)
@@ -915,7 +1289,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
while (arg_types > 0) {
if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
- FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_S0 - saved_arg_count) | RS1(tmp) | IMM_I(0)));
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(SLJIT_S0 - saved_arg_count) | C_RS2(tmp)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_S0 - saved_arg_count) | RS1(tmp) | IMM_I(0)));
saved_arg_count++;
}
tmp++;
@@ -979,18 +1356,28 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit
SLJIT_ASSERT(local_size > 0);
offset = local_size - SSIZE_OF(sw);
- if (!is_return_to)
- FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset)));
+ if (!is_return_to) {
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_LOAD(offset) | C_RD(RETURN_ADDR_REG)));
+ else
+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(RETURN_ADDR_REG) | RS1(SLJIT_SP) | IMM_I(offset)));
+ }
tmp = SLJIT_S0 - compiler->saveds;
for (i = SLJIT_S0 - SLJIT_KEPT_SAVEDS_COUNT(compiler->options); i > tmp; i--) {
offset -= SSIZE_OF(sw);
- FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_LOAD(offset) | C_RD(i)));
+ else
+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
}
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
offset -= SSIZE_OF(sw);
- FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
+ if (RISCV_HAS_COMPRESSED(200) && C_STACK_OFFSET_CHECK(offset))
+ FAIL_IF(push_inst16(compiler, C_STACK_LOAD(offset) | C_RD(i)));
+ else
+ FAIL_IF(push_inst(compiler, STACK_LOAD | RD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
}
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
@@ -1002,12 +1389,23 @@ static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit
tmp = SLJIT_FS0 - compiler->fsaveds;
for (i = SLJIT_FS0; i > tmp; i--) {
offset -= SSIZE_OF(f64);
- FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)
+ FAIL_IF(push_inst16(compiler, C_FLDSP | C_FRD(i) | C_LD64_SP(offset)));
+ else
+ FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
}
for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
offset -= SSIZE_OF(f64);
- FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
+ if (RISCV_HAS_COMPRESSED(200) && offset <= 0x1f8)
+ FAIL_IF(push_inst16(compiler, C_FLDSP | C_FRD(i) | C_LD64_SP(offset)));
+ else
+ FAIL_IF(push_inst(compiler, FLD | FRD(i) | RS1(SLJIT_SP) | IMM_I(offset)));
+ }
+
+ if (RISCV_HAS_COMPRESSED(200) && local_size <= 0x1f0) {
+ SLJIT_ASSERT((local_size & 0xf) == 0);
+ return push_inst16(compiler, C_ADDI16SP | (sljit_u16)(((local_size & 0x10) << 2) | ((local_size & 0x20) >> 3) | ((local_size & 0x40) >> 1) | ((local_size & 0x180) >> 4)));
}
return push_inst(compiler, ADDI | RD(SLJIT_SP) | RS1(SLJIT_SP) | IMM_I(local_size));
@@ -1087,14 +1485,80 @@ static const sljit_ins data_transfer_insts[16 + 4] = {
static sljit_s32 push_mem_inst(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 base, sljit_sw offset)
{
sljit_ins ins;
+ sljit_s32 signed_flags;
+ sljit_s32 load_flags;
SLJIT_ASSERT(FAST_IS_REG(base) && offset <= 0xfff && offset >= SIMM_MIN);
- ins = data_transfer_insts[flags & MEM_MASK] | RS1(base);
+ flags &= MEM_MASK;
+
+ if (RISCV_HAS_COMPRESSED(200) && offset >= 0) {
+ if (base == SLJIT_SP) {
+ signed_flags = flags | SIGNED_DATA;
+
+ if ((offset & 0x3) == 0 && offset <= 0xfc) {
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if ((signed_flags == (SIGNED_DATA | LOAD_DATA) || signed_flags == (INT_DATA | SIGNED_DATA | LOAD_DATA)))
+ return push_inst16(compiler, C_LWSP | C_RD(reg) | C_LD32_SP(offset));
+ if ((signed_flags == SIGNED_DATA || signed_flags == (INT_DATA | SIGNED_DATA)))
+ return push_inst16(compiler, C_SWSP | C_RS2(reg) | C_ST32_SP(offset));
+ if (flags == (SINGLE_DATA | LOAD_DATA))
+ return push_inst16(compiler, C_FLWSP | C_FRD(reg) | C_LD32_SP(offset));
+ if (flags == SINGLE_DATA)
+ return push_inst16(compiler, C_FSWSP | C_FRS2(reg) | C_ST32_SP(offset));
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ if (flags == (INT_DATA | SIGNED_DATA | LOAD_DATA))
+ return push_inst16(compiler, C_LWSP | C_RD(reg) | C_LD32_SP(offset));
+ if (signed_flags == (INT_DATA | SIGNED_DATA))
+ return push_inst16(compiler, C_SWSP | C_RS2(reg) | C_ST32_SP(offset));
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ }
+
+ if ((offset & 0x7) == 0 && offset <= 0x1f8) {
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (signed_flags == (SIGNED_DATA | LOAD_DATA))
+ return push_inst16(compiler, C_LDSP | C_RD(reg) | C_LD64_SP(offset));
+ if (signed_flags == SIGNED_DATA)
+ return push_inst16(compiler, C_SDSP | C_RS2(reg) | C_ST64_SP(offset));
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ if (flags == (DOUBLE_DATA | LOAD_DATA))
+ return push_inst16(compiler, C_FLDSP | C_FRD(reg) | C_LD64_SP(offset));
+ if (flags == DOUBLE_DATA)
+ return push_inst16(compiler, C_FSDSP | C_FRS2(reg) | C_ST64_SP(offset));
+ }
+ } else if (C_IS_R3(base) && (flags <= GPR_REG ? C_IS_R3(reg) : C_IS_FR3(reg))) {
+ SLJIT_COMPILE_ASSERT(LOAD_DATA == 1, load_data_bit_error);
+ signed_flags = flags | LOAD_DATA | SIGNED_DATA;
+ load_flags = flags | LOAD_DATA;
+
+ if ((offset & 0x3) == 0 && offset <= 0x7c) {
+#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
+ if (signed_flags == (SIGNED_DATA | LOAD_DATA) || signed_flags == (INT_DATA | SIGNED_DATA | LOAD_DATA))
+ return push_inst16(compiler, (C_SW ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_RS2_R3(reg) | C_MEM32(offset));
+ if (load_flags == (SINGLE_DATA | LOAD_DATA))
+ return push_inst16(compiler, (C_FSW ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_FRS2_R3(reg) | C_MEM32(offset));
+#else /* !SLJIT_CONFIG_RISCV_32 */
+ if (load_flags == (INT_DATA | SIGNED_DATA | LOAD_DATA))
+ return push_inst16(compiler, (C_SW ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_RS2_R3(reg) | C_MEM32(offset));
+#endif /* SLJIT_CONFIG_RISCV_32 */
+ }
+
+ if ((offset & 0x7) == 0 && offset <= 0xf8) {
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (signed_flags == (SIGNED_DATA | LOAD_DATA))
+ return push_inst16(compiler, (C_SD ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_RS2_R3(reg) | C_MEM64(offset));
+#endif /* SLJIT_CONFIG_RISCV_64 */
+ if (load_flags == (DOUBLE_DATA | LOAD_DATA))
+ return push_inst16(compiler, (C_FSD ^ (sljit_u16)((flags & LOAD_DATA) << 15)) | C_RS1_R3(base) | C_FRS2_R3(reg) | C_MEM64(offset));
+ }
+ }
+ }
+
+ ins = data_transfer_insts[flags] | RS1(base);
if (flags & LOAD_DATA)
- ins |= ((flags & MEM_MASK) <= GPR_REG ? RD(reg) : FRD(reg)) | IMM_I(offset);
+ ins |= (flags <= GPR_REG ? RD(reg) : FRD(reg)) | IMM_I(offset);
else
- ins |= ((flags & MEM_MASK) <= GPR_REG ? RS2(reg) : FRS2(reg)) | IMM_S(offset);
+ ins |= (flags <= GPR_REG ? RS2(reg) : FRS2(reg)) | IMM_S(offset);
return push_inst(compiler, ins);
}
@@ -1148,9 +1612,7 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
sljit_s32 base = arg & REG_MASK;
sljit_s32 tmp_r = (flags & MEM_USE_TMP2) ? TMP_REG2 : TMP_REG1;
sljit_sw offset, argw_hi;
-#if defined __riscv_zba
sljit_ins ins = ADD;
-#endif /* __riscv_zba */
SLJIT_ASSERT(arg & SLJIT_MEM);
if (!(next_arg & SLJIT_MEM)) {
@@ -1161,20 +1623,22 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
argw &= 0x3;
-#if defined __riscv_zba
- switch (argw) {
- case 1:
- ins = SH1ADD;
- break;
- case 2:
- ins = SH2ADD;
- break;
- case 3:
- ins = SH3ADD;
- break;
+ if (RISCV_HAS_BITMANIP_A(93)) {
+ switch (argw) {
+ case 1:
+ ins = SH1ADD;
+ break;
+ case 2:
+ ins = SH2ADD;
+ break;
+ case 3:
+ ins = SH3ADD;
+ break;
+ }
+ FAIL_IF(push_inst(compiler, ins | RD(tmp_r) | RS1(OFFS_REG(arg)) | RS2(base)));
+ return push_mem_inst(compiler, flags, reg, tmp_r, 0);
}
- FAIL_IF(push_inst(compiler, ins | RD(tmp_r) | RS1(OFFS_REG(arg)) | RS2(base)));
-#else /* !__riscv_zba */
+
/* Using the cache. */
if (argw == compiler->cache_argw) {
if (arg == compiler->cache_arg)
@@ -1206,7 +1670,6 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
}
else
FAIL_IF(push_inst(compiler, ADD | RD(tmp_r) | RS1(base) | RS2(!argw ? OFFS_REG(arg) : TMP_REG3)));
-#endif /* __riscv_zba */
return push_mem_inst(compiler, flags, reg, tmp_r, 0);
}
@@ -1294,7 +1757,27 @@ static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, slji
#define WORD_32 0x08
#define IMM_EXTEND(v) (IMM_I((op & SLJIT_32) ? (v) : (32 + (v))))
#endif /* SLJIT_CONFIG_RISCV_32 */
-#ifndef __riscv_zbb
+
+static sljit_s32 emit_add(struct sljit_compiler *compiler, sljit_ins word, sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
+{
+ SLJIT_UNUSED_ARG(word);
+
+ if (dst == src2) {
+ src2 = src1;
+ src1 = dst;
+ }
+
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1) {
+ if (WORD == 0 && src2 != 0)
+ return push_inst16(compiler, C_ADD | C_RD(dst) | C_RS2(src2));
+
+ if (WORD == 0x8 && C_IS_R3(dst) && C_IS_R3(src2))
+ return push_inst16(compiler, C_ADDW | C_RS1_R3(dst) | C_RS2_R3(src2));
+ }
+
+ return push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2));
+}
+
static sljit_s32 emit_clz_ctz(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw src)
{
sljit_s32 is_clz = (GET_OPCODE(op) == SLJIT_CLZ);
@@ -1378,7 +1861,11 @@ static sljit_s32 emit_rev(struct sljit_compiler *compiler, sljit_s32 op, sljit_s
FAIL_IF(push_inst(compiler, SRLI | WORD_32 | RD(TMP_REG1) | RS1(dst) | IMM_I(8)));
FAIL_IF(push_inst(compiler, AND | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
FAIL_IF(push_inst(compiler, AND | RD(TMP_REG1) | RS1(TMP_REG1) | RS2(OTHER_FLAG)));
- FAIL_IF(push_inst(compiler, SLLI | WORD_32 | RD(dst) | RS1(dst) | IMM_I(8)));
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ FAIL_IF(push_inst(compiler, SLLI | (GET_OPCODE(op) == SLJIT_REV_S32 ? WORD_32 : 0) | RD(dst) | RS1(dst) | IMM_I(8)));
+#else /* !SLJIT_CONFIG_RISCV_64 */
+ FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(8)));
+#endif /* SLJIT_CONFIG_RISCV_64 */
return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));
}
@@ -1397,26 +1884,33 @@ static sljit_s32 emit_rev16(struct sljit_compiler *compiler, sljit_s32 op, sljit
FAIL_IF(push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | WORD | RD(dst) | RS1(dst) | IMM_I(word_size - 16)));
return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(TMP_REG1));
}
-#endif /* !__riscv_zbb */
-#define EMIT_LOGICAL(op_imm, op_reg) \
+#define EMIT_LOGICAL(op_imm, op_c_imm, op_reg, op_c_reg) \
if (flags & SRC2_IMM) { \
if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, op_imm | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2))); \
- if (!(flags & UNUSED_DEST)) \
- FAIL_IF(push_inst(compiler, op_imm | RD(dst) | RS1(src1) | IMM_I(src2))); \
- } \
- else { \
+ if (!(flags & UNUSED_DEST)) { \
+ if (op_c_imm != 0 && RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN && C_IS_R3(dst)) \
+ FAIL_IF(push_inst16(compiler, op_c_imm | C_RS1_R3(dst) | C_IMM_I(src2))); \
+ else \
+ FAIL_IF(push_inst(compiler, op_imm | RD(dst) | RS1(src1) | IMM_I(src2))); \
+ } \
+ } else { \
+ if (dst == src2) { \
+ src2 = src1; \
+ src1 = dst; \
+ } \
+ \
if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, op_reg | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2))); \
- if (!(flags & UNUSED_DEST)) \
- FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RS1(src1) | RS2(src2))); \
+ if (!(flags & UNUSED_DEST)) { \
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2)) \
+ FAIL_IF(push_inst16(compiler, op_c_reg | C_RS1_R3(dst) | C_RS2_R3(src2))); \
+ else \
+ FAIL_IF(push_inst(compiler, op_reg | RD(dst) | RS1(src1) | RS2(src2))); \
+ } \
}
-#define EMIT_SHIFT(imm, reg) \
- op_imm = (imm); \
- op_reg = (reg);
-
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
{
@@ -1431,9 +1925,16 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
- if (dst != src2)
+ if (dst == src2)
+ return SLJIT_SUCCESS;
+
+ if (!RISCV_HAS_COMPRESSED(200))
return push_inst(compiler, ADDI | RD(dst) | RS1(src2) | IMM_I(0));
- return SLJIT_SUCCESS;
+
+ /* Revert the x0 to immediate 0. */
+ if (src2 == 0)
+ return push_inst16(compiler, C_LI | C_RD(dst));
+ return push_inst16(compiler, C_MV | C_RD(dst) | C_RS2(src2));
case SLJIT_MOV_U8:
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
@@ -1443,9 +1944,9 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return SLJIT_SUCCESS;
case SLJIT_MOV_S8:
-#if defined __riscv_zbb
- return push_inst(compiler, SEXTB | RD(dst) | RS1(src2));
-#else /* !__riscv_zbb */
+ if (RISCV_HAS_BITMANIP_B(93))
+ return push_inst(compiler, SEXTB | RD(dst) | RS1(src2));
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(24)));
@@ -1453,12 +1954,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
}
SLJIT_ASSERT(dst == src2);
return SLJIT_SUCCESS;
-#endif /* __riscv_zbb */
case SLJIT_MOV_U16:
-#if defined __riscv_zbb
- return push_inst(compiler, ZEXTH | RD(dst) | RS1(src2));
-#else /* !__riscv_zbb */
+ if (RISCV_HAS_BITMANIP_B(93))
+ return push_inst(compiler, ZEXTH | RD(dst) | RS1(src2));
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));
@@ -1466,12 +1966,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
}
SLJIT_ASSERT(dst == src2);
return SLJIT_SUCCESS;
-#endif /* __riscv_zbb */
case SLJIT_MOV_S16:
-#if defined __riscv_zbb
- return push_inst(compiler, SEXTH | RD(dst) | RS1(src2));
-#else /* !__riscv_zbb */
+ if (RISCV_HAS_BITMANIP_B(93))
+ return push_inst(compiler, SEXTH | RD(dst) | RS1(src2));
+
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
FAIL_IF(push_inst(compiler, SLLI | WORD | RD(dst) | RS1(src2) | IMM_EXTEND(16)));
@@ -1479,7 +1978,6 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
}
SLJIT_ASSERT(dst == src2);
return SLJIT_SUCCESS;
-#endif /* !__riscv_zbb */
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
case SLJIT_MOV_U32:
@@ -1493,74 +1991,54 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
case SLJIT_MOV_S32:
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
- if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ if (RISCV_HAS_COMPRESSED(200) && dst == src2)
+ return push_inst16(compiler, C_ADDIW | C_RD(dst));
return push_inst(compiler, ADDI | 0x8 | RD(dst) | RS1(src2) | IMM_I(0));
+ }
SLJIT_ASSERT(dst == src2);
return SLJIT_SUCCESS;
#endif /* SLJIT_CONFIG_RISCV_64 */
case SLJIT_CLZ:
-#if defined __riscv_zbb
- return push_inst(compiler, CLZ | WORD | RD(dst) | RS1(src2));
-#endif /* __riscv_zbb */
case SLJIT_CTZ:
-#if defined __riscv_zbb
- return push_inst(compiler, CTZ | WORD | RD(dst) | RS1(src2));
-#else /* !__riscv_zbb */
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
+ if (RISCV_HAS_BITMANIP_B(93))
+ return push_inst(compiler, ((GET_OPCODE(op) == SLJIT_CLZ) ? CLZ : CTZ) | WORD | RD(dst) | RS1(src2));
+
return emit_clz_ctz(compiler, op, dst, src2);
-#endif /* __riscv_zbb */
case SLJIT_REV:
-#if defined __riscv_zbb
- SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
- FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));
-#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64
- if (op & SLJIT_32)
- return push_inst(compiler, SRAI | RD(dst) | RS1(dst) | IMM_I(32));
- return SLJIT_SUCCESS;
-#else /* !SLJIT_CONFIG_RISCV_64 */
- return SLJIT_SUCCESS;
-#endif /* SLJIT_CONFIG_RISCV_64 */
-#endif /* __riscv_zbb */
case SLJIT_REV_S32:
-#if ((defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32) || defined __riscv_zbb)
case SLJIT_REV_U32:
-#endif /* SLJIT_CONFIG_RISCV_32 || __riscv_zbb */
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
-#if defined __riscv_zbb
- FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));
+ if (RISCV_HAS_BITMANIP_B(93)) {
#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64
- return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U32 ? SRLI : SRAI )| RD(dst) | RS1(dst) | IMM_I(32));
+ FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));
+ if ((op & SLJIT_32) || GET_OPCODE(op) != SLJIT_REV)
+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U32 ? SRLI : SRAI)| RD(dst) | RS1(dst) | IMM_I(32));
+ return SLJIT_SUCCESS;
#else /* !SLJIT_CONFIG_RISCV_64 */
- return SLJIT_SUCCESS;
+ return push_inst(compiler, REV8 | RD(dst) | RS1(src2));
#endif /* SLJIT_CONFIG_RISCV_64 */
-#else /* !__riscv_zbb */
+ }
+
return emit_rev(compiler, op, dst, src2);
-#endif /* __riscv_zbb */
+
case SLJIT_REV_U16:
case SLJIT_REV_S16:
SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM));
-#if defined __riscv_zbb
- FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));
+ if (RISCV_HAS_BITMANIP_B(93)) {
+ FAIL_IF(push_inst(compiler, REV8 | RD(dst) | RS1(src2)));
#if defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64
- return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI )| RD(dst) | RS1(dst) | IMM_I(48));
+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI)| RD(dst) | RS1(dst) | IMM_I(48));
#else /* !SLJIT_CONFIG_RISCV_64 */
- return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | RD(dst) | RS1(dst) | IMM_I(16));
+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_REV_U16 ? SRLI : SRAI) | RD(dst) | RS1(dst) | IMM_I(16));
#endif /* SLJIT_CONFIG_RISCV_64 */
-#else /* !__riscv_zbb */
+ }
+
return emit_rev16(compiler, op, dst, src2);
-#endif /* __riscv_zbb */
-#if ((defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64) && !defined __riscv_zbb)
- case SLJIT_REV_U32:
- SLJIT_ASSERT(src1 == TMP_ZERO && !(flags & SRC2_IMM) && dst != TMP_REG1);
- FAIL_IF(emit_rev(compiler, op, dst, src2));
- if (dst == TMP_REG2)
- return SLJIT_SUCCESS;
- FAIL_IF(push_inst(compiler, SLLI | RD(dst) | RS1(dst) | IMM_I(32)));
- return push_inst(compiler, SRLI | RD(dst) | RS1(dst) | IMM_I(32));
-#endif /* SLJIT_CONFIG_RISCV_64 && !__riscv_zbb */
case SLJIT_ADD:
/* Overflow computation (both add and sub): overflow = src1_sign ^ src2_sign ^ result_sign ^ carry_flag */
is_overflow = GET_FLAG_TYPE(op) == SLJIT_OVERFLOW;
@@ -1568,19 +2046,26 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
if (flags & SRC2_IMM) {
if (is_overflow) {
- if (src2 >= 0)
- FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
- else
+ if (src2 >= 0) {
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(src1)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
+ } else
FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1)));
}
else if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));
/* Only the zero flag is needed. */
- if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
- FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
- }
- else {
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) {
+ SLJIT_ASSERT(src2 != 0);
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
+ }
+ } else {
if (is_overflow)
FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
else if (op & SLJIT_SET_Z)
@@ -1599,7 +2084,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
/* Only the zero flag is needed. */
if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
- FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2)));
+ FAIL_IF(emit_add(compiler, WORD, dst, src1, src2));
}
/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
@@ -1614,8 +2099,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return SLJIT_SUCCESS;
FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));
- if (op & SLJIT_SET_Z)
- FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));
+ if (op & SLJIT_SET_Z) {
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(dst)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));
+ }
FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));
return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));
@@ -1623,7 +2112,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
carry_src_r = GET_FLAG_TYPE(op) == SLJIT_CARRY;
if (flags & SRC2_IMM) {
- FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
+ SLJIT_ASSERT(src2 != 0);
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
} else {
if (carry_src_r != 0) {
if (src1 != dst)
@@ -1631,12 +2124,15 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
else if (src2 != dst)
carry_src_r = (sljit_s32)src2;
else {
- FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(src1)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
carry_src_r = EQUAL_FLAG;
}
}
- FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(src1) | RS2(src2)));
+ FAIL_IF(emit_add(compiler, WORD, dst, src1, src2));
}
/* Carry is zero if a + b >= a or a + b >= b, otherwise it is 1. */
@@ -1647,7 +2143,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(dst) | RS2(carry_src_r)));
}
- FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
+ if (RISCV_HAS_COMPRESSED(200) && WORD == 0)
+ FAIL_IF(push_inst16(compiler, C_ADD | C_RD(dst) | C_RS2(OTHER_FLAG)));
+ else
+ FAIL_IF(push_inst(compiler, ADD | WORD | RD(dst) | RS1(dst) | RS2(OTHER_FLAG)));
if (carry_src_r == 0)
return SLJIT_SUCCESS;
@@ -1670,8 +2169,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
if (GET_FLAG_TYPE(op) == SLJIT_LESS) {
FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
is_handled = 1;
- }
- else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {
+ } else if (GET_FLAG_TYPE(op) == SLJIT_SIG_LESS) {
FAIL_IF(push_inst(compiler, SLTI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
is_handled = 1;
}
@@ -1682,7 +2180,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
if (flags & SRC2_IMM) {
reg = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
- FAIL_IF(push_inst(compiler, ADDI | RD(reg) | RS1(TMP_ZERO) | IMM_I(src2)));
+ if (RISCV_HAS_COMPRESSED(200) && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ FAIL_IF(push_inst16(compiler, C_LI | C_RD(reg) | C_IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(reg) | RS1(TMP_ZERO) | IMM_I(src2)));
+
src2 = reg;
flags &= ~SRC2_IMM;
}
@@ -1707,14 +2209,22 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
if (flags & SRC2_IMM) {
if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));
- if (!(flags & UNUSED_DEST))
- return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2));
- }
- else {
+ if (!(flags & UNUSED_DEST)) {
+ src2 = -src2;
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ return push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2));
+
+ return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2));
+ }
+ } else {
if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, SUB | WORD | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
- if (!(flags & UNUSED_DEST))
+ if (!(flags & UNUSED_DEST)) {
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2))
+ return push_inst16(compiler, C_SUB_W(WORD) | C_RS1_R3(dst) | C_RS2_R3(src2));
+
return push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2));
+ }
}
return SLJIT_SUCCESS;
}
@@ -1724,22 +2234,28 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
if (flags & SRC2_IMM) {
if (is_overflow) {
- if (src2 >= 0)
- FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
- else
+ if (src2 >= 0) {
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(src1)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(0)));
+ } else
FAIL_IF(push_inst(compiler, XORI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-1)));
- }
- else if (op & SLJIT_SET_Z)
+ } else if (op & SLJIT_SET_Z)
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(-src2)));
if (is_overflow || is_carry)
FAIL_IF(push_inst(compiler, SLTUI | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
/* Only the zero flag is needed. */
- if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
- FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2)));
- }
- else {
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) {
+ src2 = -src2;
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
+ }
+ } else {
if (is_overflow)
FAIL_IF(push_inst(compiler, XOR | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
else if (op & SLJIT_SET_Z)
@@ -1749,16 +2265,24 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2)));
/* Only the zero flag is needed. */
- if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK))
- FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));
+ if (!(flags & UNUSED_DEST) || (op & VARIABLE_FLAG_MASK)) {
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2))
+ FAIL_IF(push_inst16(compiler, C_SUB_W(WORD) | C_RS1_R3(dst) | C_RS2_R3(src2)));
+ else
+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));
+ }
}
if (!is_overflow)
return SLJIT_SUCCESS;
FAIL_IF(push_inst(compiler, XOR | RD(TMP_REG1) | RS1(dst) | RS2(EQUAL_FLAG)));
- if (op & SLJIT_SET_Z)
- FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));
+ if (op & SLJIT_SET_Z) {
+ if (RISCV_HAS_COMPRESSED(200))
+ FAIL_IF(push_inst16(compiler, C_MV | C_RD(EQUAL_FLAG) | C_RS2(dst)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(EQUAL_FLAG) | RS1(dst) | IMM_I(0)));
+ }
FAIL_IF(push_inst(compiler, SRLI | WORD | RD(TMP_REG1) | RS1(TMP_REG1) | IMM_EXTEND(31)));
return push_inst(compiler, XOR | RD(OTHER_FLAG) | RS1(TMP_REG1) | RS2(OTHER_FLAG));
@@ -1775,13 +2299,19 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
if (is_carry)
FAIL_IF(push_inst(compiler, SLTUI | RD(EQUAL_FLAG) | RS1(src1) | IMM_I(src2)));
- FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(-src2)));
- }
- else {
+ src2 = -src2;
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && src2 <= SIMM16_MAX && src2 >= SIMM16_MIN)
+ FAIL_IF(push_inst16(compiler, C_ADDI_W(WORD) | C_RD(dst) | C_IMM_I(src2)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
+ } else {
if (is_carry)
FAIL_IF(push_inst(compiler, SLTU | RD(EQUAL_FLAG) | RS1(src1) | RS2(src2)));
- FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));
+ if (RISCV_HAS_COMPRESSED(200) && dst == src1 && C_IS_R3(dst) && C_IS_R3(src2))
+ FAIL_IF(push_inst16(compiler, C_SUB_W(WORD) | C_RS1_R3(dst) | C_RS2_R3(src2)));
+ else
+ FAIL_IF(push_inst(compiler, SUB | WORD | RD(dst) | RS1(src1) | RS2(src2)));
}
if (is_carry)
@@ -1818,46 +2348,51 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return push_inst(compiler, SUB | RD(OTHER_FLAG) | RS1(EQUAL_FLAG) | RS2(OTHER_FLAG));
case SLJIT_AND:
- EMIT_LOGICAL(ANDI, AND);
+ EMIT_LOGICAL(ANDI, C_ANDI, AND, C_AND);
return SLJIT_SUCCESS;
case SLJIT_OR:
- EMIT_LOGICAL(ORI, OR);
+ EMIT_LOGICAL(ORI, 0, OR, C_OR);
return SLJIT_SUCCESS;
case SLJIT_XOR:
- EMIT_LOGICAL(XORI, XOR);
+ EMIT_LOGICAL(XORI, 0, XOR, C_XOR);
return SLJIT_SUCCESS;
case SLJIT_SHL:
case SLJIT_MSHL:
- EMIT_SHIFT(SLLI, SLL);
+ op_imm = SLLI;
+ op_reg = SLL;
break;
case SLJIT_LSHR:
case SLJIT_MLSHR:
- EMIT_SHIFT(SRLI, SRL);
+ op_imm = SRLI;
+ op_reg = SRL;
break;
case SLJIT_ASHR:
case SLJIT_MASHR:
- EMIT_SHIFT(SRAI, SRA);
+ op_imm = SRAI;
+ op_reg = SRA;
break;
case SLJIT_ROTL:
case SLJIT_ROTR:
if (flags & SRC2_IMM) {
SLJIT_ASSERT(src2 != 0);
-#if defined __riscv_zbb
- if (GET_OPCODE(op) == SLJIT_ROTL) {
+
+ if (RISCV_HAS_BITMANIP_B(93)) {
+ if (GET_OPCODE(op) == SLJIT_ROTL) {
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
- src2 = ((op & SLJIT_32) ? 32 : 64) - src2;
+ src2 = ((op & SLJIT_32) ? 32 : 64) - src2;
#else /* !SLJIT_CONFIG_RISCV_64 */
- src2 = 32 - src2;
+ src2 = 32 - src2;
#endif /* SLJIT_CONFIG_RISCV_64 */
+ }
+ return push_inst(compiler, RORI | WORD | RD(dst) | RS1(src1) | IMM_I(src2));
}
- return push_inst(compiler, RORI | WORD | RD(dst) | RS1(src1) | IMM_I(src2));
-#else /* !__riscv_zbb */
+
op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SLLI : SRLI;
FAIL_IF(push_inst(compiler, op_imm | WORD | RD(OTHER_FLAG) | RS1(src1) | IMM_I(src2)));
@@ -1869,12 +2404,11 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
op_imm = (GET_OPCODE(op) == SLJIT_ROTL) ? SRLI : SLLI;
FAIL_IF(push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2)));
return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));
-#endif /* !__riscv_zbb */
}
-#if defined __riscv_zbb
- return push_inst(compiler, (GET_OPCODE(op) == SLJIT_ROTL ? ROL : ROR) | WORD | RD(dst) | RS1(src1) | RS2(src2));
-#else /* !__riscv_zbb */
+ if (RISCV_HAS_BITMANIP_B(93))
+ return push_inst(compiler, (GET_OPCODE(op) == SLJIT_ROTL ? ROL : ROR) | WORD | RD(dst) | RS1(src1) | RS2(src2));
+
if (src2 == TMP_ZERO) {
if (dst != src1)
return push_inst(compiler, ADDI | WORD | RD(dst) | RS1(src1) | IMM_I(0));
@@ -1887,7 +2421,6 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
op_reg = (GET_OPCODE(op) == SLJIT_ROTL) ? SRL : SLL;
FAIL_IF(push_inst(compiler, op_reg | WORD | RD(dst) | RS1(src1) | RS2(EQUAL_FLAG)));
return push_inst(compiler, OR | RD(dst) | RS1(dst) | RS2(OTHER_FLAG));
-#endif /* !riscv_zbb */
default:
SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
@@ -1899,6 +2432,15 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
if (flags & UNUSED_DEST)
return SLJIT_SUCCESS;
+
+ if (RISCV_HAS_COMPRESSED(200) && WORD == 0 && dst == src1) {
+ if (op_imm == SLLI)
+ return push_inst16(compiler, C_SLLI | C_RD(dst) | C_IMM_I(src2));
+
+ if (C_IS_R3(dst))
+ return push_inst16(compiler, (op_imm == SRLI ? C_SRLI : C_SRAI) | C_RS1_R3(dst) | C_IMM_I(src2));
+ }
+
return push_inst(compiler, op_imm | WORD | RD(dst) | RS1(src1) | IMM_I(src2));
}
@@ -2051,9 +2593,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
switch (GET_OPCODE(op)) {
case SLJIT_BREAKPOINT:
+ if (RISCV_HAS_COMPRESSED(200))
+ return push_inst16(compiler, C_EBREAK);
return push_inst(compiler, EBREAK);
case SLJIT_NOP:
- return push_inst(compiler, ADDI | RD(TMP_ZERO) | RS1(TMP_ZERO) | IMM_I(0));
+ if (RISCV_HAS_COMPRESSED(200))
+ return push_inst16(compiler, C_NOP);
+ return push_inst(compiler, NOP);
case SLJIT_LMUL_UW:
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(SLJIT_R1) | IMM_I(0)));
FAIL_IF(push_inst(compiler, MULHU | RD(SLJIT_R1) | RS1(SLJIT_R0) | RS2(SLJIT_R1)));
@@ -2337,6 +2883,76 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *
return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r, tmp_r;
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);
+
+ if (src2 == SLJIT_IMM) {
+ src2w = src2w << shift_arg;
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, src2, src2w, src1, src1w));
+ src2 = TMP_REG2;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
+ src1 = TMP_REG1;
+ } else if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src1, src1w, dst, dstw));
+ src1 = TMP_REG1;
+ }
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+ ins = 0;
+
+ if (RISCV_HAS_BITMANIP_A(93)) {
+ switch (shift_arg) {
+ case 1:
+ ins = SH1ADD;
+ break;
+ case 2:
+ ins = SH2ADD;
+ break;
+ case 3:
+ ins = SH3ADD;
+ break;
+ }
+ }
+
+ if (ins == 0) {
+ tmp_r = (src1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
+ FAIL_IF(push_inst(compiler, SLLI | RD(tmp_r) | RS1(src2) | IMM_I(shift_arg)));
+ FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RS1(src1) | RS2(tmp_r)));
+ } else {
+ FAIL_IF(push_inst(compiler, ins | RD(dst_r) | RS1(src2) | RS2(src1)));
+ }
+
+ if (dst & SLJIT_MEM)
+ return emit_op_mem2(compiler, WORD_DATA, dst_r, dst, dstw, 0, 0);
+ return SLJIT_SUCCESS;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -2346,9 +2962,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp
switch (op) {
case SLJIT_FAST_RETURN:
- if (FAST_IS_REG(src))
- FAIL_IF(push_inst(compiler, ADDI | RD(RETURN_ADDR_REG) | RS1(src) | IMM_I(0)));
- else
+ if (FAST_IS_REG(src)) {
+ if (src != RETURN_ADDR_REG)
+ FAIL_IF(push_inst(compiler, ADDI | RD(RETURN_ADDR_REG) | RS1(src) | IMM_I(0)));
+ } else
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw));
return push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(RETURN_ADDR_REG) | IMM_I(0));
@@ -2375,8 +2992,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp
switch (op) {
case SLJIT_FAST_ENTER:
- if (FAST_IS_REG(dst))
+ if (FAST_IS_REG(dst)) {
+ if (dst == RETURN_ADDR_REG)
+ return SLJIT_SUCCESS;
return push_inst(compiler, ADDI | RD(dst) | RS1(RETURN_ADDR_REG) | IMM_I(0));
+ }
SLJIT_ASSERT(RETURN_ADDR_REG == TMP_REG2);
break;
@@ -2413,6 +3033,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
CHECK_ERROR();
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
+ if (size == 2)
+ return push_inst16(compiler, *(sljit_u16*)instruction);
+
return push_inst(compiler, *(sljit_ins*)instruction);
}
@@ -2749,11 +3372,80 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
-#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
-#define BRANCH_LENGTH ((sljit_ins)(3 * sizeof(sljit_ins)) << 7)
-#else /* !SLJIT_CONFIG_RISCV_32 */
-#define BRANCH_LENGTH ((sljit_ins)(7 * sizeof(sljit_ins)) << 7)
-#endif /* SLJIT_CONFIG_RISCV_32 */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask = 0, i;
+ struct sljit_label *label = NULL;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (RISCV_HAS_COMPRESSED(200)) {
+ if (alignment <= SLJIT_LABEL_ALIGN_2) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_u16);
+
+ for (i = (mask >> 1); i != 0; i--)
+ PTR_FAIL_IF(push_inst16(compiler, C_NOP));
+ }
+ } else {
+ if (alignment <= SLJIT_LABEL_ALIGN_4) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_ins);
+
+ for (i = (mask >> 2); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+ }
+ }
+
+ if (label == NULL) {
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ if (RISCV_HAS_COMPRESSED(200)) {
+ for (i = (buffers->size + 1) >> 1; i > 0; i--)
+ PTR_FAIL_IF(push_inst16(compiler, C_NOP));
+ } else {
+ for (i = (buffers->size + 3) >> 2; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, NOP));
+ }
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
static sljit_ins get_jump_instruction(sljit_s32 type)
{
@@ -2826,14 +3518,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
}
jump->addr = compiler->size;
- inst = JALR | RS1(TMP_REG1) | IMM_I(0);
- if (type >= SLJIT_FAST_CALL) {
+ if (type >= SLJIT_FAST_CALL)
jump->flags |= IS_CALL;
- inst |= RD(RETURN_ADDR_REG);
- }
- PTR_FAIL_IF(push_inst(compiler, inst));
+ PTR_FAIL_IF(push_inst16(compiler, 0));
/* Maximum number of instructions required for generating a constant. */
compiler->size += JUMP_MAX_SIZE - 1;
@@ -2913,9 +3602,37 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
switch (type) {
case SLJIT_EQUAL:
+ if (RISCV_HAS_COMPRESSED(200)) {
+ if (src1 == TMP_ZERO && C_IS_R3(src2)) {
+ inst = C_BNEZ | C_RS1_R3(src2) | BRANCH16_LENGTH;
+ jump->flags |= IS_COND16;
+ break;
+ }
+
+ if (src2 == TMP_ZERO && C_IS_R3(src1)) {
+ inst = C_BNEZ | C_RS1_R3(src1) | BRANCH16_LENGTH;
+ jump->flags |= IS_COND16;
+ break;
+ }
+ }
+
inst = BNE | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
break;
case SLJIT_NOT_EQUAL:
+ if (RISCV_HAS_COMPRESSED(200)) {
+ if (src1 == TMP_ZERO && C_IS_R3(src2)) {
+ inst = C_BEQZ | C_RS1_R3(src2) | BRANCH16_LENGTH;
+ jump->flags |= IS_COND16;
+ break;
+ }
+
+ if (src2 == TMP_ZERO && C_IS_R3(src1)) {
+ inst = C_BEQZ | C_RS1_R3(src1) | BRANCH16_LENGTH;
+ jump->flags |= IS_COND16;
+ break;
+ }
+ }
+
inst = BEQ | RS1(src1) | RS2(src2) | BRANCH_LENGTH;
break;
case SLJIT_LESS:
@@ -2939,23 +3656,25 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
case SLJIT_SIG_GREATER:
inst = BGE | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
break;
- case SLJIT_SIG_LESS_EQUAL:
+ default: /* SLJIT_SIG_LESS_EQUAL */
inst = BLT | RS1(src2) | RS2(src1) | BRANCH_LENGTH;
break;
}
- PTR_FAIL_IF(push_inst(compiler, inst));
+ SLJIT_COMPILE_ASSERT((C_BEQZ & 0x2) == 0 && (C_BNEZ & 0x2) == 0, branch16_bit_error);
+ if (RISCV_COMPRESSED_CHECK((inst & 0x2) == 0))
+ PTR_FAIL_IF(push_inst16(compiler, (sljit_u16)inst));
+ else
+ PTR_FAIL_IF(push_inst(compiler, inst));
jump->addr = compiler->size;
- PTR_FAIL_IF(push_inst(compiler, JALR | RD(TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0)));
+ PTR_FAIL_IF(push_inst16(compiler, 0));
/* Maximum number of instructions required for generating a constant. */
compiler->size += JUMP_MAX_SIZE - 1;
return jump;
}
-#undef BRANCH_LENGTH
-
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
{
struct sljit_jump *jump;
@@ -2969,6 +3688,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG1, src, srcw));
src = TMP_REG1;
}
+
+ if (RISCV_HAS_COMPRESSED(200))
+ return push_inst16(compiler, ((type >= SLJIT_FAST_CALL) ? C_JALR : C_JR) | C_RD(src));
+
return push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(src) | IMM_I(0));
}
@@ -2979,7 +3702,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
jump->u.target = (sljit_uw)srcw;
jump->addr = compiler->size;
- FAIL_IF(push_inst(compiler, JALR | RD((type >= SLJIT_FAST_CALL) ? RETURN_ADDR_REG : TMP_ZERO) | RS1(TMP_REG1) | IMM_I(0)));
+ FAIL_IF(push_inst16(compiler, 0));
/* Maximum number of instructions required for generating a constant. */
compiler->size += JUMP_MAX_SIZE - 1;
@@ -3110,8 +3833,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2_reg)
{
- sljit_ins *ptr;
+ sljit_u16 *ptr;
sljit_uw size;
+ sljit_ins ins;
+ sljit_s32 cond_is_1;
+ sljit_s32 is_compare = (type & SLJIT_COMPARE_SELECT);
#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
sljit_ins word = (sljit_ins)(type & SLJIT_32) >> 5;
sljit_s32 inp_flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
@@ -3126,13 +3852,92 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
ADJUST_LOCAL_OFFSET(src1, src1w);
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ if (src1 == SLJIT_IMM && word)
+ src1w = (sljit_s32)src1w;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
+
+ if (is_compare || RISCV_HAS_ICOND(100)) {
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, inp_flags, TMP_REG1, src1, src1w));
+ src1 = TMP_REG1;
+ src1w = 0;
+ } else if (src1 == SLJIT_IMM) {
+ if (src1w == 0) {
+ src1 = TMP_ZERO;
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w, TMP_REG3));
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+ }
+
+ if (RISCV_HAS_BITMANIP_B(93) && is_compare) {
+ switch (type) {
+ case SLJIT_LESS:
+ case SLJIT_LESS_EQUAL:
+ return push_inst(compiler, MINU | RD(dst_reg) | RS1(src1) | RS2(src2_reg));
+ case SLJIT_GREATER:
+ case SLJIT_GREATER_EQUAL:
+ return push_inst(compiler, MAXU | RD(dst_reg) | RS1(src1) | RS2(src2_reg));
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_LESS_EQUAL:
+ return push_inst(compiler, MIN | RD(dst_reg) | RS1(src1) | RS2(src2_reg));
+ default:
+ return push_inst(compiler, MAX | RD(dst_reg) | RS1(src1) | RS2(src2_reg));
+ }
+ }
+
+ if (RISCV_HAS_ICOND(100)) {
+ if (is_compare) {
+ cond_is_1 = 0;
+
+ switch (type) {
+ case SLJIT_LESS:
+ case SLJIT_LESS_EQUAL:
+ cond_is_1 = 1;
+ SLJIT_FALLTHROUGH
+ case SLJIT_GREATER:
+ case SLJIT_GREATER_EQUAL:
+ FAIL_IF(push_inst(compiler, SLTU | RD(OTHER_FLAG) | RS1(src1) | RS2(src2_reg)));
+ break;
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_LESS_EQUAL:
+ cond_is_1 = 1;
+ SLJIT_FALLTHROUGH
+ default:
+ FAIL_IF(push_inst(compiler, SLT | RD(OTHER_FLAG) | RS1(src1) | RS2(src2_reg)));
+ break;
+ }
+
+ type = OTHER_FLAG;
+ } else {
+ /* BEQ instruction (type is inverted). */
+ cond_is_1 = (get_jump_instruction(type) & F3(0x1)) == 0;
+ type = (type == SLJIT_EQUAL || type == SLJIT_NOT_EQUAL) ? EQUAL_FLAG : OTHER_FLAG;
+ }
+
+ if (src1 == TMP_ZERO)
+ return push_inst(compiler, (cond_is_1 ? CZERO_NEZ : CZERO_EQZ) | RD(dst_reg) | RS1(src2_reg) | RS2(type));
+
+ FAIL_IF(push_inst(compiler, (cond_is_1 ? CZERO_EQZ : CZERO_NEZ) | RD(TMP_REG1) | RS1(src1) | RS2(type)));
+ FAIL_IF(push_inst(compiler, (cond_is_1 ? CZERO_NEZ : CZERO_EQZ) | RD(dst_reg) | RS1(src2_reg) | RS2(type)));
+ return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
+ }
+ }
+
if (dst_reg != src2_reg) {
if (dst_reg == src1) {
src1 = src2_reg;
src1w = 0;
- type ^= 0x1;
+ src2_reg = dst_reg;
+ if (!is_compare)
+ type ^= 0x1;
} else {
if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
+ SLJIT_ASSERT(!(type & SLJIT_COMPARE_SELECT));
FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(dst_reg) | IMM_I(0)));
if ((src1 & REG_MASK) == dst_reg)
@@ -3146,25 +3951,77 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
}
}
+ if (src1 == SLJIT_IMM && (src1w <= 0 && src1w >= -1)) {
+ src1 = OTHER_FLAG;
+
+ if (type == SLJIT_EQUAL || type == SLJIT_NOT_EQUAL) {
+ FAIL_IF(push_inst(compiler, SLTUI | RD(TMP_REG1) | RS1(EQUAL_FLAG) | IMM_I(1)));
+ src1 = TMP_REG1;
+ cond_is_1 = (type == SLJIT_EQUAL);
+ } else {
+ /* BEQ instruction (type is inverted). */
+ cond_is_1 = (get_jump_instruction(type) & F3(0x1)) == 0;
+ }
+
+ if (src1w == 0) {
+ if (cond_is_1)
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src1) | IMM_I(-1)));
+ else
+ FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG1) | RS1(TMP_ZERO) | RS2(src1)));
+
+ return push_inst(compiler, AND | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
+ }
+
+ if (cond_is_1)
+ FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG1) | RS1(TMP_ZERO) | RS2(src1)));
+ else
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(src1) | IMM_I(-1)));
+
+ return push_inst(compiler, OR | RD(dst_reg) | RS1(dst_reg) | RS2(TMP_REG1));
+ }
+
size = compiler->size;
- ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ ptr = (sljit_u16 *)ensure_buf(compiler, sizeof(sljit_ins));
FAIL_IF(!ptr);
- compiler->size++;
+ compiler->size += 2;
if (src1 & SLJIT_MEM) {
FAIL_IF(emit_op_mem(compiler, inp_flags, dst_reg, src1, src1w));
} else if (src1 == SLJIT_IMM) {
-#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
- if (word)
- src1w = (sljit_s32)src1w;
-#endif /* SLJIT_CONFIG_RISCV_64 */
FAIL_IF(load_immediate(compiler, dst_reg, src1w, TMP_REG1));
} else
FAIL_IF(push_inst(compiler, ADDI | WORD | RD(dst_reg) | RS1(src1) | IMM_I(0)));
size = compiler->size - size;
- *ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0x7) << 9) | (sljit_ins)((size >> 3) << 25);
+
+ if (is_compare) {
+ switch (type) {
+ case SLJIT_LESS:
+ case SLJIT_LESS_EQUAL:
+ ins = BGEU;
+ break;
+ case SLJIT_GREATER:
+ case SLJIT_GREATER_EQUAL:
+ ins = BLTU;
+ break;
+ case SLJIT_SIG_LESS:
+ case SLJIT_SIG_LESS_EQUAL:
+ ins = BGE;
+ break;
+ default:
+ ins = BLT;
+ break;
+ }
+
+ ins |= RS1(src1) | RS2(src2_reg);
+ } else {
+ ins = get_jump_instruction(type);
+ }
+
+ ins |= (sljit_ins)((size & 0xf) << 8) | (sljit_ins)((size >> 4) << 25);
+ ptr[0] = (sljit_u16)ins;
+ ptr[1] = (sljit_u16)(ins >> 16);
return SLJIT_SUCCESS;
}
@@ -3175,7 +4032,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *com
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2_freg)
{
- sljit_ins *ptr;
+ sljit_u16 *ptr;
+ sljit_ins ins;
sljit_uw size;
CHECK_ERROR();
@@ -3194,9 +4052,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *com
size = compiler->size;
- ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
+ ptr = (sljit_u16 *)ensure_buf(compiler, sizeof(sljit_ins));
FAIL_IF(!ptr);
- compiler->size++;
+ compiler->size += 2;
if (src1 & SLJIT_MEM)
FAIL_IF(emit_op_mem(compiler, FLOAT_DATA(type) | LOAD_DATA, dst_freg, src1, src1w));
@@ -3204,7 +4062,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fselect(struct sljit_compiler *com
FAIL_IF(push_inst(compiler, FSGNJ_S | FMT(type) | FRD(dst_freg) | FRS1(src1) | FRS2(src1)));
size = compiler->size - size;
- *ptr = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0x7) << 9) | (sljit_ins)((size >> 3) << 25);
+ ins = get_jump_instruction(type & ~SLJIT_32) | (sljit_ins)((size & 0xf) << 8) | (sljit_ins)((size >> 4) << 25);
+ ptr[0] = (sljit_u16)ins;
+ ptr[1] = (sljit_u16)(ins >> 16);
return SLJIT_SUCCESS;
}
@@ -3276,7 +4136,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_load(struct sljit_compiler
CHECK_ERROR();
CHECK(check_sljit_emit_atomic_load(compiler, op, dst_reg, mem_reg));
- if (op & SLJIT_ATOMIC_USE_CAS)
+ if (!RISCV_HAS_ATOMIC(200) || (op & SLJIT_ATOMIC_USE_CAS))
return SLJIT_ERR_UNSUPPORTED;
switch (GET_OPCODE(op)) {
@@ -3314,7 +4174,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler
CHECK_ERROR();
CHECK(check_sljit_emit_atomic_store(compiler, op, src_reg, mem_reg, temp_reg));
- if (op & SLJIT_ATOMIC_USE_CAS)
+ if (!RISCV_HAS_ATOMIC(200) || (op & SLJIT_ATOMIC_USE_CAS))
return SLJIT_ERR_UNSUPPORTED;
switch (GET_OPCODE(op)) {
@@ -3339,6 +4199,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler
return push_inst(compiler, ins | RD(OTHER_FLAG) | RS1(mem_reg) | RS2(src_reg));
}
+static sljit_s32 sljit_max_vector_length = 0;
+
+static void init_compiler(void)
+{
+ sljit_sw vector_length;
+ sljit_s32 vector_length_log2;
+
+ if (!RISCV_HAS_VECTOR(100))
+ return;
+
+ __asm__ __volatile__ ("csrr %0, 0xc22" : "=r" (vector_length));
+
+ /* Probably something is wrong. */
+ if (vector_length < (1 << 3))
+ return;
+
+ vector_length_log2 = 3;
+ if (vector_length_log2 < 6 && vector_length > (1 << vector_length_log2))
+ vector_length_log2++;
+ sljit_max_vector_length = vector_length_log2;
+}
+
/*
SEW = Selected element width
LMUL = Vector register group multiplier
@@ -3359,13 +4241,22 @@ static SLJIT_INLINE sljit_s32 sljit_emit_vsetivli(struct sljit_compiler *compile
sljit_ins elem_size = (sljit_ins)SLJIT_SIMD_GET_ELEM_SIZE(type);
sljit_ins avl = (sljit_ins)1 << (SLJIT_SIMD_GET_REG_SIZE(type) - elem_size);
- return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | (elem_size << 23) | (vlmul << 20) | (avl << 15));
+ if (avl < 31)
+ return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | (elem_size << 23) | (vlmul << 20) | (avl << 15));
+
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(avl)));
+ return push_inst(compiler, VSETVLI | RD(TMP_REG1) | (elem_size << 23) | (vlmul << 20) | RS1(TMP_REG1));
}
static SLJIT_INLINE sljit_s32 sljit_emit_vsetivli_size(struct sljit_compiler *compiler, sljit_s32 reg_size, sljit_s32 elem_size)
{
sljit_ins avl = (sljit_ins)1 << (reg_size - elem_size);
- return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (avl << 15));
+
+ if (avl < 31)
+ return push_inst(compiler, VSETIVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | (avl << 15));
+
+ FAIL_IF(push_inst(compiler, ADDI | RD(TMP_REG1) | RS1(TMP_ZERO) | IMM_I(avl)));
+ return push_inst(compiler, VSETVLI | RD(TMP_REG1) | ((sljit_ins)elem_size << 23) | RS1(TMP_REG1));
}
static sljit_s32 sljit_emit_vmem(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 elem_size, sljit_s32 mem, sljit_sw memw)
@@ -3415,7 +4306,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_mov(struct sljit_compiler *co
ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
- if (reg_size != 4)
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
return SLJIT_ERR_UNSUPPORTED;
if (type & SLJIT_SIMD_TEST)
@@ -3484,7 +4375,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil
ADJUST_LOCAL_OFFSET(src, srcw);
- if (reg_size != 4)
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
return SLJIT_ERR_UNSUPPORTED;
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
@@ -3542,7 +4433,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_mov(struct sljit_compile
ADJUST_LOCAL_OFFSET(srcdst, srcdstw);
- if (reg_size != 4)
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
return SLJIT_ERR_UNSUPPORTED;
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
@@ -3645,7 +4536,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c
CHECK_ERROR();
CHECK(check_sljit_emit_simd_lane_replicate(compiler, type, vreg, src, src_lane_index));
- if (reg_size != 4)
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
return SLJIT_ERR_UNSUPPORTED;
if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)
@@ -3676,7 +4567,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_extend(struct sljit_compiler
ADJUST_LOCAL_OFFSET(src, srcw);
- if (reg_size != 4)
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
return SLJIT_ERR_UNSUPPORTED;
#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
@@ -3741,7 +4632,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c
ADJUST_LOCAL_OFFSET(dst, dstw);
- if (reg_size != 4)
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
return SLJIT_ERR_UNSUPPORTED;
if (((type & SLJIT_SIMD_FLOAT) && elem_size < 2) || elem_size > 3)
@@ -3749,7 +4640,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_sign(struct sljit_compiler *c
FAIL_IF(sljit_emit_vsetivli(compiler, type, 0));
FAIL_IF(push_inst(compiler, VMV_VI | VRD(TMP_VREG1) | (0x0 << 15)));
- FAIL_IF(push_inst(compiler, VMSLE_VI | VRD(TMP_VREG1) | (0x0 << 15) | VRS2(vreg)));
+ FAIL_IF(push_inst(compiler, VMSLE_VI | VRD(TMP_VREG1) | (0x1f << 15) | VRS2(vreg)));
FAIL_IF(sljit_emit_vsetivli_size(compiler, 2, 2));
FAIL_IF(push_inst(compiler, VMV_XS | RD(dst_r) | VRS2(TMP_VREG1)));
@@ -3771,7 +4662,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co
ADJUST_LOCAL_OFFSET(src2, src2w);
- if (reg_size != 4)
+ if (reg_size < 3 || reg_size > sljit_max_vector_length)
return SLJIT_ERR_UNSUPPORTED;
if ((type & SLJIT_SIMD_FLOAT) && (elem_size < 2 || elem_size > 3))
@@ -3822,13 +4713,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_op2(struct sljit_compiler *co
return push_inst(compiler, ins | VRD(dst_vreg) | VRS1(src2) | VRS2(src1_vreg));
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
{
struct sljit_const *const_;
sljit_s32 dst_r;
+ sljit_s32 mem_flags = WORD_DATA;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
@@ -3836,34 +4730,77 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
set_const(const_, compiler);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
- PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, ADDI | RD(dst_r)));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ if (init_value & 0x100)
+ init_value |= 0xf00;
+ else
+ init_value &= 0xff;
+
+ PTR_FAIL_IF(push_inst(compiler, ADDI | RD(dst_r) | IMM_I(init_value)));
+ mem_flags = BYTE_DATA;
+ break;
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ case SLJIT_MOV32:
+ mem_flags = INT_DATA;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_S32:
+ if ((init_value & 0x800) != 0)
+ init_value ^= ~(sljit_sw)0xfff;
+
+ PTR_FAIL_IF(push_inst(compiler, LUI | RD(dst_r) | (sljit_ins)(init_value & ~(sljit_sw)0xfff)));
+ PTR_FAIL_IF(push_inst(compiler, XORI | RD(dst_r) | RS1(dst_r) | IMM_I(init_value)));
+ break;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ default:
+ PTR_FAIL_IF(emit_const(compiler, dst_r, init_value, ADDI | RD(dst_r)));
+ break;
+ }
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
+ PTR_FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, dst, dstw));
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
{
struct sljit_jump *jump;
- sljit_s32 dst_r;
+ sljit_s32 dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = TMP_REG1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_REG2, dst, dstw));
+ }
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
set_mov_addr(jump, compiler, 0);
- dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
- PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));
-#if (defined SLJIT_CONFIG_RISCV_32 && SLJIT_CONFIG_RISCV_32)
- compiler->size += 1;
-#else /* !SLJIT_CONFIG_RISCV_32 */
- compiler->size += 5;
-#endif /* SLJIT_CONFIG_RISCV_32 */
+ PTR_FAIL_IF(push_inst16(compiler, (sljit_u16)target_r));
+ compiler->size += JUMP_MAX_SIZE - 1;
+
+ if (op == SLJIT_ADD_ABS_ADDR) {
+ if (RISCV_HAS_COMPRESSED(200))
+ PTR_FAIL_IF(push_inst16(compiler, C_ADD | C_RD(dst_r) | C_RS2(TMP_REG1)));
+ else
+ PTR_FAIL_IF(push_inst(compiler, ADD | RD(dst_r) | RS1(dst_r) | RS2(TMP_REG1)));
+ }
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_REG2, dst, dstw));
@@ -3871,7 +4808,48 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_com
return jump;
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ sljit_u16 *inst;
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ inst = (sljit_u16*)addr;
+ SLJIT_ASSERT((inst[0] & 0x707f) == ADDI);
+
+ if (new_constant & 0x100)
+ new_constant |= 0xf00;
+ else
+ new_constant &= 0xff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[1] = (sljit_u16)(new_constant << 4) | (inst[1] & 0xf);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+
+#if (defined SLJIT_CONFIG_RISCV_64 && SLJIT_CONFIG_RISCV_64)
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ inst = (sljit_u16*)addr;
+ SLJIT_ASSERT((inst[0] & 0x7f) == LUI && (inst[2] & 0x707f) == XORI);
+
+ if ((new_constant & 0x800) != 0)
+ new_constant ^= ~(sljit_sw)0xfff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);
+ inst[0] = (sljit_u16)((inst[0] & 0xfff) | (new_constant & 0xf000));
+ inst[1] = (sljit_u16)(new_constant >> 16);
+ inst[3] = (sljit_u16)(new_constant << 4) | (inst[3] & 0xf);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);
+ inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 4);
+ return;
+#endif /* SLJIT_CONFIG_RISCV_64 */
+
+ default:
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ return;
+ }
}
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeS390X.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeS390X.c
index 7ce9f9fcdcc..98f671e1027 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeS390X.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeS390X.c
@@ -93,9 +93,6 @@ static const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stac
#define tmp0 r0
#define tmp1 r1
-/* When reg cannot be unused. */
-#define IS_GPR_REG(reg) ((reg > 0) && (reg) <= SLJIT_SP)
-
/* Link register. */
static const sljit_gpr link_r = 14; /* r14 */
@@ -125,11 +122,6 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2] = {
#define F32(r) (R32A((sljit_ins)freg_map[r]))
#define F36(r) (R36A((sljit_ins)freg_map[r]))
-struct sljit_s390x_const {
- struct sljit_const const_; /* must be first */
- sljit_sw init_value; /* required to build literal pool */
-};
-
/* Convert SLJIT register to hardware register. */
static SLJIT_INLINE sljit_gpr gpr(sljit_s32 r)
{
@@ -169,14 +161,14 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
switch (type) {
case SLJIT_EQUAL:
if (SLJIT_ADD_SUB_NO_COMPARE(compiler->status_flags_state)) {
- sljit_s32 type = GET_FLAG_TYPE(compiler->status_flags_state);
- if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL)
+ sljit_s32 flag_type = GET_FLAG_TYPE(compiler->status_flags_state);
+ if (flag_type >= SLJIT_SIG_LESS && flag_type <= SLJIT_SIG_LESS_EQUAL)
return cc0;
- if (type == SLJIT_OVERFLOW)
+ if (flag_type == SLJIT_OVERFLOW)
return (cc0 | cc3);
return (cc0 | cc2);
}
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_ATOMIC_STORED:
case SLJIT_F_EQUAL:
@@ -185,14 +177,14 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
case SLJIT_NOT_EQUAL:
if (SLJIT_ADD_SUB_NO_COMPARE(compiler->status_flags_state)) {
- sljit_s32 type = GET_FLAG_TYPE(compiler->status_flags_state);
- if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL)
+ sljit_s32 flag_type = GET_FLAG_TYPE(compiler->status_flags_state);
+ if (flag_type >= SLJIT_SIG_LESS && flag_type <= SLJIT_SIG_LESS_EQUAL)
return (cc1 | cc2 | cc3);
- if (type == SLJIT_OVERFLOW)
+ if (flag_type == SLJIT_OVERFLOW)
return (cc1 | cc2);
return (cc1 | cc3);
}
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_UNORDERED_OR_NOT_EQUAL:
return (cc1 | cc2 | cc3);
@@ -223,7 +215,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
case SLJIT_NOT_CARRY:
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
return (cc2 | cc3);
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_SIG_LESS_EQUAL:
case SLJIT_F_LESS_EQUAL:
@@ -233,7 +225,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
case SLJIT_CARRY:
if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
return (cc0 | cc1);
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_SIG_GREATER:
case SLJIT_UNORDERED_OR_GREATER:
@@ -246,7 +238,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
case SLJIT_OVERFLOW:
if (compiler->status_flags_state & SLJIT_SET_Z)
return (cc2 | cc3);
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_UNORDERED:
return cc3;
@@ -254,7 +246,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
case SLJIT_NOT_OVERFLOW:
if (compiler->status_flags_state & SLJIT_SET_Z)
return (cc0 | cc1);
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_ORDERED:
return (cc0 | cc1 | cc2);
@@ -333,7 +325,7 @@ static SLJIT_INLINE int have_facility_static(facility_bit x)
return 0;
}
-static SLJIT_INLINE unsigned long get_hwcap()
+static SLJIT_INLINE unsigned long get_hwcap(void)
{
static unsigned long hwcap = 0;
if (SLJIT_UNLIKELY(!hwcap)) {
@@ -343,7 +335,7 @@ static SLJIT_INLINE unsigned long get_hwcap()
return hwcap;
}
-static SLJIT_INLINE int have_stfle()
+static SLJIT_INLINE int have_stfle(void)
{
if (have_facility_static(STORE_FACILITY_LIST_EXTENDED_FACILITY))
return 1;
@@ -410,10 +402,10 @@ HAVE_FACILITY(have_misc2, MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY)
#define CHECK_SIGNED(v, bitlen) \
((v) >= -(1 << ((bitlen) - 1)) && (v) < (1 << ((bitlen) - 1)))
-#define is_s8(d) CHECK_SIGNED((d), 8)
-#define is_s16(d) CHECK_SIGNED((d), 16)
+#define is_s8(d) ((sljit_sw)(d) == (sljit_s8)(d))
+#define is_s16(d) ((sljit_sw)(d) == (sljit_s16)(d))
#define is_s20(d) CHECK_SIGNED((d), 20)
-#define is_s32(d) ((d) == (sljit_s32)(d))
+#define is_s32(d) ((sljit_sw)(d) == (sljit_s32)(d))
static SLJIT_INLINE sljit_ins disp_s20(sljit_s32 d)
{
@@ -983,6 +975,12 @@ static const sljit_ins store_forms[3] = {
0xe30000000024 /* stg */
};
+static const sljit_ins store_byte_forms[3] = {
+ 0x42000000 /* stc */,
+ 0xe30000000072 /* stcy */,
+ 0
+};
+
static const sljit_ins load_halfword_forms[3] = {
0x48000000 /* lh */,
0xe30000000078 /* lhy */,
@@ -1021,6 +1019,13 @@ static SLJIT_INLINE sljit_s32 store_word(struct sljit_compiler *compiler, sljit_
return load_store_op(compiler, src_r, dst, dstw, is_32bit, store_forms);
}
+/* May clobber tmp1. */
+static SLJIT_INLINE sljit_s32 store_byte(struct sljit_compiler *compiler, sljit_gpr src_r,
+ sljit_s32 dst, sljit_sw dstw)
+{
+ return load_store_op(compiler, src_r, dst, dstw, 1, store_byte_forms);
+}
+
#undef WHEN
static sljit_s32 emit_move(struct sljit_compiler *compiler,
@@ -1029,7 +1034,7 @@ static sljit_s32 emit_move(struct sljit_compiler *compiler,
{
sljit_gpr src_r;
- SLJIT_ASSERT(!IS_GPR_REG(src) || dst_r != gpr(src & REG_MASK));
+ SLJIT_ASSERT(!FAST_IS_REG(src) || dst_r != gpr(src & REG_MASK));
if (src == SLJIT_IMM)
return push_load_imm_inst(compiler, dst_r, srcw);
@@ -1392,6 +1397,12 @@ static sljit_s32 emit_non_commutative(struct sljit_compiler *compiler, const str
return emit_rrf(compiler, ins, dst, src1, src1w, src2, src2w);
}
+static SLJIT_INLINE sljit_u16 *process_extended_label(sljit_u16 *code_ptr, struct sljit_extended_label *ext_label)
+{
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ return (sljit_u16*)((sljit_uw)code_ptr & ~(ext_label->data));
+}
+
SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler, sljit_s32 options, void *exec_allocator_data)
{
struct sljit_label *label;
@@ -1413,30 +1424,28 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_sw source, offset;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_generate_code(compiler));
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
reverse_buf(compiler);
jump = compiler->jumps;
while (jump != NULL) {
- if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR | JUMP_MOV_ADDR)) {
+ if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR)) {
/* encoded: */
/* brasl %r14, <rel_addr> (or brcl <mask>, <rel_addr>) */
/* replace with: */
/* lgrl %r1, <pool_addr> */
/* bras %r14, %r1 (or bcr <mask>, %r1) */
- pool_size += sizeof(*pool);
+ if (((jump->flags & SLJIT_REWRITABLE_JUMP) || !is_s32(jump->u.target)))
+ pool_size += sizeof(sljit_uw);
+ else
+ jump->flags |= PATCH_IMM32;
+
if (!(jump->flags & JUMP_MOV_ADDR))
ins_size += 2;
}
jump = jump->next;
}
- const_ = compiler->consts;
- while (const_) {
- pool_size += sizeof(*pool);
- const_ = const_->next;
- }
-
/* pad code size to 8 bytes so is accessible with half word offsets */
/* the literal pool needs to be doubleword aligned */
pad_size = ((ins_size + 7UL) & ~7UL) - ins_size;
@@ -1475,80 +1484,91 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!const_ || const_->addr >= half_count);
if (next_min_addr == next_label_size) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label = label->next;
next_label_size = SLJIT_GET_NEXT_SIZE(label);
}
if (next_min_addr == next_jump_addr) {
- if (SLJIT_UNLIKELY(jump->flags & JUMP_MOV_ADDR)) {
- source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
-
- jump->addr = (sljit_uw)pool_ptr;
-
- /* store target into pool */
- offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;
- pool_ptr++;
+ jump->addr = (sljit_uw)code_ptr;
- SLJIT_ASSERT(!(offset & 1));
- offset >>= 1;
- SLJIT_ASSERT(is_s32(offset));
- ins |= (sljit_ins)offset & 0xffffffff;
+ if (SLJIT_UNLIKELY(jump->flags & JUMP_MOV_ADDR)) {
+ if (jump->flags & PATCH_IMM32) {
+ SLJIT_ASSERT((jump->flags & JUMP_ADDR) && is_s32(jump->u.target));
+ ins = 0xc00100000000 /* lgfi */ | (ins & 0xf000000000);
+ } else if (jump->flags & JUMP_ADDR) {
+ source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ offset = (sljit_sw)(jump->u.target - (sljit_uw)source);
+
+ if ((offset & 0x1) != 0 || offset > 0xffffffffl || offset < -0x100000000l) {
+ jump->addr = (sljit_uw)pool_ptr;
+ jump->flags |= PATCH_POOL;
+
+ /* store target into pool */
+ offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;
+ pool_ptr++;
+
+ SLJIT_ASSERT(!(offset & 1));
+ offset >>= 1;
+ SLJIT_ASSERT(is_s32(offset));
+ ins = 0xc40800000000 /* lgrl */ | (ins & 0xf000000000) | (sljit_ins)(offset & 0xffffffff);
+ }
+ }
} else if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR)) {
- sljit_ins arg;
-
- jump->addr = (sljit_uw)pool_ptr;
-
- /* load address into tmp1 */
source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;
-
- SLJIT_ASSERT(!(offset & 1));
- offset >>= 1;
- SLJIT_ASSERT(is_s32(offset));
-
- code_ptr[0] = (sljit_u16)(0xc408 | R4A(tmp1) /* lgrl */);
- code_ptr[1] = (sljit_u16)(offset >> 16);
- code_ptr[2] = (sljit_u16)offset;
- code_ptr += 3;
- pool_ptr++;
-
- /* branch to tmp1 */
- arg = (ins >> 36) & 0xf;
- if (((ins >> 32) & 0xf) == 4) {
- /* brcl -> bcr */
- ins = bcr(arg, tmp1);
- } else {
- SLJIT_ASSERT(((ins >> 32) & 0xf) == 5);
- /* brasl -> basr */
- ins = basr(arg, tmp1);
+
+ if (jump->flags & PATCH_IMM32) {
+ SLJIT_ASSERT((jump->flags & JUMP_ADDR) && is_s32(jump->u.target));
+ code_ptr[0] = (sljit_u16)(0xc001 /* lgfi */ | R4A(tmp1));
+ code_ptr += 3;
+ } else if (!(jump->flags & SLJIT_REWRITABLE_JUMP)) {
+ offset = (sljit_sw)(jump->u.target - (sljit_uw)source);
+
+ if ((offset & 0x1) != 0 || offset > 0xffffffffl || offset < -0x100000000l)
+ jump->flags |= PATCH_POOL;
+ } else
+ jump->flags |= PATCH_POOL;
+
+ if (jump->flags & PATCH_POOL) {
+ jump->addr = (sljit_uw)pool_ptr;
+
+ /* load address into tmp1 */
+ offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;
+
+ SLJIT_ASSERT(!(offset & 1));
+ offset >>= 1;
+ SLJIT_ASSERT(is_s32(offset));
+
+ code_ptr[0] = (sljit_u16)(0xc408 /* lgrl */ | R4A(tmp1));
+ code_ptr[1] = (sljit_u16)(offset >> 16);
+ code_ptr[2] = (sljit_u16)offset;
+ code_ptr += 3;
+ pool_ptr++;
}
- /* Adjust half_count. */
- half_count += 2;
- } else
- jump->addr = (sljit_uw)code_ptr;
+ if (jump->flags & (PATCH_POOL | PATCH_IMM32)) {
+ /* branch to tmp1 */
+ if (((ins >> 32) & 0xf) == 4) {
+ /* brcl -> bcr */
+ ins = 0x0700 /* bcr */ | ((ins >> 32) & 0xf0) | R0A(tmp1);
+ } else {
+ SLJIT_ASSERT(((ins >> 32) & 0xf) == 5);
+ /* brasl -> basr */
+ ins = 0x0d00 /* basr */ | ((ins >> 32) & 0xf0) | R0A(tmp1);
+ }
+
+ /* Adjust half_count. */
+ half_count += 2;
+ }
+ }
jump = jump->next;
next_jump_addr = SLJIT_GET_NEXT_ADDRESS(jump);
- } else if (next_min_addr == next_const_addr) {
- /* update instruction with relative address of constant */
- source = (sljit_sw)code_ptr;
- offset = (sljit_sw)pool_ptr - source;
-
- SLJIT_ASSERT(!(offset & 0x1));
- offset >>= 1; /* halfword (not byte) offset */
- SLJIT_ASSERT(is_s32(offset));
-
- ins |= (sljit_ins)offset & 0xffffffff;
-
- /* update address */
- const_->addr = (sljit_uw)pool_ptr;
-
- /* store initial value into pool and update pool address */
- *(pool_ptr++) = (sljit_uw)(((struct sljit_s390x_const*)const_)->init_value);
-
- /* move to next constant */
+ } else if (next_min_addr == next_const_addr) {
+ const_->addr = (sljit_uw)code_ptr;
const_ = const_->next;
next_const_addr = SLJIT_GET_NEXT_ADDRESS(const_);
}
@@ -1574,6 +1594,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} while (buf);
if (next_label_size == half_count) {
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label = label->next;
}
@@ -1581,27 +1604,32 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!label);
SLJIT_ASSERT(!jump);
SLJIT_ASSERT(!const_);
- SLJIT_ASSERT(code + (ins_size >> 1) == code_ptr);
- SLJIT_ASSERT((sljit_u8 *)pool + pool_size == (sljit_u8 *)pool_ptr);
+ SLJIT_ASSERT(code_ptr <= code + (ins_size >> 1));
+ SLJIT_ASSERT((sljit_u8 *)pool_ptr <= (sljit_u8 *)pool + pool_size);
jump = compiler->jumps;
while (jump != NULL) {
offset = (sljit_sw)((jump->flags & JUMP_ADDR) ? jump->u.target : jump->u.label->u.addr);
- if (jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR | JUMP_MOV_ADDR)) {
- /* Store jump target into pool. */
- *(sljit_uw*)(jump->addr) = (sljit_uw)offset;
- } else {
+ if (!(jump->flags & (PATCH_POOL | PATCH_IMM32))) {
code_ptr = (sljit_u16*)jump->addr;
offset -= (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- /* offset must be halfword aligned */
+ /* Offset must be halfword aligned. */
SLJIT_ASSERT(!(offset & 1));
offset >>= 1;
SLJIT_ASSERT(is_s32(offset)); /* TODO(mundaym): handle arbitrary offsets */
code_ptr[1] = (sljit_u16)(offset >> 16);
code_ptr[2] = (sljit_u16)offset;
+ } else if (jump->flags & PATCH_POOL) {
+ /* Store jump target into pool. */
+ *(sljit_uw*)(jump->addr) = (sljit_uw)offset;
+ } else {
+ SLJIT_ASSERT(is_s32(offset));
+ code_ptr = (sljit_u16*)jump->addr;
+ code_ptr[1] = (sljit_u16)(offset >> 16);
+ code_ptr[2] = (sljit_u16)offset;
}
jump = jump->next;
}
@@ -2243,7 +2271,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
}
/* STORE and STORE IMMEDIATE */
if ((dst & SLJIT_MEM) && (FAST_IS_REG(src) || src == SLJIT_IMM)) {
- struct addr mem;
sljit_gpr reg = FAST_IS_REG(src) ? gpr(src) : tmp0;
if (src == SLJIT_IMM) {
@@ -2276,7 +2303,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
#undef LEVAL
/* MOVE CHARACTERS */
if ((dst & SLJIT_MEM) && (src & SLJIT_MEM)) {
- struct addr mem;
FAIL_IF(make_addr_bxy(compiler, &mem, src, srcw, tmp1));
switch (opcode) {
case SLJIT_MOV_U8:
@@ -2335,7 +2361,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
case SLJIT_REV_U32:
case SLJIT_REV_S32:
op |= SLJIT_32;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_REV:
case SLJIT_REV_U16:
case SLJIT_REV_S16:
@@ -2648,7 +2674,7 @@ static sljit_s32 sljit_emit_bitwise_imm(struct sljit_compiler *compiler, sljit_s
sljit_gpr dst_r = tmp0;
sljit_s32 needs_move = 1;
- if (IS_GPR_REG(dst)) {
+ if (FAST_IS_REG(dst)) {
dst_r = gpr(dst & REG_MASK);
if (dst == src1)
needs_move = 0;
@@ -3119,6 +3145,75 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *
return push_inst(compiler, 0xb9810000 /* ogr */ | R4A(dst_r) | R0A(tmp0));
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_gpr dst_r, tmp_r, src_r;
+ struct addr addr;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= 0x3f;
+
+ if (src2 == SLJIT_IMM) {
+ src2w = src2w << shift_arg;
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ tmp_r = FAST_IS_REG(dst) && (dst != src1) ? gpr(dst) : tmp0;
+
+ if (src2 & SLJIT_MEM) {
+ FAIL_IF(load_word(compiler, tmp_r, src2, src2w, 0 /* 64-bit */));
+ src_r = tmp_r;
+ } else {
+ src_r = gpr(src2);
+ }
+
+ FAIL_IF(push_inst(compiler, 0xeb000000000d /* sllg */ | R36A(tmp_r) | R32A(src_r) | ((sljit_ins)shift_arg << 16)));
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(make_addr_bxy(compiler, &addr, src1, src1w, tmp1));
+ FAIL_IF(push_inst(compiler, 0xe30000000008 /* ag */ | R36A(tmp_r) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset)));
+ src_r = tmp_r;
+ } else if (src1 == SLJIT_IMM) {
+ if (is_s32(src1w)) {
+ FAIL_IF(push_inst(compiler, 0xc20800000000 /* agfi */ | R36A(tmp_r) | (sljit_u32)src1w));
+ src_r = tmp_r;
+ } else {
+ src_r = tmp_r != tmp0 ? tmp0 : tmp1;
+ FAIL_IF(push_load_imm_inst(compiler, src_r, src1w));
+ }
+ } else {
+ src_r = gpr(src1);
+ }
+
+ dst_r = (FAST_IS_REG(dst) ? gpr(dst) : tmp0);
+
+ if (src_r != tmp_r) {
+ if (src_r == dst_r) {
+ FAIL_IF(push_inst(compiler, 0xb9080000 /* agr */ | R4A(dst_r) | R0A(tmp_r)));
+ } else {
+ FAIL_IF(push_inst(compiler, 0xb9e80000 /* agrk */ | R12A(tmp_r) | R4A(dst_r) | R0A(src_r)));
+ }
+ }
+
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, dst_r, dst, dstw, 0 /* 64-bit */);
+ return SLJIT_SUCCESS;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -3131,11 +3226,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp
switch (op) {
case SLJIT_FAST_RETURN:
- src_r = FAST_IS_REG(src) ? gpr(src) : tmp1;
- if (src & SLJIT_MEM)
- FAIL_IF(load_word(compiler, tmp1, src, srcw, 0));
+ if (FAST_IS_REG(src)) {
+ src_r = gpr(src);
+ if (src_r != link_r)
+ FAIL_IF(push_inst(compiler, lgr(link_r, src_r)));
+ } else
+ FAIL_IF(load_word(compiler, link_r, src, srcw, 0));
- return push_inst(compiler, br(src_r));
+ return push_inst(compiler, br(link_r));
case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN:
return SLJIT_SUCCESS;
case SLJIT_PREFETCH_L1:
@@ -3163,8 +3261,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_dst(struct sljit_compiler *comp
switch (op) {
case SLJIT_FAST_ENTER:
- if (FAST_IS_REG(dst))
- return push_inst(compiler, lgr(gpr(dst), link_r));
+ if (FAST_IS_REG(dst)) {
+ dst_r = gpr(dst);
+
+ if (dst_r == link_r)
+ return SLJIT_SUCCESS;
+ return push_inst(compiler, lgr(dst_r, link_r));
+ }
break;
case SLJIT_GET_RETURN_ADDRESS:
dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;
@@ -3591,6 +3694,60 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, i;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_2) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - sizeof(sljit_u16);
+
+ for (i = (mask >> 1); i != 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, 0x0700 /* 2-byte nop */));
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+
+ for (i = (buffers->size + 1) >> 1; i > 0; i--)
+ PTR_FAIL_IF(push_inst(compiler, 0x0700 /* 2-byte nop */));
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
{
struct sljit_jump *jump;
@@ -3633,25 +3790,36 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw)
{
+ struct sljit_jump *jump;
sljit_gpr src_r = FAST_IS_REG(src) ? gpr(src) : tmp1;
CHECK_ERROR();
CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
- if (src == SLJIT_IMM) {
- SLJIT_ASSERT(!(srcw & 1)); /* target address must be even */
- FAIL_IF(push_load_imm_inst(compiler, src_r, srcw));
- }
- else if (src & SLJIT_MEM) {
- ADJUST_LOCAL_OFFSET(src, srcw);
- FAIL_IF(load_word(compiler, src_r, src, srcw, 0 /* 64-bit */));
+ if (src != SLJIT_IMM) {
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(load_word(compiler, src_r, src, srcw, 0 /* 64-bit */));
+ }
+
+ /* emit jump instruction */
+ if (type >= SLJIT_FAST_CALL)
+ return push_inst(compiler, basr(link_r, src_r));
+
+ return push_inst(compiler, br(src_r));
}
- /* emit jump instruction */
+ jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump));
+ FAIL_IF(!jump);
+ set_jump(jump, compiler, JUMP_ADDR);
+ jump->addr = compiler->size;
+ jump->u.target = (sljit_uw)srcw;
+
+ type &= 0xff;
if (type >= SLJIT_FAST_CALL)
- return push_inst(compiler, basr(link_r, src_r));
+ return push_inst(compiler, brasl(link_r, 0));
- return push_inst(compiler, br(src_r));
+ return push_inst(compiler, brcl(0xf, 0));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type,
@@ -3711,7 +3879,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
break;
case SLJIT_MOV32:
op |= SLJIT_32;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case SLJIT_MOV:
/* can write straight into destination */
loc_r = dst_r;
@@ -3766,6 +3934,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
sljit_ins mask;
sljit_gpr src_r;
sljit_gpr dst_r = gpr(dst_reg);
+ sljit_s32 is_32bit = (type & SLJIT_32) != 0;
sljit_ins ins;
CHECK_ERROR();
@@ -3773,6 +3942,43 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
ADJUST_LOCAL_OFFSET(src1, src1w);
+ type &= ~SLJIT_32;
+ if (src1 == SLJIT_IMM && is_32bit)
+ src1w = (sljit_s32)src1w;
+
+ if (type & SLJIT_COMPARE_SELECT) {
+ type ^= SLJIT_COMPARE_SELECT;
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(load_word(compiler, tmp0, src1, src1w, is_32bit));
+ src1 = TMP_REG1;
+ src1w = 0;
+ } else if (src1 == SLJIT_IMM) {
+ if (type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL && src1w >= 0 && src1w <= 0x7fff) {
+ ins = is_32bit ? 0xc20f00000000 /* clfi */ : 0xc20e00000000 /* clgfi */;
+ FAIL_IF(push_inst(compiler, ins | R36A(gpr(src2_reg)) | (sljit_ins)src1w));
+ type ^= 0x1;
+ } else if (type >= SLJIT_SIG_LESS && type <= SLJIT_SIG_LESS_EQUAL && is_s20(src1w)) {
+ ins = is_32bit ? 0xc20d00000000 /* cfi */ : 0xc20c00000000 /* cgfi */;
+ FAIL_IF(push_inst(compiler, ins | R36A(gpr(src2_reg)) | ((sljit_ins)src1w & 0xffffffff)));
+ type ^= 0x1;
+ } else {
+ FAIL_IF(push_load_imm_inst(compiler, tmp0, src1w));
+ src1 = TMP_REG1;
+ src1w = 0;
+ }
+ }
+
+ if (FAST_IS_REG(src1)) {
+ if (type >= SLJIT_LESS && type <= SLJIT_LESS_EQUAL)
+ ins = is_32bit ? 0x1500 /* clr */ : 0xb9210000 /* clgr */;
+ else
+ ins = is_32bit ? 0x1900 /* cr */ : 0xb9200000 /* cgr */;
+ FAIL_IF(push_inst(compiler, ins | R4A(gpr(src1)) | R0A(gpr(src2_reg))));
+ }
+ }
+
if (dst_reg != src2_reg) {
if (src1 == dst_reg) {
src1 = src2_reg;
@@ -3780,16 +3986,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
type ^= 0x1;
} else {
if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
- FAIL_IF(load_word(compiler, dst_r, src1, src1w, type & SLJIT_32));
+ FAIL_IF(load_word(compiler, dst_r, src1, src1w, is_32bit));
src1 = src2_reg;
src1w = 0;
type ^= 0x1;
} else
- FAIL_IF(push_inst(compiler, ((type & SLJIT_32) ? 0x1800 /* lr */ : 0xb9040000 /* lgr */) | R4A(dst_r) | R0A(gpr(src2_reg))));
+ FAIL_IF(push_inst(compiler, (is_32bit ? 0x1800 /* lr */ : 0xb9040000 /* lgr */) | R4A(dst_r) | R0A(gpr(src2_reg))));
}
}
- mask = get_cc(compiler, type & ~SLJIT_32);
+ mask = get_cc(compiler, type);
if (src1 & SLJIT_MEM) {
if (src1 & OFFS_REG_MASK) {
@@ -3807,23 +4013,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
FAIL_IF(push_load_imm_inst(compiler, tmp1, src1w));
if (src1 & REG_MASK)
- FAIL_IF(push_inst(compiler, 0xb9e80000 /* agrk */ | R12A(tmp1) | R4A(tmp1) | R0A(gpr(src1 & REG_MASK))));
+ FAIL_IF(push_inst(compiler, 0xb9080000 /* agr */ | R4A(tmp1) | R0A(gpr(src1 & REG_MASK))));
src_r = tmp1;
src1w = 0;
} else
src_r = gpr(src1 & REG_MASK);
- ins = (type & SLJIT_32) ? 0xeb00000000f2 /* loc */ : 0xeb00000000e2 /* locg */;
+ ins = is_32bit ? 0xeb00000000f2 /* loc */ : 0xeb00000000e2 /* locg */;
return push_inst(compiler, ins | R36A(dst_r) | (mask << 32) | R28A(src_r) | disp_s20((sljit_s32)src1w));
}
if (src1 == SLJIT_IMM) {
- if (type & SLJIT_32)
- src1w = (sljit_s32)src1w;
-
if (have_lscond2() && is_s16(src1w)) {
- ins = (type & SLJIT_32) ? 0xec0000000042 /* lochi */ : 0xec0000000046 /* locghi */;
+ ins = is_32bit ? 0xec0000000042 /* lochi */ : 0xec0000000046 /* locghi */;
return push_inst(compiler, ins | R36A(dst_r) | (mask << 32) | (sljit_ins)(src1w & 0xffff) << 16);
}
@@ -3832,7 +4035,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
} else
src_r = gpr(src1);
- ins = (type & SLJIT_32) ? 0xb9f20000 /* locr */ : 0xb9e20000 /* locgr */;
+ ins = is_32bit ? 0xb9f20000 /* locr */ : 0xb9e20000 /* locgr */;
return push_inst(compiler, ins | (mask << 12) | R4A(dst_r) | R0A(src_r));
}
@@ -4461,40 +4664,52 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_atomic_store(struct sljit_compiler
/* Other instructions */
/* --------------------------------------------------------------------- */
-/* On s390x we build a literal pool to hold constants. This has two main
- advantages:
-
- 1. we only need one instruction in the instruction stream (LGRL)
- 2. we can store 64 bit addresses and use 32 bit offsets
-
- To retrofit the extra information needed to build the literal pool we
- add a new sljit_s390x_const struct that contains the initial value but
- can still be cast to a sljit_const. */
-
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
{
- struct sljit_s390x_const *const_;
+ struct sljit_const *const_;
sljit_gpr dst_r;
+ int is_32 = 0;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
- const_ = (struct sljit_s390x_const*)ensure_abuf(compiler,
- sizeof(struct sljit_s390x_const));
+ const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
PTR_FAIL_IF(!const_);
set_const((struct sljit_const*)const_, compiler);
- const_->init_value = init_value;
dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
- if (have_genext())
- PTR_FAIL_IF(push_inst(compiler, lgrl(dst_r, 0)));
- else {
- PTR_FAIL_IF(push_inst(compiler, larl(tmp1, 0)));
- PTR_FAIL_IF(push_inst(compiler, lg(dst_r, 0, r0, tmp1)));
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ if (init_value & 0x100)
+ init_value |= 0xff00;
+ else
+ init_value &= 0xff;
+
+ PTR_FAIL_IF(push_inst(compiler, 0xa7090000 /* lghi */ | R20A(dst_r) | (sljit_ins)(init_value & 0xffff)));
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(store_byte(compiler, dst_r, dst, dstw));
+ return (struct sljit_const*)const_;
+
+ case SLJIT_MOV32:
+ is_32 = 1;
+ SLJIT_FALLTHROUGH
+ case SLJIT_MOV_S32:
+ PTR_FAIL_IF(push_inst(compiler, 0xc00100000000 /* lgfi */ | R36A(dst_r) | (sljit_ins)(init_value & 0xffffffff)));
+ break;
+
+ default:
+ PTR_FAIL_IF(push_inst(compiler, 0xc00f00000000 /* llilf */ | R36A(dst_r) | (sljit_ins)(init_value & 0xffffffff)));
+ PTR_FAIL_IF(push_inst(compiler, 0xc00800000000 /* iihf */ | R36A(dst_r) | (sljit_ins)((init_value >> 32) & 0xffffffff)));
+ break;
}
if (dst & SLJIT_MEM)
- PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, 0 /* always 64-bit */));
+ PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, is_32));
return (struct sljit_const*)const_;
}
@@ -4511,32 +4726,85 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_CACHE_FLUSH(ptr, ptr + 1);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
+ sljit_u16 *inst = (sljit_u16*)addr;
+ SLJIT_UNUSED_ARG(executable_offset);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
+ SLJIT_ASSERT((inst[0] & 0xff0f) == 0xa709 /* lghi */);
+
+ if (new_constant & 0x100)
+ new_constant |= 0xff00;
+ else
+ new_constant &= 0xff;
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0);
+ inst[1] = (sljit_u16)new_constant;
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1);
+ inst = (sljit_u16*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 2);
+ return;
+
+ case SLJIT_MOV32:
+ case SLJIT_MOV_S32:
+ SLJIT_ASSERT((inst[0] & 0xff0f) == 0xc001 /* lgfi */);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 3, 0);
+ inst[1] = (sljit_u16)(new_constant >> 16);
+ inst[2] = (sljit_u16)new_constant;
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 3, 1);
+ inst = (sljit_u16*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 3);
+ return;
+
+ default:
+ SLJIT_ASSERT((inst[0] & 0xff0f) == 0xc00f /* llilf */ && (inst[3] & 0xff0f) == 0xc008 /* iihf */);
+
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 0);
+ inst[1] = (sljit_u16)(new_constant >> 16);
+ inst[2] = (sljit_u16)new_constant;
+ inst[4] = (sljit_u16)(new_constant >> 48);
+ inst[5] = (sljit_u16)(new_constant >> 32);
+ SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1);
+ inst = (sljit_u16*)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
+ SLJIT_CACHE_FLUSH(inst, inst + 6);
+ return;
+ }
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
{
struct sljit_jump *jump;
- sljit_gpr dst_r;
+ sljit_gpr dst_r, target_r;
+ SLJIT_UNUSED_ARG(op);
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
+ dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+
+ if (op != SLJIT_ADD_ABS_ADDR)
+ target_r = dst_r;
+ else {
+ target_r = tmp1;
+
+ if (dst & SLJIT_MEM)
+ PTR_FAIL_IF(load_word(compiler, dst_r, dst, dstw, 0));
+ }
+
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
set_mov_addr(jump, compiler, 0);
- dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+ /* Might be converted to lgrl. */
+ PTR_FAIL_IF(push_inst(compiler, 0xc00000000000 /* larl */ | R36A(target_r)));
- if (have_genext())
- PTR_FAIL_IF(push_inst(compiler, lgrl(dst_r, 0)));
- else {
- PTR_FAIL_IF(push_inst(compiler, larl(tmp1, 0)));
- PTR_FAIL_IF(push_inst(compiler, lg(dst_r, 0, r0, tmp1)));
- }
+ if (op == SLJIT_ADD_ABS_ADDR)
+ PTR_FAIL_IF(push_inst(compiler, 0xb90a0000 /* algr */ | R4A(dst_r) | R0A(tmp1)));
if (dst & SLJIT_MEM)
PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, 0));
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_32.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_32.c
index 217a1498abe..95faa74ffbf 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_32.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_32.c
@@ -105,20 +105,20 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
if (a == SLJIT_IMM) {
if (flags & EX86_BIN_INS) {
if (imma <= 127 && imma >= -128) {
- inst_size += 1;
+ inst_size += sizeof(sljit_s8);
flags |= EX86_BYTE_ARG;
} else
- inst_size += 4;
+ inst_size += sizeof(sljit_sw);
} else if (flags & EX86_SHIFT_INS) {
SLJIT_ASSERT(imma <= 0x1f);
if (imma != 1) {
- inst_size++;
+ inst_size += sizeof(sljit_s8);
flags |= EX86_BYTE_ARG;
}
} else if (flags & EX86_BYTE_ARG)
- inst_size++;
+ inst_size += sizeof(sljit_s8);
else if (flags & EX86_HALF_ARG)
- inst_size += sizeof(short);
+ inst_size += sizeof(sljit_s16);
else
inst_size += sizeof(sljit_sw);
} else
@@ -1268,41 +1268,59 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
CHECK_EXTRA_REGS(src1, src1w, (void)0);
CHECK_EXTRA_REGS(src2_reg, src2w, (void)0);
- type &= ~SLJIT_32;
-
if (dst & SLJIT_MEM) {
if (src1 == SLJIT_IMM || (!(src1 & SLJIT_MEM) && (src2_reg & SLJIT_MEM))) {
EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
src1 = src2_reg;
src1w = src2w;
- type ^= 0x1;
+ if (!(type & SLJIT_COMPARE_SELECT))
+ type ^= 0x1;
} else
EMIT_MOV(compiler, TMP_REG1, 0, src2_reg, src2w);
dst_reg = TMP_REG1;
- } else {
- if (dst_reg != src2_reg) {
- if (dst_reg == src1) {
- src1 = src2_reg;
- src1w = src2w;
+ } else if (dst_reg != src2_reg) {
+ if (dst_reg == src1) {
+ src1 = src2_reg;
+ src1w = src2w;
+ if (!(type & SLJIT_COMPARE_SELECT))
type ^= 0x1;
- } else if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
- EMIT_MOV(compiler, dst_reg, 0, src1, src1w);
- src1 = src2_reg;
- src1w = src2w;
+ } else if (ADDRESSING_DEPENDS_ON(src1, dst_reg)) {
+ EMIT_MOV(compiler, dst_reg, 0, src1, src1w);
+ src1 = src2_reg;
+ src1w = src2w;
+ if (!(type & SLJIT_COMPARE_SELECT))
type ^= 0x1;
- } else
- EMIT_MOV(compiler, dst_reg, 0, src2_reg, src2w);
- }
+ } else
+ EMIT_MOV(compiler, dst_reg, 0, src2_reg, src2w);
}
- if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && (src1 != SLJIT_IMM || dst_reg != TMP_REG1)) {
- if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {
+ if (type & SLJIT_COMPARE_SELECT) {
+ if (dst_reg != TMP_REG1 && !FAST_IS_REG(src1)) {
EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
src1 = TMP_REG1;
src1w = 0;
}
+ type ^= 0x1;
+ FAIL_IF(emit_cmp_binary(compiler, dst_reg, 0, src1, src1w));
+ }
+
+ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
+
+ if (sljit_has_cpu_feature(SLJIT_HAS_CMOV)) {
+ if (SLJIT_UNLIKELY(src1 == SLJIT_IMM)) {
+ if (dst_reg != TMP_REG1) {
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, src1w);
+ src1 = TMP_REG1;
+ src1w = 0;
+ } else {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_IMM, src1w);
+ src1 = SLJIT_MEM1(SLJIT_SP);
+ src1w = 0;
+ }
+ }
+
FAIL_IF(emit_groupf(compiler, U8(get_jump_code((sljit_uw)type) - 0x40), dst_reg, src1, src1w));
} else
FAIL_IF(emit_cmov_generic(compiler, type, dst_reg, src1, src1w));
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_64.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_64.c
index e4d3db828fa..0a2f59d2959 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_64.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_64.c
@@ -152,20 +152,20 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw
if (a == SLJIT_IMM) {
if (flags & EX86_BIN_INS) {
if (imma <= 127 && imma >= -128) {
- inst_size += 1;
+ inst_size += sizeof(sljit_s8);
flags |= EX86_BYTE_ARG;
} else
- inst_size += 4;
+ inst_size += sizeof(sljit_s32);
} else if (flags & EX86_SHIFT_INS) {
SLJIT_ASSERT(imma <= (compiler->mode32 ? 0x1f : 0x3f));
if (imma != 1) {
- inst_size++;
+ inst_size += sizeof(sljit_s8);
flags |= EX86_BYTE_ARG;
}
} else if (flags & EX86_BYTE_ARG)
- inst_size++;
+ inst_size += sizeof(sljit_s8);
else if (flags & EX86_HALF_ARG)
- inst_size += sizeof(short);
+ inst_size += sizeof(sljit_s16);
else
inst_size += sizeof(sljit_s32);
} else {
@@ -362,7 +362,7 @@ static sljit_u8* detect_far_jump_type(struct sljit_jump *jump, sljit_u8 *code_pt
{
sljit_uw type = jump->flags >> TYPE_SHIFT;
- int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && (jump->flags & JUMP_ADDR) && (jump->u.target <= 0xffffffff);
+ int short_addr = ((jump->flags & (SLJIT_REWRITABLE_JUMP | JUMP_ADDR)) == JUMP_ADDR) && (jump->u.target <= 0xffffffff);
/* The relative jump below specialized for this case. */
SLJIT_ASSERT(reg_map[TMP_REG2] >= 8 && TMP_REG2 != SLJIT_TMP_DEST_REG);
@@ -805,7 +805,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
if (word_arg_count == 0)
return SLJIT_SUCCESS;
- if (word_arg_count >= 3) {
+ if (word_arg_count >= 3 || src == SLJIT_R2) {
if (src == SLJIT_R2)
*src_ptr = TMP_REG1;
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R2, 0);
@@ -1029,13 +1029,28 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_select(struct sljit_compiler *comp
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2_reg)
{
+ sljit_u8* inst;
+
CHECK_ERROR();
CHECK(check_sljit_emit_select(compiler, type, dst_reg, src1, src1w, src2_reg));
ADJUST_LOCAL_OFFSET(src1, src1w);
compiler->mode32 = type & SLJIT_32;
- type &= ~SLJIT_32;
+
+ if (type & SLJIT_COMPARE_SELECT) {
+ if (!FAST_IS_REG(src1)) {
+ EMIT_MOV(compiler, TMP_REG2, 0, src1, src1w);
+ src1 = TMP_REG2;
+ src1w = 0;
+ }
+
+ inst = emit_x86_instruction(compiler, 1, src1, 0, src2_reg, 0);
+ FAIL_IF(!inst);
+ *inst = CMP_r_rm;
+ }
+
+ type &= ~(SLJIT_32 | SLJIT_COMPARE_SELECT);
if (dst_reg != src2_reg) {
if (dst_reg == src1) {
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_common.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_common.c
index 9f599d5fb08..25085a8f9f1 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_common.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitNativeX86_common.c
@@ -780,6 +780,22 @@ static void generate_jump_or_mov_addr(struct sljit_jump *jump, sljit_sw executab
}
}
+static sljit_u8 *process_extended_label(sljit_u8 *code_ptr, struct sljit_extended_label *ext_label)
+{
+ sljit_uw mask;
+ sljit_u8 *ptr = code_ptr;
+
+ SLJIT_ASSERT(ext_label->label.u.index == SLJIT_LABEL_ALIGNED);
+ mask = ext_label->data;
+
+ code_ptr = (sljit_u8*)(((sljit_uw)code_ptr + mask) & ~mask);
+
+ while (ptr < code_ptr)
+ *ptr++ = NOP;
+
+ return code_ptr;
+}
+
static void reduce_code_size(struct sljit_compiler *compiler)
{
struct sljit_label *label;
@@ -914,7 +930,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_const *const_;
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_generate_code(compiler));
+ CHECK_PTR(check_sljit_generate_code(compiler, options));
reduce_code_size(compiler);
@@ -944,6 +960,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
} else {
switch (len) {
case SLJIT_INST_LABEL:
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ code_ptr = process_extended_label(code_ptr, (struct sljit_extended_label*)label);
+
label->u.addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
label->size = (sljit_uw)(code_ptr - code);
label = label->next;
@@ -962,7 +981,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
#endif /* SLJIT_CONFIG_X86_32 */
}
- SLJIT_ASSERT((sljit_uw)code_ptr - addr <= ((jump->flags >> JUMP_SIZE_SHIFT) & 0x1f));
+ SLJIT_ASSERT((sljit_uw)code_ptr - addr <= ((jump->flags >> JUMP_SIZE_SHIFT) & 0xff));
jump = jump->next;
break;
case SLJIT_INST_MOV_ADDR:
@@ -974,7 +993,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
break;
default:
SLJIT_ASSERT(len == SLJIT_INST_CONST);
- const_->addr = ((sljit_uw)code_ptr) - sizeof(sljit_sw);
+ const_->addr = (sljit_uw)code_ptr;
const_ = const_->next;
break;
}
@@ -2998,6 +3017,125 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_shift_into(struct sljit_compiler *
return SLJIT_SUCCESS;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2_shift(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w,
+ sljit_sw shift_arg)
+{
+ sljit_s32 dst_r;
+ int use_lea = 0;
+ sljit_u8* inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w, shift_arg));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ shift_arg &= (sljit_sw)((sizeof(sljit_sw) * 8) - 1);
+
+ if (src2 == SLJIT_IMM) {
+ src2w = src2w << shift_arg;
+ shift_arg = 0;
+ }
+
+ if (shift_arg == 0) {
+ SLJIT_SKIP_CHECKS(compiler);
+ return sljit_emit_op2(compiler, GET_OPCODE(op), dst, dstw, src1, src1w, src2, src2w);
+ }
+
+ CHECK_EXTRA_REGS(dst, dstw, (void)0);
+ CHECK_EXTRA_REGS(src1, src1w, (void)0);
+ CHECK_EXTRA_REGS(src2, src2w, (void)0);
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = 0;
+#endif
+
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (shift_arg <= 3) {
+ use_lea = 1;
+ if (!FAST_IS_REG(src2)) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);
+ src2 = TMP_REG1;
+ }
+
+ if (!FAST_IS_REG(src1)) {
+ EMIT_MOV(compiler, src2 == TMP_REG1 ? TMP_REG2 : TMP_REG1, 0, src1, src1w);
+ src1 = src2 == TMP_REG1 ? TMP_REG2 : TMP_REG1;
+ }
+ }
+#else /* !SLJIT_CONFIG_X86_64 */
+ if (shift_arg <= 3 && (FAST_IS_REG(src1) || (FAST_IS_REG(src2) && src2 != TMP_REG1))) {
+ use_lea = 1;
+ if (!FAST_IS_REG(src2)) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src2, src2w);
+ src2 = TMP_REG1;
+ }
+
+ if (!FAST_IS_REG(src1)) {
+ EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
+ src1 = TMP_REG1;
+ }
+ }
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (use_lea) {
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, SLJIT_MEM2(src1, src2), shift_arg);
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
+
+ if (!FAST_IS_REG(dst))
+ return emit_mov(compiler, dst, dstw, dst_r, 0);
+
+ return SLJIT_SUCCESS;
+ }
+
+ if ((op & SLJIT_SRC2_UNDEFINED) != 0 && FAST_IS_REG(src2) && src1 != src2)
+ dst_r = src2;
+ else {
+ dst_r = FAST_IS_REG(dst) && (dst != src1) ? dst : TMP_REG1;
+
+ if (src2 != dst_r) {
+ EMIT_MOV(compiler, dst_r, 0, src2, src2w);
+ }
+ }
+
+ inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, shift_arg, dst_r, 0);
+ FAIL_IF(!inst);
+ inst[1] |= SHL;
+
+ if (dst == src1 && dstw == src1w) {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, dst, dstw);
+ FAIL_IF(!inst);
+ *inst = ADD_rm_r;
+ return SLJIT_SUCCESS;
+ }
+
+ if (FAST_IS_REG(dst) && FAST_IS_REG(src1)) {
+ inst = emit_x86_instruction(compiler, 1, dst, 0, SLJIT_MEM2(src1, dst_r), 0);
+ FAIL_IF(!inst);
+ *inst = LEA_r_m;
+ return SLJIT_SUCCESS;
+ }
+
+ if (src1 == SLJIT_IMM) {
+ BINARY_IMM(ADD, ADD_rm_r, src1w, dst_r, 0);
+ } else {
+ inst = emit_x86_instruction(compiler, 1, dst_r, 0, src1, src1w);
+ FAIL_IF(!inst);
+ *inst = ADD_r_rm;
+ }
+
+ if (dst != dst_r)
+ return emit_mov(compiler, dst, dstw, dst_r, 0);
+
+ return SLJIT_SUCCESS;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -3438,6 +3576,82 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_aligned_label(struct sljit_compiler *compiler,
+ sljit_s32 alignment, struct sljit_read_only_buffer *buffers)
+{
+ sljit_uw mask, size;
+ sljit_u8 *inst;
+ struct sljit_label *label;
+ struct sljit_label *next_label;
+ struct sljit_extended_label *ext_label;
+
+ CHECK_ERROR_PTR();
+ CHECK_PTR(check_sljit_emit_aligned_label(compiler, alignment, buffers));
+
+ sljit_reset_read_only_buffers(buffers);
+
+ if (alignment <= SLJIT_LABEL_ALIGN_1) {
+ SLJIT_SKIP_CHECKS(compiler);
+ label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!label);
+ } else {
+ /* The used space is filled with NOPs. */
+ mask = ((sljit_uw)1 << alignment) - 1;
+ compiler->size += mask;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1);
+ PTR_FAIL_IF(!inst);
+ inst[0] = SLJIT_INST_LABEL;
+
+ ext_label = (struct sljit_extended_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ PTR_FAIL_IF(!ext_label);
+ set_extended_label(ext_label, compiler, SLJIT_LABEL_ALIGNED, mask);
+ label = &ext_label->label;
+ }
+
+ if (buffers == NULL)
+ return label;
+
+ next_label = label;
+
+ while (1) {
+ buffers->u.label = next_label;
+ size = buffers->size;
+
+ while (size >= 4) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 4);
+ PTR_FAIL_IF(!inst);
+ INC_SIZE(4);
+ inst[0] = NOP;
+ inst[1] = NOP;
+ inst[2] = NOP;
+ inst[3] = NOP;
+ size -= 4;
+ }
+
+ if (size > 0) {
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ PTR_FAIL_IF(!inst);
+ INC_SIZE(size);
+
+ do {
+ *inst++ = NOP;
+ } while (--size != 0);
+ }
+
+ buffers = buffers->next;
+
+ if (buffers == NULL)
+ break;
+
+ SLJIT_SKIP_CHECKS(compiler);
+ next_label = sljit_emit_label(compiler);
+ PTR_FAIL_IF(!next_label);
+ }
+
+ return label;
+}
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type)
{
sljit_u8 *inst;
@@ -3965,7 +4179,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_replicate(struct sljit_compil
else
FAIL_IF(emit_groupf(compiler, PSHUFLW_x_xm | EX86_PREF_F2 | EX86_SSE2, vreg, vreg, 0));
FAIL_IF(emit_byte(compiler, 0));
- /* fallthrough */
+ SLJIT_FALLTHROUGH
default:
if (use_vex)
FAIL_IF(emit_vex_instruction(compiler, PSHUFD_x_xm | EX86_PREF_66 | EX86_SSE2, vreg, 0, vreg, 0));
@@ -4539,7 +4753,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_simd_lane_replicate(struct sljit_c
return emit_vex_instruction(compiler, VPBROADCASTD_x_xm | EX86_PREF_66 | VEX_OP_0F38 | EX86_SSE2, vreg, 0, vreg, 0);
src = vreg;
- /* fallthrough */
+ SLJIT_FALLTHROUGH
case 2:
byte = U8(src_lane_index);
byte = U8(byte | (byte << 2));
@@ -5002,6 +5216,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
CHECK_ERROR();
CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
CHECK_EXTRA_REGS(dst, dstw, (void)0);
@@ -5009,8 +5224,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
compiler->mode32 = 0;
#endif
- ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
-
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (NOT_HALFWORD(offset)) {
FAIL_IF(emit_load_imm64(compiler, TMP_REG1, offset));
@@ -5028,59 +5241,105 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
return emit_mov(compiler, dst, dstw, SLJIT_SP, 0);
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_sw init_value)
{
sljit_u8 *inst;
struct sljit_const *const_;
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
sljit_s32 reg;
-#endif
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ sljit_s32 dst_is_ereg = 0;
+#endif /* !SLJIT_CONFIG_X86_32 */
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
+ CHECK_PTR(check_sljit_emit_const(compiler, op, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
- CHECK_EXTRA_REGS(dst, dstw, (void)0);
+ CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);
const_ = (struct sljit_const*)ensure_abuf(compiler, sizeof(struct sljit_const));
PTR_FAIL_IF(!const_);
set_const(const_, compiler);
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_U8:
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- compiler->mode32 = 0;
- reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ compiler->mode32 = (op & SLJIT_32);
+#endif /* SLJIT_CONFIG_X86_64 */
- if (emit_load_imm64(compiler, reg, init_value))
- return NULL;
-#else
- if (emit_mov(compiler, dst, dstw, SLJIT_IMM, init_value))
- return NULL;
-#endif
+ if ((init_value & 0x100) != 0)
+ init_value = init_value | -(sljit_sw)0x100;
+ else
+ init_value = (sljit_u8)init_value;
+
+#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
+ if (dst_is_ereg) {
+ if (emit_mov(compiler, dst, dstw, SLJIT_IMM, (sljit_s32)init_value))
+ return NULL;
+ dst = 0;
+ break;
+ }
+#endif /* !SLJIT_CONFIG_X86_32 */
+
+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (emit_mov(compiler, reg, 0, SLJIT_IMM, init_value))
+ return NULL;
+ break;
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ case SLJIT_MOV:
+ compiler->mode32 = 0;
+ reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+
+ if (emit_load_imm64(compiler, reg, init_value))
+ return NULL;
+ break;
+#endif /* SLJIT_CONFIG_X86_64 */
+ default:
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = (op == SLJIT_MOV32);
+#endif /* SLJIT_CONFIG_X86_64 */
+
+ if (emit_mov(compiler, dst, dstw, SLJIT_IMM, (sljit_s32)init_value))
+ return NULL;
+ dst = 0;
+ break;
+ }
inst = (sljit_u8*)ensure_buf(compiler, 1);
PTR_FAIL_IF(!inst);
inst[0] = SLJIT_INST_CONST;
+ if (dst & SLJIT_MEM) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if (dst & SLJIT_MEM)
- if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))
- return NULL;
+ if (op == SLJIT_MOV) {
+ if (emit_mov(compiler, dst, dstw, TMP_REG1, 0))
+ return NULL;
+ return const_;
+ }
#endif
+ if (emit_mov_byte(compiler, 0, dst, dstw, TMP_REG1, 0))
+ return NULL;
+ }
+
return const_;
}
-SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_op_addr(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw)
{
struct sljit_jump *jump;
sljit_u8 *inst;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
sljit_s32 reg;
#endif /* SLJIT_CONFIG_X86_64 */
+ SLJIT_UNUSED_ARG(op);
CHECK_ERROR_PTR();
- CHECK_PTR(check_sljit_emit_mov_addr(compiler, dst, dstw));
+ CHECK_PTR(check_sljit_emit_op_addr(compiler, op, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
CHECK_EXTRA_REGS(dst, dstw, (void)0);
@@ -5091,7 +5350,10 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_com
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
compiler->mode32 = 0;
- reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ if (dst & SLJIT_MEM)
+ reg = TMP_REG1;
+ else
+ reg = (op != SLJIT_ADD_ABS_ADDR) ? dst : TMP_REG2;
PTR_FAIL_IF(emit_load_imm64(compiler, reg, 0));
jump->addr = compiler->size;
@@ -5099,7 +5361,17 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_com
if (reg_map[reg] >= 8)
jump->flags |= MOV_ADDR_HI;
#else /* !SLJIT_CONFIG_X86_64 */
- PTR_FAIL_IF(emit_mov(compiler, dst, dstw, SLJIT_IMM, 0));
+ if (op == SLJIT_ADD_ABS_ADDR) {
+ if (dst != SLJIT_R0) {
+ /* Must not be a signed byte argument. */
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 0x100, dst, dstw);
+ PTR_FAIL_IF(!inst);
+ *(inst + 1) |= ADD;
+ } else
+ PTR_FAIL_IF(emit_do_imm(compiler, ADD_EAX_i32, 0));
+ } else {
+ PTR_FAIL_IF(emit_mov(compiler, dst, dstw, SLJIT_IMM, 0));
+ }
#endif /* SLJIT_CONFIG_X86_64 */
inst = (sljit_u8*)ensure_buf(compiler, 1);
@@ -5108,7 +5380,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_mov_addr(struct sljit_com
inst[0] = SLJIT_INST_MOV_ADDR;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- if (dst & SLJIT_MEM)
+ if (op == SLJIT_ADD_ABS_ADDR) {
+ inst = emit_x86_instruction(compiler, 1, reg, 0, dst, dstw);
+ PTR_FAIL_IF(!inst);
+ *inst = ADD_rm_r;
+ } else if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_mov(compiler, dst, dstw, TMP_REG1, 0));
#endif /* SLJIT_CONFIG_X86_64 */
@@ -5128,11 +5404,31 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 1);
}
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_s32 op, sljit_sw new_constant, sljit_sw executable_offset)
{
+ void *start_addr;
SLJIT_UNUSED_ARG(executable_offset);
- SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_sw)), 0);
- sljit_unaligned_store_sw((void*)addr, new_constant);
- SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_sw)), 1);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (op == SLJIT_MOV) {
+ start_addr = (void*)(addr - sizeof(sljit_sw));
+ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 0);
+ sljit_unaligned_store_sw(start_addr, new_constant);
+ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 1);
+ return;
+ }
+#endif
+
+ start_addr = (void*)(addr - sizeof(sljit_s32));
+
+ if ((op | SLJIT_32) == SLJIT_MOV32_U8) {
+ if ((new_constant & 0x100) != 0)
+ new_constant = new_constant | -(sljit_sw)0x100;
+ else
+ new_constant = (sljit_u8)new_constant;
+ }
+
+ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 0);
+ sljit_unaligned_store_s32(start_addr, (sljit_s32)new_constant);
+ SLJIT_UPDATE_WX_FLAGS(start_addr, (void*)addr, 1);
}
diff --git a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitSerialize.c b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitSerialize.c
index 6ef161fd498..042cc18a89e 100644
--- a/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitSerialize.c
+++ b/src/3rdparty/pcre2/deps/sljit/sljit_src/sljitSerialize.c
@@ -24,6 +24,14 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#define SLJIT_GET_LABEL_INDEX(label) \
+ ((label)->u.index < SLJIT_LABEL_ALIGNED ? (label)->u.index : ((struct sljit_extended_label*)(label))->index)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_uw sljit_get_label_index(struct sljit_label *label)
+{
+ return SLJIT_GET_LABEL_INDEX(label);
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_jump_has_label(struct sljit_jump *jump)
{
return !(jump->flags & JUMP_ADDR) && (jump->u.label != NULL);
@@ -48,6 +56,7 @@ struct sljit_serialized_compiler {
sljit_uw buf_segment_count;
sljit_uw label_count;
+ sljit_uw aligned_label_count;
sljit_uw jump_count;
sljit_uw const_count;
@@ -94,6 +103,11 @@ struct sljit_serialized_label {
sljit_uw size;
};
+struct sljit_serialized_aligned_label {
+ sljit_uw size;
+ sljit_uw data;
+};
+
struct sljit_serialized_jump {
sljit_uw addr;
sljit_uw flags;
@@ -122,6 +136,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compile
struct sljit_const *const_;
struct sljit_serialized_compiler *serialized_compiler;
struct sljit_serialized_label *serialized_label;
+ struct sljit_serialized_aligned_label *serialized_aligned_label;
struct sljit_serialized_jump *serialized_jump;
struct sljit_serialized_const *serialized_const;
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
@@ -155,7 +170,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compile
buf = buf->next;
}
- serialized_size += compiler->label_count * sizeof(struct sljit_serialized_label);
+ label = compiler->labels;
+ while (label != NULL) {
+ used_size = sizeof(struct sljit_serialized_label);
+
+ if (label->u.index >= SLJIT_LABEL_ALIGNED)
+ used_size += sizeof(struct sljit_serialized_aligned_label);
+
+ serialized_size += used_size;
+ label = label->next;
+ }
jump = compiler->jumps;
while (jump != NULL) {
@@ -229,12 +253,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compile
serialized_compiler->buf_segment_count = counter;
label = compiler->labels;
+ counter = 0;
while (label != NULL) {
serialized_label = (struct sljit_serialized_label*)ptr;
- serialized_label->size = label->size;
+ serialized_label->size = (label->u.index < SLJIT_LABEL_ALIGNED) ? label->size : label->u.index;
ptr += sizeof(struct sljit_serialized_label);
+
+ if (label->u.index >= SLJIT_LABEL_ALIGNED) {
+ serialized_aligned_label = (struct sljit_serialized_aligned_label*)ptr;
+ serialized_aligned_label->size = label->size;
+ serialized_aligned_label->data = ((struct sljit_extended_label*)label)->data;
+ ptr += sizeof(struct sljit_serialized_aligned_label);
+ counter++;
+ }
+
label = label->next;
}
+ serialized_compiler->aligned_label_count = counter;
jump = compiler->jumps;
counter = 0;
@@ -246,7 +281,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_uw* sljit_serialize_compiler(struct sljit_compile
if (jump->flags & JUMP_ADDR)
serialized_jump->value = jump->u.target;
else if (jump->u.label != NULL)
- serialized_jump->value = jump->u.label->u.index;
+ serialized_jump->value = SLJIT_GET_LABEL_INDEX(jump->u.label);
else
serialized_jump->value = SLJIT_MAX_ADDRESS;
@@ -291,6 +326,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit
struct sljit_compiler *compiler;
struct sljit_serialized_compiler *serialized_compiler;
struct sljit_serialized_label *serialized_label;
+ struct sljit_serialized_aligned_label *serialized_aligned_label;
struct sljit_serialized_jump *serialized_jump;
struct sljit_serialized_const *serialized_const;
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
@@ -302,13 +338,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit
struct sljit_label *label;
struct sljit_label *last_label;
struct sljit_label **label_list = NULL;
+ struct sljit_label **label_list_ptr = NULL;
struct sljit_jump *jump;
struct sljit_jump *last_jump;
struct sljit_const *const_;
struct sljit_const *last_const;
sljit_u8 *ptr = (sljit_u8*)buffer;
sljit_u8 *end = ptr + size;
- sljit_uw i, used_size, aligned_size, label_count;
+ sljit_uw i, type, used_size, aligned_size;
+ sljit_uw label_count, aligned_label_count;
SLJIT_UNUSED_ARG(options);
if (size < sizeof(struct sljit_serialized_compiler) || (size & (sizeof(sljit_uw) - 1)) != 0)
@@ -403,22 +441,31 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit
last_label = NULL;
label_count = serialized_compiler->label_count;
- if ((sljit_uw)(end - ptr) < label_count * sizeof(struct sljit_serialized_label))
+ aligned_label_count = serialized_compiler->aligned_label_count;
+ i = (label_count * sizeof(struct sljit_serialized_label)) + (aligned_label_count * sizeof(struct sljit_serialized_aligned_label));
+
+ if ((sljit_uw)(end - ptr) < i)
goto error;
label_list = (struct sljit_label **)SLJIT_MALLOC(label_count * sizeof(struct sljit_label*), allocator_data);
if (label_list == NULL)
goto error;
+ label_list_ptr = label_list;
for (i = 0; i < label_count; i++) {
- label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ serialized_label = (struct sljit_serialized_label*)ptr;
+ type = serialized_label->size;
+
+ if (type < SLJIT_LABEL_ALIGNED) {
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label));
+ } else {
+ label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_extended_label));
+ }
+
if (label == NULL)
goto error;
- serialized_label = (struct sljit_serialized_label*)ptr;
label->next = NULL;
- label->u.index = i;
- label->size = serialized_label->size;
if (last_label != NULL)
last_label->next = label;
@@ -426,11 +473,33 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler *sljit_deserialize_compiler(sljit
compiler->labels = label;
last_label = label;
- label_list[i] = label;
+ *label_list_ptr++ = label;
+
ptr += sizeof(struct sljit_serialized_label);
+
+ if (type < SLJIT_LABEL_ALIGNED) {
+ label->u.index = i;
+ label->size = type;
+ } else {
+ if (aligned_label_count == 0)
+ goto error;
+
+ aligned_label_count--;
+
+ serialized_aligned_label = (struct sljit_serialized_aligned_label*)ptr;
+ label->u.index = type;
+ label->size = serialized_aligned_label->size;
+
+ ((struct sljit_extended_label*)label)->index = i;
+ ((struct sljit_extended_label*)label)->data = serialized_aligned_label->data;
+ ptr += sizeof(struct sljit_serialized_aligned_label);
+ }
}
compiler->last_label = last_label;
+ if (aligned_label_count != 0)
+ goto error;
+
last_jump = NULL;
i = serialized_compiler->jump_count;
if ((sljit_uw)(end - ptr) < i * sizeof(struct sljit_serialized_jump))
diff --git a/src/3rdparty/pcre2/import_from_pcre2_tarball.sh b/src/3rdparty/pcre2/import_from_pcre2_tarball.sh
index 15471203707..3a8c29bf010 100755
--- a/src/3rdparty/pcre2/import_from_pcre2_tarball.sh
+++ b/src/3rdparty/pcre2/import_from_pcre2_tarball.sh
@@ -44,6 +44,7 @@ copy_file() {
copy_file "src/pcre2.h.generic" "src/pcre2.h"
copy_file "src/pcre2_chartables.c.dist" "src/pcre2_chartables.c"
+copy_file "deps/sljit/LICENSE" "LICENSE-SLJIT"
FILES="
AUTHORS.md
@@ -53,6 +54,7 @@ FILES="
src/pcre2_chkdint.c
src/pcre2_compile.c
src/pcre2_compile.h
+ src/pcre2_compile_cgroup.c
src/pcre2_compile_class.c
src/pcre2_config.c
src/pcre2_context.c
@@ -63,8 +65,6 @@ FILES="
src/pcre2_internal.h
src/pcre2_intmodedep.h
src/pcre2_jit_compile.c
- src/pcre2_jit_match.c
- src/pcre2_jit_misc.c
src/pcre2_maketables.c
src/pcre2_match.c
src/pcre2_match_data.c
@@ -74,7 +74,8 @@ FILES="
src/pcre2_script_run.c
src/pcre2_serialize.c
src/pcre2_jit_char_inc.h
- src/pcre2_jit_neon_inc.h
+ src/pcre2_jit_match_inc.h
+ src/pcre2_jit_misc_inc.h
src/pcre2_jit_simd_inc.h
src/pcre2_string_utils.c
src/pcre2_study.c
@@ -83,7 +84,7 @@ FILES="
src/pcre2_tables.c
src/pcre2_ucd.c
src/pcre2_ucp.h
- src/pcre2_ucptables.c
+ src/pcre2_ucptables_inc.h
src/pcre2_util.h
src/pcre2_valid_utf.c
src/pcre2_xclass.c
diff --git a/src/3rdparty/pcre2/qt_attribution.json b/src/3rdparty/pcre2/qt_attribution.json
index 20b841eec6f..ef29ad7d951 100644
--- a/src/3rdparty/pcre2/qt_attribution.json
+++ b/src/3rdparty/pcre2/qt_attribution.json
@@ -3,37 +3,38 @@
"Id": "pcre2",
"Name": "PCRE2",
"QDocModule": "qtcore",
- "QtUsage": "Optionally used in Qt Core (QRegularExpression). Configure with -system-pcre or -no-pcre to avoid.",
+ "QtUsage": "Used in Qt Core (QRegularExpression).",
"SecurityCritical": true,
"Description": "The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl 5.",
"Homepage": "http://www.pcre.org/",
- "Version": "10.46",
- "DownloadLocation": "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.46/pcre2-10.46.tar.bz2",
+ "Version": "10.47",
+ "DownloadLocation": "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.47/pcre2-10.47.tar.bz2",
"PURL": "pkg:github/PCRE2Project/pcre2@pcre2-$<VERSION>",
"CPE": "cpe:2.3:a:pcre:pcre2:$<VERSION>:*:*:*:*:*:*:*",
"License": "BSD 3-clause \"New\" or \"Revised\" License with PCRE2 binary-like Packages Exception",
"LicenseId": "LicenseRef-BSD-3-Clause-with-PCRE2-Binary-Like-Packages-Exception",
"LicenseFile": "LICENCE.md",
- "Copyright": ["Copyright (c) 1997-2024 University of Cambridge",
+ "Copyright": ["Copyright (c) 1997-2007 University of Cambridge",
+ "Copyright (c) 2007-2024 Philip Hazel",
"Copyright (c) 2010-2024 Zoltan Herczeg"]
},
{
"Id": "pcre2-sljit",
"Name": "PCRE2 - Stack-less Just-In-Time Compiler",
"QDocModule": "qtcore",
- "QtUsage": "Optionally used in Qt Core (QRegularExpression). Configure with -system-pcre or -no-pcre to avoid.",
+ "QtUsage": "Used in Qt Core (QRegularExpression).",
"Path": "deps/sljit",
"Description": "The PCRE library is a set of functions that implement regular expression pattern matching using the same syntax and semantics as Perl 5.",
"Homepage": "http://www.pcre.org/",
- "Version": "10.46",
- "DownloadLocation": "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.46/pcre2-10.46.tar.bz2",
+ "Version": "10.47",
+ "DownloadLocation": "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.47/pcre2-10.47.tar.bz2",
"PURL": "pkg:github/PCRE2Project/pcre2@$<VERSION>",
"CPE": "cpe:2.3:a:pcre:pcre2:$<VERSION>:*:*:*:*:*:*:*",
"License": "BSD 2-clause \"Simplified\" License",
"LicenseId": "BSD-2-Clause",
- "LicenseFile": "LICENCE-SLJIT",
- "Copyright": "Copyright (c) 2009-2024 Zoltan Herczeg"
+ "LicenseFile": "LICENSE-SLJIT",
+ "Copyright": "Copyright Zoltan Herczeg"
}
]
diff --git a/src/3rdparty/pcre2/src/pcre2.h b/src/3rdparty/pcre2/src/pcre2.h
index a6c739fb918..4034e5a91d4 100644
--- a/src/3rdparty/pcre2/src/pcre2.h
+++ b/src/3rdparty/pcre2/src/pcre2.h
@@ -42,25 +42,21 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE2_MAJOR 10
-#define PCRE2_MINOR 46
+#define PCRE2_MINOR 47
#define PCRE2_PRERELEASE
-#define PCRE2_DATE 2025-08-27
+#define PCRE2_DATE 2025-10-21
-/* When an application links to a PCRE DLL in Windows, the symbols that are
+/* When an application links to a PCRE2 DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE2, the appropriate
-export setting is defined in pcre2_internal.h, which includes this file. So we
-don't change existing definitions of PCRE2_EXP_DECL. */
+export setting is defined in pcre2_internal.h, which includes this file. So, we
+don't change existing definitions of PCRE2_EXP_DECL.
-#if defined(_WIN32) && !defined(PCRE2_STATIC)
-# ifndef PCRE2_EXP_DECL
-# define PCRE2_EXP_DECL extern __declspec(dllimport)
-# endif
-#endif
-
-/* By default, we use the standard "extern" declarations. */
+By default, we use the standard "extern" declarations. */
#ifndef PCRE2_EXP_DECL
-# ifdef __cplusplus
+# if defined(_WIN32) && !defined(PCRE2_STATIC)
+# define PCRE2_EXP_DECL extern __declspec(dllimport)
+# elif defined __cplusplus
# define PCRE2_EXP_DECL extern "C"
# else
# define PCRE2_EXP_DECL extern
@@ -68,14 +64,15 @@ don't change existing definitions of PCRE2_EXP_DECL. */
#endif
/* When compiling with the MSVC compiler, it is sometimes necessary to include
-a "calling convention" before exported function names. (This is secondhand
-information; I know nothing about MSVC myself). For example, something like
+a "calling convention" before exported function names. For example:
void __cdecl function(....)
-might be needed. In order so make this easy, all the exported functions have
-PCRE2_CALL_CONVENTION just before their names. It is rarely needed; if not
-set, we ensure here that it has no effect. */
+might be needed. In order to make this easy, all the exported functions have
+PCRE2_CALL_CONVENTION just before their names.
+
+PCRE2 normally uses the platform's standard calling convention, so this should
+not be set unless you know you need it. */
#ifndef PCRE2_CALL_CONVENTION
#define PCRE2_CALL_CONVENTION
@@ -343,6 +340,10 @@ pcre2_pattern_convert(). */
#define PCRE2_ERROR_PERL_ECLASS_EMPTY_EXPR 214
#define PCRE2_ERROR_PERL_ECLASS_MISSING_CLOSE 215
#define PCRE2_ERROR_PERL_ECLASS_UNEXPECTED_CHAR 216
+#define PCRE2_ERROR_EXPECTED_CAPTURE_GROUP 217
+#define PCRE2_ERROR_MISSING_OPENING_PARENTHESIS 218
+#define PCRE2_ERROR_MISSING_NUMBER_TERMINATOR 219
+#define PCRE2_ERROR_NULL_ERROROFFSET 220
/* "Expected" matching error codes: no match and partial match. */
@@ -432,6 +433,11 @@ released, the numbers must not be changed. */
#define PCRE2_ERROR_JIT_UNSUPPORTED (-68)
#define PCRE2_ERROR_REPLACECASE (-69)
#define PCRE2_ERROR_TOOLARGEREPLACE (-70)
+#define PCRE2_ERROR_DIFFSUBSPATTERN (-71)
+#define PCRE2_ERROR_DIFFSUBSSUBJECT (-72)
+#define PCRE2_ERROR_DIFFSUBSOFFSET (-73)
+#define PCRE2_ERROR_DIFFSUBSOPTIONS (-74)
+#define PCRE2_ERROR_BAD_BACKSLASH_K (-75)
/* Request types for pcre2_pattern_info() */
@@ -484,6 +490,7 @@ released, the numbers must not be changed. */
#define PCRE2_CONFIG_NEVER_BACKSLASH_C 13
#define PCRE2_CONFIG_COMPILED_WIDTHS 14
#define PCRE2_CONFIG_TABLES_LENGTH 15
+#define PCRE2_CONFIG_EFFECTIVE_LINKSIZE 16
/* Optimization directives for pcre2_set_optimize().
For binary compatibility, only add to this list; do not renumber. */
@@ -743,14 +750,14 @@ PCRE2_EXP_DECL pcre2_match_data *PCRE2_CALL_CONVENTION \
PCRE2_EXP_DECL pcre2_match_data *PCRE2_CALL_CONVENTION \
pcre2_match_data_create_from_pattern(const pcre2_code *, \
pcre2_general_context *); \
+PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
+ pcre2_match_data_free(pcre2_match_data *); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_dfa_match(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, \
uint32_t, pcre2_match_data *, pcre2_match_context *, int *, PCRE2_SIZE); \
PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
pcre2_match(const pcre2_code *, PCRE2_SPTR, PCRE2_SIZE, PCRE2_SIZE, \
uint32_t, pcre2_match_data *, pcre2_match_context *); \
-PCRE2_EXP_DECL void PCRE2_CALL_CONVENTION \
- pcre2_match_data_free(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SPTR PCRE2_CALL_CONVENTION \
pcre2_get_mark(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
@@ -762,7 +769,9 @@ PCRE2_EXP_DECL uint32_t PCRE2_CALL_CONVENTION \
PCRE2_EXP_DECL PCRE2_SIZE *PCRE2_CALL_CONVENTION \
pcre2_get_ovector_pointer(pcre2_match_data *); \
PCRE2_EXP_DECL PCRE2_SIZE PCRE2_CALL_CONVENTION \
- pcre2_get_startchar(pcre2_match_data *);
+ pcre2_get_startchar(pcre2_match_data *); \
+PCRE2_EXP_DECL int PCRE2_CALL_CONVENTION \
+ pcre2_next_match(pcre2_match_data *, PCRE2_SIZE *, uint32_t *);
/* Convenience functions for handling matched substrings. */
@@ -942,6 +951,7 @@ pcre2_compile are called by application code. */
#define pcre2_match_data_create PCRE2_SUFFIX(pcre2_match_data_create_)
#define pcre2_match_data_create_from_pattern PCRE2_SUFFIX(pcre2_match_data_create_from_pattern_)
#define pcre2_match_data_free PCRE2_SUFFIX(pcre2_match_data_free_)
+#define pcre2_next_match PCRE2_SUFFIX(pcre2_next_match_)
#define pcre2_pattern_convert PCRE2_SUFFIX(pcre2_pattern_convert_)
#define pcre2_pattern_info PCRE2_SUFFIX(pcre2_pattern_info_)
#define pcre2_serialize_decode PCRE2_SUFFIX(pcre2_serialize_decode_)
diff --git a/src/3rdparty/pcre2/src/pcre2_auto_possess.c b/src/3rdparty/pcre2/src/pcre2_auto_possess.c
index 6d7f27b6904..408803246ac 100644
--- a/src/3rdparty/pcre2/src/pcre2_auto_possess.c
+++ b/src/3rdparty/pcre2/src/pcre2_auto_possess.c
@@ -38,16 +38,14 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
+
/* This module contains functions that scan a compiled pattern and change
repeats into possessive repeats where possible. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "pcre2_internal.h"
-#include "pcre2_internal.h"
/* This macro represents the max size of list[] and that is used to keep
track of UCD info in several places, it should be kept on sync with the
@@ -264,8 +262,10 @@ switch(ptype)
if (c < *p) return !negated;
if (c == *p++) return negated;
}
+ /* LCOV_EXCL_START */
PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */
break;
+ /* LCOV_EXCL_STOP */
/* Haven't yet thought these through. */
@@ -806,21 +806,21 @@ for(;;)
case OP_NOT_DIGIT:
invert_bits = TRUE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_DIGIT:
set2 = (const uint8_t *)(cb->cbits + cbit_digit);
break;
case OP_NOT_WHITESPACE:
invert_bits = TRUE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_WHITESPACE:
set2 = (const uint8_t *)(cb->cbits + cbit_space);
break;
case OP_NOT_WORDCHAR:
invert_bits = TRUE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_WORDCHAR:
set2 = (const uint8_t *)(cb->cbits + cbit_word);
break;
@@ -1103,7 +1103,7 @@ for(;;)
case OP_NCLASS:
if (chr > 255) return FALSE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_CLASS:
if (chr > 255) break;
@@ -1141,8 +1141,10 @@ for(;;)
if (list[1] == 0) return TRUE;
}
+/* LCOV_EXCL_START */
PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */
return FALSE; /* Avoid compiler warnings */
+/* LCOV_EXCL_STOP */
}
@@ -1181,11 +1183,13 @@ for (;;)
{
c = *code;
+ /* LCOV_EXCL_START */
if (c >= OP_TABLE_LENGTH)
{
PCRE2_DEBUG_UNREACHABLE();
return -1; /* Something gone wrong */
}
+ /* LCOV_EXCL_STOP */
if (c >= OP_STAR && c <= OP_TYPEPOSUPTO)
{
diff --git a/src/3rdparty/pcre2/src/pcre2_chartables.c b/src/3rdparty/pcre2/src/pcre2_chartables.c
index 7362c3f2345..29f9200010c 100644
--- a/src/3rdparty/pcre2/src/pcre2_chartables.c
+++ b/src/3rdparty/pcre2/src/pcre2_chartables.c
@@ -19,10 +19,6 @@ PCRE2 is configured with --enable-rebuild-chartables. However, you can run
pcre2_dftables manually with the -L option to build tables using the LC_ALL
locale. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
const uint8_t PRIV(default_tables)[] = {
diff --git a/src/3rdparty/pcre2/src/pcre2_chkdint.c b/src/3rdparty/pcre2/src/pcre2_chkdint.c
index 70830236999..7aeb6405743 100644
--- a/src/3rdparty/pcre2/src/pcre2_chkdint.c
+++ b/src/3rdparty/pcre2/src/pcre2_chkdint.c
@@ -37,16 +37,16 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
+
/* This file contains functions to implement checked integer operation */
-#ifndef PCRE2_PCRE2TEST
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#ifndef PCRE2_PCRE2TEST
#include "pcre2_internal.h"
#endif
+
+
/*************************************************
* Checked Integer Multiplication *
*************************************************/
diff --git a/src/3rdparty/pcre2/src/pcre2_compile.c b/src/3rdparty/pcre2/src/pcre2_compile.c
index 0ffac8939cb..f126e41b7b0 100644
--- a/src/3rdparty/pcre2/src/pcre2_compile.c
+++ b/src/3rdparty/pcre2/src/pcre2_compile.c
@@ -39,16 +39,14 @@ POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "pcre2_compile.h"
+
+
#define NLBLOCK cb /* Block containing newline information */
#define PSSTART start_pattern /* Field containing processed string start */
#define PSEND end_pattern /* Field containing processed string end */
-#include "pcre2_compile.h"
-
/* In rare error cases debugging might require calling pcre2_printint(). */
#if 0
@@ -57,7 +55,15 @@ POSSIBILITY OF SUCH DAMAGE.
#else
#define PRINTABLE(c) ((c) >= 32 && (c) < 127)
#endif
-#include "pcre2_printint.c"
+#define CHAR_OUTPUT(c) (c)
+#define CHAR_OUTPUT_HEX(c) (c)
+#define CHAR_INPUT(c) (c)
+#define CHAR_INPUT_HEX(c) (c)
+#include "pcre2_printint_inc.h"
+#undef PRINTABLE
+#undef CHAR_OUTPUT
+#undef CHAR_OUTPUT_HEX
+#undef CHAR_INPUT
#define DEBUG_CALL_PRINTINT
#endif
@@ -84,30 +90,6 @@ by defining macros in order to minimize #if usage. */
#endif
#endif
-/* Macros to store and retrieve a PCRE2_SIZE value in the parsed pattern, which
-consists of uint32_t elements. Assume that if uint32_t can't hold it, two of
-them will be able to (i.e. assume a 64-bit world). */
-
-#if PCRE2_SIZE_MAX <= UINT32_MAX
-#define PUTOFFSET(s,p) *p++ = s
-#define GETOFFSET(s,p) s = *p++
-#define GETPLUSOFFSET(s,p) s = *(++p)
-#define READPLUSOFFSET(s,p) s = p[1]
-#define SKIPOFFSET(p) p++
-#define SIZEOFFSET 1
-#else
-#define PUTOFFSET(s,p) \
- { *p++ = (uint32_t)(s >> 32); *p++ = (uint32_t)(s & 0xffffffff); }
-#define GETOFFSET(s,p) \
- { s = ((PCRE2_SIZE)p[0] << 32) | (PCRE2_SIZE)p[1]; p += 2; }
-#define GETPLUSOFFSET(s,p) \
- { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; p += 2; }
-#define READPLUSOFFSET(s,p) \
- { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; }
-#define SKIPOFFSET(p) p += 2
-#define SIZEOFFSET 2
-#endif
-
/* Function definitions to allow mutual recursion */
static int
@@ -216,8 +198,8 @@ static unsigned char meta_extra_lengths[] = {
3, /* META_COND_VERSION */
SIZEOFFSET, /* META_OFFSET */
0, /* META_SCS */
- 1, /* META_SCS_NAME */
- 1, /* META_SCS_NUMBER */
+ 1, /* META_CAPTURE_NAME */
+ 1, /* META_CAPTURE_NUMBER */
0, /* META_DOLLAR */
0, /* META_DOT */
0, /* META_ESCAPE - one more for ESC_P and ESC_p */
@@ -400,10 +382,10 @@ static const short int escapes[] = {
/* 4 */ 0, /* 5 */ 0,
/* 6 */ 0, /* 7 */ 0,
/* 8 */ 0, /* 9 */ 0,
- /* : */ CHAR_COLON, /* ; */ CHAR_SEMICOLON,
- /* < */ CHAR_LESS_THAN_SIGN, /* = */ CHAR_EQUALS_SIGN,
- /* > */ CHAR_GREATER_THAN_SIGN, /* ? */ CHAR_QUESTION_MARK,
- /* @ */ CHAR_COMMERCIAL_AT, /* A */ -ESC_A,
+ /* : */ ESCAPES_FIRST+0x0a, /* ; */ ESCAPES_FIRST+0x0b,
+ /* < */ ESCAPES_FIRST+0x0c, /* = */ ESCAPES_FIRST+0x0d,
+ /* > */ ESCAPES_FIRST+0x0e, /* ? */ ESCAPES_FIRST+0x0f,
+ /* @ */ ESCAPES_FIRST+0x10, /* A */ -ESC_A,
/* B */ -ESC_B, /* C */ -ESC_C,
/* D */ -ESC_D, /* E */ -ESC_E,
/* F */ 0, /* G */ -ESC_G,
@@ -416,10 +398,10 @@ static const short int escapes[] = {
/* T */ 0, /* U */ 0,
/* V */ -ESC_V, /* W */ -ESC_W,
/* X */ -ESC_X, /* Y */ 0,
- /* Z */ -ESC_Z, /* [ */ CHAR_LEFT_SQUARE_BRACKET,
- /* \ */ CHAR_BACKSLASH, /* ] */ CHAR_RIGHT_SQUARE_BRACKET,
- /* ^ */ CHAR_CIRCUMFLEX_ACCENT, /* _ */ CHAR_UNDERSCORE,
- /* ` */ CHAR_GRAVE_ACCENT, /* a */ CHAR_BEL,
+ /* Z */ -ESC_Z, /* [ */ ESCAPES_FIRST+0x2b,
+ /* \ */ ESCAPES_FIRST+0x2c, /* ] */ ESCAPES_FIRST+0x2d,
+ /* ^ */ ESCAPES_FIRST+0x2e, /* _ */ ESCAPES_FIRST+0x2f,
+ /* ` */ ESCAPES_FIRST+0x30, /* a */ CHAR_BEL,
/* b */ -ESC_b, /* c */ 0,
/* d */ -ESC_d, /* e */ CHAR_ESC,
/* f */ CHAR_FF, /* g */ 0,
@@ -438,43 +420,94 @@ static const short int escapes[] = {
#else
/* This is the "abnormal" table for EBCDIC systems without UTF-8 support.
-It runs from 'a' to '9'. For some minimal testing of EBCDIC features, the code
-is sometimes compiled on an ASCII system. In this case, we must not use CHAR_a
-because it is defined as 'a', which of course picks up the ASCII value. */
+It runs from 'a' to '9'. Our EBCDIC support can be provided via the compiler,
+which can interpret character literals like 'a' or '[' in an EBCDIC codepage;
+in this case, there is wide variance between codepages on the interpretation of
+characters between the letters ('[' and '{' and so on are placed in all sorts of
+different positions in the table). Thankfully however, all EBCDIC codepages
+place the letters and digits in the same location, so we hardcode that here.
+Our EBCDIC support can also be provided via numeric literals instead of
+character literals, so either way, 'CHAR_a' will be 0x81 when PCRE2 is compiled
+in EBCDIC mode. */
-#if 'a' == 0x81 /* Check for a real EBCDIC environment */
#define ESCAPES_FIRST CHAR_a
#define ESCAPES_LAST CHAR_9
#define UPPER_CASE(c) (c+64)
-#else /* Testing in an ASCII environment */
-#define ESCAPES_FIRST ((unsigned char)'\x81') /* EBCDIC 'a' */
-#define ESCAPES_LAST ((unsigned char)'\xf9') /* EBCDIC '9' */
-#define UPPER_CASE(c) (c-32)
-#endif
static const short int escapes[] = {
-/* 80 */ CHAR_BEL, -ESC_b, 0, -ESC_d, CHAR_ESC, CHAR_FF, 0,
-/* 88 */ -ESC_h, 0, 0, '{', 0, 0, 0, 0,
-/* 90 */ 0, 0, -ESC_k, 0, 0, CHAR_LF, 0, -ESC_p,
-/* 98 */ 0, CHAR_CR, 0, '}', 0, 0, 0, 0,
-/* A0 */ 0, '~', -ESC_s, CHAR_HT, 0, -ESC_v, -ESC_w, 0,
-/* A8 */ 0, -ESC_z, 0, 0, 0, '[', 0, 0,
-/* B0 */ 0, 0, 0, 0, 0, 0, 0, 0,
-/* B8 */ 0, 0, 0, 0, 0, ']', '=', '-',
-/* C0 */ '{', -ESC_A, -ESC_B, -ESC_C, -ESC_D, -ESC_E, 0, -ESC_G,
-/* C8 */ -ESC_H, 0, 0, 0, 0, 0, 0, 0,
-/* D0 */ '}', 0, -ESC_K, 0, 0, -ESC_N, 0, -ESC_P,
-/* D8 */ -ESC_Q, -ESC_R, 0, 0, 0, 0, 0, 0,
-/* E0 */ '\\', 0, -ESC_S, 0, 0, -ESC_V, -ESC_W, -ESC_X,
-/* E8 */ 0, -ESC_Z, 0, 0, 0, 0, 0, 0,
-/* F0 */ 0, 0, 0, 0, 0, 0, 0, 0,
-/* F8 */ 0, 0
+ /* 0x81 a */ CHAR_BEL, /* 0x82 b */ -ESC_b,
+ /* 0x83 c */ 0, /* 0x84 d */ -ESC_d,
+ /* 0x85 e */ CHAR_ESC, /* 0x86 f */ CHAR_FF,
+ /* 0x87 g */ 0, /* 0x88 h */ -ESC_h,
+ /* 0x89 i */ 0, /* 0x8a */ ESCAPES_FIRST+0x09,
+ /* 0x8b */ ESCAPES_FIRST+0x0a, /* 0x8c */ ESCAPES_FIRST+0x0b,
+ /* 0x8d */ ESCAPES_FIRST+0x0c, /* 0x8e */ ESCAPES_FIRST+0x0d,
+ /* 0x8f */ ESCAPES_FIRST+0x0e, /* 0x90 */ ESCAPES_FIRST+0x0f,
+ /* 0x91 j */ 0, /* 0x92 k */ -ESC_k,
+ /* 0x93 l */ 0, /* 0x94 m */ 0,
+ /* 0x95 n */ CHAR_LF, /* 0x96 o */ 0,
+ /* 0x97 p */ -ESC_p, /* 0x98 q */ 0,
+ /* 0x99 r */ CHAR_CR, /* 0x9a */ ESCAPES_FIRST+0x19,
+ /* 0x9b */ ESCAPES_FIRST+0x1a, /* 0x9c */ ESCAPES_FIRST+0x1b,
+ /* 0x9d */ ESCAPES_FIRST+0x1c, /* 0x9e */ ESCAPES_FIRST+0x1d,
+ /* 0x9f */ ESCAPES_FIRST+0x1e, /* 0xa0 */ ESCAPES_FIRST+0x1f,
+ /* 0xa1 */ ESCAPES_FIRST+0x20, /* 0xa2 s */ -ESC_s,
+ /* 0xa3 t */ CHAR_HT, /* 0xa4 u */ 0,
+ /* 0xa5 v */ -ESC_v, /* 0xa6 w */ -ESC_w,
+ /* 0xa7 x */ 0, /* 0xa8 y */ 0,
+ /* 0xa9 z */ -ESC_z, /* 0xaa */ ESCAPES_FIRST+0x29,
+ /* 0xab */ ESCAPES_FIRST+0x2a, /* 0xac */ ESCAPES_FIRST+0x2b,
+ /* 0xad */ ESCAPES_FIRST+0x2c, /* 0xae */ ESCAPES_FIRST+0x2d,
+ /* 0xaf */ ESCAPES_FIRST+0x2e, /* 0xb0 */ ESCAPES_FIRST+0x2f,
+ /* 0xb1 */ ESCAPES_FIRST+0x30, /* 0xb2 */ ESCAPES_FIRST+0x31,
+ /* 0xb3 */ ESCAPES_FIRST+0x32, /* 0xb4 */ ESCAPES_FIRST+0x33,
+ /* 0xb5 */ ESCAPES_FIRST+0x34, /* 0xb6 */ ESCAPES_FIRST+0x35,
+ /* 0xb7 */ ESCAPES_FIRST+0x36, /* 0xb8 */ ESCAPES_FIRST+0x37,
+ /* 0xb9 */ ESCAPES_FIRST+0x38, /* 0xba */ ESCAPES_FIRST+0x39,
+ /* 0xbb */ ESCAPES_FIRST+0x3a, /* 0xbc */ ESCAPES_FIRST+0x3b,
+ /* 0xbd */ ESCAPES_FIRST+0x3c, /* 0xbe */ ESCAPES_FIRST+0x3d,
+ /* 0xbf */ ESCAPES_FIRST+0x3e, /* 0xc0 */ ESCAPES_FIRST+0x3f,
+ /* 0xc1 A */ -ESC_A, /* 0xc2 B */ -ESC_B,
+ /* 0xc3 C */ -ESC_C, /* 0xc4 D */ -ESC_D,
+ /* 0xc5 E */ -ESC_E, /* 0xc6 F */ 0,
+ /* 0xc7 G */ -ESC_G, /* 0xc8 H */ -ESC_H,
+ /* 0xc9 I */ 0, /* 0xca */ ESCAPES_FIRST+0x49,
+ /* 0xcb */ ESCAPES_FIRST+0x4a, /* 0xcc */ ESCAPES_FIRST+0x4b,
+ /* 0xcd */ ESCAPES_FIRST+0x4c, /* 0xce */ ESCAPES_FIRST+0x4d,
+ /* 0xcf */ ESCAPES_FIRST+0x4e, /* 0xd0 */ ESCAPES_FIRST+0x4f,
+ /* 0xd1 J */ 0, /* 0xd2 K */ -ESC_K,
+ /* 0xd3 L */ 0, /* 0xd4 M */ 0,
+ /* 0xd5 N */ -ESC_N, /* 0xd6 O */ 0,
+ /* 0xd7 P */ -ESC_P, /* 0xd8 Q */ -ESC_Q,
+ /* 0xd9 R */ -ESC_R, /* 0xda */ ESCAPES_FIRST+0x59,
+ /* 0xdb */ ESCAPES_FIRST+0x5a, /* 0xdc */ ESCAPES_FIRST+0x5b,
+ /* 0xdd */ ESCAPES_FIRST+0x5c, /* 0xde */ ESCAPES_FIRST+0x5d,
+ /* 0xdf */ ESCAPES_FIRST+0x5e, /* 0xe0 */ ESCAPES_FIRST+0x5f,
+ /* 0xe1 */ ESCAPES_FIRST+0x60, /* 0xe2 S */ -ESC_S,
+ /* 0xe3 T */ 0, /* 0xe4 U */ 0,
+ /* 0xe5 V */ -ESC_V, /* 0xe6 W */ -ESC_W,
+ /* 0xe7 X */ -ESC_X, /* 0xe8 Y */ 0,
+ /* 0xe9 Z */ -ESC_Z, /* 0xea */ ESCAPES_FIRST+0x69,
+ /* 0xeb */ ESCAPES_FIRST+0x6a, /* 0xec */ ESCAPES_FIRST+0x6b,
+ /* 0xed */ ESCAPES_FIRST+0x6c, /* 0xee */ ESCAPES_FIRST+0x6d,
+ /* 0xef */ ESCAPES_FIRST+0x6e, /* 0xf0 0 */ 0,
+ /* 0xf1 1 */ 0, /* 0xf2 2 */ 0,
+ /* 0xf3 3 */ 0, /* 0xf4 4 */ 0,
+ /* 0xf5 5 */ 0, /* 0xf6 6 */ 0,
+ /* 0xf7 7 */ 0, /* 0xf8 8 */ 0,
+ /* 0xf9 9 */ 0,
};
/* We also need a table of characters that may follow \c in an EBCDIC
environment for characters 0-31. */
-static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_";
+static unsigned char ebcdic_escape_c[] = {
+ CHAR_COMMERCIAL_AT, CHAR_A, CHAR_B, CHAR_C, CHAR_D, CHAR_E, CHAR_F, CHAR_G,
+ CHAR_H, CHAR_I, CHAR_J, CHAR_K, CHAR_L, CHAR_M, CHAR_N, CHAR_O, CHAR_P,
+ CHAR_Q, CHAR_R, CHAR_S, CHAR_T, CHAR_U, CHAR_V, CHAR_W, CHAR_X, CHAR_Y,
+ CHAR_Z, CHAR_LEFT_SQUARE_BRACKET, CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET,
+ CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE
+};
#endif /* EBCDIC */
@@ -1037,12 +1070,12 @@ for (;;)
fprintf(stderr, "META (*scan_substring:");
break;
- case META_SCS_NAME:
- fprintf(stderr, "META_SCS_NAME length=%d relative_offset=%d", *pptr++, (int)meta_arg);
+ case META_CAPTURE_NAME:
+ fprintf(stderr, "META_CAPTURE_NAME length=%d relative_offset=%d", *pptr++, (int)meta_arg);
break;
- case META_SCS_NUMBER:
- fprintf(stderr, "META_SCS_NUMBER %d relative_offset=%d", *pptr++, (int)meta_arg);
+ case META_CAPTURE_NUMBER:
+ fprintf(stderr, "META_CAPTURE_NUMBER %d relative_offset=%d", *pptr++, (int)meta_arg);
break;
case META_MARK:
@@ -1533,6 +1566,13 @@ else if ((i = escapes[c - ESCAPES_FIRST]) != 0)
goto COME_FROM_NU;
}
#endif
+
+ /* Improve error offset. */
+ ptr = p + 2;
+ while (ptr < ptrend && XDIGIT(*ptr) != 0xff) ptr++;
+ while (ptr < ptrend && (*ptr == CHAR_SPACE || *ptr == CHAR_HT)) ptr++;
+ if (ptr < ptrend && *ptr == CHAR_RIGHT_CURLY_BRACKET) ptr++;
+
*errorcodeptr = ERR93;
}
@@ -1541,6 +1581,7 @@ else if ((i = escapes[c - ESCAPES_FIRST]) != 0)
else if (isclass || cb == NULL)
{
+ ptr++; /* Skip over the opening brace */
*errorcodeptr = ERR37;
}
@@ -1551,7 +1592,10 @@ else if ((i = escapes[c - ESCAPES_FIRST]) != 0)
{
if (!read_repeat_counts(&p, ptrend, NULL, NULL, errorcodeptr) &&
*errorcodeptr == 0)
+ {
+ ptr++; /* Skip over the opening brace */
*errorcodeptr = ERR37;
+ }
}
}
}
@@ -1572,11 +1616,11 @@ else
if (cb == NULL)
{
- if (c < CHAR_0 ||
- (c > CHAR_9 && (c != CHAR_c && c != CHAR_o && c != CHAR_x && c != CHAR_g)))
+ if (!(c >= CHAR_0 && c <= CHAR_9) && c != CHAR_c && c != CHAR_o &&
+ c != CHAR_x && c != CHAR_g)
{
*errorcodeptr = ERR3;
- return 0;
+ goto EXIT;
}
alt_bsux = FALSE; /* Do not modify \x handling */
}
@@ -1601,7 +1645,9 @@ else
because otherwise \u{ 12} (for example) would be treated as u{12}. */
case CHAR_u:
- if (!alt_bsux) *errorcodeptr = ERR37; else
+ if (!alt_bsux)
+ *errorcodeptr = ERR37;
+ else
{
uint32_t xc;
@@ -1727,8 +1773,8 @@ else
if (p >= ptrend || *p != CHAR_GREATER_THAN_SIGN)
{
- /* not advancing ptr; report error at the \g character */
- *errorcodeptr = ERR57;
+ ptr = p;
+ *errorcodeptr = ERR119; /* Missing terminator for number */
break;
}
@@ -1764,8 +1810,8 @@ else
if (p >= ptrend || *p != CHAR_RIGHT_CURLY_BRACKET)
{
- /* not advancing ptr; report error at the \g character */
- *errorcodeptr = ERR57;
+ ptr = p;
+ *errorcodeptr = ERR119; /* Missing terminator for number */
break;
}
ptr = p + 1;
@@ -1890,7 +1936,7 @@ else
if (c >= CHAR_8) break;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* \0 always starts an octal number, but we may drop through to here with a
larger first octal digit. The original code used just to take the least
@@ -1922,12 +1968,12 @@ else
with optional spaces or tabs after { and before }. */
case CHAR_o:
- if (ptr >= ptrend || *ptr++ != CHAR_LEFT_CURLY_BRACKET)
+ if (ptr >= ptrend || *ptr != CHAR_LEFT_CURLY_BRACKET)
{
- ptr--;
*errorcodeptr = ERR55;
break;
}
+ ptr++;
while (ptr < ptrend && (*ptr == CHAR_SPACE || *ptr == CHAR_HT)) ptr++;
if (ptr >= ptrend || *ptr == CHAR_RIGHT_CURLY_BRACKET)
@@ -1962,19 +2008,19 @@ else
while (ptr < ptrend && *ptr >= CHAR_0 && *ptr <= CHAR_7) ptr++;
*errorcodeptr = ERR34;
}
- else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)
+ else if (utf && c >= 0xd800 && c <= 0xdfff &&
+ (xoptions & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)
{
- if (utf && c >= 0xd800 && c <= 0xdfff &&
- (xoptions & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)
- {
- ptr--;
- *errorcodeptr = ERR73;
- }
+ *errorcodeptr = ERR73;
+ }
+ else if (ptr < ptrend && *ptr == CHAR_RIGHT_CURLY_BRACKET)
+ {
+ ptr++;
}
else
{
- ptr--;
*errorcodeptr = ERR64;
+ goto ESCAPE_FAILED_FORWARD;
}
break;
@@ -2043,14 +2089,14 @@ else
while (ptr < ptrend && XDIGIT(*ptr) != 0xff) ptr++;
*errorcodeptr = ERR34;
}
- else if (ptr < ptrend && *ptr++ == CHAR_RIGHT_CURLY_BRACKET)
+ else if (utf && c >= 0xd800 && c <= 0xdfff &&
+ (xoptions & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)
{
- if (utf && c >= 0xd800 && c <= 0xdfff &&
- (xoptions & PCRE2_EXTRA_ALLOW_SURROGATE_ESCAPES) == 0)
- {
- ptr--;
- *errorcodeptr = ERR73;
- }
+ *errorcodeptr = ERR73;
+ }
+ else if (ptr < ptrend && *ptr == CHAR_RIGHT_CURLY_BRACKET)
+ {
+ ptr++;
}
/* If the sequence of hex digits (followed by optional space) does not
@@ -2060,8 +2106,8 @@ else
else
{
- ptr--;
*errorcodeptr = ERR67;
+ goto ESCAPE_FAILED_FORWARD;
}
} /* End of \x{} processing */
@@ -2113,11 +2159,7 @@ else
For testing the EBCDIC handling of \c in an ASCII environment, recognize
the EBCDIC value of 'c' explicitly. */
-#if defined EBCDIC && 'a' != 0x81
- case 0x83:
-#else
case CHAR_c:
-#endif
if (ptr >= ptrend)
{
*errorcodeptr = ERR2;
@@ -2132,7 +2174,7 @@ else
if (c < 32 || c > 126) /* Excludes all non-printable ASCII */
{
*errorcodeptr = ERR68;
- break;
+ goto ESCAPE_FAILED_FORWARD;
}
c ^= 0x40;
@@ -2143,14 +2185,20 @@ else
#else
if (c == CHAR_QUESTION_MARK)
- c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff;
+ c = (CHAR_BACKSLASH == 188 && CHAR_GRAVE_ACCENT == 74)? 0x5f : 0xff;
else
{
for (i = 0; i < 32; i++)
{
if (c == ebcdic_escape_c[i]) break;
}
- if (i < 32) c = i; else *errorcodeptr = ERR68;
+ if (i < 32)
+ c = i;
+ else
+ {
+ *errorcodeptr = ERR68;
+ goto ESCAPE_FAILED_FORWARD;
+ }
}
#endif /* EBCDIC */
@@ -2162,16 +2210,25 @@ else
default:
*errorcodeptr = ERR3;
- *ptrptr = ptr - 1; /* Point to the character at fault */
- return 0;
+ break;
}
}
/* Set the pointer to the next character before returning. */
+EXIT:
*ptrptr = ptr;
*chptr = c;
return escape;
+
+/* Some errors need to indicate the next character. */
+
+ESCAPE_FAILED_FORWARD:
+ptr++;
+#ifdef SUPPORT_UNICODE
+if (utf) FORWARDCHARTEST(ptr, ptrend);
+#endif
+goto EXIT;
}
@@ -2188,6 +2245,7 @@ after the final code unit of the escape sequence.
Arguments:
ptrptr the pattern position pointer
+ utf true if the input is UTF-encoded
negptr a boolean that is set TRUE for negation else FALSE
ptypeptr an unsigned int that is set to the type value
pdataptr an unsigned int that is set to the detailed property value
@@ -2198,18 +2256,23 @@ Returns: TRUE if the type value was found, or FALSE for an invalid type
*/
static BOOL
-get_ucp(PCRE2_SPTR *ptrptr, BOOL *negptr, uint16_t *ptypeptr,
+get_ucp(PCRE2_SPTR *ptrptr, BOOL utf, BOOL *negptr, uint16_t *ptypeptr,
uint16_t *pdataptr, int *errorcodeptr, compile_block *cb)
{
-PCRE2_UCHAR c;
-PCRE2_SIZE i, bot, top;
+uint32_t c;
+ptrdiff_t i;
+PCRE2_SIZE bot, top;
PCRE2_SPTR ptr = *ptrptr;
PCRE2_UCHAR name[50];
PCRE2_UCHAR *vptr = NULL;
uint16_t ptscript = PT_NOTSCRIPT;
+#ifndef MAYBE_UTF_MULTI
+(void)utf; /* Avoid compiler warning */
+#endif
+
if (ptr >= cb->end_pattern) goto ERROR_RETURN;
-c = *ptr++;
+GETCHARINCTEST(c, ptr);
*negptr = FALSE;
/* \P or \p can be followed by a name in {}, optionally preceded by ^ for
@@ -2230,15 +2293,14 @@ if (c == CHAR_LEFT_CURLY_BRACKET)
REDO:
if (ptr >= cb->end_pattern) goto ERROR_RETURN;
- c = *ptr++;
+ GETCHARINCTEST(c, ptr);
/* Skip ignorable Unicode characters. */
- while (c == CHAR_UNDERSCORE || c == CHAR_MINUS || c == CHAR_SPACE ||
- (c >= CHAR_HT && c <= CHAR_CR))
+ if (c == CHAR_UNDERSCORE || c == CHAR_MINUS || c == CHAR_SPACE ||
+ (c >= CHAR_HT && c <= CHAR_CR))
{
- if (ptr >= cb->end_pattern) goto ERROR_RETURN;
- c = *ptr++;
+ goto REDO;
}
/* The first significant character being circumflex negates the meaning of
@@ -2506,7 +2568,7 @@ return -1;
the name of a subpattern or a (*VERB) or an (*alpha_assertion). The initial
pointer must be to the preceding character. If that character is '*' we are
reading a verb or alpha assertion name. The pointer is updated to point after
-the name, for a VERB or alpha assertion name, or after tha name's terminator
+the name, for a VERB or alpha assertion name, or after the name's terminator
for a subpattern name. Returning both the offset and the name pointer is
redundant information, but some callers use one and some the other, so it is
simplest just to return both. When the name is in braces, spaces and tabs are
@@ -2559,12 +2621,14 @@ by Unicode properties, and underscores, but must not start with a digit. */
if (utf && is_group)
{
uint32_t c, type;
+ PCRE2_SPTR p = ptr;
- GETCHAR(c, ptr);
+ GETCHARINC(c, p); /* Peek at next character */
type = UCD_CHARTYPE(c);
if (type == ucp_Nd)
{
+ ptr = p;
*errorcodeptr = ERR44;
goto FAILED;
}
@@ -2573,10 +2637,9 @@ if (utf && is_group)
{
if (type != ucp_Nd && PRIV(ucp_gentype)[type] != ucp_L &&
c != CHAR_UNDERSCORE) break;
- ptr++;
- FORWARDCHARTEST(ptr, ptrend);
- if (ptr >= ptrend) break;
- GETCHAR(c, ptr);
+ ptr = p; /* Accept character and peek again */
+ if (p >= ptrend) break;
+ GETCHARINC(c, p);
type = UCD_CHARTYPE(c);
}
}
@@ -2592,6 +2655,7 @@ won't be recognized. */
{
if (is_group && IS_DIGIT(*ptr))
{
+ ++ptr;
*errorcodeptr = ERR44;
goto FAILED;
}
@@ -2604,7 +2668,7 @@ won't be recognized. */
/* Check name length */
-if (ptr > *nameptr + MAX_NAME_SIZE)
+if (ptr - *nameptr > MAX_NAME_SIZE)
{
*errorcodeptr = ERR48;
goto FAILED;
@@ -2623,12 +2687,15 @@ if (is_group)
}
if (is_braced)
while (ptr < ptrend && (*ptr == CHAR_SPACE || *ptr == CHAR_HT)) ptr++;
- if (ptr >= ptrend || *ptr != (PCRE2_UCHAR)terminator)
+ if (terminator != 0)
{
- *errorcodeptr = ERR42;
- goto FAILED;
+ if (ptr >= ptrend || *ptr != (PCRE2_UCHAR)terminator)
+ {
+ *errorcodeptr = ERR42;
+ goto FAILED;
+ }
+ ptr++;
}
- ptr++;
}
*ptrptr = ptr;
@@ -2641,6 +2708,128 @@ return FALSE;
+/**************************************************
+* Parse capturing bracket argument list *
+**************************************************/
+
+/* Reads a list of capture references. The references
+can be numbers or names.
+
+Arguments:
+ ptrptr points to the character pointer variable
+ ptrend points to the end of the input string
+ utf true if the input is UTF-encoded
+ parsed_pattern the parsed pattern pointer
+ offset last known offset
+ errcodeptr where to put an error code
+ cb pointer to the compile data block
+
+Returns: updated parsed_pattern pointer on success
+ NULL otherwise
+*/
+
+static uint32_t *
+parse_capture_list(PCRE2_SPTR *ptrptr, PCRE2_SPTR ptrend,
+ BOOL utf, uint32_t *parsed_pattern, PCRE2_SIZE offset,
+ int *errorcodeptr, compile_block *cb)
+{
+PCRE2_SIZE next_offset;
+PCRE2_SPTR ptr = *ptrptr;
+PCRE2_SPTR name;
+PCRE2_UCHAR terminator;
+uint32_t meta, namelen;
+int i;
+
+if (ptr >= ptrend || *ptr != CHAR_LEFT_PARENTHESIS)
+ {
+ *errorcodeptr = ERR118;
+ goto FAILED;
+ }
+
+for (;;)
+ {
+ ptr++;
+ next_offset = (PCRE2_SIZE)(ptr - cb->start_pattern);
+
+ if (ptr >= ptrend)
+ {
+ *errorcodeptr = ERR117;
+ goto FAILED;
+ }
+
+ /* Handle [+-]number cases */
+ if (read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61,
+ &i, errorcodeptr))
+ {
+ PCRE2_ASSERT(i >= 0);
+ if (i <= 0)
+ {
+ *errorcodeptr = ERR15;
+ goto FAILED;
+ }
+ meta = META_CAPTURE_NUMBER;
+ namelen = (uint32_t)i;
+ }
+ else if (*errorcodeptr != 0) goto FAILED; /* Number too big */
+ else
+ {
+ /* Handle 'name' or <name> cases. */
+ if (*ptr == CHAR_LESS_THAN_SIGN)
+ terminator = CHAR_GREATER_THAN_SIGN;
+ else if (*ptr == CHAR_APOSTROPHE)
+ terminator = CHAR_APOSTROPHE;
+ else
+ {
+ *errorcodeptr = ERR117;
+ goto FAILED;
+ }
+
+ if (!read_name(&ptr, ptrend, utf, terminator, &next_offset,
+ &name, &namelen, errorcodeptr, cb)) goto FAILED;
+
+ meta = META_CAPTURE_NAME;
+ }
+
+ PCRE2_ASSERT(next_offset > 0);
+ if (offset == 0 || (next_offset - offset) >= 0x10000)
+ {
+ *parsed_pattern++ = META_OFFSET;
+ PUTOFFSET(next_offset, parsed_pattern);
+ offset = next_offset;
+ }
+
+ /* The offset is encoded as a relative offset, because for some
+ inputs such as ",2" in (1,2,3), we only have space for two uint32_t
+ values, and an opcode and absolute offset may require three uint32_t
+ values. */
+ *parsed_pattern++ = meta | (uint32_t)(next_offset - offset);
+ *parsed_pattern++ = namelen;
+ offset = next_offset;
+
+ if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
+
+ if (*ptr == CHAR_RIGHT_PARENTHESIS) break;
+
+ if (*ptr != CHAR_COMMA)
+ {
+ *errorcodeptr = ERR24;
+ goto FAILED;
+ }
+ }
+
+*ptrptr = ptr + 1;
+return parsed_pattern;
+
+UNCLOSED_PARENTHESIS:
+*errorcodeptr = ERR14;
+
+FAILED:
+*ptrptr = ptr;
+return NULL;
+}
+
+
+
/*************************************************
* Manage callouts at start of cycle *
*************************************************/
@@ -2719,21 +2908,21 @@ switch(escape)
{
case ESC_D:
prop = ESC_P;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case ESC_d:
ascii_option = PCRE2_EXTRA_ASCII_BSD;
break;
case ESC_S:
prop = ESC_P;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case ESC_s:
ascii_option = PCRE2_EXTRA_ASCII_BSS;
break;
case ESC_W:
prop = ESC_P;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case ESC_w:
ascii_option = PCRE2_EXTRA_ASCII_BSW;
break;
@@ -2942,6 +3131,7 @@ uint32_t add_after_mark = 0;
uint16_t nest_depth = 0;
int16_t class_depth_m1 = -1; /* The m1 means minus 1. */
int16_t class_maxdepth_m1 = -1;
+uint16_t hash;
int after_manual_callout = 0;
int expect_cond_assert = 0;
int errorcode = 0;
@@ -2951,7 +3141,7 @@ BOOL inescq = FALSE;
BOOL inverbname = FALSE;
BOOL utf = (options & PCRE2_UTF) != 0;
BOOL auto_callout = (options & PCRE2_AUTO_CALLOUT) != 0;
-BOOL isdupname;
+BOOL is_dupname;
BOOL negate_class;
BOOL okquantifier = FALSE;
PCRE2_SPTR thisptr;
@@ -2996,12 +3186,15 @@ if ((options & PCRE2_LITERAL) != 0)
{
while (ptr < ptrend)
{
+ /* LCOV_EXCL_START */
if (parsed_pattern >= parsed_pattern_end)
{
PCRE2_DEBUG_UNREACHABLE();
errorcode = ERR63; /* Internal error (parsed pattern overflow) */
goto FAILED;
}
+ /* LCOV_EXCL_STOP */
+
thisptr = ptr;
GETCHARINCTEST(c, ptr);
if (auto_callout)
@@ -3067,6 +3260,7 @@ while (ptr < ptrend)
ptr_check = ptr;
#endif
+ /* LCOV_EXCL_START */
if (parsed_pattern >= parsed_pattern_end)
{
/* Weak pre-write check; only ensures parsed_pattern[0] is writeable
@@ -3075,6 +3269,7 @@ while (ptr < ptrend)
errorcode = ERR63; /* Internal error (parsed pattern overflow) */
goto FAILED;
}
+ /* LCOV_EXCL_STOP */
/* If the last time round this loop something was added, parsed_pattern will
no longer be equal to this_parsed_item. Remember where the previous item
@@ -3104,12 +3299,6 @@ while (ptr < ptrend)
}
else
{
- if (expect_cond_assert > 0) /* A literal is not allowed if we are */
- { /* expecting a conditional assertion, */
- ptr--; /* but an empty \Q\E sequence is OK. */
- errorcode = ERR28;
- goto FAILED;
- }
if (inverbname)
{ /* Don't use PARSED_LITERAL() because it */
#if PCRE2_CODE_UNIT_WIDTH == 32 /* sets okquantifier. */
@@ -3238,6 +3427,15 @@ while (ptr < ptrend)
{
if (*ptr == CHAR_Q || *ptr == CHAR_E)
{
+ /* A literal inside a \Q...\E is not allowed if we are expecting a
+ conditional assertion, but an empty \Q\E sequence is OK. */
+ if (expect_cond_assert > 0 && *ptr == CHAR_Q &&
+ !(ptrend - ptr >= 3 && ptr[1] == CHAR_BACKSLASH && ptr[2] == CHAR_E))
+ {
+ ptr--;
+ errorcode = ERR28;
+ goto FAILED;
+ }
inescq = *ptr == CHAR_Q;
ptr++;
continue;
@@ -3347,9 +3545,9 @@ while (ptr < ptrend)
if (!ok)
{
- ptr--; /* Adjust error offset */
errorcode = ERR28;
- goto FAILED;
+ if (expect_cond_assert == 2) goto FAILED;
+ goto FAILED_BACK;
}
}
@@ -3425,7 +3623,7 @@ while (ptr < ptrend)
else if (escape < 0)
{
- offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 1);
+ offset = (PCRE2_SIZE)(ptr - cb->start_pattern);
escape = -escape - 1;
*parsed_pattern++ = META_BACKREF | (uint32_t)escape;
if (escape < 10)
@@ -3523,7 +3721,7 @@ while (ptr < ptrend)
{
BOOL negated;
uint16_t ptype = 0, pdata = 0;
- if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb))
+ if (!get_ucp(&ptr, utf, &negated, &ptype, &pdata, &errorcode, cb))
goto ESCAPE_FAILED;
if (negated) escape = (escape == ESC_P)? ESC_p : ESC_P;
*parsed_pattern++ = META_ESCAPE + escape;
@@ -3565,10 +3763,11 @@ while (ptr < ptrend)
{
if (p >= ptrend || *p != terminator)
{
- errorcode = ERR57;
+ ptr = p;
+ errorcode = ERR119; /* Missing terminator for number */
goto ESCAPE_FAILED;
}
- ptr = p;
+ ptr = p + 1;
goto SET_RECURSION;
}
if (errorcode != 0) goto ESCAPE_FAILED;
@@ -3649,7 +3848,7 @@ while (ptr < ptrend)
if (!prev_okquantifier)
{
errorcode = ERR9;
- goto FAILED_BACK; // TODO https://github.com/PCRE2Project/pcre2/issues/549
+ goto FAILED;
}
/* Most (*VERB)s are not allowed to be quantified, but an ungreedy
@@ -3738,6 +3937,7 @@ while (ptr < ptrend)
check_posix_syntax(ptr, ptrend, &tempptr))
{
errorcode = (*ptr-- == CHAR_COLON)? ERR12 : ERR13;
+ ptr = tempptr + 2;
goto FAILED;
}
@@ -3965,8 +4165,9 @@ while (ptr < ptrend)
/* Validate nesting depth */
if (class_depth_m1 >= ECLASS_NEST_LIMIT - 1)
{
- errorcode = ERR107;
- goto FAILED; /* Classes too deeply nested */
+ ptr--; /* Point rightwards at the paren, same as ERR19. */
+ errorcode = ERR107; /* Classes too deeply nested */
+ goto FAILED;
}
/* Process the character class start. If the first character is '^', set
@@ -4081,7 +4282,8 @@ while (ptr < ptrend)
if (c == CHAR_RIGHT_SQUARE_BRACKET && class_depth_m1 != 0)
{
errorcode = ERR14;
- goto FAILED_BACK;
+ ptr--; /* Correct the offset */
+ goto FAILED;
}
if (c == CHAR_RIGHT_PARENTHESIS && class_depth_m1 < 1)
{
@@ -4301,7 +4503,6 @@ while (ptr < ptrend)
case ESC_R:
case ESC_X:
errorcode = ERR7;
- ptr--; // TODO https://github.com/PCRE2Project/pcre2/issues/549
goto FAILED;
case ESC_N: /* Not permitted by Perl either */
@@ -4336,7 +4537,7 @@ while (ptr < ptrend)
{
BOOL negated;
uint16_t ptype = 0, pdata = 0;
- if (!get_ucp(&ptr, &negated, &ptype, &pdata, &errorcode, cb))
+ if (!get_ucp(&ptr, utf, &negated, &ptype, &pdata, &errorcode, cb))
goto FAILED;
/* In caseless matching, particular characteristics Lu, Ll, and Lt
@@ -4362,9 +4563,11 @@ while (ptr < ptrend)
/* All others are not allowed in a class */
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
+ /* LCOV_EXCL_STOP */
case ESC_A:
case ESC_Z:
@@ -4373,7 +4576,6 @@ while (ptr < ptrend)
case ESC_K:
case ESC_C:
errorcode = ERR7;
- ptr--; // TODO https://github.com/PCRE2Project/pcre2/issues/549
goto FAILED;
}
@@ -4464,7 +4666,7 @@ while (ptr < ptrend)
else if (parsed_pattern[-2] > c) /* Check range is in order */
{
errorcode = ERR8;
- goto FAILED_BACK; // TODO https://github.com/PCRE2Project/pcre2/issues/549
+ goto FAILED;
}
else
{
@@ -4560,10 +4762,11 @@ while (ptr < ptrend)
vn = alasnames;
if (!read_name(&ptr, ptrend, utf, 0, &offset, &name, &namelen,
&errorcode, cb)) goto FAILED;
- if (ptr >= ptrend || *ptr != CHAR_COLON)
+ if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
+ if (*ptr != CHAR_COLON)
{
errorcode = ERR95; /* Malformed */
- goto FAILED;
+ goto FAILED_FORWARD;
}
/* Scan the table of alpha assertion names */
@@ -4598,10 +4801,12 @@ while (ptr < ptrend)
switch(meta)
{
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
errorcode = ERR89; /* Unknown code; should never occur because */
goto FAILED; /* the meta values come from a table above. */
+ /* LCOV_EXCL_STOP */
case META_ATOMIC:
goto ATOMIC_GROUP;
@@ -4616,87 +4821,12 @@ while (ptr < ptrend)
goto NEGATIVE_LOOK_AHEAD;
case META_SCS:
- if (++ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
-
- if (*ptr != CHAR_LEFT_PARENTHESIS)
- {
- errorcode = ERR15;
- goto FAILED;
- }
-
ptr++;
*parsed_pattern++ = META_SCS;
- /* Temporary variable, zero in the first iteration. */
- offset = 0;
-
- for (;;)
- {
- PCRE2_SIZE next_offset = (PCRE2_SIZE)(ptr - cb->start_pattern);
-
- /* Handle (scan_substring:([+-]number)... */
- if (read_number(&ptr, ptrend, cb->bracount, MAX_GROUP_NUMBER, ERR61,
- &i, &errorcode))
- {
- PCRE2_ASSERT(i >= 0);
- if (i <= 0)
- {
- errorcode = ERR15;
- goto FAILED;
- }
- meta = META_SCS_NUMBER;
- namelen = (uint32_t)i;
- }
- else if (errorcode != 0) goto FAILED; /* Number too big */
- else
- {
- if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
- /* Handle (*scan_substring:('name') or (*scan_substring:(<name>) */
- if (*ptr == CHAR_LESS_THAN_SIGN)
- terminator = CHAR_GREATER_THAN_SIGN;
- else if (*ptr == CHAR_APOSTROPHE)
- terminator = CHAR_APOSTROPHE;
- else
- {
- errorcode = ERR15;
- goto FAILED;
- }
-
- if (!read_name(&ptr, ptrend, utf, terminator, &next_offset,
- &name, &namelen, &errorcode, cb)) goto FAILED;
-
- meta = META_SCS_NAME;
- }
-
- PCRE2_ASSERT(next_offset > 0);
- if (offset == 0 || (next_offset - offset) >= 0x10000)
- {
- *parsed_pattern++ = META_OFFSET;
- PUTOFFSET(next_offset, parsed_pattern);
- offset = next_offset;
- }
-
- /* The offset is encoded as a relative offset, because for some
- inputs such as ",2" in (*scs:(1,2,3)...), we only have space for
- two uint32_t values, and an opcode and absolute offset may require
- three uint32_t values. */
- *parsed_pattern++ = meta | (uint32_t)(next_offset - offset);
- *parsed_pattern++ = namelen;
- offset = next_offset;
-
- if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS;
-
- if (*ptr == CHAR_RIGHT_PARENTHESIS) break;
-
- if (*ptr != CHAR_COMMA)
- {
- errorcode = ERR24;
- goto FAILED;
- }
-
- ptr++;
- }
- ptr++;
+ parsed_pattern = parse_capture_list(&ptr, ptrend, utf, parsed_pattern,
+ 0, &errorcode, cb);
+ if (parsed_pattern == NULL) goto FAILED;
goto POST_ASSERTION;
case META_LOOKBEHIND:
@@ -4923,7 +5053,6 @@ while (ptr < ptrend)
if (!hyphenok)
{
errorcode = ERR94;
- ptr--; /* Correct the offset */
goto FAILED;
}
optset = &unset;
@@ -4997,7 +5126,6 @@ while (ptr < ptrend)
default:
errorcode = ERR11;
- ptr--; /* Correct the offset */
goto FAILED;
}
}
@@ -5066,7 +5194,7 @@ while (ptr < ptrend)
if (*ptr != CHAR_EQUALS_SIGN)
{
errorcode = ERR41;
- goto FAILED;
+ goto FAILED_FORWARD;
}
if (!read_name(&ptr, ptrend, utf, CHAR_RIGHT_PARENTHESIS, &offset, &name,
&namelen, &errorcode, cb)) goto FAILED;
@@ -5082,23 +5210,30 @@ while (ptr < ptrend)
case CHAR_R:
i = 0; /* (?R) == (?R0) */
ptr++;
- if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)
+ if (ptr >= ptrend || (*ptr != CHAR_RIGHT_PARENTHESIS && *ptr != CHAR_LEFT_PARENTHESIS))
{
errorcode = ERR58;
goto FAILED;
}
+ terminator = CHAR_NUL;
goto SET_RECURSION;
/* An item starting (?- followed by a digit comes here via the "default"
case because (?- followed by a non-digit is an options setting. */
case CHAR_PLUS:
- if (ptrend - ptr < 2 || !IS_DIGIT(ptr[1]))
+ if (ptr + 1 >= ptrend)
+ {
+ ++ptr;
+ goto UNCLOSED_PARENTHESIS;
+ }
+ if (!IS_DIGIT(ptr[1]))
{
errorcode = ERR29; /* Missing number */
- goto FAILED;
+ ++ptr;
+ goto FAILED_FORWARD;
}
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case CHAR_0: case CHAR_1: case CHAR_2: case CHAR_3: case CHAR_4:
case CHAR_5: case CHAR_6: case CHAR_7: case CHAR_8: case CHAR_9:
@@ -5108,28 +5243,43 @@ while (ptr < ptrend)
MAX_GROUP_NUMBER, ERR61,
&i, &errorcode)) goto FAILED;
PCRE2_ASSERT(i >= 0); /* NB (?0) is permitted, represented by i=0 */
- if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)
- goto UNCLOSED_PARENTHESIS;
+ terminator = CHAR_NUL;
SET_RECURSION:
*parsed_pattern++ = META_RECURSE | (uint32_t)i;
offset = (PCRE2_SIZE)(ptr - cb->start_pattern);
- ptr++;
- PUTOFFSET(offset, parsed_pattern);
- okquantifier = TRUE;
- break; /* End of recursive call by number handling */
+ /* End of recursive call by number handling */
+ goto READ_RECURSION_ARGUMENTS;
/* ---- Recursion/subroutine calls by name ---- */
case CHAR_AMPERSAND:
RECURSE_BY_NAME:
- if (!read_name(&ptr, ptrend, utf, CHAR_RIGHT_PARENTHESIS, &offset, &name,
+ if (!read_name(&ptr, ptrend, utf, 0, &offset, &name,
&namelen, &errorcode, cb)) goto FAILED;
*parsed_pattern++ = META_RECURSE_BYNAME;
*parsed_pattern++ = namelen;
+ terminator = CHAR_NUL;
+
+ READ_RECURSION_ARGUMENTS:
PUTOFFSET(offset, parsed_pattern);
okquantifier = TRUE;
+
+ /* Arguments are not supported for \g construct. */
+ if (terminator != CHAR_NUL) break;
+
+ if (ptr < ptrend && *ptr == CHAR_LEFT_PARENTHESIS)
+ {
+ parsed_pattern = parse_capture_list(&ptr, ptrend, utf, parsed_pattern,
+ offset, &errorcode, cb);
+ if (parsed_pattern == NULL) goto FAILED;
+ }
+
+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)
+ goto UNCLOSED_PARENTHESIS;
+
+ ptr++;
break;
/* ---- Callout with numerical or string argument ---- */
@@ -5137,6 +5287,7 @@ while (ptr < ptrend)
case CHAR_C:
if ((xoptions & PCRE2_EXTRA_NEVER_CALLOUT) != 0)
{
+ ptr++;
errorcode = ERR103;
goto FAILED;
}
@@ -5189,7 +5340,7 @@ while (ptr < ptrend)
if (delimiter == 0)
{
errorcode = ERR82;
- goto FAILED;
+ goto FAILED_FORWARD;
}
*parsed_pattern = META_CALLOUT_STRING;
@@ -5333,20 +5484,31 @@ while (ptr < ptrend)
references its argument twice. */
if (*ptr != CHAR_EQUALS_SIGN || (ptr++, !IS_DIGIT(*ptr)))
- goto BAD_VERSION_CONDITION;
+ {
+ errorcode = ERR79;
+ if (!ge) goto FAILED_FORWARD;
+ goto FAILED;
+ }
if (!read_number(&ptr, ptrend, -1, 1000, ERR79, &major, &errorcode))
goto FAILED;
- if (ptr >= ptrend) goto BAD_VERSION_CONDITION;
- if (*ptr == CHAR_DOT)
+ if (ptr < ptrend && *ptr == CHAR_DOT)
{
- if (++ptr >= ptrend || !IS_DIGIT(*ptr)) goto BAD_VERSION_CONDITION;
- minor = (*ptr++ - CHAR_0) * 10;
- if (ptr >= ptrend) goto BAD_VERSION_CONDITION;
- if (IS_DIGIT(*ptr)) minor += *ptr++ - CHAR_0;
- if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)
- goto BAD_VERSION_CONDITION;
+ if (++ptr >= ptrend || !IS_DIGIT(*ptr))
+ {
+ errorcode = ERR79;
+ if (ptr < ptrend) goto FAILED_FORWARD;
+ goto FAILED;
+ }
+ if (!read_number(&ptr, ptrend, -1, 1000, ERR79, &minor, &errorcode))
+ goto FAILED;
+ }
+ if (ptr >= ptrend || *ptr != CHAR_RIGHT_PARENTHESIS)
+ {
+ errorcode = ERR79;
+ if (ptr < ptrend) goto FAILED_FORWARD;
+ goto FAILED;
}
*parsed_pattern++ = META_COND_VERSION;
@@ -5380,6 +5542,7 @@ while (ptr < ptrend)
terminator = CHAR_RIGHT_PARENTHESIS;
ptr--; /* Point to char before name */
}
+
if (!read_name(&ptr, ptrend, utf, terminator, &offset, &name, &namelen,
&errorcode, cb)) goto FAILED;
@@ -5559,21 +5722,37 @@ while (ptr < ptrend)
scanning in case this is a duplicate with the same number. For
non-duplicate names, give an error if the number is duplicated. */
- isdupname = FALSE;
+ is_dupname = FALSE;
+ hash = PRIV(compile_get_hash_from_name)(name, namelen);
ng = cb->named_groups;
for (i = 0; i < cb->names_found; i++, ng++)
{
- if (namelen == ng->length &&
+ if (namelen == ng->length && hash == NAMED_GROUP_GET_HASH(ng) &&
PRIV(strncmp)(name, ng->name, (PCRE2_SIZE)namelen) == 0)
{
+ /* When a bracket is referenced by the same name multiple
+ times, is not considered as a duplicate and ignored. */
if (ng->number == cb->bracount) break;
if ((options & PCRE2_DUPNAMES) == 0)
{
errorcode = ERR43;
goto FAILED;
}
- isdupname = ng->isdup = TRUE; /* Mark as a duplicate */
+
+ ng->hash_dup |= NAMED_GROUP_IS_DUPNAME;
+ is_dupname = TRUE; /* Mark as a duplicate */
cb->dupnames = TRUE; /* Duplicate names exist */
+
+ /* The entry represents a duplicate. */
+ name = ng->name;
+ namelen = 0;
+
+ /* Even duplicated names may refer to the same
+ capture index. These references are also ignored. */
+ for (; i < cb->names_found; i++, ng++)
+ if (ng->name == name && ng->number == cb->bracount)
+ break;
+ break;
}
else if (ng->number == cb->bracount)
{
@@ -5582,7 +5761,8 @@ while (ptr < ptrend)
}
}
- if (i < cb->names_found) break; /* Ignore duplicate with same number */
+ /* Ignore duplicate with same number. */
+ if (i < cb->names_found) break;
/* Increase the list size if necessary */
@@ -5608,11 +5788,13 @@ while (ptr < ptrend)
}
/* Add this name to the list */
+ if (is_dupname)
+ hash |= NAMED_GROUP_IS_DUPNAME;
cb->named_groups[cb->names_found].name = name;
cb->named_groups[cb->names_found].length = (uint16_t)namelen;
cb->named_groups[cb->names_found].number = cb->bracount;
- cb->named_groups[cb->names_found].isdup = (uint16_t)isdupname;
+ cb->named_groups[cb->names_found].hash_dup = hash;
cb->names_found++;
break;
@@ -5678,7 +5860,7 @@ while (ptr < ptrend)
if (nest_depth == 0) /* Unmatched closing parenthesis */
{
errorcode = ERR22;
- goto FAILED_BACK; // TODO https://github.com/PCRE2Project/pcre2/issues/549
+ goto FAILED;
}
nest_depth--;
*parsed_pattern++ = META_KET;
@@ -5723,12 +5905,14 @@ else if ((xoptions & PCRE2_EXTRA_MATCH_WORD) != 0)
/* Terminate the parsed pattern, then return success if all groups are closed.
Otherwise we have unclosed parentheses. */
+/* LCOV_EXCL_START */
if (parsed_pattern >= parsed_pattern_end)
{
PCRE2_DEBUG_UNREACHABLE();
errorcode = ERR63; /* Internal error (parsed pattern overflow) */
goto FAILED;
}
+/* LCOV_EXCL_STOP */
*parsed_pattern = META_END;
if (nest_depth == 0) return 0;
@@ -5746,12 +5930,18 @@ return errorcode;
FAILED_BACK:
ptr--;
+#ifdef SUPPORT_UNICODE
+if (utf) BACKCHAR(ptr);
+#endif
goto FAILED;
-/* This failure happens several times. */
+/* Some errors need to indicate the next character. */
-BAD_VERSION_CONDITION:
-errorcode = ERR79;
+FAILED_FORWARD:
+ptr++;
+#ifdef SUPPORT_UNICODE
+if (utf) FORWARDCHARTEST(ptr, ptrend);
+#endif
goto FAILED;
}
@@ -5795,7 +5985,7 @@ for (;;)
case OP_UCP_WORD_BOUNDARY:
case OP_NOT_UCP_WORD_BOUNDARY:
if (!skipassert) return code;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_CALLOUT:
case OP_CREF:
@@ -5836,78 +6026,9 @@ for (;;)
}
}
+/* LCOV_EXCL_START */
PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */
-}
-
-
-
-/*************************************************
-* Find details of duplicate group names *
-*************************************************/
-
-/* This is called from compile_branch() when it needs to know the index and
-count of duplicates in the names table when processing named backreferences,
-either directly, or as conditions.
-
-Arguments:
- name points to the name
- length the length of the name
- indexptr where to put the index
- countptr where to put the count of duplicates
- errorcodeptr where to put an error code
- cb the compile block
-
-Returns: TRUE if OK, FALSE if not, error code set
-*/
-
-static BOOL
-find_dupname_details(PCRE2_SPTR name, uint32_t length, int *indexptr,
- int *countptr, int *errorcodeptr, compile_block *cb)
-{
-uint32_t i, groupnumber;
-int count;
-PCRE2_UCHAR *slot = cb->name_table;
-
-/* Find the first entry in the table */
-
-for (i = 0; i < cb->names_found; i++)
- {
- if (PRIV(strncmp)(name, slot+IMM2_SIZE, length) == 0 &&
- slot[IMM2_SIZE+length] == 0) break;
- slot += cb->name_entry_size;
- }
-
-/* This should not occur, because this function is called only when we know we
-have duplicate names. Give an internal error. */
-
-if (i >= cb->names_found)
- {
- PCRE2_DEBUG_UNREACHABLE();
- *errorcodeptr = ERR53;
- cb->erroroffset = name - cb->start_pattern;
- return FALSE;
- }
-
-/* Record the index and then see how many duplicates there are, updating the
-backref map and maximum back reference as we do. */
-
-*indexptr = i;
-count = 0;
-
-for (;;)
- {
- count++;
- groupnumber = GET2(slot,0);
- cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;
- if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;
- if (++i >= cb->names_found) break;
- slot += cb->name_entry_size;
- if (PRIV(strncmp)(name, slot+IMM2_SIZE, length) != 0 ||
- (slot+IMM2_SIZE)[length] != 0) break;
- }
-
-*countptr = count;
-return TRUE;
+/* LCOV_EXCL_STOP */
}
@@ -5965,7 +6086,7 @@ uint32_t meta, meta_arg;
uint32_t firstcuflags, reqcuflags;
uint32_t zeroreqcuflags, zerofirstcuflags;
uint32_t req_caseopt, reqvary, tempreqvary;
-/* Some opcodes, such as META_SCS_NUMBER or META_SCS_NAME,
+/* Some opcodes, such as META_CAPTURE_NUMBER or META_CAPTURE_NAME,
depends on the previous value of offset. */
PCRE2_SIZE offset = 0;
PCRE2_SIZE length_prevgroup = 0;
@@ -6042,16 +6163,21 @@ for (;; pptr++)
if (lengthptr != NULL)
{
+ /* LCOV_EXCL_START */
+ if (code >= cb->start_workspace + cb->workspace_size)
+ {
+ PCRE2_DEBUG_UNREACHABLE();
+ *errorcodeptr = ERR52; /* Over-ran workspace - internal error */
+ cb->erroroffset = 0;
+ return 0;
+ }
+ /* LCOV_EXCL_STOP */
+
if (code > cb->start_workspace + cb->workspace_size -
WORK_SIZE_SAFETY_MARGIN) /* Check for overrun */
{
- if (code >= cb->start_workspace + cb->workspace_size)
- {
- PCRE2_DEBUG_UNREACHABLE();
- *errorcodeptr = ERR52; /* Over-ran workspace - internal error */
- }
- else
- *errorcodeptr = ERR86;
+ *errorcodeptr = ERR86; /* Pattern too complicated */
+ cb->erroroffset = 0;
return 0;
}
@@ -6072,12 +6198,14 @@ for (;; pptr++)
if (OFLOW_MAX - *lengthptr < (PCRE2_SIZE)(code - orig_code))
{
*errorcodeptr = ERR20; /* Integer overflow */
+ cb->erroroffset = 0;
return 0;
}
*lengthptr += (PCRE2_SIZE)(code - orig_code);
if (*lengthptr > MAX_PATTERN_SIZE)
{
*errorcodeptr = ERR20; /* Pattern is too large */
+ cb->erroroffset = 0;
return 0;
}
code = orig_code;
@@ -6380,7 +6508,7 @@ for (;; pptr++)
case META_PRUNE:
case META_SKIP:
cb->had_pruneorskip = TRUE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case META_COMMIT:
case META_FAIL:
*code++ = verbops[(meta - META_MARK) >> 16];
@@ -6405,7 +6533,7 @@ for (;; pptr++)
case META_PRUNE_ARG:
case META_SKIP_ARG:
cb->had_pruneorskip = TRUE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case META_MARK:
case META_COMMIT_ARG:
VERB_ARG:
@@ -6450,8 +6578,63 @@ for (;; pptr++)
req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS : 0;
break;
+ /* ===================================================================*/
+ /* Handle scan substring. Scan substring assertion starts with META_SCS,
+ which recursively calls compile_branch. The first opcode processed by
+ this recursive call is always META_OFFSET. */
+
case META_OFFSET:
- GETPLUSOFFSET(offset, pptr);
+ if (lengthptr != NULL)
+ {
+ pptr = PRIV(compile_parse_scan_substr_args)(pptr, errorcodeptr, cb, lengthptr);
+ if (pptr == NULL)
+ return 0;
+ break;
+ }
+
+ while (TRUE)
+ {
+ int count, index;
+ named_group *ng;
+
+ switch (META_CODE(*pptr))
+ {
+ case META_OFFSET:
+ pptr++;
+ SKIPOFFSET(pptr);
+ continue;
+
+ case META_CAPTURE_NAME:
+ ng = cb->named_groups + pptr[1];
+ pptr += 2;
+ count = 0;
+ index = 0;
+
+ if (!PRIV(compile_find_dupname_details)(ng->name, ng->length, &index,
+ &count, errorcodeptr, cb)) return 0;
+
+ code[0] = OP_DNCREF;
+ PUT2(code, 1, index);
+ PUT2(code, 1 + IMM2_SIZE, count);
+ code += 1 + 2 * IMM2_SIZE;
+ continue;
+
+ case META_CAPTURE_NUMBER:
+ pptr += 2;
+ if (pptr[-1] == 0) continue;
+
+ code[0] = OP_CREF;
+ PUT2(code, 1, pptr[-1]);
+ code += 1 + IMM2_SIZE;
+ continue;
+
+ default:
+ break;
+ }
+
+ break;
+ }
+ --pptr;
break;
case META_SCS:
@@ -6470,19 +6653,17 @@ for (;; pptr++)
case META_COND_RNUMBER: /* (?(Rdigits) */
case META_COND_NAME: /* (?(name) or (?'name') or ?(<name>) */
case META_COND_RNAME: /* (?(R&name) - test for recursion */
- case META_SCS_NAME: /* Name of scan substring */
bravalue = OP_COND;
+
+ if (lengthptr != NULL)
{
- int count, index;
- unsigned int i;
+ uint32_t i;
PCRE2_SPTR name;
- named_group *ng = cb->named_groups;
+ named_group *ng;
+ uint32_t *start_pptr = pptr;
uint32_t length = *(++pptr);
- if (meta == META_SCS_NAME)
- offset += meta_arg;
- else
- GETPLUSOFFSET(offset, pptr);
+ GETPLUSOFFSET(offset, pptr);
name = cb->start_pattern + offset;
/* In the first pass, the names generated in the pre-pass are available,
@@ -6491,11 +6672,9 @@ for (;; pptr++)
this name is duplicated. If it is not duplicated, we can handle it as a
numerical group. */
- for (i = 0; i < cb->names_found; i++, ng++)
- if (length == ng->length &&
- PRIV(strncmp)(name, ng->name, length) == 0) break;
+ ng = PRIV(compile_find_named_group)(name, length, cb);
- if (i >= cb->names_found)
+ if (ng == NULL)
{
/* If the name was not found we have a bad reference, unless we are
dealing with R<digits>, which is treated as a recursion test by
@@ -6528,61 +6707,88 @@ for (;; pptr++)
translated into RREF_ANY (which is 0xffff). */
if (groupnumber == 0) groupnumber = RREF_ANY;
- code[1+LINK_SIZE] = OP_RREF;
- PUT2(code, 2+LINK_SIZE, groupnumber);
+ PCRE2_ASSERT(start_pptr[0] == META_COND_RNUMBER);
+ start_pptr[1] = groupnumber;
skipunits = 1+IMM2_SIZE;
goto GROUP_PROCESS_NOTE_EMPTY;
}
- else if (!ng->isdup)
+
+ /* From here on, we know we have a name (not a number),
+ so treat META_COND_RNUMBER the same as META_COND_NAME. */
+ if (meta == META_COND_RNUMBER) meta = META_COND_NAME;
+
+ if ((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) == 0)
{
- /* Otherwise found a duplicated name */
+ /* Found a non-duplicated name. Since it is a global,
+ it is enough to update it in the pre-processing phase. */
if (ng->number > cb->top_backref) cb->top_backref = ng->number;
- if (meta == META_SCS_NAME)
- {
- code[0] = OP_CREF;
- PUT2(code, 1, ng->number);
- code += 1+IMM2_SIZE;
- break;
- }
+ start_pptr[0] = meta;
+ start_pptr[1] = ng->number;
- code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF;
- PUT2(code, 2+LINK_SIZE, ng->number);
- skipunits = 1+IMM2_SIZE;
- if (meta != META_SCS_NAME) goto GROUP_PROCESS_NOTE_EMPTY;
- cb->assert_depth += 1;
- goto GROUP_PROCESS;
+ skipunits = 1 + IMM2_SIZE;
+ goto GROUP_PROCESS_NOTE_EMPTY;
}
/* We have a duplicated name. In the compile pass we have to search the
main table in order to get the index and count values. */
- count = 0; /* Values for first pass (avoids compiler warning) */
- index = 0;
- if (lengthptr == NULL && !find_dupname_details(name, length, &index,
- &count, errorcodeptr, cb)) return 0;
+ start_pptr[0] = meta | 1;
+ start_pptr[1] = (uint32_t)(ng - cb->named_groups);
- if (meta == META_SCS_NAME)
+ /* A duplicated name was found. Note that if an R<digits> name is found
+ (META_COND_RNUMBER), it is a reference test, not a recursion test. */
+ skipunits = 1 + 2 * IMM2_SIZE;
+ }
+ else
+ {
+ /* Otherwise lengthptr equals to NULL,
+ which is the second phase of compilation. */
+ int count, index;
+ named_group *ng;
+
+ /* Generate code using the data
+ collected in the pre-processing phase. */
+
+ if (meta == META_COND_RNUMBER)
{
- code[0] = OP_DNCREF;
- PUT2(code, 1, index);
- PUT2(code, 1+IMM2_SIZE, count);
- code += 1+2*IMM2_SIZE;
- break;
+ code[1+LINK_SIZE] = OP_RREF;
+ PUT2(code, 2 + LINK_SIZE, pptr[1]);
+ skipunits = 1 + IMM2_SIZE;
+ pptr += 1 + SIZEOFFSET;
+ goto GROUP_PROCESS_NOTE_EMPTY;
+ }
+
+ if (meta_arg == 0)
+ {
+ code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_RREF : OP_CREF;
+ PUT2(code, 2 + LINK_SIZE, pptr[1]);
+ skipunits = 1 + IMM2_SIZE;
+ pptr += 1 + SIZEOFFSET;
+ goto GROUP_PROCESS_NOTE_EMPTY;
}
+ ng = cb->named_groups + pptr[1];
+ count = 0; /* Values for first pass (avoids compiler warning) */
+ index = 0;
+
+ /* The failed case is an internal error. */
+ if (!PRIV(compile_find_dupname_details)(ng->name, ng->length, &index,
+ &count, errorcodeptr, cb)) return 0;
+
/* A duplicated name was found. Note that if an R<digits> name is found
(META_COND_RNUMBER), it is a reference test, not a recursion test. */
- code[1+LINK_SIZE] = (meta == META_COND_RNAME)? OP_DNRREF : OP_DNCREF;
+ code[1 + LINK_SIZE] = (meta == META_COND_RNAME)? OP_DNRREF : OP_DNCREF;
/* Insert appropriate data values. */
- skipunits = 1+2*IMM2_SIZE;
- PUT2(code, 2+LINK_SIZE, index);
- PUT2(code, 2+LINK_SIZE+IMM2_SIZE, count);
+ PUT2(code, 2 + LINK_SIZE, index);
+ PUT2(code, 2 + LINK_SIZE + IMM2_SIZE, count);
+ skipunits = 1 + 2 * IMM2_SIZE;
+ pptr += 1 + SIZEOFFSET;
}
- PCRE2_ASSERT(meta != META_SCS_NAME);
+ PCRE2_ASSERT(meta != META_CAPTURE_NAME);
goto GROUP_PROCESS_NOTE_EMPTY;
/* The DEFINE condition is always false. Its internal groups may never
@@ -6599,12 +6805,8 @@ for (;; pptr++)
/* Conditional test of a group's being set. */
case META_COND_NUMBER:
- case META_SCS_NUMBER:
bravalue = OP_COND;
- if (meta == META_SCS_NUMBER)
- offset += meta_arg;
- else
- GETPLUSOFFSET(offset, pptr);
+ GETPLUSOFFSET(offset, pptr);
groupnumber = *(++pptr);
if (groupnumber > cb->bracount)
@@ -6615,14 +6817,6 @@ for (;; pptr++)
}
if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;
- if (meta == META_SCS_NUMBER)
- {
- code[0] = OP_CREF;
- PUT2(code, 1, groupnumber);
- code += 1+IMM2_SIZE;
- break;
- }
-
/* Point at initial ( for too many branches error */
offset -= 2;
code[1+LINK_SIZE] = OP_CREF;
@@ -6930,8 +7124,7 @@ for (;; pptr++)
{
int count, index;
PCRE2_SPTR name;
- BOOL is_dupname = FALSE;
- named_group *ng = cb->named_groups;
+ named_group *ng;
uint32_t length = *(++pptr);
GETPLUSOFFSET(offset, pptr);
@@ -6942,47 +7135,39 @@ for (;; pptr++)
generated in the pre-pass in order to get a number and whether or not
this name is duplicated. */
- groupnumber = 0;
- for (unsigned int i = 0; i < cb->names_found; i++, ng++)
+ ng = PRIV(compile_find_named_group)(name, length, cb);
+
+ if (ng == NULL)
{
- if (length == ng->length &&
- PRIV(strncmp)(name, ng->name, length) == 0)
- {
- is_dupname = ng->isdup;
- groupnumber = ng->number;
+ /* If the name was not found we have a bad reference. */
+ *errorcodeptr = ERR15;
+ cb->erroroffset = offset;
+ return 0;
+ }
- /* For a recursion, that's all that is needed. We can now go to
- the code that handles numerical recursion, applying it to the first
- group with the given name. */
+ groupnumber = ng->number;
- if (meta == META_RECURSE_BYNAME)
- {
- meta_arg = groupnumber;
- goto HANDLE_NUMERICAL_RECURSION;
- }
-
- /* For a back reference, update the back reference map and the
- maximum back reference. */
+ /* For a recursion, that's all that is needed. We can now go to
+ the code that handles numerical recursion, applying it to the first
+ group with the given name. */
- cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;
- if (groupnumber > cb->top_backref)
- cb->top_backref = groupnumber;
- }
+ if (meta == META_RECURSE_BYNAME)
+ {
+ meta_arg = groupnumber;
+ goto HANDLE_NUMERICAL_RECURSION;
}
- /* If the name was not found we have a bad reference. */
+ /* For a back reference, update the back reference map and the
+ maximum back reference. */
- if (groupnumber == 0)
- {
- *errorcodeptr = ERR15;
- cb->erroroffset = offset;
- return 0;
- }
+ cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;
+ if (groupnumber > cb->top_backref)
+ cb->top_backref = groupnumber;
/* If a back reference name is not duplicated, we can handle it as
a numerical reference. */
- if (!is_dupname)
+ if ((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) == 0)
{
meta_arg = groupnumber;
goto HANDLE_SINGLE_REFERENCE;
@@ -6994,8 +7179,8 @@ for (;; pptr++)
count = 0; /* Values for first pass (avoids compiler warning) */
index = 0;
- if (lengthptr == NULL && !find_dupname_details(name, length, &index,
- &count, errorcodeptr, cb)) return 0;
+ if (lengthptr == NULL && !PRIV(compile_find_dupname_details)(name, length,
+ &index, &count, errorcodeptr, cb)) return 0;
if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
*code++ = ((options & PCRE2_CASELESS) != 0)? OP_DNREFI : OP_DNREF;
@@ -7279,6 +7464,7 @@ for (;; pptr++)
if (repeat_min > 0 && (repeat_min != 1 || repeat_max != REPEAT_UNLIMITED))
{
int replicate = repeat_min;
+
if (repeat_min == repeat_max) replicate--;
/* In the pre-compile phase, we don't actually do the replication. We
@@ -7288,7 +7474,7 @@ for (;; pptr++)
if (lengthptr != NULL)
{
PCRE2_SIZE delta;
- if (PRIV(ckd_smul)(&delta, replicate, 1 + LINK_SIZE) ||
+ if (PRIV(ckd_smul)(&delta, replicate, (int)length_prevgroup) ||
OFLOW_MAX - *lengthptr < delta)
{
*errorcodeptr = ERR20;
@@ -7296,12 +7482,11 @@ for (;; pptr++)
}
*lengthptr += delta;
}
-
else for (int i = 0; i < replicate; i++)
{
- memcpy(code, previous, CU2BYTES(1 + LINK_SIZE));
+ memcpy(code, previous, CU2BYTES(length_prevgroup));
previous = code;
- code += 1 + LINK_SIZE;
+ code += length_prevgroup;
}
/* If the number of repeats is fixed, we are done. Otherwise, adjust
@@ -7313,18 +7498,21 @@ for (;; pptr++)
}
/* Wrap the recursion call in OP_BRA brackets. */
+ {
+ PCRE2_SIZE length = (lengthptr != NULL) ? 1 + LINK_SIZE : length_prevgroup;
- (void)memmove(previous + 1 + LINK_SIZE, previous, CU2BYTES(1 + LINK_SIZE));
- op_previous = *previous = OP_BRA;
- PUT(previous, 1, 2 + 2*LINK_SIZE);
- previous[2 + 2*LINK_SIZE] = OP_KET;
- PUT(previous, 3 + 2*LINK_SIZE, 2 + 2*LINK_SIZE);
+ (void)memmove(previous + 1 + LINK_SIZE, previous, CU2BYTES(length));
+ op_previous = *previous = OP_BRA;
+ PUT(previous, 1, 1 + LINK_SIZE + length);
+ previous[1 + LINK_SIZE + length] = OP_KET;
+ PUT(previous, 2 + LINK_SIZE + length, 1 + LINK_SIZE + length);
+ }
code += 2 + 2 * LINK_SIZE;
- length_prevgroup = 3 + 3*LINK_SIZE;
+ length_prevgroup += 2 + 2 * LINK_SIZE;
group_return = -1; /* Set "may match empty string" */
/* Now treat as a repeated OP_BRA. */
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* If previous was a bracket group, we may have to replicate it in
certain cases. Note that at this point we can encounter only the "basic"
@@ -7664,13 +7852,16 @@ for (;; pptr++)
here because it just makes it horribly messy. */
default:
+
+ /* LCOV_EXCL_START */
if (op_previous >= OP_EODN || op_previous <= OP_WORD_BOUNDARY)
{
PCRE2_DEBUG_UNREACHABLE();
*errorcodeptr = ERR10; /* Not a character type - internal error */
return 0;
}
- else
+ /* LCOV_EXCL_STOP */
+
{
int prop_type, prop_value;
PCRE2_UCHAR *oldcode;
@@ -7993,6 +8184,52 @@ for (;; pptr++)
*code = OP_RECURSE;
PUT(code, 1, meta_arg);
code += 1 + LINK_SIZE;
+ /* Repeat processing requires this information to
+ determine the real length in pre-compile phase. */
+ length_prevgroup = 1 + LINK_SIZE;
+
+ if (META_CODE(pptr[1]) == META_OFFSET ||
+ META_CODE(pptr[1]) == META_CAPTURE_NAME ||
+ META_CODE(pptr[1]) == META_CAPTURE_NUMBER)
+ {
+ recurse_arguments *args;
+
+ if (lengthptr != NULL)
+ {
+ if (!PRIV(compile_parse_recurse_args)(pptr, offset, errorcodeptr, cb))
+ return 0;
+
+ args = (recurse_arguments*)cb->last_data;
+ length_prevgroup += (args->size * (1 + IMM2_SIZE));
+ *lengthptr += (args->size * (1 + IMM2_SIZE));
+ pptr += args->skip_size;
+ }
+ else
+ {
+ uint16_t *current, *end;
+
+ args = (recurse_arguments*)cb->first_data;
+ PCRE2_ASSERT(args != NULL && args->header.type == CDATA_RECURSE_ARGS);
+
+ current = (uint16_t*)(args + 1);
+ end = current + args->size;
+ PCRE2_ASSERT(end > current);
+
+ do
+ {
+ code[0] = OP_CREF;
+ PUT2(code, 1, *current);
+ code += 1 + IMM2_SIZE;
+ }
+ while (++current < end);
+
+ length_prevgroup += (args->size * (1 + IMM2_SIZE));
+ pptr += args->skip_size;
+ cb->first_data = args->header.next;
+ cb->cx->memctl.free(args, cb->cx->memctl.memory_data);
+ }
+ }
+
groupsetfirstcu = FALSE;
cb->had_recurse = TRUE;
if (firstcuflags == REQ_UNSET) firstcuflags = REQ_NONE;
@@ -8117,6 +8354,7 @@ for (;; pptr++)
cb->external_flags |= PCRE2_HASBKC; /* Record */
#if PCRE2_CODE_UNIT_WIDTH == 32
meta_arg = OP_ALLANY;
+ (void)utf; /* Avoid compiler warning. */
#else
if (!utf) meta_arg = OP_ALLANY;
#endif
@@ -8127,11 +8365,15 @@ for (;; pptr++)
if ((options & PCRE2_UCP) != 0 && (xoptions & PCRE2_EXTRA_ASCII_BSW) == 0)
meta_arg = (meta_arg == ESC_B)? OP_NOT_UCP_WORD_BOUNDARY :
OP_UCP_WORD_BOUNDARY;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case ESC_A:
if (cb->max_lookbehind == 0) cb->max_lookbehind = 1;
break;
+
+ case ESC_K:
+ cb->external_flags |= PCRE2_HASBSK; /* Record */
+ break;
}
*code++ = meta_arg;
@@ -8143,12 +8385,14 @@ for (;; pptr++)
META_END is a literal. Otherwise we have a problem. */
default:
+ /* LCOV_EXCL_START */
if (meta >= META_END)
{
PCRE2_DEBUG_UNREACHABLE();
*errorcodeptr = ERR89; /* Internal error - unrecognized. */
return 0;
}
+ /* LCOV_EXCL_STOP */
/* Handle a literal character. We come here by goto in the case of a
32-bit, non-UTF character whose value is greater than META_END. */
@@ -8280,8 +8524,10 @@ for (;; pptr++)
} /* End of big switch */
} /* End of big loop */
+/* LCOV_EXCL_START */
PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */
return 0; /* Avoid compiler warnings */
+/* LCOV_EXCL_STOP */
}
@@ -8346,6 +8592,7 @@ if (cb->cx->stack_guard != NULL &&
cb->cx->stack_guard(cb->parens_depth, cb->cx->stack_guard_data))
{
*errorcodeptr= ERR33;
+ cb->erroroffset = 0;
return 0;
}
@@ -8587,8 +8834,10 @@ for (;;)
pptr++;
}
+/* LCOV_EXCL_START */
PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */
return 0; /* Avoid compiler warnings */
+/* LCOV_EXCL_STOP */
}
@@ -9060,7 +9309,7 @@ do {
case OP_EXACT:
scode += IMM2_SIZE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_CHAR:
case OP_PLUS:
@@ -9073,7 +9322,7 @@ do {
case OP_EXACTI:
scode += IMM2_SIZE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_CHARI:
case OP_PLUSI:
@@ -9109,67 +9358,6 @@ return c;
/*************************************************
-* Add an entry to the name/number table *
-*************************************************/
-
-/* This function is called between compiling passes to add an entry to the
-name/number table, maintaining alphabetical order. Checking for permitted
-and forbidden duplicates has already been done.
-
-Arguments:
- cb the compile data block
- name the name to add
- length the length of the name
- groupno the group number
- tablecount the count of names in the table so far
-
-Returns: nothing
-*/
-
-static void
-add_name_to_table(compile_block *cb, PCRE2_SPTR name, int length,
- unsigned int groupno, uint32_t tablecount)
-{
-uint32_t i;
-PCRE2_UCHAR *slot = cb->name_table;
-
-for (i = 0; i < tablecount; i++)
- {
- int crc = memcmp(name, slot+IMM2_SIZE, CU2BYTES(length));
- if (crc == 0 && slot[IMM2_SIZE+length] != 0)
- crc = -1; /* Current name is a substring */
-
- /* Make space in the table and break the loop for an earlier name. For a
- duplicate or later name, carry on. We do this for duplicates so that in the
- simple case (when ?(| is not used) they are in order of their numbers. In all
- cases they are in the order in which they appear in the pattern. */
-
- if (crc < 0)
- {
- (void)memmove(slot + cb->name_entry_size, slot,
- CU2BYTES((tablecount - i) * cb->name_entry_size));
- break;
- }
-
- /* Continue the loop for a later or duplicate name */
-
- slot += cb->name_entry_size;
- }
-
-PUT2(slot, 0, groupno);
-memcpy(slot + IMM2_SIZE, name, CU2BYTES(length));
-
-/* Add a terminating zero and fill the rest of the slot with zeroes so that
-the memory is all initialized. Otherwise valgrind moans about uninitialized
-memory when saving serialized compiled patterns. */
-
-memset(slot + IMM2_SIZE + length, 0,
- CU2BYTES(cb->name_entry_size - length - IMM2_SIZE));
-}
-
-
-
-/*************************************************
* Skip in parsed pattern *
*************************************************/
@@ -9210,13 +9398,14 @@ for (;; pptr++)
if (meta < META_END) continue; /* Literal */
break;
- case META_END:
-
/* The parsed regex is malformed; we have reached the end and did
not find the end of the construct which we are skipping over. */
+ /* LCOV_EXCL_START */
+ case META_END:
PCRE2_DEBUG_UNREACHABLE();
return NULL;
+ /* LCOV_EXCL_STOP */
/* The data for these items is variable in length. */
@@ -9281,7 +9470,9 @@ for (;; pptr++)
pptr += meta_extra_lengths[meta];
}
+/* LCOV_EXCL_START */
PCRE2_UNREACHABLE(); /* Control never reaches here */
+/* LCOV_EXCL_STOP */
}
@@ -9566,36 +9757,30 @@ for (;; pptr++)
case META_BACKREF_BYNAME:
if ((cb->external_options & PCRE2_MATCH_UNSET_BACKREF) != 0)
goto ISNOTFIXED;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case META_RECURSE_BYNAME:
{
- int i;
PCRE2_SPTR name;
BOOL is_dupname = FALSE;
- named_group *ng = cb->named_groups;
+ named_group *ng;
uint32_t meta_code = META_CODE(*pptr);
uint32_t length = *(++pptr);
GETPLUSOFFSET(offset, pptr);
name = cb->start_pattern + offset;
- for (i = 0; i < cb->names_found; i++, ng++)
- {
- if (length == ng->length && PRIV(strncmp)(name, ng->name, length) == 0)
- {
- group = ng->number;
- is_dupname = ng->isdup;
- break;
- }
- }
+ ng = PRIV(compile_find_named_group)(name, length, cb);
- if (group == 0)
+ if (ng == NULL)
{
*errcodeptr = ERR15; /* Non-existent subpattern */
cb->erroroffset = offset;
return -1;
}
+ group = ng->number;
+ is_dupname = (ng->hash_dup & NAMED_GROUP_IS_DUPNAME) != 0;
+
/* A numerical back reference can be fixed length if duplicate capturing
groups are not being used. A non-duplicate named back reference can also
be handled. */
@@ -9621,7 +9806,7 @@ for (;; pptr++)
goto RECURSE_OR_BACKREF_LENGTH;
}
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* For groups >= 10 - picking up group twice does no harm. */
/* A true recursion implies not fixed length, but a subroutine call may
@@ -9701,7 +9886,7 @@ for (;; pptr++)
case META_CAPTURE:
group = META_DATA(*pptr);
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case META_ATOMIC:
case META_NOCAPTURE:
@@ -9748,7 +9933,7 @@ for (;; pptr++)
else itemlength = (max - 1) * lastitemlength;
break;
}
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* Any other item means this branch does not have a fixed length. */
@@ -9783,10 +9968,12 @@ EXIT:
*minptr = branchminlength;
return branchlength;
+/* LCOV_EXCL_START */
PARSED_SKIP_FAILED:
PCRE2_DEBUG_UNREACHABLE();
*errcodeptr = ERR90; /* Unhandled META code - internal error */
return -1;
+/* LCOV_EXCL_STOP */
}
@@ -9922,15 +10109,16 @@ for (; *pptr != META_END; pptr++)
switch (META_CODE(*pptr))
{
- default:
-
/* The following erroroffset is a bogus but safe value. This branch should
be avoided by providing a proper implementation for all supported cases
below. */
+ /* LCOV_EXCL_START */
+ default:
PCRE2_DEBUG_UNREACHABLE();
cb->erroroffset = 0;
return ERR70; /* Unrecognized meta code */
+ /* LCOV_EXCL_STOP */
case META_ESCAPE:
if (*pptr - META_ESCAPE == ESC_P || *pptr - META_ESCAPE == ESC_p)
@@ -10021,8 +10209,8 @@ for (; *pptr != META_END; pptr++)
case META_BIGVALUE:
case META_POSIX:
case META_POSIX_NEG:
- case META_SCS_NAME:
- case META_SCS_NUMBER:
+ case META_CAPTURE_NAME:
+ case META_CAPTURE_NUMBER:
pptr += 1;
break;
@@ -10093,8 +10281,9 @@ pcre2_real_code *re = NULL; /* What we will return */
compile_block cb; /* "Static" compile-time data */
const uint8_t *tables; /* Char tables base pointer */
+PCRE2_UCHAR null_str[1] = { 0xcd }; /* Dummy for handling null inputs */
PCRE2_UCHAR *code; /* Current pointer in compiled code */
-PCRE2_UCHAR * codestart; /* Start of compiled code */
+PCRE2_UCHAR *codestart; /* Start of compiled code */
PCRE2_SPTR ptr; /* Current pointer in pattern */
uint32_t *pptr; /* Current pointer in parsed pattern */
@@ -10141,7 +10330,16 @@ PCRE2_UCHAR *cworkspace = (PCRE2_UCHAR *)c16workspace;
/* There must be error code and offset pointers. */
-if (errorptr == NULL || erroroffset == NULL) return NULL;
+if (errorptr == NULL)
+ {
+ if (erroroffset != NULL) *erroroffset = 0;
+ return NULL;
+ }
+if (erroroffset == NULL)
+ {
+ if (errorptr != NULL) *errorptr = ERR120;
+ return NULL;
+ }
*errorptr = ERR0;
*erroroffset = 0;
@@ -10149,7 +10347,9 @@ if (errorptr == NULL || erroroffset == NULL) return NULL;
if (pattern == NULL)
{
- if (patlen == 0) pattern = (PCRE2_SPTR)""; else
+ if (patlen == 0)
+ pattern = null_str;
+ else
{
*errorptr = ERR16;
return NULL;
@@ -10245,9 +10445,9 @@ cb.start_code = cworkspace;
cb.start_pattern = pattern;
cb.start_workspace = cworkspace;
cb.workspace_size = COMPILE_WORK_SIZE;
+cb.first_data = NULL;
+cb.last_data = NULL;
#ifdef SUPPORT_WIDE_CHARS
-cb.cranges = NULL;
-cb.next_cranges = NULL;
cb.char_lists_size = 0;
#endif
@@ -10341,6 +10541,7 @@ if ((options & PCRE2_LITERAL) == 0)
{
errorcode = ERR60;
ptr += pp;
+ utf = FALSE; /* Used by HAD_EARLY_ERROR */
goto HAD_EARLY_ERROR;
}
if (p->type == PSO_LIMH) limit_heap = c;
@@ -10373,11 +10574,13 @@ if ((options & PCRE2_LITERAL) == 0)
break;
+ /* LCOV_EXCL_START */
default:
/* All values in the enum need an explicit entry for this switch
but until a better way to prevent coding mistakes is invented keep
a catch all that triggers a debug build assert as a failsafe */
PCRE2_DEBUG_UNREACHABLE();
+ /* LCOV_EXCL_STOP */
}
break; /* Out of the table scan loop */
}
@@ -10500,10 +10703,12 @@ switch(newline)
cb.nltype = NLTYPE_ANYCRLF;
break;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
errorcode = ERR56;
goto HAD_EARLY_ERROR;
+ /* LCOV_EXCL_STOP */
}
/* Pre-scan the pattern to do two things: (1) Discover the named groups and
@@ -10632,6 +10837,7 @@ if (length > MAX_PATTERN_SIZE)
#endif
{
errorcode = ERR20;
+ cb.erroroffset = 0;
goto HAD_CB_ERROR;
}
@@ -10660,6 +10866,7 @@ re_blocksize += CU2BYTES(length);
if (re_blocksize > ccontext->max_pattern_compiled_length)
{
errorcode = ERR101;
+ cb.erroroffset = 0;
goto HAD_CB_ERROR;
}
@@ -10669,6 +10876,7 @@ re = (pcre2_real_code *)
if (re == NULL)
{
errorcode = ERR21;
+ cb.erroroffset = 0;
goto HAD_CB_ERROR;
}
@@ -10734,8 +10942,14 @@ created in the pre-pass. */
if (cb.names_found > 0)
{
named_group *ng = cb.named_groups;
+ uint32_t tablecount = 0;
+
+ /* Length 0 represents duplicates, and they have already been handled. */
for (i = 0; i < cb.names_found; i++, ng++)
- add_name_to_table(&cb, ng->name, ng->length, ng->number, i);
+ if (ng->length > 0)
+ tablecount = PRIV(compile_add_name_to_table)(&cb, ng, tablecount);
+
+ PCRE2_ASSERT(tablecount == cb.names_found);
}
/* Set up a starting, non-extracting bracket, then compile the expression. On
@@ -10767,18 +10981,20 @@ memory as unaddressable, so that any out-of-bound reads can be detected. */
*code++ = OP_END;
usedlength = code - codestart;
+/* LCOV_EXCL_START */
if (usedlength > length)
{
PCRE2_DEBUG_UNREACHABLE();
errorcode = ERR23; /* Overflow of code block - internal error */
+ cb.erroroffset = 0;
+ goto HAD_CB_ERROR;
}
-else
- {
- re->blocksize -= CU2BYTES(length - usedlength);
+/* LCOV_EXCL_STOP */
+
+re->blocksize -= CU2BYTES(length - usedlength);
#ifdef SUPPORT_VALGRIND
- VALGRIND_MAKE_MEM_NOACCESS(code, CU2BYTES(length - usedlength));
+VALGRIND_MAKE_MEM_NOACCESS(code, CU2BYTES(length - usedlength));
#endif
- }
/* Scan the pattern for recursion/subroutine calls and convert the group
numbers into offsets. Maintain a small cache so that repeated groups containing
@@ -10823,12 +11039,15 @@ if (errorcode == 0 && cb.had_recurse)
if (rgroup == NULL)
{
rgroup = PRIV(find_bracket)(search_from, utf, groupnumber);
+ /* LCOV_EXCL_START */
if (rgroup == NULL)
{
PCRE2_DEBUG_UNREACHABLE();
errorcode = ERR53;
break;
}
+ /* LCOV_EXCL_STOP */
+
if (--start < 0) start = RSCAN_CACHE_SIZE - 1;
rc[start].groupnumber = groupnumber;
rc[start].group = rgroup;
@@ -10858,11 +11077,15 @@ function call. */
if (errorcode == 0 && (optim_flags & PCRE2_OPTIM_AUTO_POSSESS) != 0)
{
PCRE2_UCHAR *temp = (PCRE2_UCHAR *)codestart;
- if (PRIV(auto_possessify)(temp, &cb) != 0)
+ int possessify_rc = PRIV(auto_possessify)(temp, &cb);
+ /* LCOV_EXCL_START */
+ if (possessify_rc != 0)
{
PCRE2_DEBUG_UNREACHABLE();
errorcode = ERR80;
+ cb.erroroffset = 0;
}
+ /* LCOV_EXCL_STOP */
}
/* Failed to compile, or error while post-processing. */
@@ -10892,6 +11115,7 @@ unit. */
if ((optim_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0)
{
int minminlength = 0; /* For minimal minlength from first/required CU */
+ int study_rc;
/* If we do not have a first code unit, see if there is one that is asserted
(these are not saved during the compile because they can cause conflicts with
@@ -11015,12 +11239,16 @@ if ((optim_flags & PCRE2_OPTIM_START_OPTIMIZE) != 0)
/* Study the compiled pattern to set up information such as a bitmap of
starting code units and a minimum matching length. */
- if (PRIV(study)(re) != 0)
+ study_rc = PRIV(study)(re);
+ /* LCOV_EXCL_START */
+ if (study_rc != 0)
{
PCRE2_DEBUG_UNREACHABLE();
errorcode = ERR31;
+ cb.erroroffset = 0;
goto HAD_CB_ERROR;
}
+ /* LCOV_EXCL_STOP */
/* If study() set a bitmap of starting code units, it implies a minimum
length of at least one. */
@@ -11041,7 +11269,8 @@ groups if a larger one had to be obtained, and likewise the group information
vector. */
#ifdef SUPPORT_UNICODE
-PCRE2_ASSERT(cb.cranges == NULL);
+/* All items must be freed. */
+PCRE2_ASSERT(cb.first_data == NULL);
#endif
EXIT:
@@ -11067,8 +11296,22 @@ HAD_CB_ERROR:
ptr = pattern + cb.erroroffset;
HAD_EARLY_ERROR:
-PCRE2_ASSERT(ptr >= pattern); /* Ensure we don't return invalid erroroffset */
+/* Ensure we don't return out-of-range erroroffset. */
+PCRE2_ASSERT(ptr >= pattern);
PCRE2_ASSERT(ptr <= (pattern + patlen));
+/* Ensure that the erroroffset never slices a UTF-encoded character in half.
+If the input is invalid, then we return an offset just before the first invalid
+character, so the text to the left of the offset must always be valid. */
+#if defined PCRE2_DEBUG && defined SUPPORT_UNICODE
+if (ptr > pattern && utf)
+ {
+ PCRE2_SPTR prev = ptr - 1;
+ PCRE2_SIZE dummyoffset;
+ BACKCHAR(prev);
+ PCRE2_ASSERT(prev >= pattern);
+ PCRE2_ASSERT(PRIV(valid_utf)(prev, ptr - prev, &dummyoffset) == 0);
+ }
+#endif
*erroroffset = ptr - pattern;
HAD_ERROR:
@@ -11076,19 +11319,18 @@ HAD_ERROR:
pcre2_code_free(re);
re = NULL;
-#ifdef SUPPORT_WIDE_CHARS
-if (cb.cranges != NULL)
+if (cb.first_data != NULL)
{
- class_ranges* cranges = cb.cranges;
+ compile_data* current_data = cb.first_data;
do
{
- class_ranges* next_cranges = cranges->next;
- cb.cx->memctl.free(cranges, cb.cx->memctl.memory_data);
- cranges = next_cranges;
+ compile_data* next_data = current_data->next;
+ cb.cx->memctl.free(current_data, cb.cx->memctl.memory_data);
+ current_data = next_data;
}
- while (cranges != NULL);
+ while (current_data != NULL);
}
-#endif
+
goto EXIT;
}
diff --git a/src/3rdparty/pcre2/src/pcre2_compile.h b/src/3rdparty/pcre2/src/pcre2_compile.h
index c8bf610bed5..331ca3ad396 100644
--- a/src/3rdparty/pcre2/src/pcre2_compile.h
+++ b/src/3rdparty/pcre2/src/pcre2_compile.h
@@ -51,18 +51,18 @@ pcre2.h.in must be updated - their values are exactly 100 greater than these
values. */
enum { ERR0 = COMPILE_ERROR_BASE,
- ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10,
- ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20,
- ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, ERR30,
- ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40,
- ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, ERR50,
- ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, ERR60,
- ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70,
- ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80,
- ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90,
- ERR91, ERR92, ERR93, ERR94, ERR95, ERR96, ERR97, ERR98, ERR99, ERR100,
- ERR101,ERR102,ERR103,ERR104,ERR105,ERR106,ERR107,ERR108,ERR109,ERR110,
- ERR111,ERR112,ERR113,ERR114,ERR115,ERR116 };
+ ERR1, ERR2, ERR3, ERR4, ERR5, ERR6, ERR7, ERR8, ERR9, ERR10,
+ ERR11, ERR12, ERR13, ERR14, ERR15, ERR16, ERR17, ERR18, ERR19, ERR20,
+ ERR21, ERR22, ERR23, ERR24, ERR25, ERR26, ERR27, ERR28, ERR29, ERR30,
+ ERR31, ERR32, ERR33, ERR34, ERR35, ERR36, ERR37, ERR38, ERR39, ERR40,
+ ERR41, ERR42, ERR43, ERR44, ERR45, ERR46, ERR47, ERR48, ERR49, ERR50,
+ ERR51, ERR52, ERR53, ERR54, ERR55, ERR56, ERR57, ERR58, ERR59, ERR60,
+ ERR61, ERR62, ERR63, ERR64, ERR65, ERR66, ERR67, ERR68, ERR69, ERR70,
+ ERR71, ERR72, ERR73, ERR74, ERR75, ERR76, ERR77, ERR78, ERR79, ERR80,
+ ERR81, ERR82, ERR83, ERR84, ERR85, ERR86, ERR87, ERR88, ERR89, ERR90,
+ ERR91, ERR92, ERR93, ERR94, ERR95, ERR96, ERR97, ERR98, ERR99, ERR100,
+ ERR101, ERR102, ERR103, ERR104, ERR105, ERR106, ERR107, ERR108, ERR109, ERR110,
+ ERR111, ERR112, ERR113, ERR114, ERR115, ERR116, ERR117, ERR118, ERR119, ERR120 };
/* Code values for parsed patterns, which are stored in a vector of 32-bit
unsigned ints. Values less than META_END are literal data values. The coding
@@ -96,11 +96,11 @@ code (meta_extra_lengths) must be updated to remain in step. */
#define META_COND_RNAME 0x80130000u /* (?(R&name)... */
#define META_COND_RNUMBER 0x80140000u /* (?(Rdigits)... */
#define META_COND_VERSION 0x80150000u /* (?(VERSION<op>x.y)... */
-#define META_OFFSET 0x80160000u /* Setting offset for various
- META codes (e.g. META_SCS_NAME) */
+#define META_OFFSET 0x80160000u /* Setting offset for various META
+ codes (e.g. META_CAPTURE_NAME) */
#define META_SCS 0x80170000u /* (*scan_substring:... */
-#define META_SCS_NAME 0x80180000u /* Next <name> of scan_substring */
-#define META_SCS_NUMBER 0x80190000u /* Next digits of scan_substring */
+#define META_CAPTURE_NAME 0x80180000u /* Next <name> in capture lists */
+#define META_CAPTURE_NUMBER 0x80190000u /* Next digits in capture lists */
#define META_DOLLAR 0x801a0000u /* $ metacharacter */
#define META_DOT 0x801b0000u /* . metacharacter */
#define META_ESCAPE 0x801c0000u /* \d and friends */
@@ -186,6 +186,36 @@ therefore no need for it to have a length entry, so use a high value. */
#define META_DATA(x) (x & 0x0000ffffu)
#define META_DIFF(x,y) ((x-y)>>16)
+/* Macros to store and retrieve a PCRE2_SIZE value in the parsed pattern, which
+consists of uint32_t elements. Assume that if uint32_t can't hold it, two of
+them will be able to (i.e. assume a 64-bit world). */
+
+#if PCRE2_SIZE_MAX <= UINT32_MAX
+#define PUTOFFSET(s,p) *p++ = s
+#define GETOFFSET(s,p) s = *p++
+#define GETPLUSOFFSET(s,p) s = *(++p)
+#define READPLUSOFFSET(s,p) s = p[1]
+#define SKIPOFFSET(p) p++
+#define SIZEOFFSET 1
+#else
+#define PUTOFFSET(s,p) \
+ { *p++ = (uint32_t)(s >> 32); *p++ = (uint32_t)(s & 0xffffffff); }
+#define GETOFFSET(s,p) \
+ { s = ((PCRE2_SIZE)p[0] << 32) | (PCRE2_SIZE)p[1]; p += 2; }
+#define GETPLUSOFFSET(s,p) \
+ { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; p += 2; }
+#define READPLUSOFFSET(s,p) \
+ { s = ((PCRE2_SIZE)p[1] << 32) | (PCRE2_SIZE)p[2]; }
+#define SKIPOFFSET(p) p += 2
+#define SIZEOFFSET 2
+#endif
+
+#ifdef PCRE2_DEBUG
+/* Compile data types. */
+#define CDATA_RECURSE_ARGS 0 /* Argument list for recurse */
+#define CDATA_CRANGE 1 /* Character range list */
+#endif
+
/* Extended class management flags. */
#define CLASS_IS_ECLASS 0x1
@@ -236,10 +266,16 @@ typedef struct {
/* Macros for the definitions below, to prevent name collisions. */
-#define _pcre2_posix_class_maps PCRE2_SUFFIX(_pcre2_posix_class_maps)
-#define _pcre2_update_classbits PCRE2_SUFFIX(_pcre2_update_classbits_)
-#define _pcre2_compile_class_nested PCRE2_SUFFIX(_pcre2_compile_class_nested_)
-#define _pcre2_compile_class_not_nested PCRE2_SUFFIX(_pcre2_compile_class_not_nested_)
+#define _pcre2_posix_class_maps PCRE2_SUFFIX(_pcre2_posix_class_maps)
+#define _pcre2_update_classbits PCRE2_SUFFIX(_pcre2_update_classbits_)
+#define _pcre2_compile_class_nested PCRE2_SUFFIX(_pcre2_compile_class_nested_)
+#define _pcre2_compile_class_not_nested PCRE2_SUFFIX(_pcre2_compile_class_not_nested_)
+#define _pcre2_compile_get_hash_from_name PCRE2_SUFFIX(_pcre2_compile_get_hash_from_name)
+#define _pcre2_compile_find_named_group PCRE2_SUFFIX(_pcre2_compile_find_named_group)
+#define _pcre2_compile_find_dupname_details PCRE2_SUFFIX(_pcre2_compile_find_dupname_details)
+#define _pcre2_compile_add_name_to_table PCRE2_SUFFIX(_pcre2_compile_add_name_to_table)
+#define _pcre2_compile_parse_scan_substr_args PCRE2_SUFFIX(_pcre2_compile_parse_scan_substr_args)
+#define _pcre2_compile_parse_recurse_args PCRE2_SUFFIX(_pcre2_compile_parse_recurse_args)
/* Indices of the POSIX classes in posix_names, posix_name_lengths,
@@ -253,6 +289,14 @@ posix_class_maps, and posix_substitutes. They must be kept in sync. */
extern const int PRIV(posix_class_maps)[];
+/* Defines for hash_dup member in named_group structure. */
+
+#define NAMED_GROUP_HASH_MASK ((uint16_t)0x7fff)
+#define NAMED_GROUP_IS_DUPNAME ((uint16_t)0x8000)
+
+#define NAMED_GROUP_GET_HASH(ng) ((ng)->hash_dup & NAMED_GROUP_HASH_MASK)
+
+/* Exported functions from pcre2_compile_class.c file: */
/* Set bits in classbits according to the property type */
@@ -275,6 +319,38 @@ BOOL PRIV(compile_class_nested)(uint32_t options, uint32_t xoptions,
uint32_t **pptr, PCRE2_UCHAR **pcode, int *errorcodeptr,
compile_block *cb, PCRE2_SIZE *lengthptr);
+/* Exported functions from pcre2_compile_cgroup.c file: */
+
+/* Compute hash from a capture name. */
+
+uint16_t PRIV(compile_get_hash_from_name)(PCRE2_SPTR name, uint32_t length);
+
+/* Get the descriptor of a known named capture. */
+
+named_group *PRIV(compile_find_named_group)(PCRE2_SPTR name,
+ uint32_t length, compile_block *cb);
+
+/* Add entires to name table in alphabetical order. */
+
+uint32_t PRIV(compile_add_name_to_table)(compile_block *cb,
+ named_group *ng, uint32_t tablecount);
+
+/* Searches the properties of duplicated names, and returns them
+in indexptr and countptr. */
+
+BOOL PRIV(compile_find_dupname_details)(PCRE2_SPTR name, uint32_t length,
+ int *indexptr, int *countptr, int *errorcodeptr, compile_block *cb);
+
+/* Parse the arguments of recurse operations. */
+
+uint32_t * PRIV(compile_parse_scan_substr_args)(uint32_t *pptr,
+ int *errorcodeptr, compile_block *cb, PCRE2_SIZE *lengthptr);
+
+/* Parse the arguments of recurse operations. */
+
+BOOL PRIV(compile_parse_recurse_args)(uint32_t *pptr_start,
+ PCRE2_SIZE offset, int *errorcodeptr, compile_block *cb);
+
#endif /* PCRE2_COMPILE_H_IDEMPOTENT_GUARD */
/* End of pcre2_compile.h */
diff --git a/src/3rdparty/pcre2/src/pcre2_compile_cgroup.c b/src/3rdparty/pcre2/src/pcre2_compile_cgroup.c
new file mode 100644
index 00000000000..ee0cd06b70a
--- /dev/null
+++ b/src/3rdparty/pcre2/src/pcre2_compile_cgroup.c
@@ -0,0 +1,632 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016-2024 University of Cambridge
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+
+#include "pcre2_compile.h"
+
+/*************************************************
+* Compute the hash code from a capture name *
+*************************************************/
+
+/* This function returns with a simple hash code
+computed from the name of a capture group.
+
+Arguments:
+ name name of the capture group
+ length the length of the name
+
+Returns: hash code
+*/
+
+uint16_t
+PRIV(compile_get_hash_from_name)(PCRE2_SPTR name, uint32_t length)
+{
+uint16_t hash;
+
+PCRE2_ASSERT(length > 0);
+
+hash = (uint16_t)((name[0] & 0x7f) | ((name[length - 1] & 0xff) << 7));
+PCRE2_ASSERT(hash <= NAMED_GROUP_HASH_MASK);
+return hash;
+}
+
+
+/*************************************************
+* Get the descriptor of a known named capture *
+*************************************************/
+
+/* This function returns the descriptor in the
+named group list of a known capture group.
+
+Arguments:
+ name name of the capture group
+ length the length of the name
+
+Returns: pointer to the descriptor when found,
+ NULL otherwise
+ */
+
+named_group *
+PRIV(compile_find_named_group)(PCRE2_SPTR name,
+ uint32_t length, compile_block *cb)
+{
+uint16_t hash = PRIV(compile_get_hash_from_name)(name, length);
+named_group *ng;
+named_group *end = cb->named_groups + cb->names_found;
+
+for (ng = cb->named_groups; ng < end; ng++)
+ if (length == ng->length && hash == NAMED_GROUP_GET_HASH(ng) &&
+ PRIV(strncmp)(name, ng->name, length) == 0) return ng;
+
+return NULL;
+}
+
+
+/*************************************************
+* Add an entry to the name/number table *
+*************************************************/
+
+/* This function is called between compiling passes to add an entry to the
+name/number table, maintaining alphabetical order. Checking for permitted
+and forbidden duplicates has already been done.
+
+Arguments:
+ cb the compile data block
+ nb named group entry
+ tablecount the count of names in the table so far
+
+Returns: new tablecount
+*/
+
+uint32_t
+PRIV(compile_add_name_to_table)(compile_block *cb,
+ named_group *ng, uint32_t tablecount)
+{
+uint32_t i;
+PCRE2_SPTR name = ng->name;
+int length = ng->length;
+uint32_t duplicate_count = 1;
+
+PCRE2_UCHAR *slot = cb->name_table;
+
+PCRE2_ASSERT(length > 0);
+
+if ((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) != 0)
+ {
+ named_group *ng_it;
+ named_group *end = cb->named_groups + cb->names_found;
+
+ for (ng_it = ng + 1; ng_it < end; ng_it++)
+ if (ng_it->name == name) duplicate_count++;
+ }
+
+for (i = 0; i < tablecount; i++)
+ {
+ int crc = memcmp(name, slot + IMM2_SIZE, CU2BYTES(length));
+ if (crc == 0 && slot[IMM2_SIZE + length] != 0)
+ crc = -1; /* Current name is a substring */
+
+ /* Make space in the table and break the loop for an earlier name. For a
+ duplicate or later name, carry on. We do this for duplicates so that in the
+ simple case (when ?(| is not used) they are in order of their numbers. In all
+ cases they are in the order in which they appear in the pattern. */
+
+ if (crc < 0)
+ {
+ (void)memmove(slot + cb->name_entry_size * duplicate_count, slot,
+ CU2BYTES((tablecount - i) * cb->name_entry_size));
+ break;
+ }
+
+ /* Continue the loop for a later or duplicate name */
+
+ slot += cb->name_entry_size;
+ }
+
+tablecount += duplicate_count;
+
+while (TRUE)
+ {
+ PUT2(slot, 0, ng->number);
+ memcpy(slot + IMM2_SIZE, name, CU2BYTES(length));
+
+ /* Add a terminating zero and fill the rest of the slot with zeroes so that
+ the memory is all initialized. Otherwise valgrind moans about uninitialized
+ memory when saving serialized compiled patterns. */
+
+ memset(slot + IMM2_SIZE + length, 0,
+ CU2BYTES(cb->name_entry_size - length - IMM2_SIZE));
+
+ if (--duplicate_count == 0) break;
+
+ while (TRUE)
+ {
+ ++ng;
+ if (ng->name == name) break;
+ }
+
+ slot += cb->name_entry_size;
+ }
+
+return tablecount;
+}
+
+
+/*************************************************
+* Find details of duplicate group names *
+*************************************************/
+
+/* This is called from compile_branch() when it needs to know the index and
+count of duplicates in the names table when processing named backreferences,
+either directly, or as conditions.
+
+Arguments:
+ name points to the name
+ length the length of the name
+ indexptr where to put the index
+ countptr where to put the count of duplicates
+ errorcodeptr where to put an error code
+ cb the compile block
+
+Returns: TRUE if OK, FALSE if not, error code set
+*/
+
+BOOL
+PRIV(compile_find_dupname_details)(PCRE2_SPTR name, uint32_t length,
+ int *indexptr, int *countptr, int *errorcodeptr, compile_block *cb)
+{
+uint32_t i, groupnumber;
+int count;
+PCRE2_UCHAR *slot = cb->name_table;
+
+/* Find the first entry in the table */
+
+for (i = 0; i < cb->names_found; i++)
+ {
+ if (PRIV(strncmp)(name, slot + IMM2_SIZE, length) == 0 &&
+ slot[IMM2_SIZE + length] == 0) break;
+ slot += cb->name_entry_size;
+ }
+
+/* This should not occur, because this function is called only when we know we
+have duplicate names. Give an internal error. */
+
+/* LCOV_EXCL_START */
+if (i >= cb->names_found)
+ {
+ PCRE2_DEBUG_UNREACHABLE();
+ *errorcodeptr = ERR53;
+ cb->erroroffset = name - cb->start_pattern;
+ return FALSE;
+ }
+/* LCOV_EXCL_STOP */
+
+/* Record the index and then see how many duplicates there are, updating the
+backref map and maximum back reference as we do. */
+
+*indexptr = i;
+count = 0;
+
+for (;;)
+ {
+ count++;
+ groupnumber = GET2(slot, 0);
+ cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1;
+ if (groupnumber > cb->top_backref) cb->top_backref = groupnumber;
+ if (++i >= cb->names_found) break;
+ slot += cb->name_entry_size;
+ if (PRIV(strncmp)(name, slot + IMM2_SIZE, length) != 0 ||
+ (slot + IMM2_SIZE)[length] != 0) break;
+ }
+
+*countptr = count;
+return TRUE;
+}
+
+
+/* Process the capture list of scan substring and recurse
+operations. Since at least one argument must be present,
+a 0 return value represents error. */
+
+static size_t
+PRIV(compile_process_capture_list)(uint32_t *pptr, PCRE2_SIZE offset,
+ int *errorcodeptr, compile_block *cb)
+{
+size_t i, size = 0;
+named_group *ng;
+PCRE2_SPTR name;
+uint32_t length;
+named_group *end = cb->named_groups + cb->names_found;
+
+while (TRUE)
+ {
+ ++pptr;
+
+ switch (META_CODE(*pptr))
+ {
+ case META_OFFSET:
+ GETPLUSOFFSET(offset, pptr);
+ continue;
+
+ case META_CAPTURE_NAME:
+ offset += META_DATA(*pptr);
+ length = *(++pptr);
+ name = cb->start_pattern + offset;
+
+ ng = PRIV(compile_find_named_group)(name, length, cb);
+
+ if (ng == NULL)
+ {
+ *errorcodeptr = ERR15;
+ cb->erroroffset = offset;
+ return 0;
+ }
+
+ if ((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) == 0)
+ {
+ pptr[-1] = META_CAPTURE_NUMBER;
+ pptr[0] = ng->number;
+ size++;
+ continue;
+ }
+
+ /* Remains only for duplicated names. */
+ pptr[-1] = META_CAPTURE_NAME;
+ pptr[0] = (uint32_t)(ng - cb->named_groups);
+ size++;
+ name = ng->name;
+
+ while (++ng < end)
+ if (ng->name == name) size++;
+ continue;
+
+ case META_CAPTURE_NUMBER:
+ offset += META_DATA(*pptr);
+
+ i = *(++pptr);
+ if (i > cb->bracount)
+ {
+ *errorcodeptr = ERR15;
+ cb->erroroffset = offset;
+ return 0;
+ }
+ if (i > cb->top_backref) cb->top_backref = (uint16_t)i;
+ size++;
+ continue;
+
+ default:
+ break;
+ }
+
+ PCRE2_ASSERT(size > 0);
+ return size;
+ }
+}
+
+
+/*******************************************************
+* Parse the arguments of scan substring operations *
+********************************************************/
+
+/* This function parses the arguments of scan substring operations.
+
+Arguments:
+ pptr_start points to the current parsed pattern pointer
+ offset argument starting offset in the pattern
+ errorcodeptr where to put an error code
+ cb the compile block
+ lengthptr NULL during the real compile phase
+ points to length accumulator during pre-compile phase
+
+Returns: TRUE if OK, FALSE if not, error code set
+*/
+
+uint32_t *
+PRIV(compile_parse_scan_substr_args)(uint32_t *pptr,
+ int *errorcodeptr, compile_block *cb, PCRE2_SIZE *lengthptr)
+{
+uint8_t *captures;
+uint8_t *capture_ptr;
+uint8_t bit;
+PCRE2_SPTR name;
+named_group *ng;
+named_group *end = cb->named_groups + cb->names_found;
+BOOL all_found;
+size_t size;
+
+PCRE2_ASSERT(*pptr == META_OFFSET);
+if (PRIV(compile_process_capture_list)(pptr - 1, 0, errorcodeptr, cb) == 0)
+ return NULL;
+
+/* Align to bytes. Since the highest capture can
+be equal to bracount, +1 is added before the aligning. */
+size = (cb->bracount + 1 + 7) >> 3;
+captures = (uint8_t*)cb->cx->memctl.malloc(size, cb->cx->memctl.memory_data);
+if (captures == NULL)
+ {
+ *errorcodeptr = ERR21;
+ READPLUSOFFSET(cb->erroroffset, pptr);
+ return NULL;
+ }
+
+memset(captures, 0, size);
+
+while (TRUE)
+ {
+ switch (META_CODE(*pptr))
+ {
+ case META_OFFSET:
+ pptr++;
+ SKIPOFFSET(pptr);
+ continue;
+
+ case META_CAPTURE_NAME:
+ ng = cb->named_groups + pptr[1];
+ PCRE2_ASSERT((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) != 0);
+ pptr += 2;
+ name = ng->name;
+
+ all_found = TRUE;
+ do
+ {
+ if (ng->name != name) continue;
+
+ capture_ptr = captures + (ng->number >> 3);
+ PCRE2_ASSERT(capture_ptr < captures + size);
+ bit = (uint8_t)(1 << (ng->number & 0x7));
+
+ if ((*capture_ptr & bit) == 0)
+ {
+ *capture_ptr |= bit;
+ all_found = FALSE;
+ }
+ }
+ while (++ng < end);
+
+ if (!all_found)
+ {
+ *lengthptr += 1 + 2 * IMM2_SIZE;
+ continue;
+ }
+
+ pptr[-2] = META_CAPTURE_NUMBER;
+ pptr[-1] = 0;
+ continue;
+
+ case META_CAPTURE_NUMBER:
+ pptr += 2;
+
+ capture_ptr = captures + (pptr[-1] >> 3);
+ PCRE2_ASSERT(capture_ptr < captures + size);
+ bit = (uint8_t)(1 << (pptr[-1] & 0x7));
+
+ if ((*capture_ptr & bit) != 0)
+ {
+ pptr[-1] = 0;
+ continue;
+ }
+
+ *capture_ptr |= bit;
+ *lengthptr += 1 + IMM2_SIZE;
+ continue;
+
+ default:
+ break;
+ }
+
+ break;
+ }
+
+cb->cx->memctl.free(captures, cb->cx->memctl.memory_data);
+return pptr - 1;
+}
+
+
+/* Implement heapsort heapify algorithm. */
+
+static void do_heapify_u16(uint16_t *captures, size_t size, size_t i)
+{
+size_t max;
+size_t left;
+size_t right;
+uint16_t tmp;
+
+while (TRUE)
+ {
+ max = i;
+ left = (i << 1) + 1;
+ right = left + 1;
+
+ if (left < size && captures[left] > captures[max]) max = left;
+ if (right < size && captures[right] > captures[max]) max = right;
+ if (i == max) return;
+
+ tmp = captures[i];
+ captures[i] = captures[max];
+ captures[max] = tmp;
+ i = max;
+ }
+}
+
+
+/*************************************************
+* Parse the arguments of recurse operations *
+*************************************************/
+
+/* This function parses the arguments of recurse operations.
+
+Arguments:
+ pptr_start the current parsed pattern pointer
+ offset argument starting offset in the pattern
+ errorcodeptr where to put an error code
+ cb the compile block
+ lengthptr NULL during the real compile phase
+ points to length accumulator during pre-compile phase
+
+Returns: TRUE if OK, FALSE if not, error code set
+*/
+
+BOOL
+PRIV(compile_parse_recurse_args)(uint32_t *pptr_start,
+ PCRE2_SIZE offset, int *errorcodeptr, compile_block *cb)
+{
+uint32_t *pptr = pptr_start;
+size_t i, size;
+PCRE2_SPTR name;
+named_group *ng;
+named_group *end = cb->named_groups + cb->names_found;
+recurse_arguments *args;
+uint16_t *captures;
+uint16_t *current;
+uint16_t *captures_end;
+uint16_t tmp;
+
+/* Process all arguments, compute the required size. */
+
+size = PRIV(compile_process_capture_list)(pptr, offset, errorcodeptr, cb);
+if (size == 0) return FALSE;
+
+args = cb->cx->memctl.malloc(
+ sizeof(recurse_arguments) + size * sizeof(uint16_t), cb->cx->memctl.memory_data);
+
+if (args == NULL)
+ {
+ *errorcodeptr = ERR21;
+ cb->erroroffset = offset;
+ return FALSE;
+ }
+
+args->header.next = NULL;
+#ifdef PCRE2_DEBUG
+args->header.type = CDATA_RECURSE_ARGS;
+#endif
+args->size = size;
+
+/* Caching the pre-processed capture list. */
+if (cb->last_data != NULL)
+ cb->last_data->next = &args->header;
+else
+ cb->first_data = &args->header;
+
+cb->last_data = &args->header;
+
+/* Create the capture list size. */
+
+captures = (uint16_t*)(args + 1);
+
+while (TRUE)
+ {
+ ++pptr;
+
+ switch (META_CODE(*pptr))
+ {
+ case META_OFFSET:
+ SKIPOFFSET(pptr);
+ continue;
+
+ case META_CAPTURE_NAME:
+ ng = cb->named_groups + *(++pptr);
+ PCRE2_ASSERT((ng->hash_dup & NAMED_GROUP_IS_DUPNAME) != 0);
+ *captures++ = (uint16_t)(ng->number);
+
+ name = ng->name;
+
+ while (++ng < end)
+ if (ng->name == name) *captures++ = (uint16_t)(ng->number);
+ continue;
+
+ case META_CAPTURE_NUMBER:
+ *captures++ = *(++pptr);
+ continue;
+
+ default:
+ break;
+ }
+
+ break;
+ }
+
+PCRE2_ASSERT(size == (size_t)(captures - (uint16_t*)(args + 1)));
+args->skip_size = (size_t)(pptr - pptr_start) - 1;
+
+if (size == 1) return TRUE;
+
+/* Sort captures. */
+
+captures = (uint16_t*)(args + 1);
+i = (size >> 1) - 1;
+while (TRUE)
+ {
+ do_heapify_u16(captures, size, i);
+ if (i == 0) break;
+ i--;
+ }
+
+for (i = size - 1; i > 0; i--)
+ {
+ tmp = captures[0];
+ captures[0] = captures[i];
+ captures[i] = tmp;
+
+ do_heapify_u16(captures, i, 0);
+ }
+
+/* Remove duplicates. */
+
+captures_end = captures + size;
+tmp = *captures++;
+current = captures;
+
+while (current < captures_end)
+ {
+ if (*current != tmp)
+ {
+ tmp = *current;
+ *captures++ = tmp;
+ }
+
+ current++;
+ }
+
+args->size = (size_t)(captures - (uint16_t*)(args + 1));
+return TRUE;
+}
+
+/* End of pcre2_compile_cgroup.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_compile_class.c b/src/3rdparty/pcre2/src/pcre2_compile_class.c
index 6a73bb9a71b..9a1fc022fff 100644
--- a/src/3rdparty/pcre2/src/pcre2_compile_class.c
+++ b/src/3rdparty/pcre2/src/pcre2_compile_class.c
@@ -38,12 +38,11 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
#include "pcre2_compile.h"
+
+
typedef struct {
/* Option bits for eclass. */
uint32_t options;
@@ -66,7 +65,7 @@ b) none of the cases here:
#define CLASS_END_CASES(meta) \
default: \
PCRE2_ASSERT((meta) <= META_END); \
- /* Fall through */ \
+ PCRE2_FALLTHROUGH /* Fall through */ \
case META_CLASS: \
case META_CLASS_NOT: \
case META_CLASS_EMPTY: \
@@ -525,6 +524,9 @@ if (xoptions & PCRE2_EXTRA_CASELESS_RESTRICT)
if (xoptions & PCRE2_EXTRA_TURKISH_CASING)
class_options |= PARSE_CLASS_TURKISH_UTF;
+#else
+(void)options; /* Avoid compiler warning. */
+(void)xoptions; /* Avoid compiler warning. */
#endif
/* Compute required space for the range. */
@@ -543,7 +545,10 @@ cranges = cb->cx->memctl.malloc(
if (cranges == NULL) return NULL;
-cranges->next = NULL;
+cranges->header.next = NULL;
+#ifdef PCRE2_DEBUG
+cranges->header.type = CDATA_CRANGE;
+#endif
cranges->range_list_size = (uint16_t)range_list_size;
cranges->char_lists_types = 0;
cranges->char_lists_size = 0;
@@ -905,6 +910,10 @@ uint8_t *classbits = cb->classbits.classbits;
uint32_t c, byte_start, byte_end;
uint32_t classbits_end = (end <= 0xff ? end : 0xff);
+#ifndef SUPPORT_UNICODE
+(void)xoptions; /* Avoid compiler warning. */
+#endif
+
/* If caseless matching is required, scan the range and process alternate
cases. In Unicode, there are 8-bit characters that have alternate cases that
are greater than 255 and vice-versa (though these may be ignored if caseless
@@ -1080,6 +1089,10 @@ BOOL utf = FALSE;
uint32_t xclass_props;
PCRE2_UCHAR *class_uchardata;
class_ranges* cranges;
+#else
+(void)has_bitmap; /* Avoid compiler warning. */
+(void)errorcodeptr; /* Avoid compiler warning. */
+(void)lengthptr; /* Avoid compiler warning. */
#endif
/* If an XClass contains a negative special such as \S, we need to flip the
@@ -1112,19 +1125,19 @@ if (utf)
}
/* Caching the pre-processed character ranges. */
- if (cb->next_cranges != NULL)
- cb->next_cranges->next = cranges;
+ if (cb->last_data != NULL)
+ cb->last_data->next = &cranges->header;
else
- cb->cranges = cranges;
+ cb->first_data = &cranges->header;
- cb->next_cranges = cranges;
+ cb->last_data = &cranges->header;
}
else
{
/* Reuse the pre-processed character ranges. */
- cranges = cb->cranges;
- PCRE2_ASSERT(cranges != NULL);
- cb->cranges = cranges->next;
+ cranges = (class_ranges*)cb->first_data;
+ PCRE2_ASSERT(cranges != NULL && cranges->header.type == CDATA_CRANGE);
+ cb->first_data = cranges->header.next;
}
if (cranges->range_list_size > 0)
@@ -1270,8 +1283,23 @@ while (TRUE)
value of 1 removes vertical space and 2 removes underscore. */
if (tabopt < 0) tabopt = -tabopt;
+#ifdef EBCDIC
+ {
+ uint8_t posix_vertical[4] = { CHAR_LF, CHAR_VT, CHAR_FF, CHAR_CR };
+ uint8_t posix_underscore = CHAR_UNDERSCORE;
+ uint8_t *chars = NULL;
+ int n = 0;
+
+ if (tabopt == 1) { chars = posix_vertical; n = 4; }
+ else if (tabopt == 2) { chars = &posix_underscore; n = 1; }
+
+ for (; n > 0; ++chars, --n)
+ pbits.classbits[*chars/8] &= ~(1u << (*chars&7));
+ }
+#else
if (tabopt == 1) pbits.classbits[1] &= ~0x3c;
- else if (tabopt == 2) pbits.classbits[11] &= 0x7f;
+ else if (tabopt == 2) pbits.classbits[11] &= 0x7f;
+#endif
/* Add the POSIX table or its complement into the main table that is
being built and we are done. */
@@ -2079,9 +2107,11 @@ switch (op)
lhs_op_info->bits.classwords[i] ^= rhs_op_info->bits.classwords[i];
break;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
break;
+ /* LCOV_EXCL_STOP */
}
}
@@ -2141,7 +2171,7 @@ switch (meta)
}
ptr++;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
default:
/* Scan forward characters, ranges, and properties.
@@ -2158,11 +2188,13 @@ switch (meta)
/* We must have a 100% guarantee that ptr increases when
compile_class_operand() returns, even on Release builds, so that we can
statically prove our loops terminate. */
+ /* LCOV_EXCL_START */
if (ptr <= prev_ptr)
{
PCRE2_DEBUG_UNREACHABLE();
return FALSE;
}
+ /* LCOV_EXCL_STOP */
/* If we fell through above, consume the closing ']'. */
if (meta == META_CLASS || meta == META_CLASS_NOT)
diff --git a/src/3rdparty/pcre2/src/pcre2_config.c b/src/3rdparty/pcre2/src/pcre2_config.c
index 031981b09bf..045f6e78d11 100644
--- a/src/3rdparty/pcre2/src/pcre2_config.c
+++ b/src/3rdparty/pcre2/src/pcre2_config.c
@@ -38,17 +38,10 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-/* Save the configured link size, which is in bytes. In 16-bit and 32-bit modes
-its value gets changed by pcre2_intmodedep.h (included by pcre2_internal.h) to
-be in code units. */
+#include "pcre2_internal.h"
-static int configured_link_size = LINK_SIZE;
-#include "pcre2_internal.h"
/* These macros are the standard way of turning unquoted text into C strings.
They allow macros like PCRE2_MAJOR to be defined without quotes, which is
@@ -79,7 +72,7 @@ pcre2_config(uint32_t what, void *where)
{
if (where == NULL) /* Requests a length */
{
- switch(what)
+ switch (what)
{
default:
return PCRE2_ERROR_BADOPTION;
@@ -87,6 +80,7 @@ if (where == NULL) /* Requests a length */
case PCRE2_CONFIG_BSR:
case PCRE2_CONFIG_COMPILED_WIDTHS:
case PCRE2_CONFIG_DEPTHLIMIT:
+ case PCRE2_CONFIG_EFFECTIVE_LINKSIZE:
case PCRE2_CONFIG_HEAPLIMIT:
case PCRE2_CONFIG_JIT:
case PCRE2_CONFIG_LINKSIZE:
@@ -124,13 +118,13 @@ switch (what)
case PCRE2_CONFIG_COMPILED_WIDTHS:
*((uint32_t *)where) = 0
#ifdef SUPPORT_PCRE2_8
- + 1
+ + (1 << 0)
#endif
#ifdef SUPPORT_PCRE2_16
- + 2
+ + (1 << 1)
#endif
#ifdef SUPPORT_PCRE2_32
- + 4
+ + (1 << 2)
#endif
;
break;
@@ -139,6 +133,10 @@ switch (what)
*((uint32_t *)where) = MATCH_LIMIT_DEPTH;
break;
+ case PCRE2_CONFIG_EFFECTIVE_LINKSIZE:
+ *((uint32_t *)where) = LINK_SIZE * sizeof(PCRE2_UCHAR);
+ break;
+
case PCRE2_CONFIG_HEAPLIMIT:
*((uint32_t *)where) = HEAP_LIMIT;
break;
@@ -163,7 +161,7 @@ switch (what)
#endif
case PCRE2_CONFIG_LINKSIZE:
- *((uint32_t *)where) = (uint32_t)configured_link_size;
+ *((uint32_t *)where) = (uint32_t)CONFIGURED_LINK_SIZE;
break;
case PCRE2_CONFIG_MATCHLIMIT:
@@ -206,8 +204,7 @@ switch (what)
#endif
return (int)(1 + ((where == NULL)?
strlen(v) : PRIV(strcpy_c8)((PCRE2_UCHAR *)where, v)));
- }
- break;
+ }
case PCRE2_CONFIG_UNICODE:
#if defined SUPPORT_UNICODE
@@ -244,6 +241,7 @@ switch (what)
return (int)(1 + ((where == NULL)?
strlen(v) : PRIV(strcpy_c8)((PCRE2_UCHAR *)where, v)));
}
+
}
return 0;
diff --git a/src/3rdparty/pcre2/src/pcre2_context.c b/src/3rdparty/pcre2/src/pcre2_context.c
index 2345145d3f5..6246683df52 100644
--- a/src/3rdparty/pcre2/src/pcre2_context.c
+++ b/src/3rdparty/pcre2/src/pcre2_context.c
@@ -39,10 +39,6 @@ POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
@@ -506,10 +502,7 @@ return 0;
}
/* These functions became obsolete at release 10.30. The first is kept as a
-synonym for backwards compatibility. The second now does nothing. Exclude both
-from coverage reports. */
-
-/* LCOV_EXCL_START */
+synonym for backwards compatibility. The second now does nothing. */
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_recursion_limit(pcre2_match_context *mcontext, uint32_t limit)
@@ -529,8 +522,6 @@ pcre2_set_recursion_memory_management(pcre2_match_context *mcontext,
return 0;
}
-/* LCOV_EXCL_STOP */
-
/* ------------ Convert context ------------ */
@@ -543,10 +534,20 @@ ccontext->glob_separator = separator;
return 0;
}
+static const char *globpunct =
+ STR_EXCLAMATION_MARK STR_QUOTATION_MARK STR_NUMBER_SIGN STR_DOLLAR_SIGN
+ STR_PERCENT_SIGN STR_AMPERSAND STR_APOSTROPHE STR_LEFT_PARENTHESIS
+ STR_RIGHT_PARENTHESIS STR_ASTERISK STR_PLUS STR_COMMA STR_MINUS STR_DOT
+ STR_SLASH STR_COLON STR_SEMICOLON STR_LESS_THAN_SIGN STR_EQUALS_SIGN
+ STR_GREATER_THAN_SIGN STR_QUESTION_MARK STR_COMMERCIAL_AT
+ STR_LEFT_SQUARE_BRACKET STR_BACKSLASH STR_RIGHT_SQUARE_BRACKET
+ STR_CIRCUMFLEX_ACCENT STR_UNDERSCORE STR_GRAVE_ACCENT STR_LEFT_CURLY_BRACKET
+ STR_VERTICAL_LINE STR_RIGHT_CURLY_BRACKET STR_TILDE;
+
PCRE2_EXP_DEFN int PCRE2_CALL_CONVENTION
pcre2_set_glob_escape(pcre2_convert_context *ccontext, uint32_t escape)
{
-if (escape > 255 || (escape != 0 && !ispunct(escape)))
+if (escape > 255 || (escape != 0 && strchr(globpunct, escape) == NULL))
return PCRE2_ERROR_BADDATA;
ccontext->glob_escape = escape;
return 0;
diff --git a/src/3rdparty/pcre2/src/pcre2_dfa_match.c b/src/3rdparty/pcre2/src/pcre2_dfa_match.c
index ebf31d284d2..f507acf8d59 100644
--- a/src/3rdparty/pcre2/src/pcre2_dfa_match.c
+++ b/src/3rdparty/pcre2/src/pcre2_dfa_match.c
@@ -72,16 +72,14 @@ Overall, I concluded that the gains in some cases did not outweigh the losses
in others, so I abandoned this code. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "pcre2_internal.h"
+
+
#define NLBLOCK mb /* Block containing newline information */
#define PSSTART start_subject /* Field containing processed string start */
#define PSEND end_subject /* Field containing processed string end */
-#include "pcre2_internal.h"
-
#define PUBLIC_DFA_MATCH_OPTIONS \
(PCRE2_ANCHORED|PCRE2_ENDANCHORED|PCRE2_NOTBOL|PCRE2_NOTEOL|PCRE2_NOTEMPTY| \
PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK|PCRE2_PARTIAL_HARD| \
@@ -2330,7 +2328,7 @@ for (;;)
case 0x2029:
#endif /* Not EBCDIC */
if (mb->bsr_convention == PCRE2_BSR_ANYCRLF) break;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case CHAR_LF:
ADD_NEW(state_offset + 1, 0);
@@ -2442,7 +2440,7 @@ for (;;)
caseless = TRUE;
codevalue -= OP_STARI - OP_STAR;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_PLUS:
case OP_MINPLUS:
case OP_POSPLUS:
@@ -2486,7 +2484,7 @@ for (;;)
case OP_NOTPOSQUERYI:
caseless = TRUE;
codevalue -= OP_STARI - OP_STAR;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_QUERY:
case OP_MINQUERY:
case OP_POSQUERY:
@@ -2527,7 +2525,7 @@ for (;;)
case OP_NOTPOSSTARI:
caseless = TRUE;
codevalue -= OP_STARI - OP_STAR;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_STAR:
case OP_MINSTAR:
case OP_POSSTAR:
@@ -2564,7 +2562,7 @@ for (;;)
case OP_NOTEXACTI:
caseless = TRUE;
codevalue -= OP_STARI - OP_STAR;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_EXACT:
case OP_NOTEXACT:
count = current_state->count; /* Number already matched */
@@ -2599,7 +2597,7 @@ for (;;)
case OP_NOTPOSUPTOI:
caseless = TRUE;
codevalue -= OP_STARI - OP_STAR;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_UPTO:
case OP_MINUPTO:
case OP_POSUPTO:
@@ -2941,6 +2939,9 @@ for (;;)
uint32_t recno = (callpat == mb->start_code)? 0 :
GET2(callpat, 1 + LINK_SIZE);
+ /* Argument list has not been supported yet. */
+ if (code[1 + LINK_SIZE] == OP_CREF) return PCRE2_ERROR_DFA_UITEM;
+
if (rws->free < RWS_RSIZE + RWS_OVEC_RSIZE)
{
rc = more_workspace(&rws, RWS_OVEC_RSIZE, mb);
@@ -3341,10 +3342,12 @@ pcre2_dfa_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
pcre2_match_context *mcontext, int *workspace, PCRE2_SIZE wscount)
{
int rc;
-int was_zero_terminated = 0;
const pcre2_real_code *re = (const pcre2_real_code *)code;
+uint32_t original_options = options;
+PCRE2_UCHAR null_str[1] = { 0xcd };
+PCRE2_SPTR original_subject = subject;
PCRE2_SPTR start_match;
PCRE2_SPTR end_subject;
PCRE2_SPTR bumpalong_limit;
@@ -3386,44 +3389,46 @@ rws->free = RWS_BASE_SIZE - RWS_ANCHOR_SIZE;
/* Recognize NULL, length 0 as an empty string. */
-if (subject == NULL && length == 0) subject = (PCRE2_SPTR)"";
+if (subject == NULL && length == 0) subject = null_str;
/* Plausibility checks */
-if ((options & ~PUBLIC_DFA_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;
-if (re == NULL || subject == NULL || workspace == NULL || match_data == NULL)
- return PCRE2_ERROR_NULL;
+if (match_data == NULL) return PCRE2_ERROR_NULL;
+if (re == NULL || subject == NULL || workspace == NULL)
+ { rc = PCRE2_ERROR_NULL; goto EXIT; }
+if ((options & ~PUBLIC_DFA_MATCH_OPTIONS) != 0)
+ { rc = PCRE2_ERROR_BADOPTION; goto EXIT; }
if (length == PCRE2_ZERO_TERMINATED)
{
length = PRIV(strlen)(subject);
- was_zero_terminated = 1;
}
-if (wscount < 20) return PCRE2_ERROR_DFA_WSSIZE;
-if (start_offset > length) return PCRE2_ERROR_BADOFFSET;
+if (wscount < 20) { rc = PCRE2_ERROR_DFA_WSSIZE; goto EXIT; }
+if (start_offset > length) { rc = PCRE2_ERROR_BADOFFSET; goto EXIT; }
/* Partial matching and PCRE2_ENDANCHORED are currently not allowed at the same
time. */
if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0 &&
((re->overall_options | options) & PCRE2_ENDANCHORED) != 0)
- return PCRE2_ERROR_BADOPTION;
+ { rc = PCRE2_ERROR_BADOPTION; goto EXIT; }
/* Invalid UTF support is not available for DFA matching. */
if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0)
- return PCRE2_ERROR_DFA_UINVALID_UTF;
+ { rc = PCRE2_ERROR_DFA_UINVALID_UTF; goto EXIT; }
/* Check that the first field in the block is the magic number. If it is not,
return with PCRE2_ERROR_BADMAGIC. */
-if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;
+if (re->magic_number != MAGIC_NUMBER)
+ { rc = PCRE2_ERROR_BADMAGIC; goto EXIT; }
/* Check the code unit width. */
if ((re->flags & PCRE2_MODE_MASK) != PCRE2_CODE_UNIT_WIDTH/8)
- return PCRE2_ERROR_BADMODE;
+ { rc = PCRE2_ERROR_BADMODE; goto EXIT; }
/* PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART are match-time flags in the
options variable for this function. Users of PCRE2 who are not calling the
@@ -3449,8 +3454,8 @@ of the workspace. */
if ((options & PCRE2_DFA_RESTART) != 0)
{
if ((workspace[0] & (-2)) != 0 || workspace[1] < 1 ||
- workspace[1] > (int)((wscount - 2)/INTS_PER_STATEBLOCK))
- return PCRE2_ERROR_DFA_BADRESTART;
+ workspace[1] > (int)((wscount - 2)/INTS_PER_STATEBLOCK))
+ { rc = PCRE2_ERROR_DFA_BADRESTART; goto EXIT; }
}
/* Set some local values */
@@ -3498,7 +3503,7 @@ else
if (mcontext->offset_limit != PCRE2_UNSET)
{
if ((re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)
- return PCRE2_ERROR_BADOFFSETLIMIT;
+ { rc = PCRE2_ERROR_BADOFFSETLIMIT; goto EXIT; }
bumpalong_limit = subject + mcontext->offset_limit;
}
mb->callout = mcontext->callout;
@@ -3565,9 +3570,12 @@ switch(re->newline_convention)
mb->nltype = NLTYPE_ANYCRLF;
break;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
- return PCRE2_ERROR_INTERNAL;
+ rc = PCRE2_ERROR_INTERNAL;
+ goto EXIT;
+ /* LCOV_EXCL_STOP */
}
/* Check a UTF string for validity if required. For 8-bit and 16-bit strings,
@@ -3588,7 +3596,7 @@ if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)
#if PCRE2_CODE_UNIT_WIDTH != 32
unsigned int i;
if (start_match < end_subject && NOT_FIRSTCU(*start_match))
- return PCRE2_ERROR_BADUTFOFFSET;
+ { rc = PCRE2_ERROR_BADUTFOFFSET; goto EXIT; }
for (i = re->max_lookbehind; i > 0 && check_subject > subject; i--)
{
check_subject--;
@@ -3609,12 +3617,12 @@ if (utf && (options & PCRE2_NO_UTF_CHECK) == 0)
/* Validate the relevant portion of the subject. After an error, adjust the
offset to be an absolute offset in the whole string. */
- match_data->rc = PRIV(valid_utf)(check_subject,
+ rc = PRIV(valid_utf)(check_subject,
length - (PCRE2_SIZE)(check_subject - subject), &(match_data->startchar));
- if (match_data->rc != 0)
+ if (rc != 0)
{
match_data->startchar += (PCRE2_SIZE)(check_subject - subject);
- return match_data->rc;
+ goto EXIT;
}
}
#endif /* SUPPORT_UNICODE */
@@ -3678,9 +3686,10 @@ if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0)
/* Fill in fields that are always returned in the match data. */
match_data->code = re;
-match_data->subject = NULL; /* Default for no match */
+match_data->subject = NULL; /* Default for match error */
match_data->mark = NULL;
match_data->matchedby = PCRE2_MATCHEDBY_DFA_INTERPRETER;
+match_data->options = original_options;
/* Call the main matching function, looping for a non-anchored regex after a
failed match. If not restarting, perform certain optimizations at the start of
@@ -4032,29 +4041,40 @@ for (;;)
if (rc != PCRE2_ERROR_NOMATCH || anchored)
{
+ if (rc == PCRE2_ERROR_NOMATCH) goto NOMATCH_EXIT;
+
if (rc == PCRE2_ERROR_PARTIAL && match_data->oveccount > 0)
{
match_data->ovector[0] = (PCRE2_SIZE)(start_match - subject);
match_data->ovector[1] = (PCRE2_SIZE)(end_subject - subject);
}
- match_data->subject_length = length;
- match_data->leftchar = (PCRE2_SIZE)(mb->start_used_ptr - subject);
- match_data->rightchar = (PCRE2_SIZE)(mb->last_used_ptr - subject);
- match_data->startchar = (PCRE2_SIZE)(start_match - subject);
- match_data->rc = rc;
- if (rc >= 0 &&(options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
+ if (rc >= 0 || rc == PCRE2_ERROR_PARTIAL)
+ {
+ match_data->subject_length = length;
+ match_data->start_offset = start_offset;
+ match_data->leftchar = (PCRE2_SIZE)(mb->start_used_ptr - subject);
+ match_data->rightchar = (PCRE2_SIZE)(mb->last_used_ptr - subject);
+ match_data->startchar = (PCRE2_SIZE)(start_match - subject);
+ }
+
+ if (rc >= 0 && (options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
{
- length = CU2BYTES(length + was_zero_terminated);
- match_data->subject = match_data->memctl.malloc(length,
- match_data->memctl.memory_data);
- if (match_data->subject == NULL) return PCRE2_ERROR_NOMEMORY;
- memcpy((void *)match_data->subject, subject, length);
+ if (length != 0)
+ {
+ match_data->subject = match_data->memctl.malloc(CU2BYTES(length),
+ match_data->memctl.memory_data);
+ if (match_data->subject == NULL)
+ { rc = PCRE2_ERROR_NOMEMORY; goto EXIT; }
+ memcpy((void *)match_data->subject, subject, CU2BYTES(length));
+ }
+ else
+ match_data->subject = NULL;
match_data->flags |= PCRE2_MD_COPIED_SUBJECT;
}
- else
+ else if (rc >= 0 || rc == PCRE2_ERROR_PARTIAL)
{
- if (rc >= 0 || rc == PCRE2_ERROR_PARTIAL) match_data->subject = subject;
+ match_data->subject = original_subject;
}
goto EXIT;
}
@@ -4088,6 +4108,9 @@ for (;;)
} /* "Bumpalong" loop */
NOMATCH_EXIT:
+match_data->subject = original_subject;
+match_data->subject_length = length;
+match_data->start_offset = start_offset;
rc = PCRE2_ERROR_NOMATCH;
EXIT:
@@ -4098,6 +4121,7 @@ while (rws->next != NULL)
mb->memctl.free(next, mb->memctl.memory_data);
}
+match_data->rc = rc;
return rc;
}
diff --git a/src/3rdparty/pcre2/src/pcre2_error.c b/src/3rdparty/pcre2/src/pcre2_error.c
index 8b7423c6c64..df26add2be9 100644
--- a/src/3rdparty/pcre2/src/pcre2_error.c
+++ b/src/3rdparty/pcre2/src/pcre2_error.c
@@ -39,12 +39,10 @@ POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
+
+
#define STRING(a) # a
#define XSTRING(s) STRING(s)
@@ -97,7 +95,7 @@ static const unsigned char compile_error_texts[] =
"a relative value of zero is not allowed\0"
"conditional subpattern contains more than two branches\0"
"atomic assertion expected after (?( or (?(?C)\0"
- "digit expected after (?+ or (?-\0"
+ "digit expected after (?+\0"
/* 30 */
"unknown POSIX class name\0"
"internal error in pcre2_study(): should not occur\0"
@@ -148,7 +146,7 @@ static const unsigned char compile_error_texts[] =
#ifndef EBCDIC
"\\c must be followed by a printable ASCII character\0"
#else
- "\\c must be followed by a letter or one of [\\]^_?\0"
+ "\\c must be followed by a letter or one of @[\\]^_?\0"
#endif
"\\k is not followed by a braced, angle-bracketed, or quoted name\0"
/* 70 */
@@ -208,6 +206,11 @@ static const unsigned char compile_error_texts[] =
/* 115 */
"terminating ] with no following closing parenthesis in (?[...]\0"
"unexpected character in (?[...]) extended character class\0"
+ "expected capture group number or name\0"
+ "missing opening parenthesis\0"
+ "syntax error in subpattern number (missing terminator?)\0"
+ /* 120 */
+ "erroroffset passed as NULL\0"
;
/* Match-time and UTF error texts are in the same format. */
@@ -291,13 +294,18 @@ static const unsigned char match_error_texts[] =
"heap limit exceeded\0"
"invalid syntax\0"
/* 65 */
- "internal error - duplicate substitution match\0"
+ "internal error: duplicate substitution match\0"
"PCRE2_MATCH_INVALID_UTF is not supported for DFA matching\0"
- "INTERNAL ERROR: invalid substring offset\0"
+ "internal error: invalid substring offset\0"
"feature is not supported by the JIT compiler\0"
"error performing replacement case transformation\0"
/* 70 */
"replacement too large (longer than PCRE2_SIZE)\0"
+ "substitute pattern differs from prior match call\0"
+ "substitute subject differs from prior match call\0"
+ "substitute start offset differs from prior match call\0"
+ "substitute options differ from prior match call\0"
+ "disallowed use of \\K in lookaround\0"
;
@@ -324,7 +332,7 @@ pcre2_get_error_message(int enumber, PCRE2_UCHAR *buffer, PCRE2_SIZE size)
{
const unsigned char *message;
PCRE2_SIZE i;
-int n;
+int n, rc = 0;
if (size == 0) return PCRE2_ERROR_NOMEMORY;
@@ -346,7 +354,7 @@ else /* Invalid error number */
for (; n > 0; n--)
{
- while (*message++ != CHAR_NUL) {};
+ while (*message++ != CHAR_NUL) {}
if (*message == CHAR_NUL) return PCRE2_ERROR_BADDATA;
}
@@ -354,14 +362,23 @@ for (i = 0; *message != 0; i++)
{
if (i >= size - 1)
{
- buffer[i] = 0; /* Terminate partial message */
- return PCRE2_ERROR_NOMEMORY;
+ rc = PCRE2_ERROR_NOMEMORY;
+ break;
}
buffer[i] = *message++;
}
-buffer[i] = 0;
-return (int)i;
+#if defined EBCDIC && 'a' != 0x81
+/* If compiling for EBCDIC, but the compiler's string literals are not EBCDIC,
+then we are in the "force EBCDIC 1047" mode. I have chosen to add a few lines
+here to translate the error strings on the fly, rather than require the string
+literals above to be written out arduously using the "STR_XYZ" macros. */
+for (PCRE2_SIZE j = 0; j < i; ++j)
+ buffer[j] = PRIV(ascii_to_ebcdic_1047)[buffer[j]];
+#endif
+
+buffer[i] = 0; /* Terminate message, even if truncated. */
+return rc? rc : (int)i;
}
/* End of pcre2_error.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_extuni.c b/src/3rdparty/pcre2/src/pcre2_extuni.c
index 91d839e2970..1b7f04b4b2f 100644
--- a/src/3rdparty/pcre2/src/pcre2_extuni.c
+++ b/src/3rdparty/pcre2/src/pcre2_extuni.c
@@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
+
/* This module contains an internal function that is used to match a Unicode
extended grapheme sequence. It is used by both pcre2_match() and
pcre2_dfa_match(). However, it is called only when Unicode support is being
@@ -45,14 +46,10 @@ compiled. Nevertheless, we provide a dummy function when there is no Unicode
support, because some compilers do not like functionless source files. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-
#include "pcre2_internal.h"
+
/* Dummy function */
#ifndef SUPPORT_UNICODE
diff --git a/src/3rdparty/pcre2/src/pcre2_find_bracket.c b/src/3rdparty/pcre2/src/pcre2_find_bracket.c
index 486f4539d89..e26ee9923fe 100644
--- a/src/3rdparty/pcre2/src/pcre2_find_bracket.c
+++ b/src/3rdparty/pcre2/src/pcre2_find_bracket.c
@@ -46,13 +46,10 @@ function is called from pcre2_compile.c and also from pcre2_study.c when
finding the minimum matching length. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
+
/*************************************************
* Scan compiled regex for specific bracket *
*************************************************/
diff --git a/src/3rdparty/pcre2/src/pcre2_internal.h b/src/3rdparty/pcre2/src/pcre2_internal.h
index 6e0a5e05d03..aa79409572e 100644
--- a/src/3rdparty/pcre2/src/pcre2_internal.h
+++ b/src/3rdparty/pcre2/src/pcre2_internal.h
@@ -41,6 +41,15 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef PCRE2_INTERNAL_H_IDEMPOTENT_GUARD
#define PCRE2_INTERNAL_H_IDEMPOTENT_GUARD
+/* We do not assume that the config.h file has an idempotent include guard,
+since it may well be written by clients. The standard Autoheader config.h does
+not have an include guard (although we could customise that). */
+
+#if defined HAVE_CONFIG_H && !defined PCRE2_CONFIG_H_IDEMPOTENT_GUARD
+#define PCRE2_CONFIG_H_IDEMPOTENT_GUARD
+#include "config.h"
+#endif
+
/* We do not support both EBCDIC and Unicode at the same time. The "configure"
script prevents both being selected, but not everybody uses "configure". EBCDIC
is only supported for the 8-bit library, but the check for this has to be later
@@ -59,13 +68,12 @@ be including this file. There is no explicit way of forcing a compile to be
abandoned, but trying to include a non-existent file seems cleanest. Otherwise
there will be many irrelevant consequential errors. */
-#if (!defined PCRE2_BUILDING_PCRE2TEST && !defined PCRE2_DFTABLES) && \
+#if (!defined PCRE2_PCRE2TEST && !defined PCRE2_DFTABLES) && \
(!defined PCRE2_CODE_UNIT_WIDTH || \
(PCRE2_CODE_UNIT_WIDTH != 8 && \
PCRE2_CODE_UNIT_WIDTH != 16 && \
PCRE2_CODE_UNIT_WIDTH != 32))
#error PCRE2_CODE_UNIT_WIDTH must be defined as 8, 16, or 32.
-#include <AbandonCompile>
#endif
@@ -120,13 +128,12 @@ MSVC 10/2010. Except for VC6 (which is missing some fundamentals and fails). */
#endif
/* When compiling a DLL for Windows, the exported symbols have to be declared
-using some MS magic. I found some useful information on this web page:
-http://msdn2.microsoft.com/en-us/library/y4h7bcy6(VS.80).aspx. According to the
-information there, using __declspec(dllexport) without "extern" we have a
-definition; with "extern" we have a declaration. The settings here override the
-setting in pcre2.h (which is included below); it defines only PCRE2_EXP_DECL,
-which is all that is needed for applications (they just import the symbols). We
-use:
+using some MS magic, as documented here:
+https://learn.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-declspec-dllexport
+
+In pcre2.h (which is included below), we define only PCRE2_EXP_DECL,
+which is all that is needed for applications (they just import the symbols). To
+compile the library, we use:
PCRE2_EXP_DECL for declarations
PCRE2_EXP_DEFN for definitions
@@ -140,24 +147,23 @@ special-purpose environments) might want to stick other stuff in front of
exported symbols. That's why, in the non-Windows case, we set PCRE2_EXP_DEFN
only if it is not already set. */
+#if defined __cplusplus
+#error This project uses C99. C++ is not supported.
+#endif
+
#ifndef PCRE2_EXP_DECL
-# ifdef _WIN32
-# ifndef PCRE2_STATIC
-# define PCRE2_EXP_DECL extern __declspec(dllexport)
-# define PCRE2_EXP_DEFN __declspec(dllexport)
-# else
-# define PCRE2_EXP_DECL extern PCRE2_EXPORT
-# define PCRE2_EXP_DEFN
-# endif
+# if defined(_WIN32) && !defined(PCRE2_STATIC)
+# define PCRE2_EXP_DECL extern __declspec(dllexport)
# else
-# ifdef __cplusplus
-# define PCRE2_EXP_DECL extern "C" PCRE2_EXPORT
-# else
-# define PCRE2_EXP_DECL extern PCRE2_EXPORT
-# endif
-# ifndef PCRE2_EXP_DEFN
-# define PCRE2_EXP_DEFN PCRE2_EXP_DECL
-# endif
+# define PCRE2_EXP_DECL extern PCRE2_EXPORT
+# endif
+#endif
+
+#ifndef PCRE2_EXP_DEFN
+# if defined(_WIN32) && !defined(PCRE2_STATIC)
+# define PCRE2_EXP_DEFN extern __declspec(dllexport)
+# else
+# define PCRE2_EXP_DEFN extern PCRE2_EXPORT
# endif
#endif
@@ -167,19 +173,6 @@ property values. This must follow the setting of PCRE2_EXP_DECL above. */
#include "pcre2.h"
#include "pcre2_ucp.h"
-/* When PCRE2 is compiled as a C++ library, the subject pointer can be replaced
-with a custom type. This makes it possible, for example, to allow pcre2_match()
-to process subject strings that are discontinuous by using a smart pointer
-class. It must always be possible to inspect all of the subject string in
-pcre2_match() because of the way it backtracks. */
-
-/* WARNING: This is as yet untested for PCRE2. */
-
-#ifdef CUSTOM_SUBJECT_PTR
-#undef PCRE2_SPTR
-#define PCRE2_SPTR CUSTOM_SUBJECT_PTR
-#endif
-
/* When checking for integer overflow, we need to handle large integers.
If a 64-bit integer type is available, we can use that.
Otherwise we have to cast to double, which of course requires floating point
@@ -201,28 +194,6 @@ code that a non-static object is being referenced. */
#define PRIV(name) _pcre2_##name
#endif
-/* When compiling for use with the Virtual Pascal compiler, these functions
-need to have their names changed. PCRE2 must be compiled with the -DVPCOMPAT
-option on the command line. */
-
-#ifdef VPCOMPAT
-#define strlen(s) _strlen(s)
-#define strncmp(s1,s2,m) _strncmp(s1,s2,m)
-#define memcmp(s,c,n) _memcmp(s,c,n)
-#define memcpy(d,s,n) _memcpy(d,s,n)
-#define memmove(d,s,n) _memmove(d,s,n)
-#define memset(s,c,n) _memset(s,c,n)
-#else /* VPCOMPAT */
-
-/* Otherwise, to cope with SunOS4 and other systems that lack memmove(), define
-a macro that calls an emulating function. */
-
-#ifndef HAVE_MEMMOVE
-#undef memmove /* Some systems may have a macro */
-#define memmove(a, b, c) PRIV(memmove)(a, b, c)
-#endif /* not HAVE_MEMMOVE */
-#endif /* not VPCOMPAT */
-
/* This is an unsigned int value that no UTF character can ever have, as
Unicode doesn't go beyond 0x0010ffff. */
@@ -406,7 +377,7 @@ PCRE (both APIs) for a long time. */
#define HSPACE_LIST \
CHAR_HT, CHAR_SPACE, CHAR_NBSP, \
0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \
- 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202f, 0x205f, 0x3000, \
+ 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x202f, 0x205f, 0x3000, \
NOTACHAR
#define HSPACE_MULTIBYTE_CASES \
@@ -422,7 +393,7 @@ PCRE (both APIs) for a long time. */
case 0x2007: /* FIGURE SPACE */ \
case 0x2008: /* PUNCTUATION SPACE */ \
case 0x2009: /* THIN SPACE */ \
- case 0x200A: /* HAIR SPACE */ \
+ case 0x200a: /* HAIR SPACE */ \
case 0x202f: /* NARROW NO-BREAK SPACE */ \
case 0x205f: /* MEDIUM MATHEMATICAL SPACE */ \
case 0x3000 /* IDEOGRAPHIC SPACE */
@@ -552,6 +523,7 @@ bytes in a code unit in that mode. */
#define PCRE2_DUPCAPUSED 0x00200000u /* contains (?| */
#define PCRE2_HASBKC 0x00400000u /* contains \C */
#define PCRE2_HASACCEPT 0x00800000u /* contains (*ACCEPT) */
+#define PCRE2_HASBSK 0x01000000u /* contains \K */
#define PCRE2_MODE_MASK (PCRE2_MODE8 | PCRE2_MODE16 | PCRE2_MODE32)
@@ -698,6 +670,10 @@ same code point. */
compatibility. NEL is the Unicode newline character; make sure it is
a positive value. */
+#if '\n' != 0x0a
+#error "ASCII character '\n' is not 0x0a"
+#endif
+
#define CHAR_LF '\n'
#define CHAR_NL CHAR_LF
#define CHAR_NEL ((unsigned char)'\x85')
@@ -713,7 +689,232 @@ a positive value. */
#endif /* EBCDIC */
-/* The remaining definitions work in both environments. */
+/* When we want to use EBCDIC with an ASCII compiler, for testing EBCDIC on
+ASCII platforms, then we can hardcode an EBCDIC codepage (IBM-1047). */
+
+#ifdef EBCDIC_IGNORING_COMPILER
+
+#define CHAR_NUL '\000'
+#define CHAR_HT '\005'
+#define CHAR_VT '\013'
+#define CHAR_FF '\014'
+#define CHAR_CR '\015'
+#define CHAR_BS '\026'
+#define CHAR_BEL '\057'
+
+#define CHAR_SPACE '\100'
+#define CHAR_EXCLAMATION_MARK '\132'
+#define CHAR_QUOTATION_MARK '\177'
+#define CHAR_NUMBER_SIGN '\173'
+#define CHAR_DOLLAR_SIGN '\133'
+#define CHAR_PERCENT_SIGN '\154'
+#define CHAR_AMPERSAND '\120'
+#define CHAR_APOSTROPHE '\175'
+#define CHAR_LEFT_PARENTHESIS '\115'
+#define CHAR_RIGHT_PARENTHESIS '\135'
+#define CHAR_ASTERISK '\134'
+#define CHAR_PLUS '\116'
+#define CHAR_COMMA '\153'
+#define CHAR_MINUS '\140'
+#define CHAR_DOT '\113'
+#define CHAR_SLASH '\141'
+#define CHAR_0 ((unsigned char)'\xf0')
+#define CHAR_1 ((unsigned char)'\xf1')
+#define CHAR_2 ((unsigned char)'\xf2')
+#define CHAR_3 ((unsigned char)'\xf3')
+#define CHAR_4 ((unsigned char)'\xf4')
+#define CHAR_5 ((unsigned char)'\xf5')
+#define CHAR_6 ((unsigned char)'\xf6')
+#define CHAR_7 ((unsigned char)'\xf7')
+#define CHAR_8 ((unsigned char)'\xf8')
+#define CHAR_9 ((unsigned char)'\xf9')
+#define CHAR_COLON '\172'
+#define CHAR_SEMICOLON '\136'
+#define CHAR_LESS_THAN_SIGN '\114'
+#define CHAR_EQUALS_SIGN '\176'
+#define CHAR_GREATER_THAN_SIGN '\156'
+#define CHAR_QUESTION_MARK '\157'
+#define CHAR_COMMERCIAL_AT '\174'
+#define CHAR_A ((unsigned char)'\xc1')
+#define CHAR_B ((unsigned char)'\xc2')
+#define CHAR_C ((unsigned char)'\xc3')
+#define CHAR_D ((unsigned char)'\xc4')
+#define CHAR_E ((unsigned char)'\xc5')
+#define CHAR_F ((unsigned char)'\xc6')
+#define CHAR_G ((unsigned char)'\xc7')
+#define CHAR_H ((unsigned char)'\xc8')
+#define CHAR_I ((unsigned char)'\xc9')
+#define CHAR_J ((unsigned char)'\xd1')
+#define CHAR_K ((unsigned char)'\xd2')
+#define CHAR_L ((unsigned char)'\xd3')
+#define CHAR_M ((unsigned char)'\xd4')
+#define CHAR_N ((unsigned char)'\xd5')
+#define CHAR_O ((unsigned char)'\xd6')
+#define CHAR_P ((unsigned char)'\xd7')
+#define CHAR_Q ((unsigned char)'\xd8')
+#define CHAR_R ((unsigned char)'\xd9')
+#define CHAR_S ((unsigned char)'\xe2')
+#define CHAR_T ((unsigned char)'\xe3')
+#define CHAR_U ((unsigned char)'\xe4')
+#define CHAR_V ((unsigned char)'\xe5')
+#define CHAR_W ((unsigned char)'\xe6')
+#define CHAR_X ((unsigned char)'\xe7')
+#define CHAR_Y ((unsigned char)'\xe8')
+#define CHAR_Z ((unsigned char)'\xe9')
+#define CHAR_LEFT_SQUARE_BRACKET ((unsigned char)'\xad')
+#define CHAR_BACKSLASH ((unsigned char)'\xe0')
+#define CHAR_RIGHT_SQUARE_BRACKET ((unsigned char)'\xbd')
+#define CHAR_CIRCUMFLEX_ACCENT '\137'
+#define CHAR_UNDERSCORE '\155'
+#define CHAR_GRAVE_ACCENT '\171'
+#define CHAR_a ((unsigned char)'\x81')
+#define CHAR_b ((unsigned char)'\x82')
+#define CHAR_c ((unsigned char)'\x83')
+#define CHAR_d ((unsigned char)'\x84')
+#define CHAR_e ((unsigned char)'\x85')
+#define CHAR_f ((unsigned char)'\x86')
+#define CHAR_g ((unsigned char)'\x87')
+#define CHAR_h ((unsigned char)'\x88')
+#define CHAR_i ((unsigned char)'\x89')
+#define CHAR_j ((unsigned char)'\x91')
+#define CHAR_k ((unsigned char)'\x92')
+#define CHAR_l ((unsigned char)'\x93')
+#define CHAR_m ((unsigned char)'\x94')
+#define CHAR_n ((unsigned char)'\x95')
+#define CHAR_o ((unsigned char)'\x96')
+#define CHAR_p ((unsigned char)'\x97')
+#define CHAR_q ((unsigned char)'\x98')
+#define CHAR_r ((unsigned char)'\x99')
+#define CHAR_s ((unsigned char)'\xa2')
+#define CHAR_t ((unsigned char)'\xa3')
+#define CHAR_u ((unsigned char)'\xa4')
+#define CHAR_v ((unsigned char)'\xa5')
+#define CHAR_w ((unsigned char)'\xa6')
+#define CHAR_x ((unsigned char)'\xa7')
+#define CHAR_y ((unsigned char)'\xa8')
+#define CHAR_z ((unsigned char)'\xa9')
+#define CHAR_LEFT_CURLY_BRACKET ((unsigned char)'\xc0')
+#define CHAR_VERTICAL_LINE '\117'
+#define CHAR_RIGHT_CURLY_BRACKET ((unsigned char)'\xd0')
+#define CHAR_TILDE ((unsigned char)'\xa1')
+
+#define STR_HT "\005"
+#define STR_VT "\013"
+#define STR_FF "\014"
+#define STR_CR "\015"
+#define STR_BS "\026"
+#define STR_BEL "\057"
+
+#define STR_SPACE "\100"
+#define STR_EXCLAMATION_MARK "\132"
+#define STR_QUOTATION_MARK "\177"
+#define STR_NUMBER_SIGN "\173"
+#define STR_DOLLAR_SIGN "\133"
+#define STR_PERCENT_SIGN "\154"
+#define STR_AMPERSAND "\120"
+#define STR_APOSTROPHE "\175"
+#define STR_LEFT_PARENTHESIS "\115"
+#define STR_RIGHT_PARENTHESIS "\135"
+#define STR_ASTERISK "\134"
+#define STR_PLUS "\116"
+#define STR_COMMA "\153"
+#define STR_MINUS "\140"
+#define STR_DOT "\113"
+#define STR_SLASH "\141"
+#define STR_0 "\360"
+#define STR_1 "\361"
+#define STR_2 "\362"
+#define STR_3 "\363"
+#define STR_4 "\364"
+#define STR_5 "\365"
+#define STR_6 "\366"
+#define STR_7 "\367"
+#define STR_8 "\370"
+#define STR_9 "\371"
+#define STR_COLON "\172"
+#define STR_SEMICOLON "\136"
+#define STR_LESS_THAN_SIGN "\114"
+#define STR_EQUALS_SIGN "\176"
+#define STR_GREATER_THAN_SIGN "\156"
+#define STR_QUESTION_MARK "\157"
+#define STR_COMMERCIAL_AT "\174"
+#define STR_A "\301"
+#define STR_B "\302"
+#define STR_C "\303"
+#define STR_D "\304"
+#define STR_E "\305"
+#define STR_F "\306"
+#define STR_G "\307"
+#define STR_H "\310"
+#define STR_I "\311"
+#define STR_J "\321"
+#define STR_K "\322"
+#define STR_L "\323"
+#define STR_M "\324"
+#define STR_N "\325"
+#define STR_O "\326"
+#define STR_P "\327"
+#define STR_Q "\330"
+#define STR_R "\331"
+#define STR_S "\342"
+#define STR_T "\343"
+#define STR_U "\344"
+#define STR_V "\345"
+#define STR_W "\346"
+#define STR_X "\347"
+#define STR_Y "\350"
+#define STR_Z "\351"
+#define STR_LEFT_SQUARE_BRACKET "\255"
+#define STR_BACKSLASH "\340"
+#define STR_RIGHT_SQUARE_BRACKET "\275"
+#define STR_CIRCUMFLEX_ACCENT "\137"
+#define STR_UNDERSCORE "\155"
+#define STR_GRAVE_ACCENT "\171"
+#define STR_a "\201"
+#define STR_b "\202"
+#define STR_c "\203"
+#define STR_d "\204"
+#define STR_e "\205"
+#define STR_f "\206"
+#define STR_g "\207"
+#define STR_h "\210"
+#define STR_i "\211"
+#define STR_j "\221"
+#define STR_k "\222"
+#define STR_l "\223"
+#define STR_m "\224"
+#define STR_n "\225"
+#define STR_o "\226"
+#define STR_p "\227"
+#define STR_q "\230"
+#define STR_r "\231"
+#define STR_s "\242"
+#define STR_t "\243"
+#define STR_u "\244"
+#define STR_v "\245"
+#define STR_w "\246"
+#define STR_x "\247"
+#define STR_y "\250"
+#define STR_z "\251"
+#define STR_LEFT_CURLY_BRACKET "\300"
+#define STR_VERTICAL_LINE "\117"
+#define STR_RIGHT_CURLY_BRACKET "\320"
+#define STR_TILDE "\241"
+
+#else /* EBCDIC_IGNORING_COMPILER */
+
+/* Otherwise, on a real EBCDIC compiler or an ASCII compiler, we can use simple
+string and character literals. */
+
+#ifdef EBCDIC
+#if 'a' != 0x81
+#error "EBCDIC character 'a' is not 0x81"
+#endif
+#else
+#if 'a' != 0x61
+#error "ASCII character 'a' is not 0x61"
+#endif
+#endif
#define CHAR_NUL '\0'
#define CHAR_HT '\t'
@@ -922,88 +1123,7 @@ a positive value. */
#define STR_RIGHT_CURLY_BRACKET "}"
#define STR_TILDE "~"
-#define STRING_ACCEPT0 "ACCEPT\0"
-#define STRING_COMMIT0 "COMMIT\0"
-#define STRING_F0 "F\0"
-#define STRING_FAIL0 "FAIL\0"
-#define STRING_MARK0 "MARK\0"
-#define STRING_PRUNE0 "PRUNE\0"
-#define STRING_SKIP0 "SKIP\0"
-#define STRING_THEN "THEN"
-
-#define STRING_atomic0 "atomic\0"
-#define STRING_pla0 "pla\0"
-#define STRING_plb0 "plb\0"
-#define STRING_napla0 "napla\0"
-#define STRING_naplb0 "naplb\0"
-#define STRING_nla0 "nla\0"
-#define STRING_nlb0 "nlb\0"
-#define STRING_scs0 "scs\0"
-#define STRING_sr0 "sr\0"
-#define STRING_asr0 "asr\0"
-#define STRING_positive_lookahead0 "positive_lookahead\0"
-#define STRING_positive_lookbehind0 "positive_lookbehind\0"
-#define STRING_non_atomic_positive_lookahead0 "non_atomic_positive_lookahead\0"
-#define STRING_non_atomic_positive_lookbehind0 "non_atomic_positive_lookbehind\0"
-#define STRING_negative_lookahead0 "negative_lookahead\0"
-#define STRING_negative_lookbehind0 "negative_lookbehind\0"
-#define STRING_script_run0 "script_run\0"
-#define STRING_atomic_script_run "atomic_script_run"
-#define STRING_scan_substring0 "scan_substring\0"
-
-#define STRING_alpha0 "alpha\0"
-#define STRING_lower0 "lower\0"
-#define STRING_upper0 "upper\0"
-#define STRING_alnum0 "alnum\0"
-#define STRING_ascii0 "ascii\0"
-#define STRING_blank0 "blank\0"
-#define STRING_cntrl0 "cntrl\0"
-#define STRING_digit0 "digit\0"
-#define STRING_graph0 "graph\0"
-#define STRING_print0 "print\0"
-#define STRING_punct0 "punct\0"
-#define STRING_space0 "space\0"
-#define STRING_word0 "word\0"
-#define STRING_xdigit "xdigit"
-
-#define STRING_DEFINE "DEFINE"
-#define STRING_VERSION "VERSION"
-#define STRING_WEIRD_STARTWORD "[:<:]]"
-#define STRING_WEIRD_ENDWORD "[:>:]]"
-
-#define STRING_CR_RIGHTPAR "CR)"
-#define STRING_LF_RIGHTPAR "LF)"
-#define STRING_CRLF_RIGHTPAR "CRLF)"
-#define STRING_ANY_RIGHTPAR "ANY)"
-#define STRING_ANYCRLF_RIGHTPAR "ANYCRLF)"
-#define STRING_NUL_RIGHTPAR "NUL)"
-#define STRING_BSR_ANYCRLF_RIGHTPAR "BSR_ANYCRLF)"
-#define STRING_BSR_UNICODE_RIGHTPAR "BSR_UNICODE)"
-#define STRING_UTF8_RIGHTPAR "UTF8)"
-#define STRING_UTF16_RIGHTPAR "UTF16)"
-#define STRING_UTF32_RIGHTPAR "UTF32)"
-#define STRING_UTF_RIGHTPAR "UTF)"
-#define STRING_UCP_RIGHTPAR "UCP)"
-#define STRING_NO_AUTO_POSSESS_RIGHTPAR "NO_AUTO_POSSESS)"
-#define STRING_NO_DOTSTAR_ANCHOR_RIGHTPAR "NO_DOTSTAR_ANCHOR)"
-#define STRING_NO_JIT_RIGHTPAR "NO_JIT)"
-#define STRING_NO_START_OPT_RIGHTPAR "NO_START_OPT)"
-#define STRING_NOTEMPTY_RIGHTPAR "NOTEMPTY)"
-#define STRING_NOTEMPTY_ATSTART_RIGHTPAR "NOTEMPTY_ATSTART)"
-#define STRING_CASELESS_RESTRICT_RIGHTPAR "CASELESS_RESTRICT)"
-#define STRING_TURKISH_CASING_RIGHTPAR "TURKISH_CASING)"
-#define STRING_LIMIT_HEAP_EQ "LIMIT_HEAP="
-#define STRING_LIMIT_MATCH_EQ "LIMIT_MATCH="
-#define STRING_LIMIT_DEPTH_EQ "LIMIT_DEPTH="
-#define STRING_LIMIT_RECURSION_EQ "LIMIT_RECURSION="
-#define STRING_MARK "MARK"
-
-#define STRING_bc "bc"
-#define STRING_bidiclass "bidiclass"
-#define STRING_sc "sc"
-#define STRING_script "script"
-#define STRING_scriptextensions "scriptextensions"
-#define STRING_scx "scx"
+#endif /* EBCDIC_WITH_ASCII_COMPILER */
#else /* SUPPORT_UNICODE */
@@ -1227,6 +1347,9 @@ only. */
#define STR_RIGHT_CURLY_BRACKET "\175"
#define STR_TILDE "\176"
+#endif /* SUPPORT_UNICODE */
+
+
#define STRING_ACCEPT0 STR_A STR_C STR_C STR_E STR_P STR_T "\0"
#define STRING_COMMIT0 STR_C STR_O STR_M STR_M STR_I STR_T "\0"
#define STRING_F0 STR_F "\0"
@@ -1311,8 +1434,6 @@ only. */
#define STRING_scx STR_s STR_c STR_x
-#endif /* SUPPORT_UNICODE */
-
/* -------------------- End of character and string names -------------------*/
/* -------------------- Definitions for compiled patterns -------------------*/
@@ -1791,7 +1912,7 @@ pcre2_dfa_match.c that must be updated. */
/* This macro defines textual names for all the opcodes. These are used only
for debugging, and some of them are only partial names. The macro is referenced
-only in pcre2_printint.c, which fills out the full names in many cases (and in
+only in pcre2_printint_inc.h, which fills out the full names in many cases (and in
some cases doesn't actually use these names at all). */
#define OP_NAME_LIST \
@@ -2075,7 +2196,7 @@ tables are needed only when compiling the 8-bit library. */
#if PCRE2_CODE_UNIT_WIDTH == 8
extern const int PRIV(utf8_table1)[];
-extern const int PRIV(utf8_table1_size);
+extern const unsigned PRIV(utf8_table1_size);
extern const int PRIV(utf8_table2)[];
extern const int PRIV(utf8_table3)[];
extern const uint8_t PRIV(utf8_table4)[];
@@ -2110,6 +2231,8 @@ extern const uint8_t PRIV(utf8_table4)[];
#define _pcre2_utt PCRE2_SUFFIX(_pcre2_utt_)
#define _pcre2_utt_names PCRE2_SUFFIX(_pcre2_utt_names_)
#define _pcre2_utt_size PCRE2_SUFFIX(_pcre2_utt_size_)
+#define _pcre2_ebcdic_1047_to_ascii PCRE2_SUFFIX(_pcre2_ebcdic_1047_to_ascii_)
+#define _pcre2_ascii_to_ebcdic_1047 PCRE2_SUFFIX(_pcre2_ascii_to_ebcdic_1047_)
extern const uint8_t PRIV(OP_lengths)[];
extern const uint32_t PRIV(callout_end_delims)[];
@@ -2142,6 +2265,8 @@ extern const char *PRIV(unicode_version);
extern const ucp_type_table PRIV(utt)[];
extern const char PRIV(utt_names)[];
extern const size_t PRIV(utt_size);
+extern const uint8_t PRIV(ebcdic_1047_to_ascii)[];
+extern const uint8_t PRIV(ascii_to_ebcdic_1047)[];
/* Mode-dependent macros and hidden and private structures are defined in a
separate file so that pcre2test can include them at all supported widths. When
@@ -2165,6 +2290,7 @@ is available. */
#define _pcre2_auto_possessify PCRE2_SUFFIX(_pcre2_auto_possessify_)
#define _pcre2_check_escape PCRE2_SUFFIX(_pcre2_check_escape_)
+#define _pcre2_ckd_smul PCRE2_SUFFIX(_pcre2_ckd_smul_)
#define _pcre2_extuni PCRE2_SUFFIX(_pcre2_extuni_)
#define _pcre2_find_bracket PCRE2_SUFFIX(_pcre2_find_bracket_)
#define _pcre2_is_newline PCRE2_SUFFIX(_pcre2_is_newline_)
@@ -2191,6 +2317,7 @@ extern int _pcre2_auto_possessify(PCRE2_UCHAR *,
const compile_block *);
extern int _pcre2_check_escape(PCRE2_SPTR *, PCRE2_SPTR, uint32_t *,
int *, uint32_t, uint32_t, uint32_t, BOOL, compile_block *);
+extern BOOL _pcre2_ckd_smul(PCRE2_SIZE *, int, int);
extern PCRE2_SPTR _pcre2_extuni(uint32_t, PCRE2_SPTR, PCRE2_SPTR, PCRE2_SPTR,
BOOL, int *);
extern PCRE2_SPTR _pcre2_find_bracket(PCRE2_SPTR, BOOL, int);
@@ -2217,17 +2344,8 @@ extern BOOL _pcre2_xclass(uint32_t, PCRE2_SPTR, const uint8_t *, BOOL);
extern BOOL _pcre2_eclass(uint32_t, PCRE2_SPTR, PCRE2_SPTR,
const uint8_t *, BOOL);
-/* This function is needed only when memmove() is not available. */
-
-#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)
-#define _pcre2_memmove PCRE2_SUFFIX(_pcre2_memmove)
-extern void * _pcre2_memmove(void *, const void *, size_t);
-#endif
-
#endif /* PCRE2_CODE_UNIT_WIDTH */
-extern BOOL PRIV(ckd_smul)(PCRE2_SIZE *, int, int);
-
#include "pcre2_util.h"
#endif /* PCRE2_INTERNAL_H_IDEMPOTENT_GUARD */
diff --git a/src/3rdparty/pcre2/src/pcre2_intmodedep.h b/src/3rdparty/pcre2/src/pcre2_intmodedep.h
index 6b858139f57..6cefb61d374 100644
--- a/src/3rdparty/pcre2/src/pcre2_intmodedep.h
+++ b/src/3rdparty/pcre2/src/pcre2_intmodedep.h
@@ -47,9 +47,16 @@ to have access to the hidden structures at all supported widths.
Some of the mode-dependent macros are required at different widths for
different parts of the pcre2test code (in particular, the included
-pcre2_printint.c file). We undefine them here so that they can be re-defined for
-multiple inclusions. Not all of these are used in pcre2test, but it's easier
-just to undefine them all. */
+pcre2_printint_inc.h file). We undefine them here so that they can be re-defined
+for multiple inclusions. Not all of these are used in pcre2test, but it's easier
+just to undefine them all.
+
+You can also include pcre2_intmodedep.h with PCRE2_CODE_UNIT_WIDTH defined to
+zero in order to simply clear the previous macros. */
+
+#ifndef PCRE2_CODE_UNIT_WIDTH
+#error PCRE2_CODE_UNIT_WIDTH must be defined
+#endif
#undef ACROSSCHAR
#undef BACKCHAR
@@ -81,9 +88,14 @@ just to undefine them all. */
#undef PUTINC
#undef TABLE_GET
+/*************************************************
+* MACROS *
+*************************************************/
+/* Macros may be undefined and re-defined if the same file handles multiple
+bit-widths. */
-/* -------------------------- MACROS ----------------------------- */
+#if PCRE2_CODE_UNIT_WIDTH != 0
/* PCRE keeps offsets in its compiled code as at least 16-bit quantities
(always stored in big-endian order in 8-bit mode) by default. These are used,
@@ -97,11 +109,23 @@ unit string is now handled by the macros that are defined here.
The macros are controlled by the value of LINK_SIZE. This defaults to 2, but
values of 3 or 4 are also supported. */
+#ifndef CONFIGURED_LINK_SIZE
+#if LINK_SIZE == 2
+#define CONFIGURED_LINK_SIZE 2
+#elif LINK_SIZE == 3
+#define CONFIGURED_LINK_SIZE 3
+#elif LINK_SIZE == 4
+#define CONFIGURED_LINK_SIZE 4
+#else
+#error LINK_SIZE must be 2, 3, or 4
+#endif
+#endif /* CONFIGURED_LINK_SIZE */
+
/* ------------------- 8-bit support ------------------ */
#if PCRE2_CODE_UNIT_WIDTH == 8
-#if LINK_SIZE == 2
+#if CONFIGURED_LINK_SIZE == 2
#define PUT(a,n,d) \
(a[n] = (PCRE2_UCHAR)((d) >> 8)), \
(a[(n)+1] = (PCRE2_UCHAR)((d) & 255))
@@ -109,7 +133,7 @@ values of 3 or 4 are also supported. */
(unsigned int)(((a)[n] << 8) | (a)[(n)+1])
#define MAX_PATTERN_SIZE (1 << 16)
-#elif LINK_SIZE == 3
+#elif CONFIGURED_LINK_SIZE == 3
#define PUT(a,n,d) \
(a[n] = (PCRE2_UCHAR)((d) >> 16)), \
(a[(n)+1] = (PCRE2_UCHAR)((d) >> 8)), \
@@ -118,7 +142,7 @@ values of 3 or 4 are also supported. */
(unsigned int)(((a)[n] << 16) | ((a)[(n)+1] << 8) | (a)[(n)+2])
#define MAX_PATTERN_SIZE (1 << 24)
-#elif LINK_SIZE == 4
+#elif CONFIGURED_LINK_SIZE == 4
#define PUT(a,n,d) \
(a[n] = (PCRE2_UCHAR)((d) >> 24)), \
(a[(n)+1] = (PCRE2_UCHAR)((d) >> 16)), \
@@ -128,8 +152,6 @@ values of 3 or 4 are also supported. */
(unsigned int)(((a)[n] << 24) | ((a)[(n)+1] << 16) | ((a)[(n)+2] << 8) | (a)[(n)+3])
#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */
-#else
-#error LINK_SIZE must be 2, 3, or 4
#endif
@@ -137,7 +159,7 @@ values of 3 or 4 are also supported. */
#elif PCRE2_CODE_UNIT_WIDTH == 16
-#if LINK_SIZE == 2
+#if CONFIGURED_LINK_SIZE == 2
#undef LINK_SIZE
#define LINK_SIZE 1
#define PUT(a,n,d) \
@@ -146,7 +168,7 @@ values of 3 or 4 are also supported. */
(a[n])
#define MAX_PATTERN_SIZE (1 << 16)
-#elif LINK_SIZE == 3 || LINK_SIZE == 4
+#elif CONFIGURED_LINK_SIZE == 3 || CONFIGURED_LINK_SIZE == 4
#undef LINK_SIZE
#define LINK_SIZE 2
#define PUT(a,n,d) \
@@ -156,8 +178,6 @@ values of 3 or 4 are also supported. */
(unsigned int)(((a)[n] << 16) | (a)[(n)+1])
#define MAX_PATTERN_SIZE (1 << 30) /* Keep it positive */
-#else
-#error LINK_SIZE must be 2, 3, or 4
#endif
@@ -194,7 +214,7 @@ arithmetic results in a signed value. Hence the cast. */
#define GET2(a,n) (unsigned int)(((a)[n] << 8) | (a)[(n)+1])
#define PUT2(a,n,d) a[n] = (d) >> 8, a[(n)+1] = (d) & 255
-#else /* Code units are 16 or 32 bits */
+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
#define IMM2_SIZE 1
#define GET2(a,n) a[n]
#define PUT2(a,n,d) a[n] = d
@@ -219,7 +239,7 @@ check is needed before accessing these tables. */
#define CHMAX_255(c) TRUE
#endif /* SUPPORT_UNICODE */
-#else /* Code units are 16 or 32 bits */
+#elif PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
#define CHMAX_255(c) ((c) <= 255u)
#define MAX_255(c) ((c) <= 255u)
#define MAX_MARK ((1u << 16) - 1)
@@ -285,7 +305,7 @@ UTF support is omitted, we don't even define them. */
#define HAS_EXTRALEN(c) HASUTF8EXTRALEN(c)
-/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.
+/* Returns with the additional number of characters if HAS_EXTRALEN(c) is TRUE.
Otherwise it has an undefined behaviour. */
#define GET_EXTRALEN(c) (PRIV(utf8_table4)[(c) & 0x3fu])
@@ -371,7 +391,7 @@ because almost all calls are already within a block of UTF-8 only code. */
#define HAS_EXTRALEN(c) (((c) & 0xfc00u) == 0xd800u)
-/* Returns with the additional number of characters if IS_MULTICHAR(c) is TRUE.
+/* Returns with the additional number of characters if HAS_EXTRALEN(c) is TRUE.
Otherwise it has an undefined behaviour. */
#define GET_EXTRALEN(c) 1
@@ -466,7 +486,7 @@ code. */
/* ------------------- 32-bit support ------------------ */
-#else
+#elif PCRE2_CODE_UNIT_WIDTH == 32
/* These are trivial for the 32-bit library, since all UTF-32 characters fit
into one PCRE2_UCHAR unit. */
@@ -547,6 +567,32 @@ These are all no-ops since all UTF-32 characters fit into one PCRE2_UCHAR. */
#define PUTINC(a,n,d) PUT(a,n,d), a += LINK_SIZE
#define PUT2INC(a,n,d) PUT2(a,n,d), a += IMM2_SIZE
+#endif /* PCRE2_CODE_UNIT_WIDTH != 0 */
+
+
+
+/*************************************************
+* STRUCTURES *
+*************************************************/
+
+/* We need a more complex include guard than usual, because the file can be
+included once for each bit-width to define the various structures. */
+
+#if PCRE2_CODE_UNIT_WIDTH == 8 && !defined PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_8
+#define PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_8
+#define PCRE2_INTMODEDEP_CAN_DEFINE
+#endif
+#if PCRE2_CODE_UNIT_WIDTH == 16 && !defined PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_16
+#define PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_16
+#define PCRE2_INTMODEDEP_CAN_DEFINE
+#endif
+#if PCRE2_CODE_UNIT_WIDTH == 32 && !defined PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_32
+#define PCRE2_INTMODEDEP_IDEMPOTENT_GUARD_32
+#define PCRE2_INTMODEDEP_CAN_DEFINE
+#endif
+
+#ifdef PCRE2_INTMODEDEP_CAN_DEFINE
+#undef PCRE2_INTMODEDEP_CAN_DEFINE
/* ----------------------- HIDDEN STRUCTURES ----------------------------- */
@@ -624,7 +670,7 @@ have 16-bit arguments in 8-bit and 16-bit modes, so we need no more than a
#define CODE_BLOCKSIZE_TYPE PCRE2_SIZE
#undef LOOKBEHIND_MAX
-#define LOOKBEHIND_MAX UINT16_MAX
+#define LOOKBEHIND_MAX ((int)UINT16_MAX)
typedef struct pcre2_real_code {
pcre2_memctl memctl; /* Memory control fields */
@@ -672,12 +718,14 @@ typedef struct pcre2_real_match_data {
struct heapframe *heapframes; /* Backtracking frames heap memory */
PCRE2_SIZE heapframes_size; /* Malloc-ed size */
PCRE2_SIZE subject_length; /* Subject length */
+ PCRE2_SIZE start_offset; /* Offset to start of search */
PCRE2_SIZE leftchar; /* Offset to leftmost code unit */
PCRE2_SIZE rightchar; /* Offset to rightmost code unit */
PCRE2_SIZE startchar; /* Offset to starting code unit */
uint8_t matchedby; /* Type of match (normal, JIT, DFA) */
uint8_t flags; /* Various flags */
uint16_t oveccount; /* Number of pairs */
+ uint32_t options; /* Options passed in to the match call */
int rc; /* The return code from the match */
PCRE2_SIZE ovector[131072]; /* Must be last in the structure */
} pcre2_real_match_data;
@@ -718,20 +766,31 @@ typedef struct branch_chain {
} branch_chain;
/* Structure for building a list of named groups during the first pass of
-compiling. */
+compiling. When a duplicate name is stored in the list, its name is set to
+the name of the first entry with the same name, and its length is set to 0. */
typedef struct named_group {
PCRE2_SPTR name; /* Points to the name in the pattern */
uint32_t number; /* Group number */
uint16_t length; /* Length of the name */
- uint16_t isdup; /* TRUE if a duplicate */
+ uint16_t hash_dup; /* A concatenation of a 15 bit hash code and
+ a singe bit which represents duplication */
} named_group;
+/* Structure for storing compile time data. */
+
+typedef struct compile_data {
+ struct compile_data *next; /* Next compile data */
+#ifdef PCRE2_DEBUG
+ uint8_t type; /* Debug only type of the data */
+#endif
+} compile_data;
+
/* Structure for caching sorted ranges. This improves the performance
of translating META code to byte code. */
typedef struct class_ranges {
- struct class_ranges *next; /* Next class ranges */
+ compile_data header; /* Common header */
size_t char_lists_size; /* Total size of encoded char lists */
size_t char_lists_start; /* Start offset of encoded char lists */
uint16_t range_list_size; /* Size of ranges array */
@@ -739,6 +798,14 @@ typedef struct class_ranges {
/* Followed by the list of ranges (start/end pairs) */
} class_ranges;
+/* Structure for sorted recurse arguments. */
+
+typedef struct recurse_arguments {
+ compile_data header; /* Common header */
+ size_t size; /* Total size */
+ size_t skip_size; /* Space consumed by arguments */
+} recurse_arguments;
+
typedef union class_bits_storage {
uint8_t classbits[32];
uint32_t classwords[8];
@@ -789,9 +856,9 @@ typedef struct compile_block {
BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
BOOL had_recurse; /* Had a pattern recursion or subroutine call */
BOOL dupnames; /* Duplicate names exist */
+ compile_data *first_data; /* First item in the compile data list */
+ compile_data *last_data; /* Last item in the compile data list */
#ifdef SUPPORT_WIDE_CHARS
- class_ranges *cranges; /* First class range. */
- class_ranges *next_cranges; /* Next class range. */
size_t char_lists_size; /* Current size of character lists */
#endif
} compile_block;
@@ -902,7 +969,9 @@ typedef struct match_block {
uint32_t match_call_count; /* Number of times a new frame is created */
BOOL hitend; /* Hit the end of the subject at some point */
BOOL hasthen; /* Pattern contains (*THEN) */
+ BOOL hasbsk; /* Pattern contains \K */
BOOL allowemptypartial; /* Allow empty hard partial */
+ BOOL allowlookaroundbsk; /* Allow \K within lookarounds */
const uint8_t *lcc; /* Points to lower casing table */
const uint8_t *fcc; /* Points to case-flipping table */
const uint8_t *ctypes; /* Points to table of type maps */
@@ -970,4 +1039,6 @@ typedef struct dfa_match_block {
#endif /* PCRE2_PCRE2TEST */
+#endif /* PCRE2_INTMODEDEP_CAN_DEFINE */
+
/* End of pcre2_intmodedep.h */
diff --git a/src/3rdparty/pcre2/src/pcre2_jit_char_inc.h b/src/3rdparty/pcre2/src/pcre2_jit_char_inc.h
index 69fe938fc5b..0976742bb3b 100644
--- a/src/3rdparty/pcre2/src/pcre2_jit_char_inc.h
+++ b/src/3rdparty/pcre2/src/pcre2_jit_char_inc.h
@@ -519,6 +519,8 @@ BOOL has_cmov, last_range_set;
sljit_u32 category_list = 0;
sljit_u32 items;
int typereg = TMP1;
+#else
+(void)c; /* Avoid compiler warning. */
#endif /* SUPPORT_UNICODE */
SLJIT_ASSERT(common->locals_size >= SSIZE_OF(sw));
@@ -568,7 +570,7 @@ while (*cc == XCL_PROP || *cc == XCL_NOTPROP)
break;
}
compares++;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case PT_SC:
status |= XCLASS_HAS_SCRIPT;
@@ -696,13 +698,11 @@ if (status & XCLASS_NEEDS_UCD)
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, TMP1, 0, TMP1, 0, TMP2, 0, UCD_BLOCK_SHIFT);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
- OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3);
+ sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, TMP2, 0, TMP2, 0, TMP2, 0, 1);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);
- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
ccbegin = cc;
@@ -768,7 +768,7 @@ if (status & XCLASS_NEEDS_UCD)
case PT_SCX:
if (cc[-1] == XCL_NOTPROP)
break;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case PT_SC:
compares--;
@@ -1104,7 +1104,7 @@ if (ranges.range_count >= 6)
depth = 0;
first_item = 0;
-last_item = ranges.range_count - 2;
+last_item = (sljit_u32)(ranges.range_count - 2);
has_cmov = sljit_has_cpu_feature(SLJIT_HAS_CMOV) != 0;
while (TRUE)
@@ -1486,7 +1486,7 @@ static PCRE2_SPTR SLJIT_FUNC do_extuni_utf(jit_arguments *args, PCRE2_SPTR cc)
{
PCRE2_SPTR start_subject = args->begin;
PCRE2_SPTR end_subject = args->end;
-int lgb, rgb, ricount;
+int lgb = 0, rgb, ricount;
PCRE2_SPTR prevcc, endcc, bptr;
BOOL first = TRUE;
BOOL was_ep_ZWJ = FALSE;
@@ -1569,7 +1569,7 @@ static PCRE2_SPTR SLJIT_FUNC do_extuni_utf_invalid(jit_arguments *args, PCRE2_SP
{
PCRE2_SPTR start_subject = args->begin;
PCRE2_SPTR end_subject = args->end;
-int lgb, rgb, ricount;
+int lgb = 0, rgb, ricount;
PCRE2_SPTR prevcc, endcc, bptr;
BOOL first = TRUE;
BOOL was_ep_ZWJ = FALSE;
@@ -1964,9 +1964,9 @@ switch(type)
detect_partial_match(common, backtracks);
if (type == OP_NOT_HSPACE)
- read_char(common, 0x9, 0x3000, backtracks, READ_CHAR_UPDATE_STR_PTR);
+ read_char(common, 0x1, 0x3000, backtracks, READ_CHAR_UPDATE_STR_PTR);
else
- read_char(common, 0x9, 0x3000, NULL, 0);
+ read_char(common, 0x1, 0x3000, NULL, 0);
add_jump(compiler, &common->hspace, JUMP(SLJIT_FAST_CALL));
sljit_set_current_flags(compiler, SLJIT_SET_Z);
@@ -1979,9 +1979,9 @@ switch(type)
detect_partial_match(common, backtracks);
if (type == OP_NOT_VSPACE)
- read_char(common, 0xa, 0x2029, backtracks, READ_CHAR_UPDATE_STR_PTR);
+ read_char(common, 0x1, 0x2029, backtracks, READ_CHAR_UPDATE_STR_PTR);
else
- read_char(common, 0xa, 0x2029, NULL, 0);
+ read_char(common, 0x1, 0x2029, NULL, 0);
add_jump(compiler, &common->vspace, JUMP(SLJIT_FAST_CALL));
sljit_set_current_flags(compiler, SLJIT_SET_Z);
diff --git a/src/3rdparty/pcre2/src/pcre2_jit_compile.c b/src/3rdparty/pcre2/src/pcre2_jit_compile.c
index 175eb68535c..3ab4592c3ad 100644
--- a/src/3rdparty/pcre2/src/pcre2_jit_compile.c
+++ b/src/3rdparty/pcre2/src/pcre2_jit_compile.c
@@ -39,10 +39,6 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
#include <sanitizer/msan_interface.h>
@@ -339,6 +335,10 @@ typedef struct recurse_entry {
jump_list *backtrack_calls;
/* Points to the starting opcode. */
sljit_sw start;
+ /* Start of caller arguments. */
+ PCRE2_SPTR arg_start;
+ /* Size of caller arguments in bytes. */
+ sljit_uw arg_size;
} recurse_entry;
typedef struct recurse_backtrack {
@@ -398,8 +398,10 @@ typedef struct compiler_common {
sljit_s32 *private_data_ptrs;
/* Chain list of read-only data ptrs. */
void *read_only_data_head;
- /* Tells whether the capturing bracket is optimized. */
- sljit_u8 *optimized_cbracket;
+ /* Bitset which tells which capture brackets can be optimized. */
+ sljit_u8 *optimized_cbrackets;
+ /* Bitset for tracking capture bracket status. */
+ sljit_u8 *cbracket_bitset;
/* Tells whether the starting offset is a target of then. */
sljit_u8 *then_offsets;
/* Current position where a THEN must jump. */
@@ -443,6 +445,8 @@ typedef struct compiler_common {
/* Locals used by fast fail optimization. */
sljit_s32 early_fail_start_ptr;
sljit_s32 early_fail_end_ptr;
+ /* Byte length of optimized_cbrackets and cbracket_bitset. */
+ sljit_u32 cbracket_bitset_length;
/* Variables used by recursive call generator. */
sljit_s32 recurse_bitset_size;
uint8_t *recurse_bitset;
@@ -1143,6 +1147,18 @@ if (*cc >= OP_CRSTAR && *cc <= OP_CRPOSRANGE)
return (current_locals_size >= locals_size) ? current_locals_size : locals_size;
}
+static SLJIT_INLINE BOOL is_optimized_cbracket(compiler_common *common, sljit_s32 capture_index)
+{
+sljit_u8 bit = (sljit_u8)(1 << (capture_index & 0x7));
+return (common->optimized_cbrackets[capture_index >> 3] & bit) != 0;
+}
+
+static SLJIT_INLINE void clear_optimized_cbracket(compiler_common *common, sljit_s32 capture_index)
+{
+sljit_u8 mask = (sljit_u8)~(1 << (capture_index & 0x7));
+common->optimized_cbrackets[capture_index >> 3] &= mask;
+}
+
static BOOL check_opcode_types(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend)
{
int count;
@@ -1193,7 +1209,7 @@ while (cc < ccend)
case OP_REFI:
case OP_REF:
locals_size = ref_update_local_size(common, cc, locals_size);
- common->optimized_cbracket[GET2(cc, 1)] = 0;
+ clear_optimized_cbracket(common, GET2(cc, 1));
cc += PRIV(OP_lengths)[*cc];
break;
@@ -1208,7 +1224,7 @@ while (cc < ccend)
case OP_CBRAPOS:
case OP_SCBRAPOS:
- common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0;
+ clear_optimized_cbracket(common, GET2(cc, 1 + LINK_SIZE));
cc += 1 + LINK_SIZE + IMM2_SIZE;
break;
@@ -1222,20 +1238,20 @@ while (cc < ccend)
break;
case OP_CREF:
- common->optimized_cbracket[GET2(cc, 1)] = 0;
+ clear_optimized_cbracket(common, GET2(cc, 1));
cc += 1 + IMM2_SIZE;
break;
case OP_DNREFI:
case OP_DNREF:
locals_size = ref_update_local_size(common, cc, locals_size);
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_DNCREF:
count = GET2(cc, 1 + IMM2_SIZE);
slot = common->name_table + GET2(cc, 1) * common->name_entry_size;
while (count-- > 0)
{
- common->optimized_cbracket[GET2(slot, 0)] = 0;
+ clear_optimized_cbracket(common, GET2(slot, 0));
slot += common->name_entry_size;
}
cc += PRIV(OP_lengths)[*cc];
@@ -1245,6 +1261,11 @@ while (cc < ccend)
/* Set its value only once. */
set_recursive_head = TRUE;
cc += 1 + LINK_SIZE;
+ while (*cc == OP_CREF)
+ {
+ clear_optimized_cbracket(common, GET2(cc, 1));
+ cc += 1 + IMM2_SIZE;
+ }
break;
case OP_CALLOUT:
@@ -1263,7 +1284,7 @@ while (cc < ccend)
case OP_THEN_ARG:
common->has_then = TRUE;
common->control_head_ptr = 1;
- /* Fall through. */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_COMMIT_ARG:
case OP_PRUNE_ARG:
@@ -1313,7 +1334,7 @@ while (cc < ccend)
if (common->utf && locals_size <= 3 * SSIZE_OF(sw))
locals_size = 3 * SSIZE_OF(sw);
#endif
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
default:
cc = next_opcode(common, cc);
if (cc == NULL)
@@ -1379,7 +1400,7 @@ int result = 0;
int count, prev_count;
SLJIT_ASSERT(*cc == OP_ONCE || *cc == OP_BRA || *cc == OP_CBRA);
-SLJIT_ASSERT(*cc != OP_CBRA || common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] != 0);
+SLJIT_ASSERT(*cc != OP_CBRA || is_optimized_cbracket(common, GET2(cc, 1 + LINK_SIZE)));
SLJIT_ASSERT(start < EARLY_FAIL_ENHANCE_MAX);
next_alt = cc + GET(cc, 1);
@@ -1462,7 +1483,7 @@ do
case OP_TYPEMINPLUS:
if (count == 2)
count = 3;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_TYPESTAR:
case OP_TYPEPLUS:
@@ -1491,7 +1512,7 @@ do
case OP_TYPEMINUPTO:
case OP_TYPEPOSUPTO:
cc += IMM2_SIZE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_TYPEQUERY:
case OP_TYPEMINQUERY:
@@ -1512,7 +1533,7 @@ do
case OP_NOTMINPLUSI:
if (count == 2)
count = 3;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_STAR:
case OP_PLUS:
@@ -1565,7 +1586,7 @@ do
case OP_NOTEXACTI:
case OP_NOTPOSUPTOI:
cc += IMM2_SIZE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_QUERY:
case OP_MINQUERY:
@@ -1605,7 +1626,7 @@ do
case OP_CRMINPLUS:
if (count == 2)
count = 3;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_CRSTAR:
case OP_CRPLUS:
@@ -1627,7 +1648,7 @@ do
}
cc += 2 * IMM2_SIZE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_CRQUERY:
case OP_CRMINQUERY:
case OP_CRPOSQUERY:
@@ -1657,7 +1678,7 @@ do
count = 3;
end = bracketend(cc);
- if (end[-1 - LINK_SIZE] != OP_KET || (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0))
+ if (end[-1 - LINK_SIZE] != OP_KET || (*cc == OP_CBRA && !is_optimized_cbracket(common, GET2(cc, 1 + LINK_SIZE))))
break;
prev_count = detect_early_fail(common, cc, private_data_start, depth + 1, prev_count);
@@ -1838,7 +1859,8 @@ if (*next == OP_BRAZERO || *next == OP_BRAMINZERO)
if (i == max)
{
- common->private_data_ptrs[max_end - common->start - LINK_SIZE] = next_end - max_end;
+ /* Patterns must fit into an int32 even for link-size=4. */
+ common->private_data_ptrs[max_end - common->start - LINK_SIZE] = (sljit_s32)(next_end - max_end);
common->private_data_ptrs[max_end - common->start - LINK_SIZE + 1] = (type == OP_BRAZERO) ? OP_UPTO : OP_MINUPTO;
/* +2 the original and the last. */
common->private_data_ptrs[max_end - common->start - LINK_SIZE + 2] = max + 2;
@@ -1853,7 +1875,7 @@ if (*next == OP_BRAZERO || *next == OP_BRAMINZERO)
if (min >= 3)
{
- common->private_data_ptrs[end - common->start - LINK_SIZE] = max_end - end;
+ common->private_data_ptrs[end - common->start - LINK_SIZE] = (sljit_s32)(max_end - end);
common->private_data_ptrs[end - common->start - LINK_SIZE + 1] = OP_EXACT;
common->private_data_ptrs[end - common->start - LINK_SIZE + 2] = min;
return TRUE;
@@ -2118,11 +2140,22 @@ while (cc < ccend)
*private_data_start = private_data_ptr;
}
+static SLJIT_INLINE BOOL is_cbracket_processed(compiler_common *common, sljit_s32 capture_index)
+{
+sljit_u8 bit = (sljit_u8)(1 << (capture_index & 0x7));
+sljit_u8 *ptr = common->cbracket_bitset + (capture_index >> 3);
+sljit_u8 value = *ptr;
+
+*ptr |= bit;
+return (value & bit) != 0;
+}
+
/* Returns with a frame_types (always < 0) if no need for frame. */
static int get_framesize(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, BOOL recursive, BOOL *needs_control_head)
{
int length = 0;
int possessive = 0;
+int offset;
BOOL stack_restore = FALSE;
BOOL setsom_found = recursive;
BOOL setmark_found = recursive;
@@ -2136,6 +2169,8 @@ SLJIT_ASSERT(common->control_head_ptr != 0);
*needs_control_head = FALSE;
#endif
+memset(common->cbracket_bitset, 0, common->cbracket_bitset_length);
+
if (ccend == NULL)
{
ccend = bracketend(cc) - (1 + LINK_SIZE);
@@ -2196,7 +2231,15 @@ while (cc < ccend)
length += 2;
capture_last_found = TRUE;
}
+
cc += 1 + LINK_SIZE;
+ while (*cc == OP_CREF)
+ {
+ offset = GET2(cc, 1);
+ if (!is_cbracket_processed(common, offset))
+ length += 3;
+ cc += 1 + IMM2_SIZE;
+ }
break;
case OP_CBRA:
@@ -2209,7 +2252,10 @@ while (cc < ccend)
length += 2;
capture_last_found = TRUE;
}
- length += 3;
+
+ offset = GET2(cc, 1 + LINK_SIZE);
+ if (!is_cbracket_processed(common, offset))
+ length += 3;
cc += 1 + LINK_SIZE + IMM2_SIZE;
break;
@@ -2222,7 +2268,7 @@ while (cc < ccend)
default:
stack_restore = TRUE;
- /* Fall through. */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_NOT_WORD_BOUNDARY:
case OP_WORD_BOUNDARY:
@@ -2322,6 +2368,8 @@ int offset;
SLJIT_UNUSED_ARG(stacktop);
SLJIT_ASSERT(stackpos >= stacktop + 2);
+memset(common->cbracket_bitset, 0, common->cbracket_bitset_length);
+
stackpos = STACK(stackpos);
if (ccend == NULL)
{
@@ -2395,6 +2443,23 @@ while (cc < ccend)
capture_last_found = TRUE;
}
cc += 1 + LINK_SIZE;
+ while (*cc == OP_CREF)
+ {
+ offset = GET2(cc, 1);
+ if (!is_cbracket_processed(common, offset))
+ {
+ offset <<= 1;
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
+ stackpos -= SSIZE_OF(sw);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
+ stackpos -= SSIZE_OF(sw);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
+ stackpos -= SSIZE_OF(sw);
+ }
+ cc += 1 + IMM2_SIZE;
+ }
break;
case OP_CBRA:
@@ -2410,15 +2475,20 @@ while (cc < ccend)
stackpos -= SSIZE_OF(sw);
capture_last_found = TRUE;
}
- offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
- stackpos -= SSIZE_OF(sw);
- OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
- OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
- stackpos -= SSIZE_OF(sw);
- OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
- stackpos -= SSIZE_OF(sw);
+
+ offset = GET2(cc, 1 + LINK_SIZE);
+ if (!is_cbracket_processed(common, offset))
+ {
+ offset <<= 1;
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, SLJIT_IMM, OVECTOR(offset));
+ stackpos -= SSIZE_OF(sw);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP1, 0);
+ stackpos -= SSIZE_OF(sw);
+ OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), stackpos, TMP2, 0);
+ stackpos -= SSIZE_OF(sw);
+ }
cc += 1 + LINK_SIZE + IMM2_SIZE;
break;
@@ -2438,7 +2508,7 @@ SLJIT_ASSERT(stackpos == STACK(stacktop));
typedef struct delayed_mem_copy_status {
struct sljit_compiler *compiler;
int store_bases[RECURSE_TMP_REG_COUNT];
- int store_offsets[RECURSE_TMP_REG_COUNT];
+ sljit_s32 store_offsets[RECURSE_TMP_REG_COUNT];
int tmp_regs[RECURSE_TMP_REG_COUNT];
int saved_tmp_regs[RECURSE_TMP_REG_COUNT];
int next_tmp_reg;
@@ -2460,7 +2530,7 @@ status->compiler = common->compiler;
}
static void delayed_mem_copy_move(delayed_mem_copy_status *status, int load_base, sljit_sw load_offset,
- int store_base, sljit_sw store_offset)
+ int store_base, sljit_s32 store_offset)
{
struct sljit_compiler *compiler = status->compiler;
int next_tmp_reg = status->next_tmp_reg;
@@ -2537,17 +2607,31 @@ enum get_recurse_flags {
recurse_flag_setsom_found = (1 << 2),
recurse_flag_setmark_found = (1 << 3),
recurse_flag_control_head_found = (1 << 4),
+ recurse_flag_recurse_arg = (1 << 5),
};
static int get_recurse_data_length(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, uint32_t *result_flags)
{
int length = 1;
int size, offset;
-PCRE2_SPTR alternative;
+PCRE2_SPTR alternative, cref;
uint32_t recurse_flags = 0;
memset(common->recurse_bitset, 0, common->recurse_bitset_size);
+if (common->currententry->arg_size > 0)
+ {
+ cref = common->currententry->arg_start;
+
+ do
+ {
+ offset = GET2(cref, 1);
+ recurse_check_bit(common, OVECTOR(offset << 1));
+ cref += 1 + IMM2_SIZE;
+ }
+ while (*cref == OP_CREF);
+ }
+
#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD
SLJIT_ASSERT(common->control_head_ptr != 0);
recurse_flags |= recurse_flag_control_head_found;
@@ -2573,6 +2657,8 @@ while (cc < ccend)
if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))
length++;
cc += 1 + LINK_SIZE;
+ if (*cc == OP_CREF)
+ recurse_flags |= recurse_flag_recurse_arg;
break;
case OP_KET:
@@ -2605,6 +2691,22 @@ while (cc < ccend)
cc += 1 + LINK_SIZE;
break;
+ case OP_CREF:
+ if ((recurse_flags & recurse_flag_recurse_arg) != 0)
+ {
+ offset = GET2(cc, 1);
+ if (recurse_check_bit(common, OVECTOR(offset << 1)))
+ {
+ SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1)));
+ length += 2;
+ }
+
+ if (cc[1 + IMM2_SIZE] != OP_CREF)
+ recurse_flags &= ~(uint32_t)recurse_flag_recurse_arg;
+ }
+ cc += 1 + IMM2_SIZE;
+ break;
+
case OP_ASSERT_SCS:
SLJIT_ASSERT(PRIVATE_DATA(cc) != 0);
if (recurse_check_bit(common, PRIVATE_DATA(cc)))
@@ -2620,7 +2722,7 @@ while (cc < ccend)
SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1)));
length += 2;
}
- if (common->optimized_cbracket[offset] == 0 && recurse_check_bit(common, OVECTOR_PRIV(offset)))
+ if (!is_optimized_cbracket(common, offset) && recurse_check_bit(common, OVECTOR_PRIV(offset)))
length++;
if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))
length++;
@@ -2803,7 +2905,7 @@ static void copy_recurse_data(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR
int type, int stackptr, int stacktop, uint32_t recurse_flags)
{
delayed_mem_copy_status status;
-PCRE2_SPTR alternative;
+PCRE2_SPTR alternative, cref;
sljit_sw private_srcw[2];
sljit_sw shared_srcw[3];
sljit_sw kept_shared_srcw[2];
@@ -2812,6 +2914,19 @@ int from_sp, base_reg, offset, i;
memset(common->recurse_bitset, 0, common->recurse_bitset_size);
+if (common->currententry->arg_size > 0)
+ {
+ cref = common->currententry->arg_start;
+
+ do
+ {
+ offset = GET2(cref, 1);
+ recurse_check_bit(common, OVECTOR(offset << 1));
+ cref += 1 + IMM2_SIZE;
+ }
+ while (*cref == OP_CREF);
+ }
+
#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD
SLJIT_ASSERT(common->control_head_ptr != 0);
recurse_check_bit(common, common->control_head_ptr);
@@ -2924,12 +3039,16 @@ while (cc < ccend)
kept_shared_count++;
}
}
+
if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))
{
shared_srcw[0] = common->capture_last_ptr;
shared_count = 1;
}
+
cc += 1 + LINK_SIZE;
+ if (*cc == OP_CREF)
+ recurse_flags |= recurse_flag_recurse_arg;
break;
case OP_KET:
@@ -2962,6 +3081,24 @@ while (cc < ccend)
cc += 1 + LINK_SIZE;
break;
+ case OP_CREF:
+ if ((recurse_flags & recurse_flag_recurse_arg) != 0)
+ {
+ offset = GET2(cc, 1);
+ shared_srcw[0] = OVECTOR(offset << 1);
+ if (recurse_check_bit(common, shared_srcw[0]))
+ {
+ shared_srcw[1] = shared_srcw[0] + sizeof(sljit_sw);
+ SLJIT_ASSERT(recurse_check_bit(common, shared_srcw[1]));
+ shared_count = 2;
+ }
+
+ if (cc[1 + IMM2_SIZE] != OP_CREF)
+ recurse_flags &= ~(uint32_t)recurse_flag_recurse_arg;
+ }
+ cc += 1 + IMM2_SIZE;
+ break;
+
case OP_ASSERT_SCS:
private_srcw[0] = PRIVATE_DATA(cc);
private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
@@ -2987,7 +3124,7 @@ while (cc < ccend)
shared_count++;
}
- if (common->optimized_cbracket[offset] == 0)
+ if (!is_optimized_cbracket(common, offset))
{
private_srcw[0] = OVECTOR_PRIV(offset);
if (recurse_check_bit(common, private_srcw[0]))
@@ -3184,7 +3321,7 @@ while (cc < ccend)
SLJIT_ASSERT(private_srcw[i] != 0);
if (!from_sp)
- delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, private_srcw[i]);
+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, (sljit_s32)private_srcw[i]);
if (from_sp || type == recurse_swap_global)
delayed_mem_copy_move(&status, SLJIT_SP, private_srcw[i], base_reg, stackptr);
@@ -3204,7 +3341,7 @@ while (cc < ccend)
SLJIT_ASSERT(shared_srcw[i] != 0);
if (!from_sp)
- delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, shared_srcw[i]);
+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, (sljit_s32)shared_srcw[i]);
if (from_sp || type == recurse_swap_global)
delayed_mem_copy_move(&status, SLJIT_SP, shared_srcw[i], base_reg, stackptr);
@@ -3224,7 +3361,7 @@ while (cc < ccend)
SLJIT_ASSERT(kept_shared_srcw[i] != 0);
if (!from_sp)
- delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, kept_shared_srcw[i]);
+ delayed_mem_copy_move(&status, base_reg, stackptr, SLJIT_SP, (sljit_s32)kept_shared_srcw[i]);
if (from_sp || type == recurse_swap_global)
delayed_mem_copy_move(&status, SLJIT_SP, kept_shared_srcw[i], base_reg, stackptr);
@@ -3380,7 +3517,7 @@ OP2(SLJIT_SUB | SLJIT_SET_Z, COUNT_MATCH, 0, COUNT_MATCH, 0, SLJIT_IMM, 1);
add_jump(compiler, &common->calllimit, JUMP(SLJIT_ZERO));
}
-static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
+static SLJIT_INLINE void allocate_stack(compiler_common *common, sljit_s32 size)
{
/* May destroy all locals and registers except TMP2. */
DEFINE_COMPILER;
@@ -3401,7 +3538,7 @@ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, TMP1, 0);
add_stub(common, CMP(SLJIT_LESS, STACK_TOP, 0, STACK_LIMIT, 0));
}
-static SLJIT_INLINE void free_stack(compiler_common *common, int size)
+static SLJIT_INLINE void free_stack(compiler_common *common, sljit_s32 size)
{
DEFINE_COMPILER;
@@ -3827,9 +3964,12 @@ oc = TABLE_GET(c, common->fcc, c);
SLJIT_ASSERT(c != oc);
bit = c ^ oc;
+
+#ifndef EBCDIC
/* Optimized for English alphabet. */
if (c <= 127 && bit == 0x20)
return (0 << 8) | 0x20;
+#endif
/* Since c != oc, they must have at least 1 bit difference. */
if (!is_powerof2(bit))
@@ -5433,8 +5573,7 @@ OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, TMP1, 0, TMP1, 0, TMP2, 0, UCD_BLOCK_SHIFT);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);
@@ -5473,16 +5612,14 @@ OP2(SLJIT_LSHR, TMP2, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 1);
OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_stage1));
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BLOCK_MASK);
-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT);
-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, TMP1, 0, TMP1, 0, TMP2, 0, UCD_BLOCK_SHIFT);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
-/* TMP2 is multiplied by 12. Same as (TMP2 << 2) + ((TMP2 << 2) << 1). */
+/* TMP2 is multiplied by 12. Same as (TMP2 + (TMP2 << 1)) << 2. */
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
-OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);
-OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
-OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 1);
+sljit_emit_op2_shift(compiler, SLJIT_ADD | SLJIT_SHL_IMM | SLJIT_SRC2_UNDEFINED, TMP2, 0, TMP2, 0, TMP2, 0, 1);
+OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 2);
OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);
}
@@ -5807,7 +5944,7 @@ while (TRUE)
{
case OP_CHARI:
caseless = TRUE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_CHAR:
last = FALSE;
cc++;
@@ -5844,7 +5981,7 @@ while (TRUE)
case OP_MINPLUSI:
case OP_POSPLUSI:
caseless = TRUE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_PLUS:
case OP_MINPLUS:
case OP_POSPLUS:
@@ -5853,7 +5990,7 @@ while (TRUE)
case OP_EXACTI:
caseless = TRUE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_EXACT:
repeat = GET2(cc, 1);
last = FALSE;
@@ -5864,7 +6001,7 @@ while (TRUE)
case OP_MINQUERYI:
case OP_POSQUERYI:
caseless = TRUE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_QUERY:
case OP_MINQUERY:
case OP_POSQUERY:
@@ -5996,7 +6133,7 @@ while (TRUE)
case OP_NOT:
case OP_NOTI:
cc++;
- /* Fall through. */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_NOT_DIGIT:
case OP_NOT_WHITESPACE:
case OP_NOT_WORDCHAR:
@@ -6079,7 +6216,7 @@ while (TRUE)
case OP_CRMINQUERY:
case OP_CRPOSQUERY:
last = FALSE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_CRSTAR:
case OP_CRMINSTAR:
case OP_CRPOSSTAR:
@@ -6751,7 +6888,7 @@ if (JIT_HAS_FAST_FORWARD_CHAR_SIMD && (common->nltype == NLTYPE_FIXED || common-
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
quit = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
}
- else
+ else
{
fast_forward_char_simd(common, common->newline, common->newline, 0);
@@ -7435,10 +7572,22 @@ DEFINE_COMPILER;
sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);
-OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
-OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
+#ifdef EBCDIC
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_LF);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_VT);
+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_FF);
+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_CR);
+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NEL);
+#else
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, CHAR_LF);
+OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR - CHAR_LF);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
-OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NEL - CHAR_LF);
+#endif
#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
@@ -7446,7 +7595,7 @@ if (common->utf)
#endif
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x2029 - CHAR_LF);
#if PCRE2_CODE_UNIT_WIDTH == 8
}
#endif
@@ -7462,11 +7611,11 @@ DEFINE_COMPILER;
sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);
-OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x09);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_HT);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
-OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x20);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_SPACE);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
-OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0xa0);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NBSP);
#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
@@ -7478,7 +7627,7 @@ if (common->utf)
OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
- OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x200a - 0x2000);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
@@ -7501,10 +7650,22 @@ DEFINE_COMPILER;
sljit_emit_op_dst(compiler, SLJIT_FAST_ENTER, RETURN_ADDR, 0);
-OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
-OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
+#ifdef EBCDIC
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_LF);
+OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_VT);
+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_FF);
+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_CR);
+OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NEL);
+#else
+OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, CHAR_LF);
+OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR - CHAR_LF);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
-OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NEL - CHAR_LF);
+#endif
#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
@@ -7512,7 +7673,7 @@ if (common->utf)
#endif
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
- OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x2029 - CHAR_LF);
#if PCRE2_CODE_UNIT_WIDTH == 8
}
#endif
@@ -8447,11 +8608,18 @@ DEFINE_COMPILER;
backtrack_common *backtrack;
recurse_entry *entry = common->entries;
recurse_entry *prev = NULL;
+PCRE2_SPTR end;
sljit_sw start = GET(cc, 1);
+sljit_uw arg_size;
PCRE2_SPTR start_cc;
BOOL needs_control_head;
-PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, NULL);
+end = cc + 1 + LINK_SIZE;
+
+while (*end == OP_CREF)
+ end += 1 + IMM2_SIZE;
+
+PUSH_BACKTRACK(sizeof(recurse_backtrack), cc, end);
/* Inlining simple patterns. */
if (get_framesize(common, common->start + start, NULL, TRUE, &needs_control_head) == no_stack)
@@ -8459,12 +8627,15 @@ if (get_framesize(common, common->start + start, NULL, TRUE, &needs_control_head
start_cc = common->start + start;
compile_matchingpath(common, next_opcode(common, start_cc), bracketend(start_cc) - (1 + LINK_SIZE), backtrack);
BACKTRACK_AS(recurse_backtrack)->inlined_pattern = TRUE;
- return cc + 1 + LINK_SIZE;
+ return end;
}
+cc += 1 + LINK_SIZE;
+arg_size = (sljit_uw)IN_UCHARS(end - cc);
while (entry != NULL)
{
- if (entry->start == start)
+ if (entry->start == start && entry->arg_size == arg_size
+ && (arg_size == 0 || memcmp(cc, entry->arg_start, arg_size) == 0))
break;
prev = entry;
entry = entry->next;
@@ -8474,13 +8645,15 @@ if (entry == NULL)
{
entry = sljit_alloc_memory(compiler, sizeof(recurse_entry));
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
- return NULL;
+ return end;
entry->next = NULL;
entry->entry_label = NULL;
entry->backtrack_label = NULL;
entry->entry_calls = NULL;
entry->backtrack_calls = NULL;
entry->start = start;
+ entry->arg_start = cc;
+ entry->arg_size = arg_size;
if (prev != NULL)
prev->next = entry;
@@ -8497,7 +8670,7 @@ else
/* Leave if the match is failed. */
add_jump(compiler, &backtrack->own_backtracks, CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, 0));
BACKTRACK_AS(recurse_backtrack)->matchingpath = LABEL();
-return cc + 1 + LINK_SIZE;
+return end;
}
static sljit_s32 SLJIT_FUNC do_callout_jit(struct jit_arguments *arguments, pcre2_callout_block *callout_block, PCRE2_SPTR *jit_ovector)
@@ -8567,7 +8740,7 @@ unsigned int callout_length = (*cc == OP_CALLOUT)
sljit_sw value1;
sljit_sw value2;
sljit_sw value3;
-sljit_uw callout_arg_size = (common->re->top_bracket + 1) * 2 * SSIZE_OF(sw);
+sljit_s32 callout_arg_size = (common->re->top_bracket + 1) * 2 * SSIZE_OF(sw); /* top_bracket is uint16 so maximum is 1MiB */
PUSH_BACKTRACK(sizeof(backtrack_common), cc, NULL);
@@ -8660,7 +8833,7 @@ if (*cc == OP_REVERSE)
else
{
SLJIT_ASSERT(*cc == OP_VREVERSE);
- PUSH_BACKTRACK(sizeof(vreverse_backtrack), cc, NULL);
+ PUSH_BACKTRACK(sizeof(vreverse_backtrack), cc, cc + 1 + 2 * IMM2_SIZE);
reverse_failed = &backtrack->own_backtracks;
lmin = GET2(cc, 1);
@@ -9304,7 +9477,7 @@ if (common->capture_last_ptr != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), TMP1, 0);
stacksize++;
}
-if (common->optimized_cbracket[offset >> 1] == 0)
+if (!is_optimized_cbracket(common, offset >> 1))
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset));
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1));
@@ -9478,7 +9651,7 @@ if (opcode == OP_CBRA || opcode == OP_SCBRA)
{
/* Capturing brackets has a pre-allocated space. */
offset = GET2(ccbegin, 1 + LINK_SIZE);
- if (common->optimized_cbracket[offset] == 0)
+ if (!is_optimized_cbracket(common, offset))
{
private_data_ptr = OVECTOR_PRIV(offset);
offset <<= 1;
@@ -9659,7 +9832,7 @@ if (opcode == OP_ONCE)
else if (opcode == OP_CBRA || opcode == OP_SCBRA)
{
/* Saving the previous values. */
- if (common->optimized_cbracket[offset >> 1] != 0)
+ if (is_optimized_cbracket(common, offset >> 1))
{
SLJIT_ASSERT(private_data_ptr == OVECTOR(offset));
allocate_stack(common, 2);
@@ -9896,6 +10069,8 @@ if (opcode == OP_COND || opcode == OP_SCOND)
assert->common.cc = matchingpath;
BACKTRACK_AS(bracket_backtrack)->u.assert = assert;
matchingpath = compile_assert_matchingpath(common, matchingpath, assert, TRUE);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ return NULL;
}
}
@@ -9936,7 +10111,7 @@ if (offset != 0)
{
if (common->capture_last_ptr != 0)
stacksize++;
- if (common->optimized_cbracket[offset >> 1] == 0)
+ if (!is_optimized_cbracket(common, offset >> 1))
stacksize += 2;
}
if (has_alternatives && opcode != OP_ONCE)
@@ -9980,14 +10155,14 @@ if (has_alternatives)
if (i <= 3)
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, 0);
else
- BACKTRACK_AS(bracket_backtrack)->matching_mov_addr = sljit_emit_mov_addr(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));
+ BACKTRACK_AS(bracket_backtrack)->matching_mov_addr = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM1(STACK_TOP), STACK(stacksize));
}
if (ket != OP_KETRMAX)
BACKTRACK_AS(bracket_backtrack)->alternative_matchingpath = LABEL();
}
/* Must be after the matchingpath label. */
-if (offset != 0 && common->optimized_cbracket[offset >> 1] != 0)
+if (offset != 0 && is_optimized_cbracket(common, offset >> 1))
{
SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), STR_PTR, 0);
@@ -10149,7 +10324,7 @@ switch(opcode)
offset = GET2(cc, 1 + LINK_SIZE);
/* This case cannot be optimized in the same way as
normal capturing brackets. */
- SLJIT_ASSERT(common->optimized_cbracket[offset] == 0);
+ SLJIT_ASSERT(!is_optimized_cbracket(common, offset));
cbraprivptr = OVECTOR_PRIV(offset);
offset <<= 1;
ccbegin = cc + 1 + LINK_SIZE + IMM2_SIZE;
@@ -11331,7 +11506,7 @@ static SLJIT_INLINE PCRE2_SPTR compile_close_matchingpath(compiler_common *commo
{
DEFINE_COMPILER;
int offset = GET2(cc, 1);
-BOOL optimized_cbracket = common->optimized_cbracket[offset] != 0;
+BOOL optimized_cbracket = is_optimized_cbracket(common, offset);
/* Data will be discarded anyway... */
if (common->currententry != NULL)
@@ -12202,7 +12377,7 @@ if (offset != 0)
{
if (common->capture_last_ptr != 0)
{
- SLJIT_ASSERT(common->optimized_cbracket[offset >> 1] == 0);
+ SLJIT_ASSERT(!is_optimized_cbracket(common, offset >> 1));
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, TMP1, 0);
@@ -12211,7 +12386,7 @@ if (offset != 0)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset), TMP2, 0);
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(offset + 1), TMP1, 0);
}
- else if (common->optimized_cbracket[offset >> 1] == 0)
+ else if (!is_optimized_cbracket(common, offset >> 1))
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
@@ -12393,7 +12568,7 @@ if (has_alternatives)
{
if (common->capture_last_ptr != 0)
stacksize++;
- if (common->optimized_cbracket[offset >> 1] == 0)
+ if (!is_optimized_cbracket(common, offset >> 1))
stacksize += 2;
}
if (opcode != OP_ONCE)
@@ -12427,10 +12602,10 @@ if (has_alternatives)
if (alt_max <= 3)
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(stacksize), SLJIT_IMM, alt_count);
else
- mov_addr = sljit_emit_mov_addr(compiler, SLJIT_MEM1(STACK_TOP), STACK(stacksize));
+ mov_addr = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM1(STACK_TOP), STACK(stacksize));
}
- if (offset != 0 && ket == OP_KETRMAX && common->optimized_cbracket[offset >> 1] != 0)
+ if (offset != 0 && ket == OP_KETRMAX && is_optimized_cbracket(common, offset >> 1))
{
/* If ket is not OP_KETRMAX, this code path is executed after the jump to alternative_matchingpath. */
SLJIT_ASSERT(private_data_ptr == OVECTOR(offset + 0));
@@ -12492,7 +12667,7 @@ if (has_alternatives)
if (offset != 0)
{
/* Using both tmp register is better for instruction scheduling. */
- if (common->optimized_cbracket[offset >> 1] != 0)
+ if (is_optimized_cbracket(common, offset >> 1))
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(1));
@@ -12670,6 +12845,8 @@ if (current->cc[1] > OP_ASSERTBACK_NOT)
{
/* Manual call of compile_bracket_matchingpath and compile_bracket_backtrackingpath. */
compile_bracket_matchingpath(common, current->cc, current);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(common->compiler)))
+ return;
compile_bracket_backtrackingpath(common, current->top);
}
else
@@ -12679,6 +12856,8 @@ else
backtrack.matchingpath = CURRENT_AS(braminzero_backtrack)->matchingpath;
/* Manual call of compile_assert_matchingpath. */
compile_assert_matchingpath(common, current->cc, &backtrack, FALSE);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(common->compiler)))
+ return;
}
SLJIT_ASSERT(!current->simple_backtracks && !current->own_backtracks);
}
@@ -13093,7 +13272,7 @@ while (1)
if (alt_max > 1 || (recurse_flags & recurse_flag_accept_found))
{
if (alt_max > 3)
- mov_addr = sljit_emit_mov_addr(compiler, SLJIT_MEM1(STACK_TOP), STACK(1));
+ mov_addr = sljit_emit_op_addr(compiler, SLJIT_MOV_ADDR, SLJIT_MEM1(STACK_TOP), STACK(1));
else
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, alt_count);
}
@@ -13360,7 +13539,8 @@ if (private_data_length > ~(sljit_uw)0 / sizeof(sljit_s32))
private_data_length *= sizeof(sljit_s32);
/* Align to 32 bit. */
-total_length = ((re->top_bracket + 1) + (sljit_uw)(sizeof(sljit_s32) - 1)) & ~(sljit_uw)(sizeof(sljit_s32) - 1);
+common->cbracket_bitset_length = ((re->top_bracket + 1) + (sljit_u32)7) & ~(sljit_u32)7;
+total_length = common->cbracket_bitset_length << 1;
if (~(sljit_uw)0 - private_data_length < total_length)
return PCRE2_ERROR_NOMEMORY;
@@ -13370,12 +13550,13 @@ if (!common->private_data_ptrs)
return PCRE2_ERROR_NOMEMORY;
memset(common->private_data_ptrs, 0, private_data_length);
-common->optimized_cbracket = ((sljit_u8 *)common->private_data_ptrs) + private_data_length;
+common->optimized_cbrackets = ((sljit_u8 *)common->private_data_ptrs) + private_data_length;
#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 1
-memset(common->optimized_cbracket, 0, re->top_bracket + 1);
+memset(common->optimized_cbrackets, 0, common->cbracket_bitset_length);
#else
-memset(common->optimized_cbracket, 1, re->top_bracket + 1);
+memset(common->optimized_cbrackets, 0xff, common->cbracket_bitset_length);
#endif
+common->cbracket_bitset = common->optimized_cbrackets + common->cbracket_bitset_length;
SLJIT_ASSERT(*common->start == OP_BRA && ccend[-(1 + LINK_SIZE)] == OP_KET);
#if defined DEBUG_FORCE_UNOPTIMIZED_CBRAS && DEBUG_FORCE_UNOPTIMIZED_CBRAS == 2
@@ -13440,7 +13621,7 @@ if (common->start_ptr == 0)
/* Capturing brackets cannot be optimized if callouts are allowed. */
if (common->capture_last_ptr != 0)
- memset(common->optimized_cbracket, 0, re->top_bracket + 1);
+ memset(common->optimized_cbrackets, 0, common->cbracket_bitset_length);
SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);
@@ -13591,6 +13772,34 @@ common->accept_label = LABEL();
if (common->accept != NULL)
set_jumps(common->accept, common->accept_label);
+/* Fail if we detect that the start position was moved to be either after
+the end position (\K in lookahead) or before the start offset (\K in
+lookbehind). */
+
+if (common->has_set_som &&
+ (common->re->extra_options & PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) == 0)
+ {
+ if (HAS_VIRTUAL_REGISTERS)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
+ }
+ else
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str));
+ }
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), OVECTOR(0));
+
+ /* (ovector[0] < jit_arguments->str)? */
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, TMP1, 0);
+ /* Unconditionally set R0 (aka TMP1), in between the comparison that needs to
+ use TMP1, but before the jump. */
+ OP1(SLJIT_MOV, SLJIT_RETURN_REG, 0, SLJIT_IMM, PCRE2_ERROR_BAD_BACKSLASH_K);
+ add_jump(compiler, &common->abort, JUMP(SLJIT_LESS));
+ /* (ovector[0] > STR_PTR)? NB. ovector[1] hasn't yet been set to STR_PTR. */
+ add_jump(compiler, &common->abort, CMP(SLJIT_GREATER, TMP2, 0, STR_PTR, 0));
+ }
+
/* This means we have a match. Update the ovector. */
copy_ovector(common, re->top_bracket + 1);
common->quit_label = common->abort_label = LABEL();
@@ -14099,7 +14308,7 @@ return 0;
#define INCLUDED_FROM_PCRE2_JIT_COMPILE
-#include "pcre2_jit_match.c"
-#include "pcre2_jit_misc.c"
+#include "pcre2_jit_match_inc.h"
+#include "pcre2_jit_misc_inc.h"
/* End of pcre2_jit_compile.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_jit_match.c b/src/3rdparty/pcre2/src/pcre2_jit_match_inc.h
index 8867f768df1..32d4c8a5e1a 100644
--- a/src/3rdparty/pcre2/src/pcre2_jit_match.c
+++ b/src/3rdparty/pcre2/src/pcre2_jit_match_inc.h
@@ -99,9 +99,8 @@ pcre2_jit_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
(void)length;
(void)start_offset;
(void)options;
-(void)match_data;
(void)mcontext;
-return PCRE2_ERROR_JIT_BADOPTION;
+return match_data->rc = PCRE2_ERROR_JIT_BADOPTION;
#else /* SUPPORT_JIT */
@@ -124,7 +123,7 @@ else if ((options & PCRE2_PARTIAL_SOFT) != 0)
index = 1;
if (functions == NULL || functions->executable_funcs[index] == NULL)
- return PCRE2_ERROR_JIT_BADOPTION;
+ return match_data->rc = PCRE2_ERROR_JIT_BADOPTION;
/* Sanity checks should be handled by pcre2_match. */
arguments.str = subject + start_offset;
@@ -176,14 +175,17 @@ else
if (rc > (int)oveccount)
rc = 0;
match_data->code = re;
-match_data->subject = (rc >= 0 || rc == PCRE2_ERROR_PARTIAL)? subject : NULL;
+match_data->subject =
+ (rc >= 0 || rc == PCRE2_ERROR_NOMATCH || rc == PCRE2_ERROR_PARTIAL)? subject : NULL;
match_data->subject_length = length;
+match_data->start_offset = start_offset;
match_data->rc = rc;
match_data->startchar = arguments.startchar_ptr - subject;
match_data->leftchar = 0;
match_data->rightchar = 0;
match_data->mark = arguments.mark_ptr;
match_data->matchedby = PCRE2_MATCHEDBY_JIT;
+match_data->options = options;
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
@@ -197,4 +199,4 @@ return match_data->rc;
#endif /* SUPPORT_JIT */
}
-/* End of pcre2_jit_match.c */
+/* End of pcre2_jit_match_inc.h */
diff --git a/src/3rdparty/pcre2/src/pcre2_jit_misc.c b/src/3rdparty/pcre2/src/pcre2_jit_misc_inc.h
index c3abc0b33bd..0225fc6baf2 100644
--- a/src/3rdparty/pcre2/src/pcre2_jit_misc.c
+++ b/src/3rdparty/pcre2/src/pcre2_jit_misc_inc.h
@@ -231,4 +231,4 @@ return executable_sizes[0] + executable_sizes[1] + executable_sizes[2];
#endif
}
-/* End of pcre2_jit_misc.c */
+/* End of pcre2_jit_misc_inc.h */
diff --git a/src/3rdparty/pcre2/src/pcre2_jit_neon_inc.h b/src/3rdparty/pcre2/src/pcre2_jit_neon_inc.h
deleted file mode 100644
index 1389a16573d..00000000000
--- a/src/3rdparty/pcre2/src/pcre2_jit_neon_inc.h
+++ /dev/null
@@ -1,354 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* PCRE is a library of functions to support regular expressions whose syntax
-and semantics are as close as possible to those of the Perl 5 language.
-
- Written by Philip Hazel
- This module by Zoltan Herczeg and Sebastian Pop
- Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2019 University of Cambridge
-
------------------------------------------------------------------------------
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- * Neither the name of the University of Cambridge nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
-*/
-
-# if defined(FFCS)
-# if defined(FF_UTF)
-# define FF_FUN ffcs_utf
-# else
-# define FF_FUN ffcs
-# endif
-
-# elif defined(FFCS_2)
-# if defined(FF_UTF)
-# define FF_FUN ffcs_2_utf
-# else
-# define FF_FUN ffcs_2
-# endif
-
-# elif defined(FFCS_MASK)
-# if defined(FF_UTF)
-# define FF_FUN ffcs_mask_utf
-# else
-# define FF_FUN ffcs_mask
-# endif
-
-# elif defined(FFCPS_0)
-# if defined (FF_UTF)
-# define FF_FUN ffcps_0_utf
-# else
-# define FF_FUN ffcps_0
-# endif
-
-# elif defined (FFCPS_1)
-# if defined (FF_UTF)
-# define FF_FUN ffcps_1_utf
-# else
-# define FF_FUN ffcps_1
-# endif
-
-# elif defined (FFCPS_DEFAULT)
-# if defined (FF_UTF)
-# define FF_FUN ffcps_default_utf
-# else
-# define FF_FUN ffcps_default
-# endif
-# endif
-
-#if (defined(__GNUC__) && defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__ ) \
- || (defined(__clang__) \
- && ((__clang_major__ == 3 && __clang_minor__ >= 3) || (__clang_major__ > 3)))
-__attribute__((no_sanitize_address))
-#endif
-static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 **str_ptr, sljit_uw offs1, sljit_uw offs2, sljit_uw chars)
-#undef FF_FUN
-{
-quad_word qw;
-int_char ic;
-
-SLJIT_UNUSED_ARG(offs1);
-SLJIT_UNUSED_ARG(offs2);
-
-ic.x = chars;
-
-#if defined(FFCS)
-sljit_u8 c1 = ic.c.c1;
-vect_t vc1 = VDUPQ(c1);
-
-#elif defined(FFCS_2)
-sljit_u8 c1 = ic.c.c1;
-vect_t vc1 = VDUPQ(c1);
-sljit_u8 c2 = ic.c.c2;
-vect_t vc2 = VDUPQ(c2);
-
-#elif defined(FFCS_MASK)
-sljit_u8 c1 = ic.c.c1;
-vect_t vc1 = VDUPQ(c1);
-sljit_u8 mask = ic.c.c2;
-vect_t vmask = VDUPQ(mask);
-#endif
-
-#if defined(FFCPS)
-compare_type compare1_type = compare_match1;
-compare_type compare2_type = compare_match1;
-vect_t cmp1a, cmp1b, cmp2a, cmp2b;
-const sljit_u32 diff = IN_UCHARS(offs1 - offs2);
-PCRE2_UCHAR char1a = ic.c.c1;
-PCRE2_UCHAR char2a = ic.c.c3;
-
-# ifdef FFCPS_CHAR1A2A
-cmp1a = VDUPQ(char1a);
-cmp2a = VDUPQ(char2a);
-cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
-cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
-# else
-PCRE2_UCHAR char1b = ic.c.c2;
-PCRE2_UCHAR char2b = ic.c.c4;
-if (char1a == char1b)
- {
- cmp1a = VDUPQ(char1a);
- cmp1b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
- }
-else
- {
- sljit_u32 bit1 = char1a ^ char1b;
- if (is_powerof2(bit1))
- {
- compare1_type = compare_match1i;
- cmp1a = VDUPQ(char1a | bit1);
- cmp1b = VDUPQ(bit1);
- }
- else
- {
- compare1_type = compare_match2;
- cmp1a = VDUPQ(char1a);
- cmp1b = VDUPQ(char1b);
- }
- }
-
-if (char2a == char2b)
- {
- cmp2a = VDUPQ(char2a);
- cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */
- }
-else
- {
- sljit_u32 bit2 = char2a ^ char2b;
- if (is_powerof2(bit2))
- {
- compare2_type = compare_match1i;
- cmp2a = VDUPQ(char2a | bit2);
- cmp2b = VDUPQ(bit2);
- }
- else
- {
- compare2_type = compare_match2;
- cmp2a = VDUPQ(char2a);
- cmp2b = VDUPQ(char2b);
- }
- }
-# endif
-
-*str_ptr += IN_UCHARS(offs1);
-#endif
-
-#if PCRE2_CODE_UNIT_WIDTH != 8
-vect_t char_mask = VDUPQ(0xff);
-#endif
-
-#if defined(FF_UTF)
-restart:;
-#endif
-
-#if defined(FFCPS)
-if (*str_ptr >= str_end)
- return NULL;
-sljit_u8 *p1 = *str_ptr - diff;
-#endif
-sljit_s32 align_offset = ((uint64_t)*str_ptr & 0xf);
-*str_ptr = (sljit_u8 *) ((uint64_t)*str_ptr & ~0xf);
-vect_t data = VLD1Q(*str_ptr);
-#if PCRE2_CODE_UNIT_WIDTH != 8
-data = VANDQ(data, char_mask);
-#endif
-
-#if defined(FFCS)
-vect_t eq = VCEQQ(data, vc1);
-
-#elif defined(FFCS_2)
-vect_t eq1 = VCEQQ(data, vc1);
-vect_t eq2 = VCEQQ(data, vc2);
-vect_t eq = VORRQ(eq1, eq2);
-
-#elif defined(FFCS_MASK)
-vect_t eq = VORRQ(data, vmask);
-eq = VCEQQ(eq, vc1);
-
-#elif defined(FFCPS)
-# if defined(FFCPS_DIFF1)
-vect_t prev_data = data;
-# endif
-
-vect_t data2;
-if (p1 < *str_ptr)
- {
- data2 = VLD1Q(*str_ptr - diff);
-#if PCRE2_CODE_UNIT_WIDTH != 8
- data2 = VANDQ(data2, char_mask);
-#endif
- }
-else
- data2 = shift_left_n_lanes(data, offs1 - offs2);
-
-if (compare1_type == compare_match1)
- data = VCEQQ(data, cmp1a);
-else
- data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
-
-if (compare2_type == compare_match1)
- data2 = VCEQQ(data2, cmp2a);
-else
- data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
-
-vect_t eq = VANDQ(data, data2);
-#endif
-
-VST1Q(qw.mem, eq);
-/* Ignore matches before the first STR_PTR. */
-if (align_offset < 8)
- {
- qw.dw[0] >>= align_offset * 8;
- if (qw.dw[0])
- {
- *str_ptr += align_offset + __builtin_ctzll(qw.dw[0]) / 8;
- goto match;
- }
- if (qw.dw[1])
- {
- *str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
- goto match;
- }
- }
-else
- {
- qw.dw[1] >>= (align_offset - 8) * 8;
- if (qw.dw[1])
- {
- *str_ptr += align_offset + __builtin_ctzll(qw.dw[1]) / 8;
- goto match;
- }
- }
-*str_ptr += 16;
-
-while (*str_ptr < str_end)
- {
- vect_t orig_data = VLD1Q(*str_ptr);
-#if PCRE2_CODE_UNIT_WIDTH != 8
- orig_data = VANDQ(orig_data, char_mask);
-#endif
- data = orig_data;
-
-#if defined(FFCS)
- eq = VCEQQ(data, vc1);
-
-#elif defined(FFCS_2)
- eq1 = VCEQQ(data, vc1);
- eq2 = VCEQQ(data, vc2);
- eq = VORRQ(eq1, eq2);
-
-#elif defined(FFCS_MASK)
- eq = VORRQ(data, vmask);
- eq = VCEQQ(eq, vc1);
-#endif
-
-#if defined(FFCPS)
-# if defined (FFCPS_DIFF1)
- data2 = VEXTQ(prev_data, data, VECTOR_FACTOR - 1);
-# else
- data2 = VLD1Q(*str_ptr - diff);
-# if PCRE2_CODE_UNIT_WIDTH != 8
- data2 = VANDQ(data2, char_mask);
-# endif
-# endif
-
-# ifdef FFCPS_CHAR1A2A
- data = VCEQQ(data, cmp1a);
- data2 = VCEQQ(data2, cmp2a);
-# else
- if (compare1_type == compare_match1)
- data = VCEQQ(data, cmp1a);
- else
- data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b);
- if (compare2_type == compare_match1)
- data2 = VCEQQ(data2, cmp2a);
- else
- data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b);
-# endif
-
- eq = VANDQ(data, data2);
-#endif
-
- VST1Q(qw.mem, eq);
- if (qw.dw[0])
- *str_ptr += __builtin_ctzll(qw.dw[0]) / 8;
- else if (qw.dw[1])
- *str_ptr += 8 + __builtin_ctzll(qw.dw[1]) / 8;
- else {
- *str_ptr += 16;
-#if defined (FFCPS_DIFF1)
- prev_data = orig_data;
-#endif
- continue;
- }
-
-match:;
- if (*str_ptr >= str_end)
- /* Failed match. */
- return NULL;
-
-#if defined(FF_UTF)
- if (utf_continue((PCRE2_SPTR)*str_ptr - offs1))
- {
- /* Not a match. */
- *str_ptr += IN_UCHARS(1);
- goto restart;
- }
-#endif
-
- /* Match. */
-#if defined (FFCPS)
- *str_ptr -= IN_UCHARS(offs1);
-#endif
- return *str_ptr;
- }
-
-/* Failed match. */
-return NULL;
-}
diff --git a/src/3rdparty/pcre2/src/pcre2_jit_simd_inc.h b/src/3rdparty/pcre2/src/pcre2_jit_simd_inc.h
index 66e93cd5996..0a24cdad813 100644
--- a/src/3rdparty/pcre2/src/pcre2_jit_simd_inc.h
+++ b/src/3rdparty/pcre2/src/pcre2_jit_simd_inc.h
@@ -42,6 +42,7 @@ POSSIBILITY OF SUCH DAMAGE.
#if !(defined SUPPORT_VALGRIND)
#if ((defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \
|| (defined SLJIT_CONFIG_LOONGARCH_64 && SLJIT_CONFIG_LOONGARCH_64))
@@ -100,7 +101,7 @@ return CMP(SLJIT_NOT_EQUAL, reg, 0, SLJIT_IMM, 0xdc00);
}
#endif
-#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_S390X */
+#endif /* SLJIT_CONFIG_X86 || SLJIT_CONFIG_ARM_64 || SLJIT_CONFIG_S390X || SLJIT_CONFIG_LOONGARCH_64 */
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
@@ -228,7 +229,14 @@ switch (step)
}
}
+/* The AVX2 code path is currently disabled.
#define JIT_HAS_FAST_FORWARD_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SIMD))
+*/
+#if defined(SLJIT_CONFIG_X86_64) && SLJIT_CONFIG_X86_64
+#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1
+#else
+#define JIT_HAS_FAST_FORWARD_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_FPU))
+#endif
static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)
{
@@ -246,10 +254,10 @@ struct sljit_jump *quit;
struct sljit_jump *partial_quit[2];
vector_compare_type compare_type = vector_compare_match1;
sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);
-sljit_s32 data_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);
-sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);
-sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);
-sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);
+sljit_s32 data_ind = sljit_get_register_index(reg_type, SLJIT_VR0);
+sljit_s32 cmp1_ind = sljit_get_register_index(reg_type, SLJIT_VR1);
+sljit_s32 cmp2_ind = sljit_get_register_index(reg_type, SLJIT_VR2);
+sljit_s32 tmp_ind = sljit_get_register_index(reg_type, SLJIT_VR3);
sljit_u32 bit = 0;
int i;
@@ -365,7 +373,14 @@ if (common->utf && offset > 0)
#endif
}
+/* The AVX2 code path is currently disabled.
#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SIMD))
+*/
+#if defined(SLJIT_CONFIG_X86_64) && SLJIT_CONFIG_X86_64
+#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD 1
+#else
+#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_FPU))
+#endif
static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2)
{
@@ -380,10 +395,10 @@ struct sljit_jump *quit;
jump_list *not_found = NULL;
vector_compare_type compare_type = vector_compare_match1;
sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);
-sljit_s32 data_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);
-sljit_s32 cmp1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);
-sljit_s32 cmp2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);
-sljit_s32 tmp_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);
+sljit_s32 data_ind = sljit_get_register_index(reg_type, SLJIT_VR0);
+sljit_s32 cmp1_ind = sljit_get_register_index(reg_type, SLJIT_VR1);
+sljit_s32 cmp2_ind = sljit_get_register_index(reg_type, SLJIT_VR2);
+sljit_s32 tmp_ind = sljit_get_register_index(reg_type, SLJIT_VR3);
sljit_u32 bit = 0;
int i;
@@ -471,7 +486,14 @@ return not_found;
#ifndef _WIN64
+/* The AVX2 code path is currently disabled.
#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SIMD))
+*/
+#if defined(SLJIT_CONFIG_X86_64) && SLJIT_CONFIG_X86_64
+#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD 1
+#else
+#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_FPU))
+#endif
static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1,
PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)
@@ -488,14 +510,14 @@ sljit_u32 bit1 = 0;
sljit_u32 bit2 = 0;
sljit_u32 diff = IN_UCHARS(offs1 - offs2);
sljit_s32 tmp1_reg_ind = sljit_get_register_index(SLJIT_GP_REGISTER, TMP1);
-sljit_s32 data1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);
-sljit_s32 data2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);
-sljit_s32 cmp1a_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);
-sljit_s32 cmp2a_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);
-sljit_s32 cmp1b_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR4);
-sljit_s32 cmp2b_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR5);
-sljit_s32 tmp1_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR6);
-sljit_s32 tmp2_ind = sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_TMP_DEST_VREG);
+sljit_s32 data1_ind = sljit_get_register_index(reg_type, SLJIT_VR0);
+sljit_s32 data2_ind = sljit_get_register_index(reg_type, SLJIT_VR1);
+sljit_s32 cmp1a_ind = sljit_get_register_index(reg_type, SLJIT_VR2);
+sljit_s32 cmp2a_ind = sljit_get_register_index(reg_type, SLJIT_VR3);
+sljit_s32 cmp1b_ind = sljit_get_register_index(reg_type, SLJIT_VR4);
+sljit_s32 cmp2b_ind = sljit_get_register_index(reg_type, SLJIT_VR5);
+sljit_s32 tmp1_ind = sljit_get_register_index(reg_type, SLJIT_VR6);
+sljit_s32 tmp2_ind = sljit_get_register_index(reg_type, SLJIT_TMP_DEST_VREG);
struct sljit_label *start;
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
struct sljit_label *restart;
@@ -692,8 +714,8 @@ sljit_emit_simd_mov(compiler, reg_type, SLJIT_VR1, SLJIT_MEM1(STR_PTR), -(sljit_
for (i = 0; i < 4; i++)
{
- fast_forward_char_pair_sse2_compare(compiler, compare1_type, reg_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp2_ind);
- fast_forward_char_pair_sse2_compare(compiler, compare2_type, reg_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp1_ind);
+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, reg_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);
+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, reg_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);
}
sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | reg_type, SLJIT_VR0, SLJIT_VR0, SLJIT_VR1, 0);
@@ -744,286 +766,284 @@ if (common->match_end_ptr != 0)
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 && (defined __ARM_NEON || defined __ARM_NEON__))
-#include <arm_neon.h>
-
-typedef union {
- unsigned int x;
- struct { unsigned char c1, c2, c3, c4; } c;
-} int_char;
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-static SLJIT_INLINE int utf_continue(PCRE2_SPTR s)
-{
#if PCRE2_CODE_UNIT_WIDTH == 8
-return (*s & 0xc0) == 0x80;
+#define PCRE2_REPLICATE_TYPE (SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_8)
#elif PCRE2_CODE_UNIT_WIDTH == 16
-return (*s & 0xfc00) == 0xdc00;
+#define PCRE2_REPLICATE_TYPE (SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_16)
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+#define PCRE2_REPLICATE_TYPE (SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_32)
#else
-#error "Unknown code width"
+#error "Unsupported unit width"
#endif
-}
-#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 */
+#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1
+
+static void fast_forward_char_pair_sse2_compare(struct sljit_compiler *compiler, vector_compare_type compare_type,
+ int step, sljit_u32 dst_ind, sljit_u32 cmp1_ind, sljit_u32 cmp2_ind, sljit_u32 tmp_ind)
+{
+sljit_u32 instruction;
#if PCRE2_CODE_UNIT_WIDTH == 8
-# define VECTOR_FACTOR 16
-# define vect_t uint8x16_t
-# define VLD1Q(X) vld1q_u8((sljit_u8 *)(X))
-# define VCEQQ vceqq_u8
-# define VORRQ vorrq_u8
-# define VST1Q vst1q_u8
-# define VDUPQ vdupq_n_u8
-# define VEXTQ vextq_u8
-# define VANDQ vandq_u8
-typedef union {
- uint8_t mem[16];
- uint64_t dw[2];
-} quad_word;
+sljit_u32 size = 0 << 22;
#elif PCRE2_CODE_UNIT_WIDTH == 16
-# define VECTOR_FACTOR 8
-# define vect_t uint16x8_t
-# define VLD1Q(X) vld1q_u16((sljit_u16 *)(X))
-# define VCEQQ vceqq_u16
-# define VORRQ vorrq_u16
-# define VST1Q vst1q_u16
-# define VDUPQ vdupq_n_u16
-# define VEXTQ vextq_u16
-# define VANDQ vandq_u16
-typedef union {
- uint16_t mem[8];
- uint64_t dw[2];
-} quad_word;
+sljit_u32 size = 1 << 22;
+#elif PCRE2_CODE_UNIT_WIDTH == 32
+sljit_u32 size = 2 << 22;
#else
-# define VECTOR_FACTOR 4
-# define vect_t uint32x4_t
-# define VLD1Q(X) vld1q_u32((sljit_u32 *)(X))
-# define VCEQQ vceqq_u32
-# define VORRQ vorrq_u32
-# define VST1Q vst1q_u32
-# define VDUPQ vdupq_n_u32
-# define VEXTQ vextq_u32
-# define VANDQ vandq_u32
-typedef union {
- uint32_t mem[4];
- uint64_t dw[2];
-} quad_word;
+#error "Unsupported unit width"
#endif
-#define FFCS
-#include "pcre2_jit_neon_inc.h"
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-# define FF_UTF
-# include "pcre2_jit_neon_inc.h"
-# undef FF_UTF
-#endif
-#undef FFCS
+SLJIT_ASSERT(step >= 0 && step <= 2);
-#define FFCS_2
-#include "pcre2_jit_neon_inc.h"
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-# define FF_UTF
-# include "pcre2_jit_neon_inc.h"
-# undef FF_UTF
-#endif
-#undef FFCS_2
+if (step == 1)
+ {
+ /* CMEQ */
+ instruction = 0x6e208c00 | size | (cmp1_ind << 16) | (dst_ind << 5) | dst_ind;
+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+ return;
+ }
-#define FFCS_MASK
-#include "pcre2_jit_neon_inc.h"
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-# define FF_UTF
-# include "pcre2_jit_neon_inc.h"
-# undef FF_UTF
-#endif
-#undef FFCS_MASK
+if (compare_type != vector_compare_match2)
+ {
+ if (step == 0 && compare_type == vector_compare_match1i)
+ {
+ /* ORR */
+ instruction = 0x4ea01c00 | (cmp2_ind << 16) | (dst_ind << 5) | dst_ind;
+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+ }
+ return;
+ }
-#define JIT_HAS_FAST_FORWARD_CHAR_SIMD 1
+switch (step)
+ {
+ case 0:
+ /* CMEQ */
+ instruction = 0x6e208c00 | size | (cmp2_ind << 16) | (dst_ind << 5) | tmp_ind;
+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+ return;
+
+ case 2:
+ /* ORR */
+ instruction = 0x4ea01c00 | (tmp_ind << 16) | (dst_ind << 5) | dst_ind;
+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+ return;
+ }
+}
static void fast_forward_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2, sljit_s32 offset)
{
DEFINE_COMPILER;
-int_char ic;
-struct sljit_jump *partial_quit, *quit;
-/* Save temporary registers. */
-SLJIT_ASSERT(common->locals_size >= 2 * (int)sizeof(sljit_sw));
-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, STR_PTR, 0);
-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL1, TMP3, 0);
+sljit_u32 instruction;
+struct sljit_label *start;
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+struct sljit_label *restart;
+#endif
+struct sljit_jump *quit;
+struct sljit_jump *partial_quit[2];
+vector_compare_type compare_type = vector_compare_match1;
+sljit_u32 data_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);
+sljit_u32 cmp1_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);
+sljit_u32 cmp2_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);
+sljit_u32 tmp_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);
+sljit_u32 bit = 0;
+int i;
-/* Prepare function arguments */
-OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);
-GET_LOCAL_BASE(SLJIT_R1, 0, LOCAL0);
-OP1(SLJIT_MOV, SLJIT_R2, 0, SLJIT_IMM, offset);
+SLJIT_UNUSED_ARG(offset);
-if (char1 == char2)
+if (char1 != char2)
{
- ic.c.c1 = char1;
- ic.c.c2 = char2;
- OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);
+ bit = char1 ^ char2;
+ compare_type = vector_compare_match1i;
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
- if (common->utf && offset > 0)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_utf));
- else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs));
-#else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs));
-#endif
- }
-else
- {
- PCRE2_UCHAR mask = char1 ^ char2;
- if (is_powerof2(mask))
+ if (!is_powerof2(bit))
{
- ic.c.c1 = char1 | mask;
- ic.c.c2 = mask;
- OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);
-
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
- if (common->utf && offset > 0)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask_utf));
- else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask));
-#else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask));
-#endif
+ bit = 0;
+ compare_type = vector_compare_match2;
}
- else
- {
- ic.c.c1 = char1;
- ic.c.c2 = char2;
- OP1(SLJIT_MOV, SLJIT_R4, 0, SLJIT_IMM, ic.x);
+ }
+
+partial_quit[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
+if (common->mode == PCRE2_JIT_COMPLETE)
+ add_jump(compiler, &common->failed_match, partial_quit[0]);
+
+/* First part (unaligned start) */
+if (char1 != char2)
+ sljit_emit_op1(compiler, SLJIT_MOV, TMP2, 0, SLJIT_IMM, bit != 0 ? bit : char2);
+sljit_emit_op1(compiler, SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1 | bit);
+
+if (char1 != char2)
+ sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR2, TMP2, 0);
+sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR1, TMP1, 0);
+
+OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
- if (common->utf && offset > 0)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2_utf));
- else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2));
-#else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2));
+restart = LABEL();
#endif
- }
- }
-/* Restore registers. */
-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0);
-OP1(SLJIT_MOV, TMP3, 0, SLJIT_MEM1(SLJIT_SP), LOCAL1);
-/* Check return value. */
-partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~(sljit_sw)0xf);
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
+
+sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);
+
+for (i = 0; i < 3; i++)
+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
+
+/* SHRN */
+instruction = 0x0f0c8400 | (data_ind << 5) | data_ind;
+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+
+sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);
+
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);
+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, TMP2, 0);
+
+quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);
+
+/* Second part (aligned) */
+start = LABEL();
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
+
+partial_quit[1] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
if (common->mode == PCRE2_JIT_COMPLETE)
- add_jump(compiler, &common->failed_match, partial_quit);
+ add_jump(compiler, &common->failed_match, partial_quit[1]);
+
+sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);
+for (i = 0; i < 3; i++)
+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
+
+/* SHRN */
+instruction = 0x0f0c8400 | (data_ind << 5) | data_ind;
+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+
+sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);
+CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);
+
+JUMPHERE(quit);
+
+sljit_emit_op1(compiler, SLJIT_CTZ, TMP1, 0, TMP1, 0);
+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
-/* Fast forward STR_PTR to the result of memchr. */
-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
if (common->mode != PCRE2_JIT_COMPLETE)
{
- quit = CMP(SLJIT_NOT_ZERO, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
- JUMPHERE(partial_quit);
+ JUMPHERE(partial_quit[0]);
+ JUMPHERE(partial_quit[1]);
OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);
SELECT(SLJIT_GREATER, STR_PTR, STR_END, 0, STR_PTR);
- JUMPHERE(quit);
}
-}
-
-typedef enum {
- compare_match1,
- compare_match1i,
- compare_match2,
-} compare_type;
+else
+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
-static inline vect_t fast_forward_char_pair_compare(compare_type ctype, vect_t dst, vect_t cmp1, vect_t cmp2)
-{
-if (ctype == compare_match2)
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+if (common->utf && offset > 0)
{
- vect_t tmp = dst;
- dst = VCEQQ(dst, cmp1);
- tmp = VCEQQ(tmp, cmp2);
- dst = VORRQ(dst, tmp);
- return dst;
- }
+ SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE);
-if (ctype == compare_match1i)
- dst = VORRQ(dst, cmp2);
-dst = VCEQQ(dst, cmp1);
-return dst;
-}
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offset));
-static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void)
-{
-#if PCRE2_CODE_UNIT_WIDTH == 8
-return 15;
-#elif PCRE2_CODE_UNIT_WIDTH == 16
-return 7;
-#elif PCRE2_CODE_UNIT_WIDTH == 32
-return 3;
-#else
-#error "Unsupported unit width"
+ quit = jump_if_utf_char_start(compiler, TMP1);
+
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+ OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
+ JUMPTO(SLJIT_JUMP, restart);
+
+ JUMPHERE(quit);
+ }
#endif
}
-/* ARM doesn't have a shift left across lanes. */
-static SLJIT_INLINE vect_t shift_left_n_lanes(vect_t a, sljit_u8 n)
+#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD 1
+
+static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2)
{
-vect_t zero = VDUPQ(0);
-SLJIT_ASSERT(0 < n && n < VECTOR_FACTOR);
-/* VEXTQ takes an immediate as last argument. */
-#define C(X) case X: return VEXTQ(zero, a, VECTOR_FACTOR - X);
-switch (n)
+DEFINE_COMPILER;
+sljit_u32 instruction;
+struct sljit_label *start;
+struct sljit_jump *quit;
+jump_list *not_found = NULL;
+vector_compare_type compare_type = vector_compare_match1;
+sljit_u32 data_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);
+sljit_u32 cmp1_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);
+sljit_u32 cmp2_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);
+sljit_u32 tmp_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);
+sljit_u32 bit = 0;
+int i;
+
+if (char1 != char2)
{
- C(1); C(2); C(3);
-#if PCRE2_CODE_UNIT_WIDTH != 32
- C(4); C(5); C(6); C(7);
-# if PCRE2_CODE_UNIT_WIDTH != 16
- C(8); C(9); C(10); C(11); C(12); C(13); C(14); C(15);
-# endif
-#endif
- default:
- /* Based on the ASSERT(0 < n && n < VECTOR_FACTOR) above, this won't
- happen. The return is still here for compilers to not warn. */
- return a;
+ bit = char1 ^ char2;
+ compare_type = vector_compare_match1i;
+
+ if (!is_powerof2(bit))
+ {
+ bit = 0;
+ compare_type = vector_compare_match2;
+ }
}
-}
-#define FFCPS
-#define FFCPS_DIFF1
-#define FFCPS_CHAR1A2A
+add_jump(compiler, &not_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));
-#define FFCPS_0
-#include "pcre2_jit_neon_inc.h"
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-# define FF_UTF
-# include "pcre2_jit_neon_inc.h"
-# undef FF_UTF
-#endif
-#undef FFCPS_0
+/* First part (unaligned start) */
-#undef FFCPS_CHAR1A2A
+if (char1 != char2)
+ sljit_emit_op1(compiler, SLJIT_MOV, TMP3, 0, SLJIT_IMM, bit != 0 ? bit : char2);
+sljit_emit_op1(compiler, SLJIT_MOV, TMP2, 0, SLJIT_IMM, char1 | bit);
-#define FFCPS_1
-#include "pcre2_jit_neon_inc.h"
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-# define FF_UTF
-# include "pcre2_jit_neon_inc.h"
-# undef FF_UTF
-#endif
-#undef FFCPS_1
+if (char1 != char2)
+ sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR2, TMP3, 0);
+sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR1, TMP2, 0);
-#undef FFCPS_DIFF1
+OP2(SLJIT_AND, TMP3, 0, TMP1, 0, SLJIT_IMM, ~(sljit_sw)0xf);
+OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xf);
-#define FFCPS_DEFAULT
-#include "pcre2_jit_neon_inc.h"
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
-# define FF_UTF
-# include "pcre2_jit_neon_inc.h"
-# undef FF_UTF
-#endif
-#undef FFCPS
+sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(TMP3), 0);
+
+for (i = 0; i < 3; i++)
+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
+
+/* SHRN */
+instruction = 0x0f0c8400 | (data_ind << 5) | data_ind;
+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+
+sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);
+
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);
+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, TMP2, 0);
+
+quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);
+
+/* Second part (aligned) */
+start = LABEL();
+
+OP2(SLJIT_ADD, TMP3, 0, TMP3, 0, SLJIT_IMM, 16);
+
+add_jump(compiler, &not_found, CMP(SLJIT_GREATER_EQUAL, TMP3, 0, STR_END, 0));
+
+sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(TMP3), 0);
+
+for (i = 0; i < 3; i++)
+ fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind);
+
+/* SHRN */
+instruction = 0x0f0c8400 | (data_ind << 5) | data_ind;
+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+
+sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);
+CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);
+
+JUMPHERE(quit);
+
+sljit_emit_op1(compiler, SLJIT_CTZ, TMP1, 0, TMP1, 0);
+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);
+OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP3, 0);
+add_jump(compiler, &not_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0));
+
+return not_found;
+}
#define JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD 1
@@ -1031,81 +1051,214 @@ static void fast_forward_char_pair_simd(compiler_common *common, sljit_s32 offs1
PCRE2_UCHAR char1a, PCRE2_UCHAR char1b, sljit_s32 offs2, PCRE2_UCHAR char2a, PCRE2_UCHAR char2b)
{
DEFINE_COMPILER;
+sljit_u32 instruction;
+vector_compare_type compare1_type = vector_compare_match1;
+vector_compare_type compare2_type = vector_compare_match1;
+sljit_u32 bit1 = 0;
+sljit_u32 bit2 = 0;
sljit_u32 diff = IN_UCHARS(offs1 - offs2);
-struct sljit_jump *partial_quit;
-int_char ic;
-SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2);
-SLJIT_ASSERT(diff <= IN_UCHARS(max_fast_forward_char_pair_offset()));
-SLJIT_ASSERT(compiler->scratches == 5);
+sljit_u32 data1_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR0);
+sljit_u32 data2_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR1);
+sljit_u32 cmp1a_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR2);
+sljit_u32 cmp2a_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR3);
+sljit_u32 cmp1b_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR4);
+sljit_u32 cmp2b_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR5);
+sljit_u32 tmp1_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR6);
+sljit_u32 tmp2_ind = (sljit_u32)sljit_get_register_index(SLJIT_SIMD_REG_128, SLJIT_VR7);
+struct sljit_label *start;
+#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
+struct sljit_label *restart;
+#endif
+struct sljit_jump *jump[2];
+int i;
-/* Save temporary register STR_PTR. */
-OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCAL0, STR_PTR, 0);
+SLJIT_ASSERT(common->mode == PCRE2_JIT_COMPLETE && offs1 > offs2 && offs2 >= 0);
+SLJIT_ASSERT(diff <= (unsigned)IN_UCHARS(max_fast_forward_char_pair_offset()));
-/* Prepare arguments for the function call. */
-if (common->match_end_ptr == 0)
- OP1(SLJIT_MOV, SLJIT_R0, 0, STR_END, 0);
-else
+if (char1a != char1b)
{
- OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
- OP2(SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
+ bit1 = char1a ^ char1b;
+ compare1_type = vector_compare_match1i;
- OP2U(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, SLJIT_R0, 0);
- SELECT(SLJIT_LESS, SLJIT_R0, STR_END, 0, SLJIT_R0);
+ if (!is_powerof2(bit1))
+ {
+ bit1 = 0;
+ compare1_type = vector_compare_match2;
+ }
}
-GET_LOCAL_BASE(SLJIT_R1, 0, LOCAL0);
-OP1(SLJIT_MOV_S32, SLJIT_R2, 0, SLJIT_IMM, offs1);
-OP1(SLJIT_MOV_S32, SLJIT_R3, 0, SLJIT_IMM, offs2);
-ic.c.c1 = char1a;
-ic.c.c2 = char1b;
-ic.c.c3 = char2a;
-ic.c.c4 = char2b;
-OP1(SLJIT_MOV_U32, SLJIT_R4, 0, SLJIT_IMM, ic.x);
+if (char2a != char2b)
+ {
+ bit2 = char2a ^ char2b;
+ compare2_type = vector_compare_match1i;
+
+ if (!is_powerof2(bit2))
+ {
+ bit2 = 0;
+ compare2_type = vector_compare_match2;
+ }
+ }
+
+/* Initialize. */
+if (common->match_end_ptr != 0)
+ {
+ OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
+ OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
+ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
+
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, STR_END, 0);
+ SELECT(SLJIT_LESS, STR_END, TMP1, 0, STR_END);
+ }
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+sljit_emit_op1(compiler, SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1a | bit1);
+sljit_emit_op1(compiler, SLJIT_MOV, TMP2, 0, SLJIT_IMM, char2a | bit2);
+sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR2, TMP1, 0);
+sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR3, TMP2, 0);
+
+if (char1a != char1b)
+ sljit_emit_op1(compiler, SLJIT_MOV, TMP1, 0, SLJIT_IMM, bit1 != 0 ? bit1 : char1b);
+
+if (char2a != char2b)
+ sljit_emit_op1(compiler, SLJIT_MOV, TMP2, 0, SLJIT_IMM, bit2 != 0 ? bit2 : char2b);
+
+if (char1a != char1b)
+ sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR4, TMP1, 0);
+
+if (char2a != char2b)
+ sljit_emit_simd_replicate(compiler, PCRE2_REPLICATE_TYPE, SLJIT_VR5, TMP2, 0);
-if (diff == 1) {
- if (char1a == char1b && char2a == char2b) {
-#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
- if (common->utf)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_0_utf));
- else
-#endif
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_0));
- } else {
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
- if (common->utf)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_1_utf));
- else
+restart = LABEL();
#endif
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_1));
+
+OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, diff);
+OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
+OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~(sljit_sw)0xf);
+
+sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);
+
+jump[0] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_PTR, 0);
+
+sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128, SLJIT_VR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff);
+jump[1] = JUMP(SLJIT_JUMP);
+
+JUMPHERE(jump[0]);
+
+if (diff >= 8)
+ {
+ /* MOV (element) */
+ instruction = 0x6e180400 | (data1_ind << 5) | data2_ind;
+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+
+ if (diff > 8)
+ {
+ /* SHL */
+ instruction = 0x4f405400 | ((diff - 8) << 19) | (data2_ind << 5) | data2_ind;
+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+ }
+ }
+else
+ {
+ /* MOV (element) */
+ instruction = 0x6e180400 | (data1_ind << 5) | tmp1_ind;
+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+
+ /* SHL */
+ instruction = 0x4f405400 | (diff << 19) | (data1_ind << 5) | data2_ind;
+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+
+ /* USHR */
+ instruction = 0x6f400400 | (diff << 19) | (tmp1_ind << 5) | tmp1_ind;
+ sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+
+ sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_OR | SLJIT_SIMD_REG_128, SLJIT_VR1, SLJIT_VR1, SLJIT_VR6, 0);
+ }
+
+JUMPHERE(jump[1]);
+
+OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf);
+
+for (i = 0; i < 3; i++)
+ {
+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);
+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);
+ }
+
+sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | SLJIT_SIMD_REG_128, SLJIT_VR0, SLJIT_VR0, SLJIT_VR1, 0);
+
+/* SHRN */
+instruction = 0x0f0c8400 | (data1_ind << 5) | data1_ind;
+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+
+sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);
+
+/* Ignore matches before the first STR_PTR. */
+OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);
+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0);
+OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, TMP2, 0);
+
+jump[0] = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0);
+
+/* Main loop. */
+start = LABEL();
+
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16);
+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
+sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128 | SLJIT_SIMD_MEM_ALIGNED_128, SLJIT_VR0, SLJIT_MEM1(STR_PTR), 0);
+sljit_emit_simd_mov(compiler, SLJIT_SIMD_REG_128, SLJIT_VR1, SLJIT_MEM1(STR_PTR), -(sljit_sw)diff);
+
+for (i = 0; i < 3; i++)
+ {
+ fast_forward_char_pair_sse2_compare(compiler, compare1_type, i, data1_ind, cmp1a_ind, cmp1b_ind, tmp1_ind);
+ fast_forward_char_pair_sse2_compare(compiler, compare2_type, i, data2_ind, cmp2a_ind, cmp2b_ind, tmp2_ind);
}
-} else {
+
+sljit_emit_simd_op2(compiler, SLJIT_SIMD_OP2_AND | SLJIT_SIMD_REG_128, SLJIT_VR0, SLJIT_VR0, SLJIT_VR1, 0);
+
+/* SHRN */
+instruction = 0x0f0c8400 | (data1_ind << 5) | data1_ind;
+sljit_emit_op_custom(compiler, &instruction, sizeof(sljit_u32));
+
+sljit_emit_simd_lane_mov(compiler, SLJIT_SIMD_STORE | SLJIT_SIMD_REG_128 | SLJIT_SIMD_ELEM_64, SLJIT_VR0, 0, TMP1, 0);
+
+CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start);
+
+JUMPHERE(jump[0]);
+
+sljit_emit_op1(compiler, SLJIT_CTZ, TMP1, 0, TMP1, 0);
+OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);
+OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
+
+add_jump(compiler, &common->failed_match, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0));
+
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
- if (common->utf)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_default_utf));
- else
-#endif
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
- SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_default));
-}
+if (common->utf)
+ {
+ OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-offs1));
+
+ jump[0] = jump_if_utf_char_start(compiler, TMP1);
-/* Restore STR_PTR register. */
-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCAL0);
+ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
+ CMPTO(SLJIT_LESS, STR_PTR, 0, STR_END, 0, restart);
-/* Check return value. */
-partial_quit = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
-add_jump(compiler, &common->failed_match, partial_quit);
+ add_jump(compiler, &common->failed_match, JUMP(SLJIT_JUMP));
-/* Fast forward STR_PTR to the result of memchr. */
-OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
+ JUMPHERE(jump[0]);
+ }
+#endif
-JUMPHERE(partial_quit);
+OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(offs1));
+
+if (common->match_end_ptr != 0)
+ OP1(SLJIT_MOV, STR_END, 0, TMP3, 0);
}
+#undef PCRE2_REPLICATE_TYPE
+
#endif /* SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64 */
#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
@@ -1289,7 +1442,7 @@ if (char1 != char2)
#else /* PCRE2_CODE_UNIT_WIDTH == 32 */
-for (int i = 0; i < 2; i++)
+for (i = 0; i < 2; i++)
{
replicate_imm_vector(compiler, i, cmp1_ind, char1 | bit, TMP1);
@@ -1483,7 +1636,7 @@ if (char1 != char2)
#else /* PCRE2_CODE_UNIT_WIDTH == 32 */
-for (int i = 0; i < 2; i++)
+for (i = 0; i < 2; i++)
{
replicate_imm_vector(compiler, i, cmp1_ind, char1 | bit, TMP3);
@@ -1699,7 +1852,7 @@ if (char2a != char2b)
#else /* PCRE2_CODE_UNIT_WIDTH == 32 */
-for (int i = 0; i < 2; i++)
+for (i = 0; i < 2; i++)
{
replicate_imm_vector(compiler, i, cmp1a_ind, char1a | bit1, TMP1);
@@ -1865,21 +2018,18 @@ typedef sljit_ins sljit_u32;
#define IMM_UI2(imm) (((sljit_ins)(imm) << 10) & UI2_IMM_MASK)
// LSX OPCODES:
-#define VLD 0x2c000000
-#define VOR_V 0x71268000
-#define VAND_V 0x71260000
#define VBSLL_V 0x728e0000
#define VMSKLTZ_B 0x729c4000
#define VPICKVE2GR_WU 0x72f3e000
#if PCRE2_CODE_UNIT_WIDTH == 8
-#define VREPLGR2VR 0x729f0000
+#define VREPLGR2VR_X 0x729f0000
#define VSEQ 0x70000000
#elif PCRE2_CODE_UNIT_WIDTH == 16
-#define VREPLGR2VR 0x729f0400
+#define VREPLGR2VR_X 0x729f0400
#define VSEQ 0x70008000
#else
-#define VREPLGR2VR 0x729f0800
+#define VREPLGR2VR_X 0x729f0800
#define VSEQ 0x70010000
#endif
@@ -1956,14 +2106,14 @@ if (common->mode == PCRE2_JIT_COMPLETE)
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1 | bit);
/* VREPLGR2VR.B/H/W vd, rj */
-push_inst(compiler, VREPLGR2VR | VD(cmp1_ind) | RJ_V(tmp1_reg_ind));
+push_inst(compiler, VREPLGR2VR_X | VD(cmp1_ind) | RJ_V(tmp1_reg_ind));
if (char1 != char2)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, bit != 0 ? bit : char2);
/* VREPLGR2VR.B/H/W vd, rj */
- push_inst(compiler, VREPLGR2VR | VD(cmp2_ind) | RJ_V(tmp1_reg_ind));
+ push_inst(compiler, VREPLGR2VR_X | VD(cmp2_ind) | RJ_V(tmp1_reg_ind));
}
OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0);
@@ -2086,14 +2236,14 @@ OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, char1 | bit);
-/* VREPLGR2VR vd, rj */
-push_inst(compiler, VREPLGR2VR | VD(cmp1_ind) | RJ_V(tmp1_reg_ind));
+/* VREPLGR2VR.B/H/W vd, rj */
+push_inst(compiler, VREPLGR2VR_X | VD(cmp1_ind) | RJ_V(tmp1_reg_ind));
if (char1 != char2)
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, bit != 0 ? bit : char2);
- /* VREPLGR2VR vd, rj */
- push_inst(compiler, VREPLGR2VR | VD(cmp2_ind) | RJ_V(tmp1_reg_ind));
+ /* VREPLGR2VR.B/H/W vd, rj */
+ push_inst(compiler, VREPLGR2VR_X | VD(cmp2_ind) | RJ_V(tmp1_reg_ind));
}
OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0);
@@ -2213,13 +2363,13 @@ else
}
}
-/* VREPLGR2VR vd, rj */
-push_inst(compiler, VREPLGR2VR | VD(cmp1a_ind) | RJ_V(tmp1_reg_ind));
+/* VREPLGR2VR.B/H/W vd, rj */
+push_inst(compiler, VREPLGR2VR_X | VD(cmp1a_ind) | RJ_V(tmp1_reg_ind));
if (char1a != char1b)
{
- /* VREPLGR2VR vd, rj */
- push_inst(compiler, VREPLGR2VR | VD(cmp1b_ind) | RJ_V(tmp2_reg_ind));
+ /* VREPLGR2VR.B/H/W vd, rj */
+ push_inst(compiler, VREPLGR2VR_X | VD(cmp1b_ind) | RJ_V(tmp2_reg_ind));
}
if (char2a == char2b)
@@ -2242,13 +2392,13 @@ else
}
}
-/* VREPLGR2VR vd, rj */
-push_inst(compiler, VREPLGR2VR | VD(cmp2a_ind) | RJ_V(tmp1_reg_ind));
+/* VREPLGR2VR.B/H/W vd, rj */
+push_inst(compiler, VREPLGR2VR_X | VD(cmp2a_ind) | RJ_V(tmp1_reg_ind));
if (char2a != char2b)
{
- /* VREPLGR2VR vd, rj */
- push_inst(compiler, VREPLGR2VR | VD(cmp2b_ind) | RJ_V(tmp2_reg_ind));
+ /* VREPLGR2VR.B/H/W vd, rj */
+ push_inst(compiler, VREPLGR2VR_X | VD(cmp2b_ind) | RJ_V(tmp2_reg_ind));
}
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
diff --git a/src/3rdparty/pcre2/src/pcre2_maketables.c b/src/3rdparty/pcre2/src/pcre2_maketables.c
index 0474cc7dbb4..0f6c5110ad0 100644
--- a/src/3rdparty/pcre2/src/pcre2_maketables.c
+++ b/src/3rdparty/pcre2/src/pcre2_maketables.c
@@ -45,13 +45,13 @@ own as part of the PCRE2 library. It is also included in the compilation of
pcre2_dftables.c as a freestanding program, in which case the macro
PCRE2_DFTABLES is defined. */
+
#ifndef PCRE2_DFTABLES /* Compiling the library */
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-# include "pcre2_internal.h"
+#include "pcre2_internal.h"
#endif
+
+
/*************************************************
* Create PCRE2 character tables *
*************************************************/
@@ -64,14 +64,15 @@ supplied, but when PCRE2_DFTABLES is defined (when compiling the pcre2_dftables
freestanding auxiliary program) malloc() is used, and the function has a
different name so as not to clash with the prototype in pcre2.h.
-Arguments: none when PCRE2_DFTABLES is defined
+Arguments: pointers to character-transforming functions when PCRE2_DFTABLES is
+ defined;
else a PCRE2 general context or NULL
-Returns: pointer to the contiguous block of data
+Returns: pointer to the contiguous block of data;
else NULL if memory allocation failed
*/
#ifdef PCRE2_DFTABLES /* Included in freestanding pcre2_dftables program */
-static const uint8_t *maketables(void)
+static const uint8_t *maketables(int (*charfn_to)(int), int (*charfn_from)(int))
{
uint8_t *yield = (uint8_t *)malloc(TABLES_LENGTH);
@@ -82,6 +83,9 @@ pcre2_maketables(pcre2_general_context *gcontext)
uint8_t *yield = (uint8_t *)((gcontext != NULL)?
gcontext->memctl.malloc(TABLES_LENGTH, gcontext->memctl.memory_data) :
malloc(TABLES_LENGTH));
+
+#define charfn_to(c) (c)
+#define charfn_from(c) (c)
#endif /* PCRE2_DFTABLES */
int i;
@@ -92,13 +96,18 @@ p = yield;
/* First comes the lower casing table */
-for (i = 0; i < 256; i++) *p++ = tolower(i);
+for (i = 0; i < 256; i++)
+ {
+ int c = charfn_from(tolower(charfn_to(i)));
+ *p++ = (c < 256)? c : i;
+ }
/* Next the case-flipping table */
for (i = 0; i < 256; i++)
{
- int c = islower(i)? toupper(i) : tolower(i);
+ int c = charfn_from(islower(charfn_to(i))? toupper(charfn_to(i))
+ : tolower(charfn_to(i)));
*p++ = (c < 256)? c : i;
}
@@ -118,17 +127,17 @@ test for alnum specially. */
memset(p, 0, cbit_length);
for (i = 0; i < 256; i++)
{
- if (isdigit(i)) p[cbit_digit + i/8] |= 1u << (i&7);
- if (isupper(i)) p[cbit_upper + i/8] |= 1u << (i&7);
- if (islower(i)) p[cbit_lower + i/8] |= 1u << (i&7);
- if (isalnum(i)) p[cbit_word + i/8] |= 1u << (i&7);
- if (i == '_') p[cbit_word + i/8] |= 1u << (i&7);
- if (isspace(i)) p[cbit_space + i/8] |= 1u << (i&7);
- if (isxdigit(i)) p[cbit_xdigit + i/8] |= 1u << (i&7);
- if (isgraph(i)) p[cbit_graph + i/8] |= 1u << (i&7);
- if (isprint(i)) p[cbit_print + i/8] |= 1u << (i&7);
- if (ispunct(i)) p[cbit_punct + i/8] |= 1u << (i&7);
- if (iscntrl(i)) p[cbit_cntrl + i/8] |= 1u << (i&7);
+ if (isdigit(charfn_to(i))) p[cbit_digit + i/8] |= 1u << (i&7);
+ if (isupper(charfn_to(i))) p[cbit_upper + i/8] |= 1u << (i&7);
+ if (islower(charfn_to(i))) p[cbit_lower + i/8] |= 1u << (i&7);
+ if (isalnum(charfn_to(i))) p[cbit_word + i/8] |= 1u << (i&7);
+ if (i == CHAR_UNDERSCORE) p[cbit_word + i/8] |= 1u << (i&7);
+ if (isspace(charfn_to(i))) p[cbit_space + i/8] |= 1u << (i&7);
+ if (isxdigit(charfn_to(i))) p[cbit_xdigit + i/8] |= 1u << (i&7);
+ if (isgraph(charfn_to(i))) p[cbit_graph + i/8] |= 1u << (i&7);
+ if (isprint(charfn_to(i))) p[cbit_print + i/8] |= 1u << (i&7);
+ if (ispunct(charfn_to(i))) p[cbit_punct + i/8] |= 1u << (i&7);
+ if (iscntrl(charfn_to(i))) p[cbit_cntrl + i/8] |= 1u << (i&7);
}
p += cbit_length;
@@ -140,11 +149,11 @@ changed at release 8.34 and it's always been this way for PCRE2. */
for (i = 0; i < 256; i++)
{
int x = 0;
- if (isspace(i)) x += ctype_space;
- if (isalpha(i)) x += ctype_letter;
- if (islower(i)) x += ctype_lcletter;
- if (isdigit(i)) x += ctype_digit;
- if (isalnum(i) || i == '_') x += ctype_word;
+ if (isspace(charfn_to(i))) x += ctype_space;
+ if (isalpha(charfn_to(i))) x += ctype_letter;
+ if (islower(charfn_to(i))) x += ctype_lcletter;
+ if (isdigit(charfn_to(i))) x += ctype_digit;
+ if (isalnum(charfn_to(i)) || i == CHAR_UNDERSCORE) x += ctype_word;
*p++ = x;
}
@@ -152,6 +161,9 @@ return yield;
}
#ifndef PCRE2_DFTABLES /* Compiling the library */
+#undef charfn_to
+#undef charfn_from
+
PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION
pcre2_maketables_free(pcre2_general_context *gcontext, const uint8_t *tables)
{
diff --git a/src/3rdparty/pcre2/src/pcre2_match.c b/src/3rdparty/pcre2/src/pcre2_match.c
index 34a92eaa36e..d5574d721a2 100644
--- a/src/3rdparty/pcre2/src/pcre2_match.c
+++ b/src/3rdparty/pcre2/src/pcre2_match.c
@@ -39,12 +39,10 @@ POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
+
+
/* These defines enable debugging code */
/* #define DEBUG_FRAMES_DISPLAY */
@@ -367,6 +365,10 @@ PCRE2_SIZE length;
PCRE2_SPTR eptr;
PCRE2_SPTR eptr_start;
+#ifndef SUPPORT_UNICODE
+(void)caseopts; /* Avoid compiler warning. */
+#endif
+
/* Deal with an unset group. The default is no match, but there is an option to
match an empty string. */
@@ -385,6 +387,7 @@ if (offset >= Foffset_top || Fovector[offset] == PCRE2_UNSET)
eptr = eptr_start = Feptr;
p = mb->start_subject + Fovector[offset];
length = Fovector[offset+1] - Fovector[offset];
+PCRE2_ASSERT(eptr <= mb->end_subject);
if (caseless)
{
@@ -404,7 +407,7 @@ if (caseless)
bytes in UTF-8); a sequence of 3 of the former uses 6 bytes, as does a
sequence of two of the latter. It is important, therefore, to check the
length along the reference, not along the subject (earlier code did this
- wrong). UCP without uses Unicode properties but without UTF encoding. */
+ wrong). UCP uses Unicode properties but without UTF encoding. */
while (p < endptr)
{
@@ -483,8 +486,8 @@ else
else
{
- if ((PCRE2_SIZE)(mb->end_subject - eptr) < length) return 1; /* Partial */
- if (memcmp(p, eptr, CU2BYTES(length)) != 0) return -1; /* No match */
+ if ((PCRE2_SIZE)(mb->end_subject - eptr) < length ||
+ memcmp(p, eptr, CU2BYTES(length)) != 0) return -1; /* No match */
eptr += length;
}
}
@@ -495,6 +498,75 @@ return 0; /* Match */
+/*************************************************
+* Restore offsets after a recurse *
+*************************************************/
+
+/* This function restores the ovector values when
+a recursive block reaches its end, and the triggering
+recurse has and argument list.
+
+Arguments:
+ F the current backtracking frame pointer
+ P the previous backtracking frame pointer
+*/
+
+static void
+recurse_update_offsets(heapframe *F, heapframe *P)
+{
+PCRE2_SIZE *dst = F->ovector;
+PCRE2_SIZE *src = P->ovector;
+/* The first bracket has offset 2, because
+offset 0 is reserved for the full match. */
+PCRE2_SIZE offset = 2;
+PCRE2_SIZE offset_top = Foffset_top + 2;
+PCRE2_SIZE diff;
+PCRE2_SPTR ecode = Fecode;
+
+do
+ {
+ diff = (GET2(ecode, 1) << 1) - offset;
+ ecode += 1 + IMM2_SIZE;
+
+ if (offset + diff >= offset_top)
+ {
+ /* Some OP_CREF opcodes are not
+ processed, they must be skipped. */
+ while (*ecode == OP_CREF) ecode += 1 + IMM2_SIZE;
+ break;
+ }
+
+ if (diff == 2)
+ {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ }
+ else if (diff >= 4)
+ memcpy(dst, src, diff * sizeof(PCRE2_SIZE));
+
+ /* Skip the unmodified entry. */
+ diff += 2;
+ offset += diff;
+ dst += diff;
+ src += diff;
+ }
+while (*ecode == OP_CREF);
+
+diff = offset_top - offset;
+if (diff == 2)
+ {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ }
+else if (diff >= 4)
+ memcpy(dst, src, diff * sizeof(PCRE2_SIZE));
+
+Fecode = ecode;
+Foffset_top = (offset <= P->offset_top) ? P->offset_top : (offset - 2);
+}
+
+
+
/******************************************************************************
*******************************************************************************
"Recursion" in the match() function
@@ -898,7 +970,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
Fecode += 1 + LINK_SIZE;
continue;
}
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* OP_END itself can never be reached within a recursion because that is
picked up when the OP_KET that always precedes OP_END is reached. */
@@ -938,11 +1010,28 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
}
#ifdef DEBUG_SHOW_OPS
- fprintf(stderr, "++ Failed ACCEPT not at end (endanchnored set)\n");
+ fprintf(stderr, "++ Failed ACCEPT not at end (endanchored set)\n");
#endif
return MATCH_NOMATCH; /* (*ACCEPT) */
}
+ /* Fail if we detect that the start position was moved to be either after
+ the end position (\K in lookahead) or before the start offset (\K in
+ lookbehind). If this occurs, the pattern must have used \K in a somewhat
+ sneaky way (e.g. by pattern recursion), because if the \K is actually
+ syntactically inside the lookaround, it's blocked at compile-time. */
+
+ if (Fstart_match < mb->start_subject + mb->start_offset ||
+ Fstart_match > Feptr)
+ {
+ /* The \K expression is fairly rare. We assert it was used so that we
+ catch any unexpected invalid data in start_match. */
+ PCRE2_ASSERT(mb->hasbsk);
+
+ if (!mb->allowlookaroundbsk)
+ return PCRE2_ERROR_BAD_BACKSLASH_K;
+ }
+
/* We have a successful match of the whole pattern. Record the result and
then do a direct return from the function. If there is space in the offset
vector, set any pairs that follow the highest-numbered captured string but
@@ -982,7 +1071,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
mb->hitend = TRUE;
if (mb->partial > 1) return PCRE2_ERROR_PARTIAL;
}
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* Match any single character whatsoever. */
@@ -2779,9 +2868,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
/* This should never occur */
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
Fecode += 3;
@@ -3130,9 +3221,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
/* This should not occur */
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
}
@@ -3406,9 +3499,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
}
break;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
} /* End switch(Lctype) */
else
@@ -3659,9 +3754,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
}
break;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
}
@@ -3945,9 +4042,12 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
PCRE2_UNREACHABLE(); /* Control never reaches here */
/* This should never occur */
+
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
}
@@ -4100,9 +4200,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
RRETURN(MATCH_NOMATCH);
break;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
}
}
@@ -4245,9 +4347,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
RRETURN(MATCH_NOMATCH);
break;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
}
}
@@ -4514,9 +4618,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
}
break;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
/* Feptr is now past the end of the maximum run */
@@ -4833,9 +4939,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
}
break;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
if (reptype == REPTYPE_POS) continue; /* No backtracking */
@@ -5091,9 +5199,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
}
break;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
if (reptype == REPTYPE_POS) continue; /* No backtracking */
@@ -5990,7 +6100,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
assert_accept_frame->offset_top * sizeof(PCRE2_SIZE));
Foffset_top = assert_accept_frame->offset_top;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* In the case of a match, the captures have already been put into
the current frame. */
@@ -6263,12 +6373,18 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
/* Reinstate the previous set of captures and then carry on after the
recursion call. */
- memcpy((char *)F + offsetof(heapframe, ovector), P->ovector,
- Foffset_top * sizeof(PCRE2_SIZE));
- Foffset_top = P->offset_top;
+ Fecode = P->ecode + 1 + LINK_SIZE;
+
+ if (*Fecode != OP_CREF)
+ {
+ memcpy(F->ovector, P->ovector, Foffset_top * sizeof(PCRE2_SIZE));
+ Foffset_top = P->offset_top;
+ }
+ else
+ recurse_update_offsets(F, P);
+
Fcapture_last = P->capture_last;
Fcurrent_recurse = P->current_recurse;
- Fecode = P->ecode + 1 + LINK_SIZE;
continue; /* With next opcode */
case OP_COND: /* No need to do anything for these */
@@ -6282,7 +6398,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
case OP_ASSERTBACK_NA:
if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr)
RRETURN(MATCH_NOMATCH);
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_ASSERT_NA:
if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
@@ -6296,12 +6412,12 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
case OP_ASSERTBACK:
if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr)
RRETURN(MATCH_NOMATCH);
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_ASSERT:
if (Feptr > mb->last_used_ptr) mb->last_used_ptr = Feptr;
Feptr = P->eptr;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* For an atomic group, discard internal backtracking points. We must
also ensure that any remaining branches within the top-level of the group
@@ -6325,7 +6441,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
case OP_ASSERTBACK_NOT:
if (branch_start[1 + LINK_SIZE] == OP_VREVERSE && Feptr != P->eptr)
RRETURN(MATCH_NOMATCH);
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_ASSERT_NOT:
RRETURN(MATCH_MATCH);
@@ -6370,12 +6486,18 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
if (Fcurrent_recurse == number)
{
P = (heapframe *)((char *)N - frame_size);
- memcpy((char *)F + offsetof(heapframe, ovector), P->ovector,
- Foffset_top * sizeof(PCRE2_SIZE));
- Foffset_top = P->offset_top;
+ Fecode = P->ecode + 1 + LINK_SIZE;
+
+ if (*Fecode != OP_CREF)
+ {
+ memcpy(F->ovector, P->ovector, Foffset_top * sizeof(PCRE2_SIZE));
+ Foffset_top = P->offset_top;
+ }
+ else
+ recurse_update_offsets(F, P);
+
Fcapture_last = P->capture_last;
Fcurrent_recurse = P->current_recurse;
- Fecode = P->ecode + 1 + LINK_SIZE;
continue; /* With next opcode */
}
@@ -6453,7 +6575,7 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
if ((mb->moptions & PCRE2_NOTEOL) != 0) RRETURN(MATCH_NOMATCH);
if ((mb->poptions & PCRE2_DOLLAR_ENDONLY) == 0) goto ASSERT_NL_OR_EOS;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* Unconditional end of subject assertion (\z). */
case OP_EOD:
@@ -6751,9 +6873,11 @@ fprintf(stderr, "++ %2ld op=%3d %s\n", Fecode - mb->start_code, *Fecode,
/* There's been some horrible disaster. Arrival here can only mean there is
something seriously wrong in the code above or the OP_xxx definitions. */
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
/* Do not insert any code in here without much thought; it is assumed
@@ -6801,9 +6925,11 @@ switch (Freturn_id)
LBL(221) LBL(222) LBL(223) LBL(224)
#endif
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
#undef LBL
}
@@ -6839,9 +6965,9 @@ pcre2_match(const pcre2_code *code, PCRE2_SPTR subject, PCRE2_SIZE length,
pcre2_match_context *mcontext)
{
int rc;
-int was_zero_terminated = 0;
const uint8_t *start_bits = NULL;
const pcre2_real_code *re = (const pcre2_real_code *)code;
+uint32_t original_options = options;
BOOL anchored;
BOOL firstline;
@@ -6859,6 +6985,8 @@ PCRE2_UCHAR first_cu2 = 0;
PCRE2_UCHAR req_cu = 0;
PCRE2_UCHAR req_cu2 = 0;
+PCRE2_UCHAR null_str[1] = { 0xcd };
+PCRE2_SPTR original_subject = subject;
PCRE2_SPTR bumpalong_limit;
PCRE2_SPTR end_subject;
PCRE2_SPTR true_end_subject;
@@ -6897,33 +7025,35 @@ match_block *mb = &actual_match_block;
/* Recognize NULL, length 0 as an empty string. */
-if (subject == NULL && length == 0) subject = (PCRE2_SPTR)"";
+if (subject == NULL && length == 0) subject = null_str;
/* Plausibility checks */
-if ((options & ~PUBLIC_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;
-if (code == NULL || subject == NULL || match_data == NULL)
- return PCRE2_ERROR_NULL;
+if (match_data == NULL) return PCRE2_ERROR_NULL;
+if (code == NULL || subject == NULL)
+ return match_data->rc = PCRE2_ERROR_NULL;
+if ((options & ~PUBLIC_MATCH_OPTIONS) != 0)
+ return match_data->rc = PCRE2_ERROR_BADOPTION;
start_match = subject + start_offset;
req_cu_ptr = start_match - 1;
if (length == PCRE2_ZERO_TERMINATED)
{
length = PRIV(strlen)(subject);
- was_zero_terminated = 1;
}
true_end_subject = end_subject = subject + length;
-if (start_offset > length) return PCRE2_ERROR_BADOFFSET;
+if (start_offset > length) return match_data->rc = PCRE2_ERROR_BADOFFSET;
/* Check that the first field in the block is the magic number. */
-if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;
+if (re->magic_number != MAGIC_NUMBER)
+ return match_data->rc = PCRE2_ERROR_BADMAGIC;
/* Check the code unit width. */
if ((re->flags & PCRE2_MODE_MASK) != PCRE2_CODE_UNIT_WIDTH/8)
- return PCRE2_ERROR_BADMODE;
+ return match_data->rc = PCRE2_ERROR_BADMODE;
/* PCRE2_NOTEMPTY and PCRE2_NOTEMPTY_ATSTART are match-time flags in the
options variable for this function. Users of PCRE2 who are not calling the
@@ -6970,17 +7100,18 @@ time. */
if (mb->partial != 0 &&
((re->overall_options | options) & PCRE2_ENDANCHORED) != 0)
- return PCRE2_ERROR_BADOPTION;
+ return match_data->rc = PCRE2_ERROR_BADOPTION;
/* It is an error to set an offset limit without setting the flag at compile
time. */
if (mcontext != NULL && mcontext->offset_limit != PCRE2_UNSET &&
(re->overall_options & PCRE2_USE_OFFSET_LIMIT) == 0)
- return PCRE2_ERROR_BADOFFSETLIMIT;
+ return match_data->rc = PCRE2_ERROR_BADOFFSETLIMIT;
/* If the match data block was previously used with PCRE2_COPY_MATCHED_SUBJECT,
-free the memory that was obtained. Set the field to NULL for no match cases. */
+free the memory that was obtained. Set the field to NULL for match error
+cases. */
if ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0)
{
@@ -7017,11 +7148,11 @@ if (use_jit)
#if PCRE2_CODE_UNIT_WIDTH != 32
if (start_match < end_subject && NOT_FIRSTCU(*start_match))
{
- if (start_offset > 0) return PCRE2_ERROR_BADUTFOFFSET;
+ if (start_offset > 0) return match_data->rc = PCRE2_ERROR_BADUTFOFFSET;
#if PCRE2_CODE_UNIT_WIDTH == 8
- return PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */
+ return match_data->rc = PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */
#else
- return PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */
+ return match_data->rc = PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */
#endif
}
#endif /* WIDTH != 32 */
@@ -7056,12 +7187,12 @@ if (use_jit)
/* Validate the relevant portion of the subject. Adjust the offset of an
invalid code point to be an absolute offset in the whole string. */
- match_data->rc = PRIV(valid_utf)(start_match,
+ rc = PRIV(valid_utf)(start_match,
length - (start_match - subject), &(match_data->startchar));
- if (match_data->rc != 0)
+ if (rc != 0)
{
match_data->startchar += start_match - subject;
- return match_data->rc;
+ return match_data->rc = rc;
}
jit_checked_utf = TRUE;
}
@@ -7074,16 +7205,27 @@ if (use_jit)
match_data, mcontext);
if (rc != PCRE2_ERROR_JIT_BADOPTION)
{
- match_data->subject_length = length;
+ match_data->options = original_options;
if (rc >= 0 && (options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
{
- length = CU2BYTES(length + was_zero_terminated);
- match_data->subject = match_data->memctl.malloc(length,
- match_data->memctl.memory_data);
- if (match_data->subject == NULL) return PCRE2_ERROR_NOMEMORY;
- memcpy((void *)match_data->subject, subject, length);
+ if (length != 0)
+ {
+ match_data->subject = match_data->memctl.malloc(CU2BYTES(length),
+ match_data->memctl.memory_data);
+ if (match_data->subject == NULL)
+ return match_data->rc = PCRE2_ERROR_NOMEMORY;
+ memcpy((void *)match_data->subject, subject, CU2BYTES(length));
+ }
+ else
+ match_data->subject = NULL;
match_data->flags |= PCRE2_MD_COPIED_SUBJECT;
}
+ else
+ {
+ /* When pcre2_jit_match sets the subject, it doesn't know what the
+ original passed-in pointer was. */
+ if (match_data->subject != NULL) match_data->subject = original_subject;
+ }
return rc;
}
}
@@ -7140,11 +7282,11 @@ if (utf &&
}
else if (start_match < end_subject && NOT_FIRSTCU(*start_match))
{
- if (start_offset > 0) return PCRE2_ERROR_BADUTFOFFSET;
+ if (start_offset > 0) return match_data->rc = PCRE2_ERROR_BADUTFOFFSET;
#if PCRE2_CODE_UNIT_WIDTH == 8
- return PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */
+ return match_data->rc = PCRE2_ERROR_UTF8_ERR20; /* Isolated 0x80 byte */
#else
- return PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */
+ return match_data->rc = PCRE2_ERROR_UTF16_ERR3; /* Isolated low surrogate */
#endif
}
#endif /* WIDTH != 32 */
@@ -7192,10 +7334,10 @@ if (utf &&
for (;;)
{
- match_data->rc = PRIV(valid_utf)(mb->check_subject,
+ rc = PRIV(valid_utf)(mb->check_subject,
length - (mb->check_subject - subject), &(match_data->startchar));
- if (match_data->rc == 0) break; /* Valid UTF string */
+ if (rc == 0) break; /* Valid UTF string */
/* Invalid UTF string. Adjust the offset to be an absolute offset in the
whole string. If we are handling invalid UTF strings, set end_subject to
@@ -7203,7 +7345,7 @@ if (utf &&
Otherwise return the error. */
match_data->startchar += mb->check_subject - subject;
- if (!allow_invalid || match_data->rc > 0) return match_data->rc;
+ if (!allow_invalid || rc > 0) return match_data->rc = rc;
end_subject = subject + match_data->startchar;
/* If the end precedes start_match, it means there is invalid UTF in the
@@ -7268,8 +7410,11 @@ mb->start_offset = start_offset;
mb->end_subject = end_subject;
mb->true_end_subject = true_end_subject;
mb->hasthen = (re->flags & PCRE2_HASTHEN) != 0;
+mb->hasbsk = (re->flags & PCRE2_HASBSK) != 0;
mb->allowemptypartial = (re->max_lookbehind > 0) ||
(re->flags & PCRE2_MATCH_EMPTY) != 0;
+mb->allowlookaroundbsk =
+ (re->extra_options & PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK) != 0;
mb->poptions = re->overall_options; /* Pattern options */
mb->ignore_skip_arg = 0;
mb->mark = mb->nomatch_mark = NULL; /* In case never set */
@@ -7317,9 +7462,11 @@ switch(re->newline_convention)
mb->nltype = NLTYPE_ANYCRLF;
break;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
- return PCRE2_ERROR_INTERNAL;
+ return match_data->rc = PCRE2_ERROR_INTERNAL;
+ /* LCOV_EXCL_STOP */
}
/* The backtracking frames have fixed data at the front, and a PCRE2_SIZE
@@ -7361,7 +7508,7 @@ if (heapframes_size < START_FRAMES_SIZE) heapframes_size = START_FRAMES_SIZE;
if (heapframes_size / 1024 > mb->heap_limit)
{
PCRE2_SIZE max_size = 1024 * mb->heap_limit;
- if (max_size < frame_size) return PCRE2_ERROR_HEAPLIMIT;
+ if (max_size < frame_size) return match_data->rc = PCRE2_ERROR_HEAPLIMIT;
heapframes_size = max_size;
}
@@ -7377,7 +7524,7 @@ if (match_data->heapframes_size < heapframes_size)
if (match_data->heapframes == NULL)
{
match_data->heapframes_size = 0;
- return PCRE2_ERROR_NOMEMORY;
+ return match_data->rc = PCRE2_ERROR_NOMEMORY;
}
match_data->heapframes_size = heapframes_size;
}
@@ -7853,7 +8000,7 @@ for(;;)
new_start_match = mb->verb_skip_ptr;
break;
}
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* NOMATCH and PRUNE advance by one character. THEN at this level acts
exactly like PRUNE. Unset ignore SKIP-with-argument. */
@@ -8011,6 +8158,7 @@ if (utf && end_subject != true_end_subject &&
match_data->code = re;
match_data->mark = mb->mark;
match_data->matchedby = PCRE2_MATCHEDBY_INTERPRETER;
+match_data->options = original_options;
/* Handle a fully successful match. Set the return code to the number of
captured strings, or 0 if there were too many to fit into the ovector, and then
@@ -8022,20 +8170,26 @@ if (rc == MATCH_MATCH)
match_data->rc = ((int)mb->end_offset_top >= 2 * match_data->oveccount)?
0 : (int)mb->end_offset_top/2 + 1;
match_data->subject_length = length;
+ match_data->start_offset = start_offset;
match_data->startchar = start_match - subject;
match_data->leftchar = mb->start_used_ptr - subject;
match_data->rightchar = ((mb->last_used_ptr > mb->end_match_ptr)?
mb->last_used_ptr : mb->end_match_ptr) - subject;
if ((options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
{
- length = CU2BYTES(length + was_zero_terminated);
- match_data->subject = match_data->memctl.malloc(length,
- match_data->memctl.memory_data);
- if (match_data->subject == NULL) return PCRE2_ERROR_NOMEMORY;
- memcpy((void *)match_data->subject, subject, length);
+ if (length != 0)
+ {
+ match_data->subject = match_data->memctl.malloc(CU2BYTES(length),
+ match_data->memctl.memory_data);
+ if (match_data->subject == NULL)
+ return match_data->rc = PCRE2_ERROR_NOMEMORY;
+ memcpy((void *)match_data->subject, subject, CU2BYTES(length));
+ }
+ else
+ match_data->subject = NULL;
match_data->flags |= PCRE2_MD_COPIED_SUBJECT;
}
- else match_data->subject = subject;
+ else match_data->subject = original_subject;
return match_data->rc;
}
@@ -8057,8 +8211,9 @@ PCRE2_ERROR_PARTIAL. */
else if (match_partial != NULL)
{
- match_data->subject = subject;
+ match_data->subject = original_subject;
match_data->subject_length = length;
+ match_data->start_offset = start_offset;
match_data->ovector[0] = match_partial - subject;
match_data->ovector[1] = end_subject - subject;
match_data->startchar = match_partial - subject;
@@ -8069,7 +8224,13 @@ else if (match_partial != NULL)
/* Else this is the classic nomatch case. */
-else match_data->rc = PCRE2_ERROR_NOMATCH;
+else
+ {
+ match_data->subject = original_subject;
+ match_data->subject_length = length;
+ match_data->start_offset = start_offset;
+ match_data->rc = PCRE2_ERROR_NOMATCH;
+ }
return match_data->rc;
}
diff --git a/src/3rdparty/pcre2/src/pcre2_match_data.c b/src/3rdparty/pcre2/src/pcre2_match_data.c
index 100e7c9d944..fade67ae522 100644
--- a/src/3rdparty/pcre2/src/pcre2_match_data.c
+++ b/src/3rdparty/pcre2/src/pcre2_match_data.c
@@ -39,10 +39,6 @@ POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
@@ -85,6 +81,7 @@ PCRE2_EXP_DEFN pcre2_match_data * PCRE2_CALL_CONVENTION
pcre2_match_data_create_from_pattern(const pcre2_code *code,
pcre2_general_context *gcontext)
{
+if (code == NULL) return NULL;
if (gcontext == NULL) gcontext = (pcre2_general_context *)code;
return pcre2_match_data_create(((const pcre2_real_code *)code)->top_bracket + 1,
gcontext);
diff --git a/src/3rdparty/pcre2/src/pcre2_newline.c b/src/3rdparty/pcre2/src/pcre2_newline.c
index 6e9366db93c..a7c929921ea 100644
--- a/src/3rdparty/pcre2/src/pcre2_newline.c
+++ b/src/3rdparty/pcre2/src/pcre2_newline.c
@@ -48,10 +48,6 @@ and NLTYPE_ANY. The full list of Unicode newline characters is taken from
http://unicode.org/unicode/reports/tr18/. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
diff --git a/src/3rdparty/pcre2/src/pcre2_ord2utf.c b/src/3rdparty/pcre2/src/pcre2_ord2utf.c
index a1e9e08803b..3b8aead7595 100644
--- a/src/3rdparty/pcre2/src/pcre2_ord2utf.c
+++ b/src/3rdparty/pcre2/src/pcre2_ord2utf.c
@@ -43,13 +43,10 @@ POSSIBILITY OF SUCH DAMAGE.
into a UTF string. The behaviour is different for each code unit width. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
+
/* If SUPPORT_UNICODE is not defined, this function will never be called.
Supply a dummy function because some compilers do not like empty source
modules. */
@@ -83,16 +80,17 @@ PRIV(ord2utf)(uint32_t cvalue, PCRE2_UCHAR *buffer)
/* Convert to UTF-8 */
#if PCRE2_CODE_UNIT_WIDTH == 8
-int i, j;
+unsigned int i;
+
for (i = 0; i < PRIV(utf8_table1_size); i++)
if ((int)cvalue <= PRIV(utf8_table1)[i]) break;
buffer += i;
-for (j = i; j > 0; j--)
+for (unsigned int j = i; j != 0; j--)
{
*buffer-- = 0x80 | (cvalue & 0x3f);
cvalue >>= 6;
}
-*buffer = PRIV(utf8_table2)[i] | cvalue;
+*buffer = (PCRE2_UCHAR)(PRIV(utf8_table2)[i] | (int)cvalue);
return i + 1;
/* Convert to UTF-16 */
diff --git a/src/3rdparty/pcre2/src/pcre2_pattern_info.c b/src/3rdparty/pcre2/src/pcre2_pattern_info.c
index fe4d3c661a0..e0bd83a90e0 100644
--- a/src/3rdparty/pcre2/src/pcre2_pattern_info.c
+++ b/src/3rdparty/pcre2/src/pcre2_pattern_info.c
@@ -39,13 +39,10 @@ POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
+
/*************************************************
* Return info about compiled pattern *
*************************************************/
@@ -292,8 +289,7 @@ if (re->magic_number != MAGIC_NUMBER) return PCRE2_ERROR_BADMAGIC;
if ((re->flags & (PCRE2_CODE_UNIT_WIDTH/8)) == 0) return PCRE2_ERROR_BADMODE;
cb.version = 0;
-cc = (PCRE2_SPTR)((const uint8_t *)re + sizeof(pcre2_real_code))
- + re->name_count * re->name_entry_size;
+cc = (PCRE2_SPTR)((uint8_t *)re + re->code_start);
while (TRUE)
{
diff --git a/src/3rdparty/pcre2/src/pcre2_script_run.c b/src/3rdparty/pcre2/src/pcre2_script_run.c
index 4926fa63bbf..acdf41fe668 100644
--- a/src/3rdparty/pcre2/src/pcre2_script_run.c
+++ b/src/3rdparty/pcre2/src/pcre2_script_run.c
@@ -38,15 +38,14 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
+
/* This module contains the function for checking a script run. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
#include "pcre2_internal.h"
+
/*************************************************
* Check script run *
*************************************************/
diff --git a/src/3rdparty/pcre2/src/pcre2_serialize.c b/src/3rdparty/pcre2/src/pcre2_serialize.c
index a10e3020bbe..f10a3fa0ddd 100644
--- a/src/3rdparty/pcre2/src/pcre2_serialize.c
+++ b/src/3rdparty/pcre2/src/pcre2_serialize.c
@@ -38,16 +38,14 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
+
/* This module contains functions for serializing and deserializing
a sequence of compiled codes. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "pcre2_internal.h"
-#include "pcre2_internal.h"
/* Magic number to provide a small check against being handed junk. */
diff --git a/src/3rdparty/pcre2/src/pcre2_string_utils.c b/src/3rdparty/pcre2/src/pcre2_string_utils.c
index ebfa9434e39..f1ac718f6bd 100644
--- a/src/3rdparty/pcre2/src/pcre2_string_utils.c
+++ b/src/3rdparty/pcre2/src/pcre2_string_utils.c
@@ -38,53 +38,15 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
+
/* This module contains internal functions for comparing and finding the length
of strings. These are used instead of strcmp() etc because the standard
functions work only on 8-bit data. */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
-/*************************************************
-* Emulated memmove() for systems without it *
-*************************************************/
-
-/* This function can make use of bcopy() if it is available. Otherwise do it by
-steam, as there some non-Unix environments that lack both memmove() and
-bcopy(). */
-
-#if !defined(VPCOMPAT) && !defined(HAVE_MEMMOVE)
-void *
-PRIV(memmove)(void *d, const void *s, size_t n)
-{
-#ifdef HAVE_BCOPY
-bcopy(s, d, n);
-return d;
-#else
-size_t i;
-unsigned char *dest = (unsigned char *)d;
-const unsigned char *src = (const unsigned char *)s;
-if (dest > src)
- {
- dest += n;
- src += n;
- for (i = 0; i < n; ++i) *(--dest) = *(--src);
- return (void *)dest;
- }
-else
- {
- for (i = 0; i < n; ++i) *dest++ = *src++;
- return (void *)(dest - n);
- }
-#endif /* not HAVE_BCOPY */
-}
-#endif /* not VPCOMPAT && not HAVE_MEMMOVE */
-
/*************************************************
* Compare two zero-terminated PCRE2 strings *
diff --git a/src/3rdparty/pcre2/src/pcre2_study.c b/src/3rdparty/pcre2/src/pcre2_study.c
index 85764cea565..9f7fd6bd6b0 100644
--- a/src/3rdparty/pcre2/src/pcre2_study.c
+++ b/src/3rdparty/pcre2/src/pcre2_study.c
@@ -38,16 +38,15 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
+
/* This module contains functions for scanning a compiled pattern and
collecting data (e.g. minimum matching length). */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
+
+
/* The maximum remembered capturing brackets minimum. */
#define MAX_CACHE_BACKREF 128
@@ -139,7 +138,7 @@ for (;;)
PCRE2_UCHAR op;
PCRE2_SPTR cs, ce;
- if (branchlength >= UINT16_MAX)
+ if (branchlength >= (int)UINT16_MAX)
{
branchlength = UINT16_MAX;
cc = nextbranch;
@@ -176,7 +175,7 @@ for (;;)
cc += 1 + LINK_SIZE;
break;
}
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_ONCE:
case OP_SCRIPT_RUN:
@@ -253,7 +252,7 @@ for (;;)
case OP_ASSERT_SCS:
case OP_ASSERTBACK_NA:
do cc += GET(cc, 1); while (*cc == OP_ALT);
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* Skip over things that don't match chars */
@@ -353,7 +352,7 @@ for (;;)
case OP_PROP:
case OP_NOTPROP:
cc += 2;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_NOT_DIGIT:
case OP_DIGIT:
@@ -434,7 +433,7 @@ for (;;)
case OP_CRMINPLUS:
case OP_CRPOSPLUS:
branchlength++;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_CRSTAR:
case OP_CRMINSTAR:
@@ -628,11 +627,11 @@ for (;;)
break;
}
- /* Take care not to overflow: (1) min and d are ints, so check that their
- product is not greater than INT_MAX. (2) branchlength is limited to
- UINT16_MAX (checked at the top of the loop). */
+ /* Take care not to overflow: (1) min and d are ints, so check that their
+ product is not greater than INT_MAX. (2) branchlength is limited to
+ UINT16_MAX (checked at the top of the loop). */
- if ((d > 0 && (INT_MAX/d) < min) || UINT16_MAX - branchlength < min*d)
+ if ((d > 0 && (INT_MAX/d) < min) || (int)UINT16_MAX - branchlength < min*d)
branchlength = UINT16_MAX;
else branchlength += min * d;
break;
@@ -753,14 +752,18 @@ for (;;)
/* This should not occur: we list all opcodes explicitly so that when
new ones get added they are properly considered. */
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return -3;
+ /* LCOV_EXCL_STOP */
}
}
+/* LCOV_EXCL_START */
PCRE2_DEBUG_UNREACHABLE(); /* Control should never reach here */
return -3; /* Avoid compiler warnings */
+/* LCOV_EXCL_STOP */
}
@@ -1304,7 +1307,7 @@ do
case OP_PROP:
if (ncode[1] != PT_CLIST) break;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_ANYNL:
case OP_CHAR:
case OP_CHARI:
@@ -1328,7 +1331,7 @@ do
tcode = ncode;
continue; /* With the following significant opcode */
}
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* For a group bracket or a positive assertion without an immediately
following mandatory setting, recurse to set bits from within the
@@ -1456,7 +1459,7 @@ do
case OP_EXACT:
tcode += IMM2_SIZE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_CHAR:
case OP_PLUS:
case OP_MINPLUS:
@@ -1467,7 +1470,7 @@ do
case OP_EXACTI:
tcode += IMM2_SIZE;
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_CHARI:
case OP_PLUSI:
case OP_MINPLUSI:
@@ -1487,10 +1490,10 @@ do
SET_BIT(CHAR_SPACE);
/* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set
- the bits for 0xA0 and for code units >= 255, independently of UTF. */
+ the bits for NBSP and for code units >= 255, independently of UTF. */
#if PCRE2_CODE_UNIT_WIDTH != 8
- SET_BIT(0xA0);
+ SET_BIT(CHAR_NBSP);
SET_BIT(0xFF);
#else
/* For the 8-bit library in UTF-8 mode, set the bits for the first code
@@ -1506,12 +1509,9 @@ do
}
else
#endif
- /* For the 8-bit library not in UTF-8 mode, set the bit for 0xA0, unless
- the code is EBCDIC. */
+ /* For the 8-bit library not in UTF-8 mode, set the bit for NBSP. */
{
-#ifndef EBCDIC
- SET_BIT(0xA0);
-#endif /* Not EBCDIC */
+ SET_BIT(CHAR_NBSP);
}
#endif /* 8-bit support */
@@ -1606,7 +1606,8 @@ do
case OP_TYPEUPTO:
case OP_TYPEMINUPTO:
case OP_TYPEPOSUPTO:
- tcode += IMM2_SIZE; /* Fall through */
+ tcode += IMM2_SIZE;
+ PCRE2_FALLTHROUGH /* Fall through */
case OP_TYPESTAR:
case OP_TYPEMINSTAR:
@@ -1626,10 +1627,10 @@ do
SET_BIT(CHAR_SPACE);
/* For the 16-bit and 32-bit libraries (which can never be EBCDIC), set
- the bits for 0xA0 and for code units >= 255, independently of UTF. */
+ the bits for NBSP and for code units >= 255, independently of UTF. */
#if PCRE2_CODE_UNIT_WIDTH != 8
- SET_BIT(0xA0);
+ SET_BIT(CHAR_NBSP);
SET_BIT(0xFF);
#else
/* For the 8-bit library in UTF-8 mode, set the bits for the first code
@@ -1645,12 +1646,9 @@ do
}
else
#endif
- /* For the 8-bit library not in UTF-8 mode, set the bit for 0xA0, unless
- the code is EBCDIC. */
+ /* For the 8-bit library not in UTF-8 mode, set the bit for NBSP. */
{
-#ifndef EBCDIC
- SET_BIT(0xA0);
-#endif /* Not EBCDIC */
+ SET_BIT(CHAR_NBSP);
}
#endif /* 8-bit support */
break;
@@ -1779,9 +1777,11 @@ do
case XCL_END:
goto HANDLE_CLASSMAP;
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return SSB_UNKNOWN; /* Internal error, should not occur */
+ /* LCOV_EXCL_STOP */
}
}
#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8 */
@@ -1790,7 +1790,7 @@ do
/* It seems that the fall through comment must be outside the #ifdef if
it is to avoid the gcc compiler warning. */
- /* Fall through */
+ PCRE2_FALLTHROUGH /* Fall through */
/* Enter here for a negative non-XCLASS. In the 8-bit library, if we are
in UTF mode, any byte with a value >= 0xc4 is a potentially valid starter
@@ -1805,14 +1805,15 @@ do
re->start_bitmap[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */
memset(re->start_bitmap+25, 0xff, 7); /* Bits for 0xc9 - 0xff */
}
+ PCRE2_FALLTHROUGH /* Fall through */
#elif PCRE2_CODE_UNIT_WIDTH != 8
SET_BIT(0xFF); /* For characters >= 255 */
+ PCRE2_FALLTHROUGH /* Fall through */
#endif
- /* Fall through */
/* Enter here for a positive non-XCLASS. If we have fallen through from
an XCLASS, classmap will already be set; just advance the code pointer.
- Otherwise, set up classmap for a a non-XCLASS and advance past it. */
+ Otherwise, set up classmap for a non-XCLASS and advance past it. */
case OP_CLASS:
if (*tcode == OP_XCLASS) tcode += GET(tcode, 1); else
@@ -1930,11 +1931,13 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0)
{
int depth = 0;
int rc = set_start_bits(re, code, utf, ucp, &depth);
+ /* LCOV_EXCL_START */
if (rc == SSB_UNKNOWN)
{
PCRE2_DEBUG_UNREACHABLE();
return 1;
}
+ /* LCOV_EXCL_STOP */
/* If a list of starting code units was set up, scan the list to see if only
one or two were listed. Having only one listed is rare because usually a
@@ -2002,6 +2005,16 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0)
if (d != a) goto DONE; /* Not the other case of a */
b = c; /* Save second in b */
+
+#ifdef EBCDIC
+ /* To match ASCII (which puts the uppercase one in a), swap a & b
+ if needed. This doesn't really matter, but neatens the tests. */
+ if (TABLE_GET((unsigned int)a, re->tables + lcc_offset, a) == a)
+ {
+ b = a;
+ a = c;
+ }
+#endif
}
else goto DONE; /* More than two characters found */
}
@@ -2049,16 +2062,20 @@ if ((re->flags & (PCRE2_MATCH_EMPTY|PCRE2_HASACCEPT)) == 0 &&
case -1: /* \C in UTF mode or over-complex regex */
break; /* Leave minlength unchanged (will be zero) */
+ /* LCOV_EXCL_START */
case -2:
PCRE2_DEBUG_UNREACHABLE();
return 2; /* missing capturing bracket */
+ /* LCOV_EXCL_STOP */
+ /* LCOV_EXCL_START */
case -3:
PCRE2_DEBUG_UNREACHABLE();
return 3; /* unrecognized opcode */
+ /* LCOV_EXCL_STOP */
default:
- re->minlength = (min > UINT16_MAX)? UINT16_MAX : min;
+ re->minlength = (min > (int)UINT16_MAX)? (int)UINT16_MAX : min;
break;
}
}
diff --git a/src/3rdparty/pcre2/src/pcre2_substitute.c b/src/3rdparty/pcre2/src/pcre2_substitute.c
index 17040ce5fd4..5cb84748e0e 100644
--- a/src/3rdparty/pcre2/src/pcre2_substitute.c
+++ b/src/3rdparty/pcre2/src/pcre2_substitute.c
@@ -39,12 +39,10 @@ POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
+
+
#define PTR_STACK_SIZE 20
#define SUBSTITUTE_OPTIONS \
@@ -131,7 +129,6 @@ for (; ptr < ptrend; ptr++)
ptr += 1; /* Must point after \ */
erc = PRIV(check_escape)(&ptr, ptrend, &ch, &errorcode,
code->overall_options, code->extra_options, code->top_bracket, FALSE, NULL);
- ptr -= 1; /* Back to last code unit of escape */
if (errorcode != 0)
{
/* errorcode from check_escape is positive, so must not be returned by
@@ -327,9 +324,11 @@ if (input_len == 0) return 0;
switch (state->to_case)
{
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return 0;
+ /* LCOV_EXCL_STOP */
case PCRE2_SUBSTITUTE_CASE_LOWER: // Can be single_char TRUE or FALSE
case PCRE2_SUBSTITUTE_CASE_UPPER: // Can only be single_char FALSE
@@ -465,9 +464,11 @@ PCRE2_ASSERT(input_len != 0);
switch (state->to_case)
{
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return 0;
+ /* LCOV_EXCL_STOP */
case PCRE2_SUBSTITUTE_CASE_LOWER: // Can be single_char TRUE or FALSE
case PCRE2_SUBSTITUTE_CASE_UPPER: // Can only be single_char FALSE
@@ -751,12 +752,14 @@ BOOL use_existing_match;
BOOL replacement_only;
BOOL utf = (code->overall_options & PCRE2_UTF) != 0;
PCRE2_UCHAR temp[6];
+PCRE2_UCHAR null_str[1] = { 0xcd };
+PCRE2_SPTR original_subject = subject;
PCRE2_SPTR ptr;
PCRE2_SPTR repend = NULL;
PCRE2_SIZE extra_needed = 0;
PCRE2_SIZE buff_offset, buff_length, lengthleft, fraglength;
PCRE2_SIZE *ovector;
-PCRE2_SIZE ovecsave[3];
+PCRE2_SIZE ovecsave[2] = { 0, 0 };
pcre2_substitute_callout_block scb;
PCRE2_SIZE sub_start_extra_needed;
PCRE2_SIZE (*substitute_case_callout)(PCRE2_SPTR, PCRE2_SIZE, PCRE2_UCHAR *,
@@ -768,7 +771,6 @@ void *substitute_case_callout_data = NULL;
buff_offset = 0;
lengthleft = buff_length = *blength;
*blength = PCRE2_UNSET;
-ovecsave[0] = ovecsave[1] = ovecsave[2] = PCRE2_UNSET;
if (mcontext != NULL)
{
@@ -788,18 +790,74 @@ zero length is interpreted as an empty string. */
if (replacement == NULL)
{
if (rlength != 0) return PCRE2_ERROR_NULL;
- replacement = (PCRE2_SPTR)"";
+ replacement = null_str;
}
if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement);
repend = replacement + rlength;
+/* A NULL subject of zero length is treated as an empty string. */
+
+if (subject == NULL)
+ {
+ if (length != 0) return PCRE2_ERROR_NULL;
+ subject = null_str;
+ }
+
+if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);
+
/* Check for using a match that has already happened. Note that the subject
pointer in the match data may be NULL after a no-match. */
use_existing_match = ((options & PCRE2_SUBSTITUTE_MATCHED) != 0);
replacement_only = ((options & PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) != 0);
+if (use_existing_match && match_data == NULL) return PCRE2_ERROR_NULL;
+
+/* If an existing match is being passed in, we should check that it matches
+the passed-in subject pointer, length, and match options. We don't currently
+have a use-case for someone to match on one subject, then try and use that
+match data on a different subject. In a UTF-encoded string, a simple change
+like replacing one character for another won't preserve the code unit offsets,
+so it's hard to see, in the general case, how it would be safe or useful to
+support swapping or mutating the subject string.
+
+Similarly, using different match options between the first (external) and
+subsequent (internal, global) matches is hard to justify. */
+
+if (use_existing_match)
+ {
+ /* Return early, as the rest of the match_data may not have been
+ initialised. This duplicates and must be in sync with the check below that
+ aborts substitution on any result other than success or no-match. */
+ if (match_data->rc < 0 && match_data->rc != PCRE2_ERROR_NOMATCH)
+ return match_data->rc;
+
+ /* Not supported if the passed-in match was from the DFA interpreter. */
+ if (match_data->matchedby == PCRE2_MATCHEDBY_DFA_INTERPRETER)
+ return PCRE2_ERROR_DFA_UFUNC;
+
+ if (code != match_data->code)
+ return PCRE2_ERROR_DIFFSUBSPATTERN;
+
+ /* We want the passed-in subject strings to match. This implies the effective
+ length must match, and either: the pointers are equal (with strict matching
+ of NULL against NULL); or, the special case of PCRE2_COPY_MATCHED_SUBJECT
+ where we cannot compare pointers but we can verify the contents. */
+ if (length != match_data->subject_length ||
+ !(original_subject == match_data->subject ||
+ ((match_data->flags & PCRE2_MD_COPIED_SUBJECT) != 0 &&
+ (length == 0 ||
+ memcmp(subject, match_data->subject, CU2BYTES(length)) == 0))))
+ return PCRE2_ERROR_DIFFSUBSSUBJECT;
+
+ if (start_offset != match_data->start_offset)
+ return PCRE2_ERROR_DIFFSUBSOFFSET;
+
+ if ((options & ~SUBSTITUTE_OPTIONS) != match_data->options)
+ return PCRE2_ERROR_DIFFSUBSOPTIONS;
+ }
+
/* If starting from an existing match, there must be an externally provided
match data block. We create an internal match_data block in two cases: (a) an
external one is not supplied (and we are not starting from an existing match);
@@ -816,9 +874,8 @@ have to be changes below. */
if (match_data == NULL)
{
pcre2_general_context gcontext;
- if (use_existing_match) return PCRE2_ERROR_NULL;
gcontext.memctl = (mcontext == NULL)?
- ((const pcre2_real_code *)code)->memctl :
+ ((pcre2_real_code *)code)->memctl :
((pcre2_real_match_context *)mcontext)->memctl;
match_data = internal_match_data =
pcre2_match_data_create_from_pattern(code, &gcontext);
@@ -830,7 +887,7 @@ else if (use_existing_match)
int pairs;
pcre2_general_context gcontext;
gcontext.memctl = (mcontext == NULL)?
- ((const pcre2_real_code *)code)->memctl :
+ ((pcre2_real_code *)code)->memctl :
((pcre2_real_match_context *)mcontext)->memctl;
pairs = (code->top_bracket + 1 < match_data->oveccount)?
code->top_bracket + 1 : match_data->oveccount;
@@ -841,9 +898,15 @@ else if (use_existing_match)
+ 2*pairs*sizeof(PCRE2_SIZE));
internal_match_data->heapframes = NULL;
internal_match_data->heapframes_size = 0;
+ /* Ensure that the subject is not freed when internal_match_data is */
+ internal_match_data->flags &= ~PCRE2_MD_COPIED_SUBJECT;
match_data = internal_match_data;
}
+/* If using an internal match data, there's no need to copy the subject. */
+
+if (internal_match_data != NULL) options &= ~PCRE2_COPY_MATCHED_SUBJECT;
+
/* Remember ovector details */
ovector = pcre2_get_ovector_pointer(match_data);
@@ -856,19 +919,6 @@ scb.input = subject;
scb.output = (PCRE2_SPTR)buffer;
scb.ovector = ovector;
-/* A NULL subject of zero length is treated as an empty string. */
-
-if (subject == NULL)
- {
- if (length != 0) return PCRE2_ERROR_NULL;
- subject = (PCRE2_SPTR)"";
- }
-
-/* Find length of zero-terminated subject */
-
-if (length == PCRE2_ZERO_TERMINATED)
- length = subject? PRIV(strlen)(subject) : 0;
-
/* Check UTF replacement string if necessary. */
#ifdef SUPPORT_UNICODE
@@ -905,7 +955,7 @@ if (!replacement_only) CHECKMEMCPY(subject, start_offset);
match is taken from the match_data that was passed in. */
subs = 0;
-do
+for (;;)
{
PCRE2_SPTR ptrstack[PTR_STACK_SIZE];
uint32_t ptrstackptr = 0;
@@ -925,54 +975,12 @@ do
if (utf) options |= PCRE2_NO_UTF_CHECK; /* Only need to check once */
#endif
- /* Any error other than no match returns the error code. No match when not
- doing the special after-empty-match global rematch, or when at the end of the
- subject, breaks the global loop. Otherwise, advance the starting point by one
- character, copying it to the output, and try again. */
-
- if (rc < 0)
- {
- PCRE2_SIZE save_start;
-
- if (rc != PCRE2_ERROR_NOMATCH) goto EXIT;
- if (goptions == 0 || start_offset >= length) break;
-
- /* Advance by one code point. Then, if CRLF is a valid newline sequence and
- we have advanced into the middle of it, advance one more code point. In
- other words, do not start in the middle of CRLF, even if CR and LF on their
- own are valid newlines. */
-
- save_start = start_offset++;
- if (subject[start_offset-1] == CHAR_CR &&
- (code->newline_convention == PCRE2_NEWLINE_CRLF ||
- code->newline_convention == PCRE2_NEWLINE_ANY ||
- code->newline_convention == PCRE2_NEWLINE_ANYCRLF) &&
- start_offset < length &&
- subject[start_offset] == CHAR_LF)
- start_offset++;
-
- /* Otherwise, in UTF mode, advance past any secondary code points. */
+ /* Any error other than no match returns the error code. No match breaks the
+ global loop. */
- else if ((code->overall_options & PCRE2_UTF) != 0)
- {
-#if PCRE2_CODE_UNIT_WIDTH == 8
- while (start_offset < length && (subject[start_offset] & 0xc0) == 0x80)
- start_offset++;
-#elif PCRE2_CODE_UNIT_WIDTH == 16
- while (start_offset < length &&
- (subject[start_offset] & 0xfc00) == 0xdc00)
- start_offset++;
-#endif
- }
+ if (rc == PCRE2_ERROR_NOMATCH) break;
- /* Copy what we have advanced past (unless not required), reset the special
- global options, and continue to the next match. */
-
- fraglength = start_offset - save_start;
- if (!replacement_only) CHECKMEMCPY(subject + save_start, fraglength);
- goptions = 0;
- continue;
- }
+ if (rc < 0) goto EXIT;
/* Handle a successful match. Matches that use \K to end before they start
or start before the current point in the subject are not supported. */
@@ -983,25 +991,27 @@ do
goto EXIT;
}
- /* Check for the same match as previous. This is legitimate after matching an
- empty string that starts after the initial match offset. We have tried again
- at the match point in case the pattern is one like /(?<=\G.)/ which can never
- match at its starting point, so running the match achieves the bumpalong. If
- we do get the same (null) match at the original match point, it isn't such a
- pattern, so we now do the empty string magic. In all other cases, a repeat
- match should never occur. */
+ /* Assert that our replacement loop is making progress, checked even in
+ release builds. This should be impossible to hit, however, an infinite loop
+ would be fairly catastrophic.
- if (ovecsave[0] == ovector[0] && ovecsave[1] == ovector[1])
+ "Progress" is measured as ovector[1] strictly advancing, or, an empty match
+ after a non-empty match. */
+
+ /* LCOV_EXCL_START */
+ if (subs > 0 &&
+ !(ovector[1] > ovecsave[1] ||
+ (ovector[1] == ovector[0] && ovecsave[1] > ovecsave[0] &&
+ ovector[1] == ovecsave[1])))
{
- if (ovector[0] == ovector[1] && ovecsave[2] != start_offset)
- {
- goptions = PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED;
- ovecsave[2] = start_offset;
- continue; /* Back to the top of the loop */
- }
+ PCRE2_DEBUG_UNREACHABLE();
rc = PCRE2_ERROR_INTERNAL_DUPMATCH;
goto EXIT;
}
+ /* LCOV_EXCL_STOP */
+
+ ovecsave[0] = ovector[0];
+ ovecsave[1] = ovector[1];
/* Count substitutions with a paranoid check for integer overflow; surely no
real call to this function would ever hit this! */
@@ -1133,6 +1143,44 @@ do
subptrend = subject + length;
goto SUBPTR_SUBSTITUTE;
}
+ else if (next == CHAR_PLUS &&
+ !(ptr+1 < repend && ptr[1] == CHAR_LEFT_CURLY_BRACKET))
+ {
+ /* Perl supports $+ for "highest captured group" (not the same as $^N
+ which is mainly only useful inside Perl's match callbacks). We also
+ don't accept "$+{..." since that's Perl syntax for our ${name}. */
+ ++ptr;
+ if (code->top_bracket == 0)
+ {
+ /* Treat either as "no such group" or "all groups unset" based on the
+ PCRE2_SUBSTITUTE_UNKNOWN_UNSET option. */
+ if ((suboptions & PCRE2_SUBSTITUTE_UNKNOWN_UNSET) == 0)
+ {
+ rc = PCRE2_ERROR_NOSUBSTRING;
+ goto PTREXIT;
+ }
+ group = 0;
+ }
+ else
+ {
+ /* If we have any capture groups, then the ovector needs to be large
+ enough for all of them, or the result won't be accurate. */
+ if (match_data->oveccount < code->top_bracket + 1)
+ {
+ rc = PCRE2_ERROR_UNAVAILABLE;
+ goto PTREXIT;
+ }
+ for (group = code->top_bracket; group > 0; group--)
+ if (ovector[2*group] != PCRE2_UNSET) break;
+ }
+ if (group == 0)
+ {
+ if ((suboptions & PCRE2_SUBSTITUTE_UNSET_EMPTY) != 0) continue;
+ rc = PCRE2_ERROR_UNSET;
+ goto PTREXIT;
+ }
+ goto GROUP_SUBSTITUTE;
+ }
if (next == CHAR_LEFT_CURLY_BRACKET)
{
@@ -1627,19 +1675,25 @@ do
}
}
- /* Save the details of this match. See above for how this data is used. If we
- matched an empty string, do the magic for global matches. Update the start
- offset to point to the rest of the subject string. If we re-used an existing
- match for the first match, switch to the internal match data block. */
+ /* Exit the global loop if we are not in global mode, or if pcre2_next_match()
+ indicates we have reached the end of the subject. */
- ovecsave[0] = ovector[0];
- ovecsave[1] = ovector[1];
- ovecsave[2] = start_offset;
+ if ((suboptions & PCRE2_SUBSTITUTE_GLOBAL) == 0 ||
+ !pcre2_next_match(match_data, &start_offset, &goptions))
+ {
+ start_offset = ovector[1];
+ break;
+ }
+
+ /* Verify that pcre2_next_match() has not done a bumpalong (because we have
+ already returned PCRE2_ERROR_BADSUBSPATTERN for \K in lookarounds).
+
+ We would otherwise have to memcpy the fragment spanning from ovector[1] to the
+ new start_offset.*/
+
+ PCRE2_ASSERT(start_offset == ovector[1]);
- goptions = (ovector[0] != ovector[1] || ovector[0] > start_offset)? 0 :
- PCRE2_ANCHORED|PCRE2_NOTEMPTY_ATSTART;
- start_offset = ovector[1];
- } while ((suboptions & PCRE2_SUBSTITUTE_GLOBAL) != 0); /* Repeat "do" loop */
+ } /* End of global loop */
/* Copy the rest of the subject unless not required, and terminate the output
with a binary zero. */
diff --git a/src/3rdparty/pcre2/src/pcre2_substring.c b/src/3rdparty/pcre2/src/pcre2_substring.c
index 88afd2348bb..f68b464e058 100644
--- a/src/3rdparty/pcre2/src/pcre2_substring.c
+++ b/src/3rdparty/pcre2/src/pcre2_substring.c
@@ -39,10 +39,6 @@ POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "pcre2_internal.h"
@@ -126,7 +122,7 @@ PCRE2_SIZE size;
rc = pcre2_substring_length_bynumber(match_data, stringnumber, &size);
if (rc < 0) return rc;
if (size + 1 > *sizeptr) return PCRE2_ERROR_NOMEMORY;
-memcpy(buffer, match_data->subject + match_data->ovector[stringnumber*2],
+if (size != 0) memcpy(buffer, match_data->subject + match_data->ovector[stringnumber*2],
CU2BYTES(size));
buffer[size] = 0;
*sizeptr = size;
@@ -218,7 +214,7 @@ yield = PRIV(memctl_malloc)(sizeof(pcre2_memctl) +
(size + 1)*PCRE2_CODE_UNIT_WIDTH, (pcre2_memctl *)match_data);
if (yield == NULL) return PCRE2_ERROR_NOMEMORY;
yield = (PCRE2_UCHAR *)(((char *)yield) + sizeof(pcre2_memctl));
-memcpy(yield, match_data->subject + match_data->ovector[stringnumber*2],
+if (size != 0) memcpy(yield, match_data->subject + match_data->ovector[stringnumber*2],
CU2BYTES(size));
yield[size] = 0;
*stringptr = yield;
@@ -259,7 +255,7 @@ permits duplicate names, the first substring that is set is chosen.
Arguments:
match_data pointer to match data
stringname the name of the required substring
- sizeptr where to put the length
+ sizeptr where to put the length, if not NULL
Returns: 0 if successful, else a negative error number
*/
@@ -342,8 +338,15 @@ else /* Matched using pcre2_dfa_match() */
left = match_data->ovector[stringnumber*2];
right = match_data->ovector[stringnumber*2+1];
+/* LCOV_EXCL_START - this appears to be unreachable, as the ovector and
+subject_length should always be set consistently, no matter what misbehaviour
+the caller has committed. */
if (left > match_data->subject_length || right > match_data->subject_length)
+ {
+ PCRE2_DEBUG_UNREACHABLE();
return PCRE2_ERROR_INVALIDOFFSET;
+ }
+/* LCOV_EXCL_STOP */
if (sizeptr != NULL) *sizeptr = (left > right)? 0 : right - left;
return 0;
}
diff --git a/src/3rdparty/pcre2/src/pcre2_tables.c b/src/3rdparty/pcre2/src/pcre2_tables.c
index 097a1acca87..0b9b43bf2e5 100644
--- a/src/3rdparty/pcre2/src/pcre2_tables.c
+++ b/src/3rdparty/pcre2/src/pcre2_tables.c
@@ -38,27 +38,33 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
+
/* This module contains some fixed tables that are used by more than one of the
PCRE2 code modules. The tables are also #included by the pcre2test program,
which uses macros to change their names from _pcre2_xxx to xxxx, thereby
avoiding name clashes with the library. In this case, PCRE2_PCRE2TEST is
defined. */
-#ifndef PCRE2_PCRE2TEST /* We're compiling the library */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+
+#if !defined(PCRE2_PCRE2TEST) && !defined(PCRE2_DFTABLES) && \
+ !defined(PCRE2_PCRE2POSIX) /* We're compiling the library */
#include "pcre2_internal.h"
-#endif /* PCRE2_PCRE2TEST */
+#endif
+
+
+/* Utility macros */
+#define ARR_SIZE(x) sizeof(x)/sizeof(x[0])
+
+
+#if !defined(PCRE2_PCRE2TEST) && !defined(PCRE2_DFTABLES) && \
+ !defined(PCRE2_PCRE2POSIX)
/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that
the definition is next to the definition of the opcodes in pcre2_internal.h.
This is mode-dependent, so it is skipped when this file is included by
pcre2test. */
-#ifndef PCRE2_PCRE2TEST
const uint8_t PRIV(OP_lengths)[] = { OP_LENGTHS };
-#endif
/* Tables of horizontal and vertical whitespace characters, suitable for
adding to classes. */
@@ -66,6 +72,11 @@ adding to classes. */
const uint32_t PRIV(hspace_list)[] = { HSPACE_LIST };
const uint32_t PRIV(vspace_list)[] = { VSPACE_LIST };
+#endif /* !PCRE2_PCRE2TEST && !PCRE2_DFTABLES && !PCRE2_PCRE2POSIX */
+
+
+#if !defined(PCRE2_DFTABLES) && !defined(PCRE2_PCRE2POSIX)
+
/* These tables are the pairs of delimiters that are valid for callout string
arguments. For each starting delimiter there must be a matching ending
delimiter, which in fact is different only for bracket-like delimiters. */
@@ -80,6 +91,8 @@ const uint32_t PRIV(callout_end_delims[]) = {
CHAR_CIRCUMFLEX_ACCENT, CHAR_PERCENT_SIGN, CHAR_NUMBER_SIGN,
CHAR_DOLLAR_SIGN, CHAR_RIGHT_CURLY_BRACKET, 0 };
+#endif /* !PCRE2_DFTABLES && !PCRE2_PCRE2POSIX */
+
/*************************************************
* Tables for UTF-8 support *
@@ -90,23 +103,24 @@ as for the library in 8-bit mode, because pcre2test uses UTF-8 internally for
handling wide characters. */
#if defined PCRE2_PCRE2TEST || \
- (defined SUPPORT_UNICODE && \
- defined PCRE2_CODE_UNIT_WIDTH && \
- PCRE2_CODE_UNIT_WIDTH == 8)
+ (!defined(PCRE2_DFTABLES) && !defined(PCRE2_PCRE2POSIX) && \
+ defined SUPPORT_UNICODE && \
+ defined PCRE2_CODE_UNIT_WIDTH && \
+ PCRE2_CODE_UNIT_WIDTH == 8)
/* These are the breakpoints for different numbers of bytes in a UTF-8
character. */
const int PRIV(utf8_table1)[] =
- { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
+ { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff };
-const int PRIV(utf8_table1_size) = sizeof(PRIV(utf8_table1)) / sizeof(int);
+const unsigned PRIV(utf8_table1_size) = ARR_SIZE(PRIV(utf8_table1));
/* These are the indicator bits and the mask for the data bits to set in the
first byte of a character, indexed by the number of additional bytes. */
-const int PRIV(utf8_table2)[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
-const int PRIV(utf8_table3)[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
+const int PRIV(utf8_table2)[] = { 0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };
+const int PRIV(utf8_table3)[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
/* Table of the number of extra bytes, indexed by the first byte masked with
0x3f. The highest number for a valid UTF-8 first byte is in fact 0x3d. */
@@ -120,10 +134,11 @@ const uint8_t PRIV(utf8_table4)[] = {
#endif /* UTF-8 support needed */
/* Tables concerned with Unicode properties are relevant only when Unicode
-support is enabled. See also the pcre2_ucptables.c file, which is generated by
+support is enabled. See also the pcre2_ucptables_inc.h file, which is generated by
a Python script from Unicode data files. */
-#ifdef SUPPORT_UNICODE
+#if !defined(PCRE2_DFTABLES) && !defined(PCRE2_PCRE2POSIX) && \
+ defined(SUPPORT_UNICODE)
/* Table to translate from particular type value to the general value. */
@@ -227,8 +242,69 @@ const int PRIV(ucp_typerange)[] = {
/* Finally, include the tables that are auto-generated from the Unicode data
files. */
-#include "pcre2_ucptables.c"
+#include "pcre2_ucptables_inc.h"
+
+#endif /* Unicode support needed */
+
+
+/*************************************************
+* Tables for EBCDIC support *
+*************************************************/
+
+#if defined(EBCDIC) && \
+ (defined(PCRE2_PCRE2TEST) || defined(PCRE2_DFTABLES) || 'a' != 0x81)
+
+const uint8_t PRIV(ebcdic_1047_to_ascii)[256] = {
+ 0x00,0x01,0x02,0x03,0x9c,0x09,0x86,0x7f,0x97,0x8d,0x8e,0x0b,0x0c,0x0d,0x0e,0x0f,
+#ifdef EBCDIC_NL25
+ 0x10,0x11,0x12,0x13,0x9d,0x85,0x08,0x87,0x18,0x19,0x92,0x8f,0x1c,0x1d,0x1e,0x1f,
+ 0x80,0x81,0x82,0x83,0x84,0x0a,0x17,0x1b,0x88,0x89,0x8a,0x8b,0x8c,0x05,0x06,0x07,
+#else
+ 0x10,0x11,0x12,0x13,0x9d,0x0a,0x08,0x87,0x18,0x19,0x92,0x8f,0x1c,0x1d,0x1e,0x1f,
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x17,0x1b,0x88,0x89,0x8a,0x8b,0x8c,0x05,0x06,0x07,
+#endif
+ 0x90,0x91,0x16,0x93,0x94,0x95,0x96,0x04,0x98,0x99,0x9a,0x9b,0x14,0x15,0x9e,0x1a,
+ 0x20,0xa0,0xe2,0xe4,0xe0,0xe1,0xe3,0xe5,0xe7,0xf1,0xa2,0x2e,0x3c,0x28,0x2b,0x7c,
+ 0x26,0xe9,0xea,0xeb,0xe8,0xed,0xee,0xef,0xec,0xdf,0x21,0x24,0x2a,0x29,0x3b,0x5e,
+ 0x2d,0x2f,0xc2,0xc4,0xc0,0xc1,0xc3,0xc5,0xc7,0xd1,0xa6,0x2c,0x25,0x5f,0x3e,0x3f,
+ 0xf8,0xc9,0xca,0xcb,0xc8,0xcd,0xce,0xcf,0xcc,0x60,0x3a,0x23,0x40,0x27,0x3d,0x22,
+ 0xd8,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0xab,0xbb,0xf0,0xfd,0xfe,0xb1,
+ 0xb0,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0xaa,0xba,0xe6,0xb8,0xc6,0xa4,
+ 0xb5,0x7e,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0xa1,0xbf,0xd0,0x5b,0xde,0xae,
+ 0xac,0xa3,0xa5,0xb7,0xa9,0xa7,0xb6,0xbc,0xbd,0xbe,0xdd,0xa8,0xaf,0x5d,0xb4,0xd7,
+ 0x7b,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0xad,0xf4,0xf6,0xf2,0xf3,0xf5,
+ 0x7d,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xb9,0xfb,0xfc,0xf9,0xfa,0xff,
+ 0x5c,0xf7,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0xb2,0xd4,0xd6,0xd2,0xd3,0xd5,
+ 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xb3,0xdb,0xdc,0xd9,0xda,0x9f,
+};
+
+const uint8_t PRIV(ascii_to_ebcdic_1047)[256] = {
+#ifdef EBCDIC_NL25
+ 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f,0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f,
+#else
+ 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f,0x16,0x05,0x15,0x0b,0x0c,0x0d,0x0e,0x0f,
+#endif
+ 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26,0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f,
+ 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d,0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61,
+ 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,
+ 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,
+ 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xad,0xe0,0xbd,0x5f,0x6d,
+ 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,
+ 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07,
+#ifdef EBCDIC_NL25
+ 0x20,0x21,0x22,0x23,0x24,0x15,0x06,0x17,0x28,0x29,0x2a,0x2b,0x2c,0x09,0x0a,0x1b,
+#else
+ 0x20,0x21,0x22,0x23,0x24,0x25,0x06,0x17,0x28,0x29,0x2a,0x2b,0x2c,0x09,0x0a,0x1b,
+#endif
+ 0x30,0x31,0x1a,0x33,0x34,0x35,0x36,0x08,0x38,0x39,0x3a,0x3b,0x04,0x14,0x3e,0xff,
+ 0x41,0xaa,0x4a,0xb1,0x9f,0xb2,0x6a,0xb5,0xbb,0xb4,0x9a,0x8a,0xb0,0xca,0xaf,0xbc,
+ 0x90,0x8f,0xea,0xfa,0xbe,0xa0,0xb6,0xb3,0x9d,0xda,0x9b,0x8b,0xb7,0xb8,0xb9,0xab,
+ 0x64,0x65,0x62,0x66,0x63,0x67,0x9e,0x68,0x74,0x71,0x72,0x73,0x78,0x75,0x76,0x77,
+ 0xac,0x69,0xed,0xee,0xeb,0xef,0xec,0xbf,0x80,0xfd,0xfe,0xfb,0xfc,0xba,0xae,0x59,
+ 0x44,0x45,0x42,0x46,0x43,0x47,0x9c,0x48,0x54,0x51,0x52,0x53,0x58,0x55,0x56,0x57,
+ 0x8c,0x49,0xcd,0xce,0xcb,0xcf,0xcc,0xe1,0x70,0xdd,0xde,0xdb,0xdc,0x8d,0x8e,0xdf,
+};
-#endif /* SUPPORT_UNICODE */
+#endif /* EBCDIC support needed */
/* End of pcre2_tables.c */
diff --git a/src/3rdparty/pcre2/src/pcre2_ucd.c b/src/3rdparty/pcre2/src/pcre2_ucd.c
index 4c5e5163b3a..1cbff3afecb 100644
--- a/src/3rdparty/pcre2/src/pcre2_ucd.c
+++ b/src/3rdparty/pcre2/src/pcre2_ucd.c
@@ -42,6 +42,7 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
+
/* This file contains tables of Unicode properties that are extracted from
Unicode data files. See the comments at the start of maint/GenerateUcd.py for
details.
@@ -52,13 +53,13 @@ _pcre2_xxx to xxxx, thereby avoiding name clashes with the library. At present,
just one of these tables is actually needed. When compiling the library, some
headers are needed. */
+
#ifndef PCRE2_PCRE2TEST
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
#include "pcre2_internal.h"
#endif /* PCRE2_PCRE2TEST */
+
+
/* The tables herein are needed only when UCP support is built, and in PCRE2
that happens automatically with UTF support. This module should not be
referenced otherwise, so it should not matter whether it is compiled or not.
diff --git a/src/3rdparty/pcre2/src/pcre2_ucptables.c b/src/3rdparty/pcre2/src/pcre2_ucptables_inc.h
index d2b34037bea..6f1731d32c8 100644
--- a/src/3rdparty/pcre2/src/pcre2_ucptables.c
+++ b/src/3rdparty/pcre2/src/pcre2_ucptables_inc.h
@@ -1593,4 +1593,4 @@ const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
#endif /* SUPPORT_UNICODE */
-/* End of pcre2_ucptables.c */
+/* End of pcre2_ucptables_inc.h */
diff --git a/src/3rdparty/pcre2/src/pcre2_util.h b/src/3rdparty/pcre2/src/pcre2_util.h
index ea8635552a1..7bfbee09952 100644
--- a/src/3rdparty/pcre2/src/pcre2_util.h
+++ b/src/3rdparty/pcre2/src/pcre2_util.h
@@ -71,6 +71,8 @@ side-effects. */
} while(0)
#endif
+/* LCOV_EXCL_START */
+
/* PCRE2_UNREACHABLE() can be used to mark locations on the code that
shouldn't be reached. In non debug builds is defined as a hint for
the compiler to eliminate any code after it, so it is useful also for
@@ -107,8 +109,16 @@ the reason and the actions that should be taken if it ever triggers. */
#define PCRE2_DEBUG_UNREACHABLE() PCRE2_UNREACHABLE()
+/* LCOV_EXCL_STOP */
+
#endif /* PCRE2_DEBUG */
+#ifndef PCRE2_ASSERT
+#define PCRE2_ASSERT(x) do {} while(0)
+#endif
+
+/* LCOV_EXCL_START */
+
#ifndef PCRE2_DEBUG_UNREACHABLE
#define PCRE2_DEBUG_UNREACHABLE() do {} while(0)
#endif
@@ -123,8 +133,45 @@ the reason and the actions that should be taken if it ever triggers. */
#endif
#endif /* !PCRE2_UNREACHABLE */
-#ifndef PCRE2_ASSERT
-#define PCRE2_ASSERT(x) do {} while(0)
+/* LCOV_EXCL_STOP */
+
+/* We define this fallthrough macro for suppressing -Wimplicit-fallthrough warnings.
+Clang only allows this via an attribute, whereas other compilers (eg. GCC) match attributes
+and also specially-formatted comments.
+
+This macro should be used with no following semicolon, and ideally with a comment: */
+
+// PCRE2_FALLTHROUGH /* Fall through */
+
+#ifndef PCRE2_FALLTHROUGH
+
+#if defined(__cplusplus) && __cplusplus >= 202002L && \
+ defined(__has_cpp_attribute)
+/* Standards-compatible C++ variant. */
+#if __has_cpp_attribute(fallthrough)
+#define PCRE2_FALLTHROUGH [[fallthrough]];
+#endif
+#elif !defined(__cplusplus) && \
+ defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L && \
+ defined(__has_c_attribute)
+/* Standards-compatible C variant. */
+#if __has_c_attribute(fallthrough)
+#define PCRE2_FALLTHROUGH [[fallthrough]];
+#endif
+#elif ((defined(__clang__) && __clang_major__ >= 10) || \
+ (defined(__GNUC__) && __GNUC__ >= 7)) && \
+ defined(__has_attribute)
+/* Clang and GCC syntax. Rule out old versions because apparently Clang at
+ least has a broken implementation of __has_attribute. */
+#if __has_attribute(fallthrough)
+#define PCRE2_FALLTHROUGH __attribute__((fallthrough));
+#endif
+#endif
+
+#endif /* !PCRE2_FALLTHROUGH */
+
+#ifndef PCRE2_FALLTHROUGH
+#define PCRE2_FALLTHROUGH
#endif
#endif /* PCRE2_UTIL_H_IDEMPOTENT_GUARD */
diff --git a/src/3rdparty/pcre2/src/pcre2_valid_utf.c b/src/3rdparty/pcre2/src/pcre2_valid_utf.c
index de411b919e1..3fac931ea94 100644
--- a/src/3rdparty/pcre2/src/pcre2_valid_utf.c
+++ b/src/3rdparty/pcre2/src/pcre2_valid_utf.c
@@ -44,14 +44,13 @@ strings. This file is also #included by the pcre2test program, which uses
macros to change names from _pcre2_xxx to xxxx, thereby avoiding name clashes
with the library. In this case, PCRE2_PCRE2TEST is defined. */
+
#ifndef PCRE2_PCRE2TEST /* We're compiling the library */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
#include "pcre2_internal.h"
#endif /* PCRE2_PCRE2TEST */
+
#ifndef SUPPORT_UNICODE
/*************************************************
* Dummy function when Unicode is not supported *
diff --git a/src/3rdparty/pcre2/src/pcre2_xclass.c b/src/3rdparty/pcre2/src/pcre2_xclass.c
index 25de7cbf38b..7bcae34e0a3 100644
--- a/src/3rdparty/pcre2/src/pcre2_xclass.c
+++ b/src/3rdparty/pcre2/src/pcre2_xclass.c
@@ -38,17 +38,15 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
+
/* This module contains two internal functions that are used to match
OP_XCLASS and OP_ECLASS. It is used by pcre2_auto_possessify() and by both
pcre2_match() and pcre2_dfa_match(). */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include "pcre2_internal.h"
-#include "pcre2_internal.h"
/*************************************************
* Match character against an XCLASS *
@@ -252,9 +250,11 @@ if (*data == XCL_PROP || *data == XCL_NOTPROP)
/* This should never occur, but compilers may mutter if there is no
default. */
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return FALSE;
+ /* LCOV_EXCL_STOP */
}
data += 2;
@@ -529,9 +529,11 @@ while (ptr < data_end)
/* This should never occur, but compilers may mutter if there is no
default. */
+ /* LCOV_EXCL_START */
default:
PCRE2_DEBUG_UNREACHABLE();
return FALSE;
+ /* LCOV_EXCL_STOP */
}
}
diff --git a/src/3rdparty/sha3/qt_attribution.json b/src/3rdparty/sha3/qt_attribution.json
index ddb440cbdbd..6c6a44e1b6b 100644
--- a/src/3rdparty/sha3/qt_attribution.json
+++ b/src/3rdparty/sha3/qt_attribution.json
@@ -8,7 +8,7 @@
"Files": "brg_endian.h",
"Description": "SHA-3, originally known as Keccak, is a cryptographic hash function.",
- "Version": "4b9e13ead2c5b5e41ca27c65de4dd69ae0bac228",
+ "Version": "1.0.0",
"PURL": "pkg:github/BrianGladman/sha@$<VERSION>",
"License": "BSD 2-clause \"Simplified\" License",
"LicenseFile": "BRG_ENDIAN_LICENSE",
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java
index 779b68954d8..1d4ec370d39 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtAccessibilityDelegate.java
@@ -514,17 +514,6 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
boolean handled = false;
//Log.i(TAG, "PERFORM ACTION: " + action + " on " + virtualViewId);
switch (action) {
- case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS:
- // Only handle the FOCUS action if it's placing focus on
- // a different view that was previously focused.
- if (m_focusedVirtualViewId != virtualViewId) {
- m_focusedVirtualViewId = virtualViewId;
- m_view.invalidate();
- sendEventForVirtualViewId(virtualViewId,
- AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
- handled = true;
- }
- break;
case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
if (m_focusedVirtualViewId == virtualViewId) {
m_focusedVirtualViewId = INVALID_ID;
@@ -565,17 +554,19 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
sendEventForVirtualViewId(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED);
break;
case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS:
- success = QtNativeAccessibility.focusAction(virtualViewId);
+ if (m_focusedVirtualViewId != virtualViewId) {
+ success = QtNativeAccessibility.focusAction(virtualViewId);
+ if (!success) {
+ notifyObjectFocus(virtualViewId);
+ success = true;
+ }
+ }
break;
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
success = QtNativeAccessibility.scrollForward(virtualViewId);
- if (success)
- sendEventForVirtualViewId(virtualViewId, AccessibilityEvent.TYPE_VIEW_SCROLLED);
break;
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
success = QtNativeAccessibility.scrollBackward(virtualViewId);
- if (success)
- sendEventForVirtualViewId(virtualViewId, AccessibilityEvent.TYPE_VIEW_SCROLLED);
break;
}
return success;
diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake
index d7d737b36ff..6a83e947146 100644
--- a/src/corelib/Qt6AndroidMacros.cmake
+++ b/src/corelib/Qt6AndroidMacros.cmake
@@ -479,12 +479,7 @@ function(qt6_android_add_apk_target target)
endif()
# Use genex to get path to the deployment settings, the above check only to confirm that
# qt6_android_add_apk_target is called on an android executable target.
- string(JOIN "" deployment_file
- "$<GENEX_EVAL:"
- "$<TARGET_PROPERTY:${target},QT_ANDROID_DEPLOYMENT_SETTINGS_FILE>"
- ">"
- )
-
+ _qt_internal_android_get_deployment_settings_file_genex(deployment_file)
_qt_internal_android_get_deployment_tool(deployment_tool)
# No need to use genex for the BINARY_DIR since it's read-only.
@@ -527,16 +522,8 @@ function(qt6_android_add_apk_target target)
set(target_file_copy_relative_path
"libs/${CMAKE_ANDROID_ARCH_ABI}/$<TARGET_FILE_NAME:${target}>")
- set(extra_deps "")
-
_qt_internal_android_get_use_terminal_for_deployment(uses_terminal)
-
- # Plugins still might be added after creating the deployment targets.
- if(NOT TARGET qt_internal_plugins)
- add_custom_target(qt_internal_plugins)
- endif()
- # Before running androiddeployqt, we need to make sure all plugins are built.
- list(APPEND extra_deps qt_internal_plugins)
+ _qt_internal_android_get_common_deployment_dependencies(extra_deps)
# This target is used by Qt Creator's Android support and by the ${target}_make_apk target
# in case DEPFILEs are not supported.
@@ -726,61 +713,7 @@ function(qt6_android_add_apk_target target)
_qt_internal_android_add_global_package_dependencies(${target})
_qt_internal_create_global_apk_all_target_if_needed()
- if(QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT)
- # When building per-ABI external projects we only need to copy ABI-specific libraries and
- # resources to the "main" ABI android build folder.
-
- if("${QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR}" STREQUAL "")
- message(FATAL_ERROR "QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR is not set when building"
- " ABI specific external project. This should not happen and might mean an issue"
- " in Qt. Please report a bug with CMake traces attached.")
- endif()
- # Assume that external project mirrors build structure of the top-level ABI project and
- # replace the build root when specifying the output directory of androiddeployqt.
- file(RELATIVE_PATH androiddeployqt_output_path "${CMAKE_BINARY_DIR}" "${apk_final_dir}")
- set(androiddeployqt_output_path
- "${QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR}/${androiddeployqt_output_path}")
- _qt_internal_copy_file_if_different_command(copy_command
- "$<TARGET_FILE:${target}>"
- "${androiddeployqt_output_path}/${target_file_copy_relative_path}"
- )
- if(has_depfile_support)
- set(deploy_android_deps_dir "${apk_final_dir}/${target}_deploy_android")
- set(timestamp_file "${deploy_android_deps_dir}/timestamp")
- set(dep_file "${deploy_android_deps_dir}/${target}.d")
- add_custom_command(OUTPUT "${timestamp_file}"
- DEPENDS ${target} ${extra_deps}
- COMMAND ${CMAKE_COMMAND} -E make_directory "${deploy_android_deps_dir}"
- COMMAND ${CMAKE_COMMAND} -E touch "${timestamp_file}"
- COMMAND ${copy_command}
- COMMAND ${deployment_tool}
- --input ${deployment_file}
- --output ${androiddeployqt_output_path}
- --copy-dependencies-only
- ${extra_args}
- --depfile "${dep_file}"
- --builddir "${CMAKE_BINARY_DIR}"
- COMMENT "Resolving ${CMAKE_ANDROID_ARCH_ABI} dependencies for the ${target} APK"
- DEPFILE "${dep_file}"
- VERBATIM
- ${uses_terminal}
- )
- add_custom_target(qt_internal_${target}_copy_apk_dependencies
- DEPENDS "${timestamp_file}")
- else()
- add_custom_target(qt_internal_${target}_copy_apk_dependencies
- DEPENDS ${target} ${extra_deps}
- COMMAND ${copy_command}
- COMMAND ${deployment_tool}
- --input ${deployment_file}
- --output ${androiddeployqt_output_path}
- --copy-dependencies-only
- ${extra_args}
- COMMENT "Resolving ${CMAKE_ANDROID_ARCH_ABI} dependencies for the ${target} APK"
- ${uses_terminal}
- )
- endif()
- else()
+ if(NOT QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT)
add_dependencies(${target}_prepare_apk_dir
${target}_copy_apk_dependencies)
endif()
@@ -790,6 +723,72 @@ function(qt6_android_add_apk_target target)
_qt_internal_collect_apk_imported_dependencies_defer("${target}")
endfunction()
+function(_qt_internal_android_copy_abi_dependencies target)
+ # When building per-ABI external projects we only need to copy ABI-specific libraries and
+ # resources to the "main" ABI android build folder.
+
+ if("${QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR}" STREQUAL "")
+ message(FATAL_ERROR "QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR is not set when building"
+ " ABI specific external project. This should not happen and might mean an issue"
+ " in Qt. Please report a bug with CMake traces attached.")
+ endif()
+ _qt_internal_android_get_target_deployment_dir(deployment_dir ${target})
+ # Assume that external project mirrors build structure of the top-level ABI project and
+ # replace the build root when specifying the output directory of androiddeployqt.
+ file(RELATIVE_PATH androiddeployqt_output_path "${CMAKE_BINARY_DIR}" "${deployment_dir}")
+ set(androiddeployqt_output_path
+ "${QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR}/${androiddeployqt_output_path}")
+ set(target_file_copy_relative_path
+ "libs/${CMAKE_ANDROID_ARCH_ABI}/$<TARGET_FILE_NAME:${target}>")
+ _qt_internal_copy_file_if_different_command(copy_command
+ "$<TARGET_FILE:${target}>"
+ "${androiddeployqt_output_path}/${target_file_copy_relative_path}"
+ )
+
+ _qt_internal_android_get_deployment_tool(deployment_tool)
+ _qt_internal_android_get_deployment_settings_file_genex(deployment_file)
+ _qt_internal_android_get_use_terminal_for_deployment(uses_terminal)
+ _qt_internal_android_get_common_deployment_dependencies(extra_deps)
+
+ _qt_internal_check_depfile_support(has_depfile_support)
+ if(has_depfile_support)
+ set(deploy_android_deps_dir "${deployment_dir}/${target}_deploy_android")
+ set(timestamp_file "${deploy_android_deps_dir}/timestamp")
+ set(dep_file "${deploy_android_deps_dir}/${target}.d")
+ add_custom_command(OUTPUT "${timestamp_file}"
+ DEPENDS ${target} ${extra_deps}
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${deploy_android_deps_dir}"
+ COMMAND ${CMAKE_COMMAND} -E touch "${timestamp_file}"
+ COMMAND ${copy_command}
+ COMMAND ${deployment_tool}
+ --input ${deployment_file}
+ --output ${androiddeployqt_output_path}
+ --copy-dependencies-only
+ ${extra_args}
+ --depfile "${dep_file}"
+ --builddir "${CMAKE_BINARY_DIR}"
+ COMMENT "Resolving ${CMAKE_ANDROID_ARCH_ABI} dependencies for the ${target} APK"
+ DEPFILE "${dep_file}"
+ VERBATIM
+ ${uses_terminal}
+ )
+ add_custom_target(qt_internal_${target}_copy_apk_dependencies
+ DEPENDS "${timestamp_file}")
+ else()
+ add_custom_target(qt_internal_${target}_copy_apk_dependencies
+ DEPENDS ${target} ${extra_deps}
+ COMMAND ${copy_command}
+ COMMAND ${deployment_tool}
+ --input ${deployment_file}
+ --output ${androiddeployqt_output_path}
+ --copy-dependencies-only
+ ${extra_args}
+ COMMENT "Resolving ${CMAKE_ANDROID_ARCH_ABI} dependencies for the ${target} APK"
+ ${uses_terminal}
+ )
+ endif()
+endfunction()
+
function(_qt_internal_create_global_android_targets)
macro(_qt_internal_create_global_android_targets_impl target)
string(TOUPPER "${target}" target_upper)
@@ -1587,6 +1586,8 @@ function(_qt_internal_configure_android_multiabi_target target)
"-DCMAKE_TOOLCHAIN_FILE=${qt_abi_toolchain_path}"
"-DQT_HOST_PATH=${QT_HOST_PATH}"
"-DQT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT=ON"
+ "-DQT_USE_ANDROID_MODERN_BUNDLE=${QT_USE_ANDROID_MODERN_BUNDLE}"
+ "-DQT_USE_ANDROID_TARGET_BUILD_DIR=${QT_USE_ANDROID_TARGET_BUILD_DIR}"
"-DQT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR=${CMAKE_BINARY_DIR}"
"${config_arg}"
"${extra_cmake_args}"
@@ -1686,6 +1687,9 @@ function(_qt_internal_android_executable_finalizer target)
else()
qt6_android_add_apk_target("${target}")
endif()
+ if(QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT)
+ _qt_internal_android_copy_abi_dependencies("${target}")
+ endif()
_qt_internal_android_create_runner_wrapper("${target}")
set_property(TARGET ${target} PROPERTY _qt_android_in_finalizer "")
endfunction()
@@ -1817,21 +1821,12 @@ function(_qt_internal_expose_android_package_source_dir_to_ide target)
endfunction()
function(_qt_internal_android_add_aux_deployment target)
- cmake_parse_arguments(arg "" "OUTPUT_TARGET_NAME;DEPLOYMENT_DIRECTORY" "EXTRA_ARGS" ${ARGN})
+ cmake_parse_arguments(arg "" "OUTPUT_TARGET_NAME" "EXTRA_ARGS" ${ARGN})
_qt_internal_validate_all_args_are_parsed(arg)
- string(JOIN "" deployment_file
- "$<GENEX_EVAL:"
- "$<TARGET_PROPERTY:${target},QT_ANDROID_DEPLOYMENT_SETTINGS_FILE>"
- ">"
- )
-
+ _qt_internal_android_get_deployment_settings_file_genex(deployment_file)
_qt_internal_android_get_deployment_tool(deployment_tool)
- if(arg_DEPLOYMENT_DIRECTORY)
- set(deployment_dir "${arg_DEPLOYMENT_DIRECTORY}")
- else()
- _qt_internal_android_get_target_deployment_dir(deployment_dir ${target})
- endif()
+ _qt_internal_android_get_target_deployment_dir(deployment_dir ${target})
cmake_policy(PUSH)
if(POLICY CMP0116)
@@ -1867,7 +1862,7 @@ function(_qt_internal_android_add_aux_deployment target)
${arg_EXTRA_ARGS}
#TODO: Support signing
COMMENT "Deploying Android artifacts for ${target}"
- DEPENDS "${target}" "${deployment_file}"
+ DEPENDS "${target}" "${deployment_file}" ${target}_copy_apk_dependencies
VERBATIM
${uses_terminal}
)
@@ -2045,5 +2040,27 @@ function(_qt_internal_android_find_asan_wrap_sh out_wrap_sh_path)
endif()
endfunction()
+# Returns path to the android deployment settings
+function(_qt_internal_android_get_deployment_settings_file_genex out_var)
+ string(JOIN "" deployment_file
+ "$<GENEX_EVAL:"
+ "$<TARGET_PROPERTY:${target},QT_ANDROID_DEPLOYMENT_SETTINGS_FILE>"
+ ">"
+ )
+
+ set(${out_var} "${deployment_file}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_android_get_common_deployment_dependencies out_var)
+ # Plugins still might be added after creating the deployment targets.
+ if(NOT TARGET qt_internal_plugins)
+ add_custom_target(qt_internal_plugins)
+ endif()
+ # Before running androiddeployqt, we need to make sure all plugins are built.
+ list(APPEND extra_deps qt_internal_plugins)
+
+ set(${out_var} "${extra_deps}" PARENT_SCOPE)
+endfunction()
+
set(QT_INTERNAL_ANDROID_TARGET_BUILD_DIR_SUPPORT ON CACHE INTERNAL
"Indicates that Qt supports per-target Android build directories")
diff --git a/src/corelib/io/qlockfile.cpp b/src/corelib/io/qlockfile.cpp
index 075eb144e51..4d431b46213 100644
--- a/src/corelib/io/qlockfile.cpp
+++ b/src/corelib/io/qlockfile.cpp
@@ -379,8 +379,9 @@ QLockFilePrivate::~QLockFilePrivate()
QByteArray QLockFilePrivate::lockFileContents() const
{
// Use operator% from the fast builder to avoid multiple memory allocations.
- return QByteArray::number(QCoreApplication::applicationPid()) % '\n'
- % processNameByPid(QCoreApplication::applicationPid()).toUtf8() % '\n'
+ qint64 pid = QCoreApplication::applicationPid();
+ return QByteArray::number(pid) % '\n'
+ % processNameByPid(pid).toUtf8() % '\n'
% machineName().toUtf8() % '\n'
% QSysInfo::machineUniqueId() % '\n'
% QSysInfo::bootUniqueId() % '\n';
diff --git a/src/corelib/itemmodels/qrangemodel.cpp b/src/corelib/itemmodels/qrangemodel.cpp
index b594f1de22a..05e3a39e589 100644
--- a/src/corelib/itemmodels/qrangemodel.cpp
+++ b/src/corelib/itemmodels/qrangemodel.cpp
@@ -303,7 +303,7 @@ QRangeModel::QRangeModel(QRangeModelImplBase *impl, QObject *parent)
tree data structure needs to be homomorphic: on all levels of the tree, the
list of child rows needs to use the exact same representation as the tree
itself. In addition, the row type needs be of a static size: either a gadget
- or QObject type, or a type that implements the {C++ tuple protocol}.
+ or QObject type, or a type that implements \l{the C++ tuple protocol}.
To represent such data as a tree, QRangeModel has to be able to traverse the
data structure: for any given row, the model needs to be able to retrieve
diff --git a/src/corelib/kernel/qassociativeiterable.cpp b/src/corelib/kernel/qassociativeiterable.cpp
index 625fa0a869e..8e3072169dd 100644
--- a/src/corelib/kernel/qassociativeiterable.cpp
+++ b/src/corelib/kernel/qassociativeiterable.cpp
@@ -8,6 +8,11 @@
QT_BEGIN_NAMESPACE
/*!
+ \class QAssociativeIterator
+ \internal
+ */
+
+/*!
Returns the key this iterator points to.
*/
QVariant QAssociativeIterator::key() const
@@ -49,6 +54,11 @@ QVariantPointer<QAssociativeIterator> QAssociativeIterator::operator->() const
}
/*!
+ \class QAssociativeConstIterator
+ \internal
+ */
+
+/*!
Returns the key this iterator points to.
*/
QVariant QAssociativeConstIterator::key() const
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 0c7e7db3188..de7c4df6d1d 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -2512,7 +2512,7 @@ QString QCoreApplication::applicationFilePath()
Returns the current process ID for the application.
*/
-qint64 QCoreApplication::applicationPid()
+qint64 QCoreApplication::applicationPid() noexcept
{
#if defined(Q_OS_WIN)
return GetCurrentProcessId();
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index 55c8097adc5..054e53a4a41 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -119,7 +119,7 @@ public:
static QString applicationDirPath();
static QString applicationFilePath();
- Q_DECL_CONST_FUNCTION static qint64 applicationPid();
+ Q_DECL_CONST_FUNCTION static qint64 applicationPid() noexcept;
#if QT_CONFIG(permissions) || defined(Q_QDOC)
Qt::PermissionStatus checkPermission(const QPermission &permission);
diff --git a/src/corelib/kernel/qpermissions.cpp b/src/corelib/kernel/qpermissions.cpp
index 8c95431d01f..bbcea8338ca 100644
--- a/src/corelib/kernel/qpermissions.cpp
+++ b/src/corelib/kernel/qpermissions.cpp
@@ -132,6 +132,10 @@ Q_LOGGING_CATEGORY(lcPermissions, "qt.permissions", QtWarningMsg);
\annotatedlist permissions
+ \note The available permission types cover core functionality of Qt modules
+ like Qt Multimedia and Qt Positioning, but do not encompass all platform-specific
+ permissions. Custom permission types are not currently supported.
+
\section1 Best Practices
To ensure the best possible user experience for the end user we recommend
diff --git a/src/corelib/kernel/qsequentialiterable.cpp b/src/corelib/kernel/qsequentialiterable.cpp
index 94a2e501cd7..32c58266045 100644
--- a/src/corelib/kernel/qsequentialiterable.cpp
+++ b/src/corelib/kernel/qsequentialiterable.cpp
@@ -178,6 +178,11 @@ void QSequentialIterable::set(qsizetype idx, const QVariant &value)
*/
/*!
+ \class QSequentialIterator
+ \internal
+ */
+
+/*!
Returns the current item, converted to a QVariantRef.
*/
QVariantRef<QSequentialIterator> QSequentialIterator::operator*() const
@@ -194,6 +199,11 @@ QVariantPointer<QSequentialIterator> QSequentialIterator::operator->() const
}
/*!
+ \class QSequentialConstIterator
+ \internal
+ */
+
+/*!
Returns the current item, converted to a QVariant.
*/
QVariant QSequentialConstIterator::operator*() const
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index 4ccc58b3f39..de7043e8c1d 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -377,7 +377,6 @@ void QMimeBinaryProvider::findByMagic(const QByteArray &data, QMimeMagicResult &
void QMimeBinaryProvider::addParents(const QString &mime, QStringList &result)
{
- const QByteArray mimeStr = mime.toLatin1();
const int parentListOffset = m_cacheFile->getUint32(PosParentListOffset);
const int numEntries = m_cacheFile->getUint32(parentListOffset);
@@ -388,7 +387,7 @@ void QMimeBinaryProvider::addParents(const QString &mime, QStringList &result)
const int off = parentListOffset + 4 + 8 * medium;
const int mimeOffset = m_cacheFile->getUint32(off);
const char *aMime = m_cacheFile->getCharStar(mimeOffset);
- const int cmp = qstrcmp(aMime, mimeStr);
+ const int cmp = QLatin1StringView(aMime).compare(mime);
if (cmp < 0) {
begin = medium + 1;
} else if (cmp > 0) {
@@ -409,7 +408,6 @@ void QMimeBinaryProvider::addParents(const QString &mime, QStringList &result)
QString QMimeBinaryProvider::resolveAlias(const QString &name)
{
- const QByteArray input = name.toLatin1();
const int aliasListOffset = m_cacheFile->getUint32(PosAliasListOffset);
const int numEntries = m_cacheFile->getUint32(aliasListOffset);
int begin = 0;
@@ -419,7 +417,7 @@ QString QMimeBinaryProvider::resolveAlias(const QString &name)
const int off = aliasListOffset + 4 + 8 * medium;
const int aliasOffset = m_cacheFile->getUint32(off);
const char *alias = m_cacheFile->getCharStar(aliasOffset);
- const int cmp = qstrcmp(alias, input);
+ const int cmp = QLatin1StringView(alias).compare(name);
if (cmp < 0) {
begin = medium + 1;
} else if (cmp > 0) {
@@ -435,7 +433,6 @@ QString QMimeBinaryProvider::resolveAlias(const QString &name)
void QMimeBinaryProvider::addAliases(const QString &name, QStringList &result)
{
- const QByteArray input = name.toLatin1();
const int aliasListOffset = m_cacheFile->getUint32(PosAliasListOffset);
const int numEntries = m_cacheFile->getUint32(aliasListOffset);
for (int pos = 0; pos < numEntries; ++pos) {
@@ -443,7 +440,7 @@ void QMimeBinaryProvider::addAliases(const QString &name, QStringList &result)
const int mimeOffset = m_cacheFile->getUint32(off + 4);
const char *mimeType = m_cacheFile->getCharStar(mimeOffset);
- if (input == mimeType) {
+ if (name == QLatin1StringView(mimeType)) {
const int aliasOffset = m_cacheFile->getUint32(off);
const char *alias = m_cacheFile->getCharStar(aliasOffset);
const QString strAlias = QString::fromLatin1(alias);
@@ -586,7 +583,7 @@ QMimeBinaryProvider::loadMimeTypeExtra(const QString &mimeName)
// Binary search in the icons or generic-icons list
QLatin1StringView QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset,
- const QByteArray &inputMime)
+ QStringView inputMime)
{
const int iconsListOffset = cacheFile->getUint32(posListOffset);
const int numIcons = cacheFile->getUint32(iconsListOffset);
@@ -597,7 +594,7 @@ QLatin1StringView QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int pos
const int off = iconsListOffset + 4 + 8 * medium;
const int mimeOffset = cacheFile->getUint32(off);
const char *mime = cacheFile->getCharStar(mimeOffset);
- const int cmp = qstrcmp(mime, inputMime);
+ const int cmp = QLatin1StringView(mime).compare(inputMime);
if (cmp < 0)
begin = medium + 1;
else if (cmp > 0)
@@ -612,14 +609,12 @@ QLatin1StringView QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int pos
QString QMimeBinaryProvider::icon(const QString &name)
{
- const QByteArray inputMime = name.toLatin1();
- return iconForMime(m_cacheFile.get(), PosIconsListOffset, inputMime);
+ return iconForMime(m_cacheFile.get(), PosIconsListOffset, name);
}
QString QMimeBinaryProvider::genericIcon(const QString &name)
{
- const QByteArray inputMime = name.toLatin1();
- return iconForMime(m_cacheFile.get(), PosGenericIconsListOffset, inputMime);
+ return iconForMime(m_cacheFile.get(), PosGenericIconsListOffset, name);
}
////
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index aede727d710..d597651b362 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -111,7 +111,7 @@ private:
bool caseSensitiveCheck);
bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset,
const QByteArray &data);
- QLatin1StringView iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
+ QLatin1StringView iconForMime(CacheFile *cacheFile, int posListOffset, QStringView inputMime);
void loadMimeTypeList();
bool checkCacheChanged();
diff --git a/src/corelib/plugin/qlibrary.h b/src/corelib/plugin/qlibrary.h
index f31047b214a..95c14178b22 100644
--- a/src/corelib/plugin/qlibrary.h
+++ b/src/corelib/plugin/qlibrary.h
@@ -63,6 +63,7 @@ private:
Loaded
};
+ friend class QLibraryPrivate;
QTaggedPointer<QLibraryPrivate, LoadStatusTag> d = nullptr;
Q_DISABLE_COPY(QLibrary)
};
diff --git a/src/corelib/plugin/qlibrary_p.h b/src/corelib/plugin/qlibrary_p.h
index b4e29a79e28..2331c86d844 100644
--- a/src/corelib/plugin/qlibrary_p.h
+++ b/src/corelib/plugin/qlibrary_p.h
@@ -67,7 +67,7 @@ public:
bool load();
QtPluginInstanceFunction loadPlugin(); // loads and resolves instance
- bool unload(UnloadFlag flag = UnloadSys);
+ Q_AUTOTEST_EXPORT bool unload(UnloadFlag flag = UnloadSys);
void release();
QFunctionPointer resolve(const char *);
@@ -103,6 +103,11 @@ public:
void updatePluginState();
bool isPlugin();
+ static QLibraryPrivate* get(QLibrary* lib)
+ {
+ return lib->d.data();
+ }
+
private:
explicit QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints);
~QLibraryPrivate();
diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp
index 7d04a19a5fa..ae3bed5b751 100644
--- a/src/corelib/serialization/qdatastream.cpp
+++ b/src/corelib/serialization/qdatastream.cpp
@@ -508,50 +508,50 @@ void QDataStream::setByteOrder(ByteOrder bo)
This enum provides symbolic synonyms for the data serialization
format version numbers.
- \value Qt_1_0 Version 1 (Qt 1.x)
- \value Qt_2_0 Version 2 (Qt 2.0)
- \value Qt_2_1 Version 3 (Qt 2.1, 2.2, 2.3)
- \value Qt_3_0 Version 4 (Qt 3.0)
- \value Qt_3_1 Version 5 (Qt 3.1, 3.2)
- \value Qt_3_3 Version 6 (Qt 3.3)
- \value Qt_4_0 Version 7 (Qt 4.0, Qt 4.1)
- \value Qt_4_1 Version 7 (Qt 4.0, Qt 4.1)
- \value Qt_4_2 Version 8 (Qt 4.2)
- \value Qt_4_3 Version 9 (Qt 4.3)
- \value Qt_4_4 Version 10 (Qt 4.4)
- \value Qt_4_5 Version 11 (Qt 4.5)
- \value Qt_4_6 Version 12 (Qt 4.6, Qt 4.7, Qt 4.8)
- \value Qt_4_7 Same as Qt_4_6.
- \value Qt_4_8 Same as Qt_4_6.
- \value Qt_4_9 Same as Qt_4_6.
- \value Qt_5_0 Version 13 (Qt 5.0)
- \value Qt_5_1 Version 14 (Qt 5.1)
- \value Qt_5_2 Version 15 (Qt 5.2)
- \value Qt_5_3 Same as Qt_5_2
- \value Qt_5_4 Version 16 (Qt 5.4)
- \value Qt_5_5 Same as Qt_5_4
- \value Qt_5_6 Version 17 (Qt 5.6)
- \value Qt_5_7 Same as Qt_5_6
- \value Qt_5_8 Same as Qt_5_6
- \value Qt_5_9 Same as Qt_5_6
- \value Qt_5_10 Same as Qt_5_6
- \value Qt_5_11 Same as Qt_5_6
- \value Qt_5_12 Version 18 (Qt 5.12)
- \value Qt_5_13 Version 19 (Qt 5.13)
- \value Qt_5_14 Same as Qt_5_13
- \value Qt_5_15 Same as Qt_5_13
- \value Qt_6_0 Version 20 (Qt 6.0)
- \value Qt_6_1 Same as Qt_6_0
- \value Qt_6_2 Same as Qt_6_0
- \value Qt_6_3 Same as Qt_6_0
- \value Qt_6_4 Same as Qt_6_0
- \value Qt_6_5 Same as Qt_6_0
- \value Qt_6_6 Version 21 (Qt 6.6)
- \value Qt_6_7 Version 22 (Qt 6.7)
- \value Qt_6_8 Same as Qt_6_7
- \value Qt_6_9 Same as Qt_6_7
- \value Qt_6_10 Same as Qt_6_7
- \value Qt_6_11 Same as Qt_6_10
+ \value Qt_1_0
+ \value Qt_2_0
+ \value Qt_2_1
+ \value Qt_3_0
+ \value Qt_3_1
+ \value Qt_3_3
+ \value Qt_4_0
+ \value Qt_4_1
+ \value Qt_4_2
+ \value Qt_4_3
+ \value Qt_4_4
+ \value Qt_4_5
+ \value Qt_4_6
+ \value Qt_4_7
+ \value Qt_4_8
+ \value Qt_4_9
+ \value Qt_5_0
+ \value Qt_5_1
+ \value Qt_5_2
+ \value Qt_5_3
+ \value Qt_5_4
+ \value Qt_5_5
+ \value Qt_5_6
+ \value Qt_5_7
+ \value Qt_5_8
+ \value Qt_5_9
+ \value Qt_5_10
+ \value Qt_5_11
+ \value Qt_5_12
+ \value Qt_5_13
+ \value Qt_5_14
+ \value Qt_5_15
+ \value Qt_6_0
+ \value Qt_6_1
+ \value Qt_6_2
+ \value Qt_6_3
+ \value Qt_6_4
+ \value Qt_6_5
+ \value Qt_6_6
+ \value Qt_6_7
+ \value Qt_6_8
+ \value Qt_6_9
+ \value Qt_6_10
+ \value Qt_6_11
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 46c01bf232a..711b70ebf8f 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -7328,6 +7328,12 @@ QString QString::toCaseFolded_helper(QString &str)
\note In some cases the uppercase form of a string may be longer than the
original.
+ \note Since 2024, the German language officially prefers to uppercase ß
+ (U+00DF LATIN SMALL LETTER SHARP S) as ẞ (U+1E9E LATIN CAPITAL LETTER SHARP S).
+ Qt's implementation follows Unicode, which still mandates the use of "SS".
+ If you need to implement the new German rules, you need to manually do
+ \c{replace(u'ß', u'ẞ')} \e{before} calling this function.
+
\sa toLower(), QLocale::toLower()
*/
diff --git a/src/corelib/text/qunicodetools.cpp b/src/corelib/text/qunicodetools.cpp
index b0c2036a5a1..56fa41c51ab 100644
--- a/src/corelib/text/qunicodetools.cpp
+++ b/src/corelib/text/qunicodetools.cpp
@@ -242,16 +242,10 @@ static void getWordBreaks(const char16_t *string, qsizetype len, QCharAttributes
QUnicodeTables::WordBreakClass cls = QUnicodeTables::WordBreak_LF; // to meet WB1
auto real_cls = cls; // Unaffected by WB4
- for (qsizetype i = 0; i != len; ++i) {
- const qsizetype pos = i;
- char32_t ucs4 = string[i];
- if (QChar::isHighSurrogate(ucs4) && i + 1 != len) {
- ushort low = string[i + 1];
- if (QChar::isLowSurrogate(low)) {
- ucs4 = QChar::surrogateToUcs4(ucs4, low);
- ++i;
- }
- }
+ QStringIterator it(QStringView{string, len});
+ while (it.hasNext()) {
+ const qsizetype pos = it.index();
+ const char32_t ucs4 = it.nextOrRawCodeUnit();
const auto prop = QUnicodeTables::properties(ucs4);
QUnicodeTables::WordBreakClass ncls = (QUnicodeTables::WordBreakClass) prop->wordBreakClass;
@@ -294,15 +288,8 @@ static void getWordBreaks(const char16_t *string, qsizetype len, QCharAttributes
break;
case WB::Lookup:
case WB::LookupW:
- for (qsizetype lookahead = i + 1; lookahead < len; ++lookahead) {
- char32_t ucs4 = string[lookahead];
- if (QChar::isHighSurrogate(ucs4) && lookahead + 1 != len) {
- ushort low = string[lookahead + 1];
- if (QChar::isLowSurrogate(low)) {
- ucs4 = QChar::surrogateToUcs4(ucs4, low);
- ++lookahead;
- }
- }
+ for (auto lookahead = it; lookahead.hasNext(); /**/) {
+ const char32_t ucs4 = lookahead.nextOrRawCodeUnit();
const auto prop = QUnicodeTables::properties(ucs4);
QUnicodeTables::WordBreakClass tcls = (QUnicodeTables::WordBreakClass) prop->wordBreakClass;
@@ -314,7 +301,7 @@ static void getWordBreaks(const char16_t *string, qsizetype len, QCharAttributes
if (Q_LIKELY(tcls == cls || (action == WB::LookupW && (tcls == QUnicodeTables::WordBreak_HebrewLetter
|| tcls == QUnicodeTables::WordBreak_ALetter)))) {
- i = lookahead;
+ it = lookahead;
ncls = tcls;
action = WB::NoBreak;
}
@@ -401,16 +388,11 @@ static const uchar breakTable[BAfter + 1][QUnicodeTables::NumSentenceBreakClasse
static void getSentenceBreaks(const char16_t *string, qsizetype len, QCharAttributes *attributes)
{
uchar state = SB::BAfter; // to meet SB1
- for (qsizetype i = 0; i != len; ++i) {
- const qsizetype pos = i;
- char32_t ucs4 = string[i];
- if (QChar::isHighSurrogate(ucs4) && i + 1 != len) {
- ushort low = string[i + 1];
- if (QChar::isLowSurrogate(low)) {
- ucs4 = QChar::surrogateToUcs4(ucs4, low);
- ++i;
- }
- }
+
+ QStringIterator it(QStringView{string, len});
+ while (it.hasNext()) {
+ const qsizetype pos = it.index();
+ const char32_t ucs4 = it.nextOrRawCodeUnit();
const auto prop = QUnicodeTables::properties(ucs4);
QUnicodeTables::SentenceBreakClass ncls = (QUnicodeTables::SentenceBreakClass) prop->sentenceBreakClass;
@@ -419,15 +401,8 @@ static void getSentenceBreaks(const char16_t *string, qsizetype len, QCharAttrib
state = SB::breakTable[state][ncls];
if (Q_UNLIKELY(state == SB::Lookup)) { // SB8
state = SB::Break;
- for (qsizetype lookahead = i + 1; lookahead < len; ++lookahead) {
- char32_t ucs4 = string[lookahead];
- if (QChar::isHighSurrogate(ucs4) && lookahead + 1 != len) {
- ushort low = string[lookahead + 1];
- if (QChar::isLowSurrogate(low)) {
- ucs4 = QChar::surrogateToUcs4(ucs4, low);
- ++lookahead;
- }
- }
+ for (auto lookahead = it; lookahead.hasNext(); /**/) {
+ const char32_t ucs4 = lookahead.nextOrRawCodeUnit();
const auto prop = QUnicodeTables::properties(ucs4);
QUnicodeTables::SentenceBreakClass tcls = (QUnicodeTables::SentenceBreakClass) prop->sentenceBreakClass;
@@ -440,7 +415,7 @@ static void getSentenceBreaks(const char16_t *string, qsizetype len, QCharAttrib
case QUnicodeTables::SentenceBreak_Close:
continue;
case QUnicodeTables::SentenceBreak_Lower:
- i = lookahead;
+ it = lookahead;
state = SB::Initial;
break;
default:
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index 03eeed84465..974c486b915 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -517,6 +517,7 @@ QDate::QDate(int y, int m, int d, QCalendar cal)
*/
/*!
+ \overload primary
\fn bool QDate::isValid() const
Returns \c true if this date is valid; otherwise returns \c false.
@@ -525,6 +526,8 @@ QDate::QDate(int y, int m, int d, QCalendar cal)
*/
/*!
+ \overload primary
+
Returns the year of this date.
Uses \a cal as calendar, if supplied, else the Gregorian calendar.
@@ -557,8 +560,8 @@ int QDate::year(QCalendar cal) const
}
/*!
- \overload
- */
+ \overload year()
+*/
int QDate::year() const
{
@@ -571,6 +574,8 @@ int QDate::year() const
}
/*!
+ \overload primary
+
Returns the month-number for the date.
Numbers the months of the year starting with 1 for the first. Uses \a cal
@@ -609,8 +614,8 @@ int QDate::month(QCalendar cal) const
}
/*!
- \overload
- */
+ \overload month()
+*/
int QDate::month() const
{
@@ -623,6 +628,8 @@ int QDate::month() const
}
/*!
+ \overload primary
+
Returns the day of the month for this date.
Uses \a cal as calendar if supplied, else the Gregorian calendar (for which
@@ -642,8 +649,8 @@ int QDate::day(QCalendar cal) const
}
/*!
- \overload
- */
+ \overload day()
+*/
int QDate::day() const
{
@@ -656,6 +663,8 @@ int QDate::day() const
}
/*!
+ \overload primary
+
Returns the weekday (1 = Monday to 7 = Sunday) for this date.
Uses \a cal as calendar if supplied, else the Gregorian calendar. Returns 0
@@ -674,8 +683,8 @@ int QDate::dayOfWeek(QCalendar cal) const
}
/*!
- \overload
- */
+ \overload dayOfWeek()
+*/
int QDate::dayOfWeek() const
{
@@ -683,6 +692,8 @@ int QDate::dayOfWeek() const
}
/*!
+ \overload primary
+
Returns the day of the year (1 for the first day) for this date.
Uses \a cal as calendar if supplied, else the Gregorian calendar.
@@ -702,8 +713,8 @@ int QDate::dayOfYear(QCalendar cal) const
}
/*!
- \overload
- */
+ \overload dayOfYear()
+*/
int QDate::dayOfYear() const
{
@@ -715,6 +726,8 @@ int QDate::dayOfYear() const
}
/*!
+ \overload primary
+
Returns the number of days in the month for this date.
Uses \a cal as calendar if supplied, else the Gregorian calendar (for which
@@ -735,8 +748,8 @@ int QDate::daysInMonth(QCalendar cal) const
}
/*!
- \overload
- */
+ \overload daysInMonth()
+*/
int QDate::daysInMonth() const
{
@@ -749,6 +762,8 @@ int QDate::daysInMonth() const
}
/*!
+ \overload primary
+
Returns the number of days in the year for this date.
Uses \a cal as calendar if supplied, else the Gregorian calendar (for which
@@ -766,8 +781,8 @@ int QDate::daysInYear(QCalendar cal) const
}
/*!
- \overload
- */
+ \overload daysInYear()
+*/
int QDate::daysInYear() const
{
@@ -918,6 +933,7 @@ static QDateTime toEarliest(QDate day, const QTimeZone &zone)
/*!
\since 5.14
+ \overload primary
Returns the start-moment of the day.
@@ -972,8 +988,8 @@ QDateTime QDate::startOfDay(const QTimeZone &zone) const
}
/*!
- \overload
\since 6.5
+ \overload startOfDay()
*/
QDateTime QDate::startOfDay() const
{
@@ -982,8 +998,8 @@ QDateTime QDate::startOfDay() const
#if QT_DEPRECATED_SINCE(6, 9)
/*!
- \overload
\since 5.14
+ \overload startOfDay()
\deprecated [6.9] Use \c{startOfDay(const QTimeZone &)} instead.
Returns the start-moment of the day.
@@ -1073,6 +1089,7 @@ static QDateTime toLatest(QDate day, const QTimeZone &zone)
/*!
\since 5.14
+ \overload primary
Returns the end-moment of the day.
@@ -1127,8 +1144,8 @@ QDateTime QDate::endOfDay(const QTimeZone &zone) const
}
/*!
- \overload
\since 6.5
+ \overload endOfDay()
*/
QDateTime QDate::endOfDay() const
{
@@ -1137,8 +1154,8 @@ QDateTime QDate::endOfDay() const
#if QT_DEPRECATED_SINCE(6, 9)
/*!
- \overload
\since 5.14
+ \overload endOfDay()
\deprecated [6.9] Use \c{endOfDay(const QTimeZone &) instead.
Returns the end-moment of the day.
@@ -1199,7 +1216,7 @@ static QString toStringIsoDate(QDate date)
}
/*!
- \overload
+ \overload toString()
Returns the date as a string. The \a format parameter determines the format
of the string.
@@ -1245,9 +1262,10 @@ QString QDate::toString(Qt::DateFormat format) const
}
/*!
+ \since 5.14
+ \overload primary
\fn QString QDate::toString(const QString &format, QCalendar cal) const
\fn QString QDate::toString(QStringView format, QCalendar cal) const
- \since 5.14
Returns the date as a string. The \a format parameter determines the format
of the result string. If \a cal is supplied, it determines the calendar used
@@ -1313,8 +1331,8 @@ QString QDate::toString(QStringView format, QCalendar cal) const
// Out-of-line no-calendar overloads, since QCalendar is a non-trivial type
/*!
- \overload
\since 5.10
+ \overload toString()
*/
QString QDate::toString(QStringView format) const
{
@@ -1322,8 +1340,8 @@ QString QDate::toString(QStringView format) const
}
/*!
- \overload
\since 4.6
+ \overload toString()
*/
QString QDate::toString(const QString &format) const
{
@@ -1414,9 +1432,8 @@ QDate QDate::addDays(qint64 ndays) const
}
/*!
- \fn QDate QDate::addDuration(std::chrono::days ndays) const
-
\since 6.4
+ \fn QDate QDate::addDuration(std::chrono::days ndays) const
Returns a QDate object containing a date \a ndays later than the
date of this object (or earlier if \a ndays is negative).
@@ -1436,6 +1453,8 @@ QDate QDate::addDays(qint64 ndays) const
*/
/*!
+ \overload primary
+
Returns a QDate object containing a date \a nmonths later than the
date of this object (or earlier if \a nmonths is negative).
@@ -1477,7 +1496,7 @@ QDate QDate::addMonths(int nmonths, QCalendar cal) const
}
/*!
- \overload
+ \overload addMonths()
*/
QDate QDate::addMonths(int nmonths) const
@@ -1509,6 +1528,8 @@ QDate QDate::addMonths(int nmonths) const
}
/*!
+ \overload primary
+
Returns a QDate object containing a date \a nyears later than the
date of this object (or earlier if \a nyears is negative).
@@ -1542,7 +1563,7 @@ QDate QDate::addYears(int nyears, QCalendar cal) const
}
/*!
- \overload
+ \overload addYears()
*/
QDate QDate::addYears(int nyears) const
@@ -1638,6 +1659,7 @@ qint64 QDate::daysTo(QDate d) const
#if QT_CONFIG(datestring) // depends on, so implies, textdate
/*!
+ \overload
\fn QDate QDate::fromString(const QString &string, Qt::DateFormat format)
Returns the QDate represented by the \a string, using the
@@ -1651,8 +1673,8 @@ qint64 QDate::daysTo(QDate d) const
*/
/*!
- \overload
\since 6.0
+ \overload fromString()
*/
QDate QDate::fromString(QStringView string, Qt::DateFormat format)
{
@@ -1702,6 +1724,7 @@ QDate QDate::fromString(QStringView string, Qt::DateFormat format)
}
/*!
+ \overload primary
\fn QDate QDate::fromString(const QString &string, const QString &format, int baseYear, QCalendar cal)
Returns the QDate represented by the \a string, using the \a
@@ -1833,14 +1856,14 @@ QDate QDate::fromString(QStringView string, Qt::DateFormat format)
*/
/*!
- \fn QDate QDate::fromString(QStringView string, QStringView format, QCalendar cal)
- \overload
\since 6.0
+ \overload fromString()
+ \fn QDate QDate::fromString(QStringView string, QStringView format, QCalendar cal)
*/
/*!
- \overload
\since 6.0
+ \overload fromString()
*/
QDate QDate::fromString(const QString &string, QStringView format, int baseYear, QCalendar cal)
{
@@ -1860,34 +1883,34 @@ QDate QDate::fromString(const QString &string, QStringView format, int baseYear,
}
/*!
- \fn QDate QDate::fromString(const QString &string, const QString &format, QCalendar cal)
- \overload
\since 5.14
+ \overload fromString()
+ \fn QDate QDate::fromString(const QString &string, const QString &format, QCalendar cal)
*/
/*!
- \fn QDate QDate::fromString(const QString &string, QStringView format, QCalendar cal)
- \overload
\since 6.0
+ \overload fromString()
+ \fn QDate QDate::fromString(const QString &string, QStringView format, QCalendar cal)
*/
/*!
- \fn QDate QDate::fromString(QStringView string, QStringView format, int baseYear, QCalendar cal)
- \overload
\since 6.7
+ \overload fromString()
+ \fn QDate QDate::fromString(QStringView string, QStringView format, int baseYear, QCalendar cal)
*/
/*!
- \fn QDate QDate::fromString(QStringView string, QStringView format, int baseYear)
- \overload
\since 6.7
+ \overload fromString()
+ \fn QDate QDate::fromString(QStringView string, QStringView format, int baseYear)
Uses a default-constructed QCalendar.
*/
/*!
- \overload
\since 6.7
+ \overload fromString()
Uses a default-constructed QCalendar.
*/
@@ -1897,16 +1920,16 @@ QDate QDate::fromString(const QString &string, QStringView format, int baseYear)
}
/*!
- \fn QDate QDate::fromString(const QString &string, const QString &format, int baseYear)
- \overload
\since 6.7
+ \overload fromString()
+ \fn QDate QDate::fromString(const QString &string, const QString &format, int baseYear)
Uses a default-constructed QCalendar.
*/
#endif // datestring
/*!
- \overload
+ \overload isValid()
Returns \c true if the specified date (\a year, \a month, and \a day) is
valid in the Gregorian calendar; otherwise returns \c false.
@@ -2037,6 +2060,8 @@ QTime::QTime(int h, int m, int s, int ms)
*/
/*!
+ \overload primary
+
Returns \c true if the time is valid; otherwise returns \c false. For example,
the time 23:30:55.746 is valid, but 24:12:30 is invalid.
@@ -2115,7 +2140,7 @@ int QTime::msec() const
#if QT_CONFIG(datestring) // depends on, so implies, textdate
/*!
- \overload
+ \overload toString()
Returns the time as a string. The \a format parameter determines
the format of the string.
@@ -2155,6 +2180,7 @@ QString QTime::toString(Qt::DateFormat format) const
}
/*!
+ \overload primary
\fn QString QTime::toString(const QString &format) const
\fn QString QTime::toString(QStringView format) const
@@ -2261,11 +2287,11 @@ QString QTime::toString(Qt::DateFormat format) const
\sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
*/
-// ### Qt 7 The 't' format specifiers should be specific to QDateTime (compare fromString).
QString QTime::toString(QStringView format) const
{
return QLocale::c().toString(*this, format);
}
+// ### Qt 7 The 't' format specifiers should be specific to QDateTime (compare fromString).
#endif // datestring
/*!
@@ -2557,6 +2583,7 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
}
/*!
+ \overload
\fn QTime QTime::fromString(const QString &string, Qt::DateFormat format)
Returns the time represented in the \a string as a QTime using the
@@ -2566,8 +2593,8 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
*/
/*!
- \overload
\since 6.0
+ \overload fromString()
*/
QTime QTime::fromString(QStringView string, Qt::DateFormat format)
{
@@ -2586,6 +2613,7 @@ QTime QTime::fromString(QStringView string, Qt::DateFormat format)
}
/*!
+ \overload primary
\fn QTime QTime::fromString(const QString &string, const QString &format)
Returns the QTime represented by the \a string, using the \a
@@ -2664,14 +2692,14 @@ QTime QTime::fromString(QStringView string, Qt::DateFormat format)
*/
/*!
- \fn QTime QTime::fromString(QStringView string, QStringView format)
- \overload
\since 6.0
+ \overload fromString()
+ \fn QTime QTime::fromString(QStringView string, QStringView format)
*/
/*!
- \overload
\since 6.0
+ \overload fromString()
*/
QTime QTime::fromString(const QString &string, QStringView format)
{
@@ -2691,7 +2719,7 @@ QTime QTime::fromString(const QString &string, QStringView format)
/*!
- \overload
+ \overload isValid()
Returns \c true if the specified time is valid; otherwise returns
false.
@@ -4012,6 +4040,7 @@ QDateTime::QDateTime(QDate date, QTime time, Qt::TimeSpec spec, int offsetSecond
/*!
\since 5.2
+ \overload primary
Constructs a datetime with the given \a date and \a time, using the time
representation described by \a timeZone.
@@ -4620,7 +4649,7 @@ void QDateTime::setSecsSinceEpoch(qint64 secs)
#if QT_CONFIG(datestring) // depends on, so implies, textdate
/*!
- \overload
+ \overload toString()
Returns the datetime as a string in the \a format given.
@@ -4712,9 +4741,10 @@ QString QDateTime::toString(Qt::DateFormat format) const
}
/*!
+ \since 5.14
+ \overload primary
\fn QString QDateTime::toString(const QString &format, QCalendar cal) const
\fn QString QDateTime::toString(QStringView format, QCalendar cal) const
- \since 5.14
Returns the datetime as a string. The \a format parameter determines the
format of the result string. If \a cal is supplied, it determines the
@@ -4761,8 +4791,8 @@ QString QDateTime::toString(QStringView format, QCalendar cal) const
// Out-of-line no-calendar overloads, since QCalendar is a non-trivial type
/*!
- \overload
\since 5.10
+ \overload toString()
*/
QString QDateTime::toString(QStringView format) const
{
@@ -4770,8 +4800,8 @@ QString QDateTime::toString(QStringView format) const
}
/*!
- \overload
\since 4.6
+ \overload toString()
*/
QString QDateTime::toString(const QString &format) const
{
@@ -5370,6 +5400,7 @@ Qt::weak_ordering compareThreeWay(const QDateTime &lhs, const QDateTime &rhs)
/*!
\since 6.5
+ \overload primary
\fn QDateTime QDateTime::currentDateTime(const QTimeZone &zone)
Returns the system clock's current datetime, using the time representation
@@ -5379,8 +5410,8 @@ Qt::weak_ordering compareThreeWay(const QDateTime &lhs, const QDateTime &rhs)
*/
/*!
- \overload
\since 0.90
+ \overload currentDateTime()
*/
QDateTime QDateTime::currentDateTime()
{
@@ -5426,8 +5457,9 @@ QDateTime QDateTime::currentDateTimeUtc()
*/
/*!
- \fn template <typename Clock, typename Duration> QDateTime QDateTime::fromStdTimePoint(const std::chrono::time_point<Clock, Duration> &time)
\since 6.4
+ \overload primary
+ \fn template <typename Clock, typename Duration> QDateTime QDateTime::fromStdTimePoint(const std::chrono::time_point<Clock, Duration> &time)
Constructs a datetime representing the same point in time as \a time,
using Qt::UTC as its time representation.
@@ -5451,7 +5483,7 @@ QDateTime QDateTime::currentDateTimeUtc()
/*!
\since 6.4
- \overload
+ \overload fromStdTimePoint()
Constructs a datetime representing the same point in time as \a time,
using Qt::UTC as its time representation.
@@ -5627,7 +5659,7 @@ qint64 QDateTime::currentSecsSinceEpoch() noexcept
#if QT_DEPRECATED_SINCE(6, 9)
/*!
\since 5.2
- \overload
+ \overload fromMSecsSinceEpoch()
\deprecated [6.9] Pass a \l QTimeZone instead, or omit \a spec and \a offsetSeconds.
Returns a datetime representing a moment the given number \a msecs of
@@ -5656,7 +5688,7 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int of
/*!
\since 5.8
- \overload
+ \overload fromSecsSinceEpoch
\deprecated [6.9] Pass a \l QTimeZone instead, or omit \a spec and \a offsetSeconds.
Returns a datetime representing a moment the given number \a secs of seconds
@@ -5686,6 +5718,7 @@ QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec, int offs
/*!
\since 5.2
+ \overload primary
Returns a datetime representing a moment the given number \a msecs of
milliseconds after the start, in UTC, of the year 1970, described as
@@ -5707,7 +5740,7 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone
}
/*!
- \overload
+ \overload fromMSecsSinceEpoch()
*/
QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
{
@@ -5716,6 +5749,7 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
/*!
\since 5.8
+ \overload primary
Returns a datetime representing a moment the given number \a secs of seconds
after the start, in UTC, of the year 1970, described as specified by \a
@@ -5737,7 +5771,7 @@ QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, const QTimeZone &timeZone)
}
/*!
- \overload
+ \overload fromSecsSinceEpoch()
*/
QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs)
{
@@ -5747,6 +5781,7 @@ QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs)
#if QT_CONFIG(datestring) // depends on, so implies, textdate
/*!
+ \overload
\fn QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
Returns the QDateTime represented by the \a string, using the
@@ -5759,8 +5794,8 @@ QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs)
*/
/*!
- \overload
\since 6.0
+ \overload fromString()
*/
QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
{
@@ -5901,6 +5936,7 @@ QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
}
/*!
+ \overload primary
\fn QDateTime QDateTime::fromString(const QString &string, const QString &format, int baseYear, QCalendar cal)
Returns the QDateTime represented by the \a string, using the \a
@@ -5984,14 +6020,14 @@ QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format)
*/
/*!
- \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, QCalendar cal)
- \overload
\since 6.0
+ \overload fromString()
+ \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, QCalendar cal)
*/
/*!
- \overload
\since 6.0
+ \overload fromString()
*/
QDateTime QDateTime::fromString(const QString &string, QStringView format, int baseYear,
QCalendar cal)
@@ -6015,34 +6051,34 @@ QDateTime QDateTime::fromString(const QString &string, QStringView format, int b
}
/*!
- \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, QCalendar cal)
- \overload
\since 5.14
+ \overload fromString()
+ \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, QCalendar cal)
*/
/*!
- \fn QDateTime QDateTime::fromString(const QString &string, QStringView format, QCalendar cal)
- \overload
\since 6.0
+ \overload fromString()
+ \fn QDateTime QDateTime::fromString(const QString &string, QStringView format, QCalendar cal)
*/
/*!
- \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, int baseYear, QCalendar cal)
- \overload
\since 6.7
+ \overload fromString()
+ \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, int baseYear, QCalendar cal)
*/
/*!
- \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, int baseYear)
- \overload
\since 6.7
+ \overload fromString()
+ \fn QDateTime QDateTime::fromString(QStringView string, QStringView format, int baseYear)
Uses a default-constructed QCalendar.
*/
/*!
- \overload
\since 6.7
+ \overload fromString()
Uses a default-constructed QCalendar.
*/
@@ -6052,9 +6088,9 @@ QDateTime QDateTime::fromString(const QString &string, QStringView format, int b
}
/*!
- \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, int baseYear)
- \overload
\since 6.7
+ \overload fromString()
+ \fn QDateTime QDateTime::fromString(const QString &string, const QString &format, int baseYear)
Uses a default-constructed QCalendar.
*/
diff --git a/src/dbus/qt_attribution.json b/src/dbus/qt_attribution.json
index 9e00c2a8bd9..067e3013bb1 100644
--- a/src/dbus/qt_attribution.json
+++ b/src/dbus/qt_attribution.json
@@ -1,6 +1,6 @@
{
"Id": "libdbus-1-headers",
- "Name": "libdus-1 headers",
+ "Name": "libdbus-1 headers",
"QDocModule": "qtdbus",
"QtUsage": "Qt D-Bus uses constants and typedefs from libdbus-1 headers.",
diff --git a/src/gui/accessible/linux/atspiadaptor.cpp b/src/gui/accessible/linux/atspiadaptor.cpp
index c2c1fc6596c..dad0ac2b74a 100644
--- a/src/gui/accessible/linux/atspiadaptor.cpp
+++ b/src/gui/accessible/linux/atspiadaptor.cpp
@@ -1888,7 +1888,7 @@ void AtSpiAdaptor::addMatchingDescendants(QList<QAccessibleInterface *> &matches
const QSpiMatchRuleMatcher &matcher, bool invert,
int count, bool traverse)
{
- if (!accessible || matches.size() >= count)
+ if (!accessible || (count != 0 && matches.size() >= count))
return;
const int childCount = accessible->childCount();
@@ -1900,7 +1900,7 @@ void AtSpiAdaptor::addMatchingDescendants(QList<QAccessibleInterface *> &matches
if (traverse)
addMatchingDescendants(matches, child, matcher, invert, count, traverse);
- if (matches.size() >= count)
+ if (count != 0 && matches.size() >= count)
return;
}
}
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 43540d4e64d..30ebe90da0b 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -971,9 +971,21 @@ void QAccessible::updateAccessibility(QAccessibleEvent *event)
pfAccessibility->notifyAccessibilityUpdate(event);
}
+static std::pair<int, int> qAccessibleTextBoundaryHelperHelper(QTextCursor &cursor,
+ QTextCursor::MoveOperation start,
+ QTextCursor::MoveOperation end)
+{
+ std::pair<int, int> result;
+ cursor.movePosition(start, QTextCursor::MoveAnchor);
+ result.first = cursor.position();
+ cursor.movePosition(end, QTextCursor::KeepAnchor);
+ result.second = cursor.position();
+ return result;
+}
+
/*!
\internal
- \brief getBoundaries is a helper function to find the accessible text boundaries for QTextCursor based documents.
+ \brief qAccessibleTextBoundaryHelper is a helper function to find the accessible text boundaries for QTextCursor based documents.
\param documentCursor a valid cursor bound to the document (not null). It needs to ba at the position to look for the boundary
\param boundaryType the type of boundary to find
\return the boundaries as pair
@@ -982,32 +994,20 @@ std::pair< int, int > QAccessible::qAccessibleTextBoundaryHelper(const QTextCurs
{
Q_ASSERT(!offsetCursor.isNull());
- QTextCursor endCursor = offsetCursor;
- endCursor.movePosition(QTextCursor::End);
- int characterCount = endCursor.position();
-
- std::pair<int, int> result;
QTextCursor cursor = offsetCursor;
switch (boundaryType) {
case CharBoundary:
- result.first = cursor.position();
- cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
- result.second = cursor.position();
- break;
+ return qAccessibleTextBoundaryHelperHelper(cursor, QTextCursor::NoMove,
+ QTextCursor::NextCharacter);
case WordBoundary:
- cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor);
- result.first = cursor.position();
- cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
- result.second = cursor.position();
- break;
+ return qAccessibleTextBoundaryHelperHelper(cursor, QTextCursor::StartOfWord,
+ QTextCursor::EndOfWord);
case SentenceBoundary: {
// QCursor does not provide functionality to move to next sentence.
// We therefore find the current block, then go through the block using
// QTextBoundaryFinder and find the sentence the \offset represents
- cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
- result.first = cursor.position();
- cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
- result.second = cursor.position();
+ std::pair<int, int> result = qAccessibleTextBoundaryHelperHelper(
+ cursor, QTextCursor::StartOfBlock, QTextCursor::EndOfBlock);
QString blockText = cursor.selectedText();
const int offsetWithinBlockText = offsetCursor.position() - result.first;
QTextBoundaryFinder sentenceFinder(QTextBoundaryFinder::Sentence, blockText);
@@ -1021,25 +1021,19 @@ std::pair< int, int > QAccessible::qAccessibleTextBoundaryHelper(const QTextCurs
result.second = result.first + nextBoundary;
if (prevBoundary != -1)
result.first += prevBoundary;
- break; }
+ return result;
+ }
case LineBoundary:
- cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::MoveAnchor);
- result.first = cursor.position();
- cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
- result.second = cursor.position();
- break;
+ return qAccessibleTextBoundaryHelperHelper(cursor, QTextCursor::StartOfLine,
+ QTextCursor::EndOfLine);
case ParagraphBoundary:
- cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor);
- result.first = cursor.position();
- cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
- result.second = cursor.position();
- break;
+ return qAccessibleTextBoundaryHelperHelper(cursor, QTextCursor::StartOfBlock,
+ QTextCursor::EndOfBlock);
case NoBoundary:
- result.first = 0;
- result.second = characterCount;
- break;
+ return qAccessibleTextBoundaryHelperHelper(cursor, QTextCursor::Start, QTextCursor::End);
}
- return result;
+
+ Q_UNREACHABLE_RETURN({});
}
/*!
@@ -2277,13 +2271,16 @@ QString QAccessibleTextInterface::textBeforeOffset(int offset, QAccessible::Text
break;
} while (boundary.toPreviousBoundary() > 0);
Q_ASSERT(boundary.position() >= 0);
- *endOffset = boundary.position();
+ const int endPos = boundary.position();
while (boundary.toPreviousBoundary() > 0) {
if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem)))
break;
}
- Q_ASSERT(boundary.position() >= 0);
+ if (boundary.position() < 0)
+ return QString();
+
+ *endOffset = endPos;
*startOffset = boundary.position();
return txt.mid(*startOffset, *endOffset - *startOffset);
@@ -2440,13 +2437,17 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun
break;
} while (boundary.toPreviousBoundary() > 0);
Q_ASSERT(boundary.position() >= 0);
- *startOffset = boundary.position();
+ const int startPos = boundary.position();
while (boundary.toNextBoundary() < txt.size()) {
if ((boundary.boundaryReasons() & (QTextBoundaryFinder::StartOfItem | QTextBoundaryFinder::EndOfItem)))
break;
+ if (boundary.position() == -1)
+ return QString();
}
+
Q_ASSERT(boundary.position() <= txt.size());
+ *startOffset = startPos;
*endOffset = boundary.position();
return txt.mid(*startOffset, *endOffset - *startOffset);
diff --git a/src/gui/accessible/qaccessiblehelper.cpp b/src/gui/accessible/qaccessiblehelper.cpp
index 2ae8ebbac08..9ea72b1f6c9 100644
--- a/src/gui/accessible/qaccessiblehelper.cpp
+++ b/src/gui/accessible/qaccessiblehelper.cpp
@@ -3,6 +3,8 @@
#include "qaccessiblehelper_p.h"
+#include <QtGui/qtextcursor.h>
+
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
@@ -48,4 +50,79 @@ QString qt_accStripAmp(const QString &text)
return newText.replace("&&"_L1, "&"_L1);
}
+QString qt_accTextBeforeOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType, int *startOffset,
+ int *endOffset)
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+ *startOffset = *endOffset = -1;
+
+ QTextCursor cursor = textCursor;
+ cursor.setPosition(offset);
+ std::pair<int, int> boundaries =
+ QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ if (boundaries.second > offset) {
+ cursor.setPosition(boundaries.first);
+ while (boundaries.second > offset) {
+ if (!cursor.movePosition(QTextCursor::PreviousCharacter))
+ return QString();
+ boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ }
+ }
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return textInterface.text(boundaries.first, boundaries.second);
+}
+
+QString qt_accTextAfterOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType, int *startOffset,
+ int *endOffset)
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+ *startOffset = *endOffset = -1;
+
+ QTextCursor cursor = textCursor;
+ cursor.setPosition(offset);
+ std::pair<int, int> boundaries =
+ QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ if (boundaries.first <= offset) {
+ cursor.setPosition(boundaries.second);
+ while (boundaries.first <= offset) {
+ if (!cursor.movePosition(QTextCursor::NextCharacter))
+ return QString();
+ boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+ }
+ }
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return textInterface.text(boundaries.first, boundaries.second);
+}
+
+QString qt_accTextAtOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType, int *startOffset,
+ int *endOffset)
+{
+ Q_ASSERT(startOffset);
+ Q_ASSERT(endOffset);
+
+ QTextCursor cursor = textCursor;
+ cursor.setPosition(offset);
+ std::pair<int, int> boundaries =
+ QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
+
+ *startOffset = boundaries.first;
+ *endOffset = boundaries.second;
+
+ return textInterface.text(boundaries.first, boundaries.second);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/accessible/qaccessiblehelper_p.h b/src/gui/accessible/qaccessiblehelper_p.h
index 38cc493fdea..03cccbbe539 100644
--- a/src/gui/accessible/qaccessiblehelper_p.h
+++ b/src/gui/accessible/qaccessiblehelper_p.h
@@ -16,12 +16,30 @@
//
#include <QtCore/QString>
+#include <QtGui/qaccessible.h>
#include <QtGui/qtguiglobal.h>
+class QTextCursor;
+
QT_BEGIN_NAMESPACE
Q_GUI_EXPORT QString qt_accStripAmp(const QString &text);
+Q_GUI_EXPORT QString qt_accTextBeforeOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset);
+
+Q_GUI_EXPORT QString qt_accTextAfterOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset);
+
+Q_GUI_EXPORT QString qt_accTextAtOffsetHelper(const QAccessibleTextInterface &textInterface,
+ const QTextCursor &textCursor, int offset,
+ QAccessible::TextBoundaryType boundaryType,
+ int *startOffset, int *endOffset);
+
QT_END_NAMESPACE
#endif // QACCESSIBLEHELPER_P_H
diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h
index d1509e4a251..75550439521 100644
--- a/src/gui/text/qfont_p.h
+++ b/src/gui/text/qfont_p.h
@@ -166,6 +166,7 @@ public:
QFontPrivate();
QFontPrivate(const QFontPrivate &other);
+ QFontPrivate &operator=(const QFontPrivate &) = delete;
~QFontPrivate();
QFontEngine *engineForScript(int script) const;
@@ -206,9 +207,6 @@ public:
void setVariableAxis(QFont::Tag tag, float value);
void unsetVariableAxis(QFont::Tag tag);
bool hasVariableAxis(QFont::Tag tag, float value) const;
-
-private:
- QFontPrivate &operator=(const QFontPrivate &) { return *this; }
};
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 08c9f5d5ba2..2989b4d6df3 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -161,6 +161,7 @@ static void populateRoleMap()
roleMap[QAccessible::Graphic] = NSAccessibilityImageRole;
roleMap[QAccessible::Tree] = NSAccessibilityOutlineRole;
roleMap[QAccessible::BlockQuote] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::LayeredPane] = NSAccessibilityGroupRole;
}
/*
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 144c0519155..238f2ea2307 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -714,6 +714,25 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
iface->setText(QAccessible::Description, QString::fromNSString(label));
}
+- (NSAccessibilityOrientation)accessibilityOrientation {
+ QAccessibleInterface *iface = self.qtInterface;
+ if (!iface)
+ return NSAccessibilityOrientationUnknown;
+
+ NSAccessibilityOrientation nsOrientation = NSAccessibilityOrientationUnknown;
+ if (QAccessibleAttributesInterface *attributesIface = iface->attributesInterface()) {
+ const QVariant orientationVariant =
+ attributesIface->attributeValue(QAccessible::Attribute::Orientation);
+ if (orientationVariant.isValid()) {
+ Q_ASSERT(orientationVariant.canConvert<Qt::Orientation>());
+ const Qt::Orientation orientation = orientationVariant.value<Qt::Orientation>();
+ nsOrientation = orientation == Qt::Horizontal ? NSAccessibilityOrientationHorizontal
+ : NSAccessibilityOrientationVertical;
+ }
+ }
+ return nsOrientation;
+}
+
- (id) accessibilityValue {
if (QAccessibleInterface *iface = self.qtInterface) {
// VoiceOver asks for the value attribute for all elements. Return nil
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
index 5fa79482217..a87c33c8346 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.cpp
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
@@ -401,6 +401,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
case QAccessible::PageTabList:{
element = document.call<emscripten::val>("createElement", std::string("div"));
setAttribute(element, "role", "tablist");
+ setHtmlElementOrientation(element, iface);
m_elements[iface] = element;
@@ -423,6 +424,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("div"));
setAttribute(element, "role", "scrollbar");
setAttribute(element, "aria-valuenow", valueString);
+ setHtmlElementOrientation(element, iface);
addEventListener(iface, element, "change");
} break;
@@ -437,6 +439,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("div"));
setAttribute(element, "role", "toolbar");
setAttribute(element, "title", text.toStdString());
+ setHtmlElementOrientation(element, iface);
addEventListener(iface, element, "click");
}break;
case QAccessible::MenuItem:
@@ -453,6 +456,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
element = document.call<emscripten::val>("createElement", std::string("div"));
setAttribute(element, "role", "menubar");
setAttribute(element, "title", text.toStdString());
+ setHtmlElementOrientation(element, iface);
m_elements[iface] = element;
for (int i = 0; i < iface->childCount(); ++i) {
@@ -661,6 +665,21 @@ void QWasmAccessibility::setHtmlElementDisabled(QAccessibleInterface *iface)
setAttribute(element, "aria-disabled", iface->state().disabled);
}
+void QWasmAccessibility::setHtmlElementOrientation(emscripten::val element, QAccessibleInterface *iface)
+{
+ Q_ASSERT(iface);
+ if (QAccessibleAttributesInterface *attributesIface = iface->attributesInterface()) {
+ const QVariant orientationVariant =
+ attributesIface->attributeValue(QAccessible::Attribute::Orientation);
+ if (orientationVariant.isValid()) {
+ Q_ASSERT(orientationVariant.canConvert<Qt::Orientation>());
+ const Qt::Orientation orientation = orientationVariant.value<Qt::Orientation>();
+ const std::string value = orientation == Qt::Horizontal ? "horizontal" : "vertical";
+ setAttribute(element, "aria-orientation", value);
+ }
+ }
+}
+
void QWasmAccessibility::handleStaticTextUpdate(QAccessibleEvent *event)
{
switch (event->type()) {
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.h b/src/plugins/platforms/wasm/qwasmaccessibility.h
index 26f3e0e9afe..ddbfec918d6 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.h
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.h
@@ -77,6 +77,7 @@ private:
void setHtmlElementTextNameLE(QAccessibleInterface *iface);
void setHtmlElementFocus(QAccessibleInterface *iface);
void setHtmlElementDisabled(QAccessibleInterface *iface);
+ void setHtmlElementOrientation(emscripten::val element, QAccessibleInterface *iface);
void handleStaticTextUpdate(QAccessibleEvent *event);
void handleButtonUpdate(QAccessibleEvent *event);
diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgtopleveliconv1.cpp b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgtopleveliconv1.cpp
index 84ecc289c59..9aa8af39090 100644
--- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgtopleveliconv1.cpp
+++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgtopleveliconv1.cpp
@@ -2,7 +2,6 @@
// Copyright (C) 2024 David Edmundson <[email protected]>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include "qwaylandshmbackingstore_p.h"
#include "qwaylandxdgtopleveliconv1_p.h"
#include <QtWaylandClient/private/qwaylanddisplay_p.h>
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
index 6ce43714a35..34b32da289c 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
@@ -729,11 +729,11 @@ public:
void QWaylandInputDevice::Pointer::pointer_leave(uint32_t serial, struct wl_surface *surface)
{
+ Q_UNUSED(serial);
+
invalidateFocus();
mButtons = Qt::NoButton;
- mParent->mSerial = serial;
-
// The event may arrive after destroying the window, indicated by
// a null surface.
if (!surface)
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 53548622dfc..482810d5b7e 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -553,12 +553,14 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData)
const bool orientationChanged = m_data.orientation != newData.orientation;
const bool primaryChanged = (newData.flags & QWindowsScreenData::PrimaryScreen)
&& !(m_data.flags & QWindowsScreenData::PrimaryScreen);
+ const bool refreshRateChanged = m_data.refreshRateHz != newData.refreshRateHz;
m_data.dpi = newData.dpi;
m_data.orientation = newData.orientation;
m_data.geometry = newData.geometry;
m_data.availableGeometry = newData.availableGeometry;
m_data.flags = (m_data.flags & ~QWindowsScreenData::PrimaryScreen)
| (newData.flags & QWindowsScreenData::PrimaryScreen);
+ m_data.refreshRateHz = newData.refreshRateHz;
if (dpiChanged) {
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(),
@@ -573,6 +575,9 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData)
}
if (primaryChanged)
QWindowSystemInterface::handlePrimaryScreenChanged(this);
+
+ if (refreshRateChanged)
+ QWindowSystemInterface::handleScreenRefreshRateChange(screen(), newData.refreshRateHz);
}
HMONITOR QWindowsScreen::handle() const
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index 0144786ce5e..b7bf97f5c4b 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -654,6 +654,21 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
*pRetVal = QComVariant{ name }.release();
break;
}
+ case UIA_OrientationPropertyId: {
+ OrientationType orientationType = OrientationType_None;
+ if (QAccessibleAttributesInterface *attributesIface = accessible->attributesInterface()) {
+ const QVariant orientationVariant =
+ attributesIface->attributeValue(QAccessible::Attribute::Orientation);
+ if (orientationVariant.isValid()) {
+ Q_ASSERT(orientationVariant.canConvert<Qt::Orientation>());
+ const Qt::Orientation orientation = orientationVariant.value<Qt::Orientation>();
+ orientationType = orientation == Qt::Horizontal ? OrientationType_Horizontal
+ : OrientationType_Vertical;
+ }
+ }
+ *pRetVal = QComVariant{ long(orientationType) }.release();
+ break;
+ }
case UIA_StyleIdAttributeId:
setStyle(accessible, pRetVal);
break;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
index b2675d5b884..835499d3554 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
@@ -154,6 +154,7 @@ long roleToControlTypeId(QAccessible::Role role)
{QAccessible::WebDocument, UIA_DocumentControlTypeId},
{QAccessible::Heading, UIA_TextControlTypeId},
{QAccessible::BlockQuote, UIA_GroupControlTypeId},
+ {QAccessible::LayeredPane, UIA_PaneControlTypeId},
};
long controlType = mapping.value(role, UIA_CustomControlTypeId);
diff --git a/src/plugins/platforms/xcb/qxcbatom.cpp b/src/plugins/platforms/xcb/qxcbatom.cpp
index 5f712d33d56..e609b84ad5f 100644
--- a/src/plugins/platforms/xcb/qxcbatom.cpp
+++ b/src/plugins/platforms/xcb/qxcbatom.cpp
@@ -9,6 +9,7 @@
#include <string.h>
#include <algorithm>
+#include <cstdlib>
static const char *xcb_atomnames = {
// window-manager <-> client protocols
diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp
index c4a35115639..f79dea194e8 100644
--- a/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -580,21 +580,18 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt
if (combobox->frame)
drawLineEditFrame(painter, frameRect, combobox, combobox->editable);
- const bool isMouseOver = state & State_MouseOver;
const bool hasFocus = state & State_HasFocus;
- if (isMouseOver && !hasFocus && !highContrastTheme)
- drawRoundedRect(painter, frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor));
+ QStyleOption opt(*option);
+ opt.state.setFlag(QStyle::State_On, false);
+ drawRoundedRect(painter, frameRect, Qt::NoPen, controlFillBrush(&opt, ControlType::Control));
if (sub & SC_ComboBoxArrow) {
QRectF rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget).adjusted(4, 0, -4, 1);
painter->setFont(d->assetFont);
- painter->setPen(combobox->palette.text().color());
+ painter->setPen(controlTextColor(option));
painter->drawText(rect, Qt::AlignCenter, ChevronDownMed);
}
- if (state & State_HasFocus) {
- drawPrimitive(PE_FrameFocusRect, option, painter, widget);
- }
- if (state & State_KeyboardFocusChange && state & State_HasFocus) {
+ if (state & State_KeyboardFocusChange && hasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*option);
proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
@@ -1055,6 +1052,18 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption
painter->setBrush(vopt->palette.base());
painter->drawRect(rect);
+ if (option->state & State_Selected && !highContrastTheme) {
+ // keep in sync with CE_ItemViewItem QListView indicator painting
+ const auto col = option->palette.accent().color();
+ painter->setBrush(col);
+ painter->setPen(col);
+ const auto xPos = isRtl ? rect.right() - 4.5f : rect.left() + 3.5f;
+ const auto yOfs = rect.height() / 4.;
+ QRectF r(QPointF(xPos, rect.y() + yOfs),
+ QPointF(xPos + 1, rect.y() + rect.height() - yOfs));
+ painter->drawRoundedRect(r, 1, 1);
+ }
+
const bool isTreeDecoration = vopt->features.testFlag(
QStyleOptionViewItem::IsDecorationForRootColumn);
if (isTreeDecoration && vopt->state.testAnyFlags(State_Selected | State_MouseOver) &&
@@ -1182,11 +1191,14 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
painter->setRenderHint(QPainter::Antialiasing);
switch (element) {
case QStyle::CE_ComboBoxLabel:
+#if QT_CONFIG(combobox)
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
+ painter->setPen(controlTextColor(option));
QStyleOptionComboBox newOption = *cb;
newOption.rect.adjust(4,0,-4,0);
QCommonStyle::drawControl(element, &newOption, painter, widget);
}
+#endif // QT_CONFIG(combobox)
break;
case QStyle::CE_TabBarTabShape:
#if QT_CONFIG(tabbar)
@@ -1429,26 +1441,6 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget))
tf |= Qt::TextHideMnemonic;
- if (btn->features & QStyleOptionButton::HasMenu) {
- QPainterStateGuard psg(painter);
-
- const auto indSize = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
- const auto indRect = QRect(btn->rect.right() - indSize - contentItemHMargin, textRect.top(),
- indSize + contentItemHMargin, btn->rect.height());
- const auto vindRect = visualRect(btn->direction, btn->rect, indRect);
- textRect.setWidth(textRect.width() - indSize);
-
- int fontSize = painter->font().pointSize();
- QFont f(d->assetFont);
- f.setPointSize(qRound(fontSize * 0.9f)); // a little bit smaller
- painter->setFont(f);
- QColor penColor = option->palette.color(isEnabled ? QPalette::Active : QPalette::Disabled,
- QPalette::Text);
- if (isEnabled)
- penColor.setAlpha(percentToAlpha(60.63)); // fillColorTextSecondary
- painter->setPen(penColor);
- painter->drawText(vindRect, Qt::AlignCenter, ChevronDownMed);
- }
if (!btn->icon.isNull()) {
//Center both icon and text
QIcon::Mode mode = isEnabled ? QIcon::Normal : QIcon::Disabled;
@@ -1475,6 +1467,8 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
break;
case CE_PushButtonBevel:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
+ using namespace StyleOptionHelper;
+
QRectF rect = btn->rect.marginsRemoved(QMargins(2, 2, 2, 2));
painter->setPen(Qt::NoPen);
if (btn->features.testFlag(QStyleOptionButton::Flat)) {
@@ -1501,6 +1495,29 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
painter->setPen(defaultButton ? WINUI3Colors[colorSchemeIndex][controlStrokeOnAccentSecondary]
: WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]);
}
+ if (btn->features.testFlag(QStyleOptionButton::HasMenu)) {
+ QPainterStateGuard psg(painter);
+
+ const bool isEnabled = !isDisabled(option);
+ QRect textRect = btn->rect.marginsRemoved(QMargins(contentHMargin, 0, contentHMargin, 0));
+ const auto indSize = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
+ const auto indRect =
+ QRect(btn->rect.right() - indSize - contentItemHMargin, textRect.top(),
+ indSize + contentItemHMargin, btn->rect.height());
+ const auto vindRect = visualRect(btn->direction, btn->rect, indRect);
+ textRect.setWidth(textRect.width() - indSize);
+
+ int fontSize = painter->font().pointSize();
+ QFont f(d->assetFont);
+ f.setPointSize(qRound(fontSize * 0.9f)); // a little bit smaller
+ painter->setFont(f);
+ QColor penColor = option->palette.color(
+ isEnabled ? QPalette::Active : QPalette::Disabled, QPalette::Text);
+ if (isEnabled)
+ penColor.setAlpha(percentToAlpha(60.63)); // fillColorTextSecondary
+ painter->setPen(penColor);
+ painter->drawText(vindRect, Qt::AlignCenter, ChevronDownMed);
+ }
}
break;
case CE_MenuBarItem:
@@ -2057,6 +2074,20 @@ QRect QWindows11Style::subControlRect(ComplexControl control, const QStyleOption
}
break;
}
+ case CC_ComboBox: {
+ if (subControl == SC_ComboBoxArrow) {
+ const auto indicatorWidth =
+ proxy()->pixelMetric(PM_MenuButtonIndicator, option, widget);
+ const int endX = option->rect.right() - contentHMargin - 2;
+ const int startX = endX - indicatorWidth;
+ const QRect rect(QPoint(startX, option->rect.top()),
+ QPoint(endX, option->rect.bottom()));
+ ret = visualRect(option->direction, option->rect, rect);
+ } else {
+ ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
+ }
+ break;
+ }
default:
ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
}
@@ -2147,14 +2178,18 @@ QSize QWindows11Style::sizeFromContents(ContentsType type, const QStyleOption *o
break;
}
#endif
+#if QT_CONFIG(combobox)
case CT_ComboBox:
if (const auto *comboBoxOpt = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget); // don't rely on QWindowsThemeData
contentSize += QSize(4, 4); // default win11 style margins
- if (comboBoxOpt->subControls & SC_ComboBoxArrow)
- contentSize += QSize(8, 0); // arrow margins
+ if (comboBoxOpt->subControls & SC_ComboBoxArrow) {
+ const auto w = proxy()->pixelMetric(PM_MenuButtonIndicator, option, widget);
+ contentSize.rwidth() += w + contentItemHMargin;
+ }
}
break;
+#endif
case CT_HeaderSection:
// windows vista does not honor the indicator (as it was drawn above the text, not on the
// side) so call QWindowsStyle::styleHint directly to get the correct size hint
@@ -2262,10 +2297,17 @@ int QWindows11Style::pixelMetric(PixelMetric metric, const QStyleOption *option,
res = contentItemHMargin;
if (widget) {
const int fontSize = widget->font().pointSize();
- QFont f(d->assetFont);
- f.setPointSize(qRound(fontSize * 0.9f)); // a little bit smaller
- QFontMetrics fm(f);
- res += fm.horizontalAdvance(ChevronDownMed);
+ auto it = m_fontPoint2ChevronDownMedWidth.find(fontSize);
+ if (it == m_fontPoint2ChevronDownMedWidth.end()) {
+ QFont f(d->assetFont);
+ f.setPointSize(qRound(fontSize * 0.9f)); // a little bit smaller
+ QFontMetrics fm(f);
+ const auto width = fm.horizontalAdvance(ChevronDownMed);
+ m_fontPoint2ChevronDownMedWidth.insert(fontSize, width);
+ res += width;
+ } else {
+ res += it.value();
+ }
} else {
res += 12;
}
@@ -2278,6 +2320,9 @@ int QWindows11Style::pixelMetric(PixelMetric metric, const QStyleOption *option,
case PM_ButtonShiftVertical:
res = 0;
break;
+ case PM_TreeViewIndentation:
+ res = 30;
+ break;
default:
res = QWindowsVistaStyle::pixelMetric(metric, option, widget);
}
@@ -2365,6 +2410,13 @@ void QWindows11Style::unpolish(QWidget *widget)
widget->setProperty("_q_original_menubar_maxheight", QVariant());
}
#endif
+ const auto comboBoxContainer = qobject_cast<const QComboBoxPrivateContainer *>(widget);
+ if (comboBoxContainer) {
+ widget->setAttribute(Qt::WA_OpaquePaintEvent, true);
+ widget->setAttribute(Qt::WA_TranslucentBackground, false);
+ widget->setWindowFlag(Qt::FramelessWindowHint, false);
+ widget->setWindowFlag(Qt::NoDropShadowWindowHint, false);
+ }
if (const auto *scrollarea = qobject_cast<QAbstractScrollArea *>(widget);
scrollarea
diff --git a/src/plugins/styles/modernwindows/qwindows11style_p.h b/src/plugins/styles/modernwindows/qwindows11style_p.h
index de1aee4fce9..736caae956c 100644
--- a/src/plugins/styles/modernwindows/qwindows11style_p.h
+++ b/src/plugins/styles/modernwindows/qwindows11style_p.h
@@ -114,6 +114,8 @@ private:
bool highContrastTheme = false;
int colorSchemeIndex = 0;
+
+ mutable QVarLengthFlatMap<int, int, 8> m_fontPoint2ChevronDownMedWidth;
};
class QWindows11StylePrivate : public QWindowsVistaStylePrivate {
diff --git a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
index abe0bde540f..22ca18b10bf 100644
--- a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
@@ -1626,6 +1626,12 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
break;
case PE_Frame:
+ if (widget && widget->inherits("QComboBoxPrivateContainer")){
+ QStyleOption copy = *option;
+ copy.state |= State_Raised;
+ proxy()->drawPrimitive(PE_PanelMenu, &copy, painter, widget);
+ break;
+ }
#if QT_CONFIG(accessibility)
if (QStyleHelper::isInstanceOf(option->styleObject, QAccessible::EditableText)
|| QStyleHelper::isInstanceOf(option->styleObject, QAccessible::StaticText) ||
@@ -1704,6 +1710,14 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
return;
}
+ case PE_PanelMenu:
+ if (widget && widget->inherits("QComboBoxPrivateContainer")){
+ //fill combobox popup background
+ QWindowsThemeData popupbackgroundTheme(widget, painter, QWindowsVistaStylePrivate::MenuTheme,
+ MENU_POPUPBACKGROUND, stateId, option->rect);
+ d->drawBackground(popupbackgroundTheme);
+ }
+
case PE_PanelMenuBar:
break;
diff --git a/src/tools/bootstrap/CMakeLists.txt b/src/tools/bootstrap/CMakeLists.txt
index ee82d6b99f9..e6f920dcf32 100644
--- a/src/tools/bootstrap/CMakeLists.txt
+++ b/src/tools/bootstrap/CMakeLists.txt
@@ -162,6 +162,7 @@ qt_internal_extend_target(Bootstrap CONDITION CMAKE_CROSSCOMPILING OR NOT QT_FEA
../../3rdparty/pcre2/src/pcre2_chartables.c
../../3rdparty/pcre2/src/pcre2_chkdint.c
../../3rdparty/pcre2/src/pcre2_compile.c
+ ../../3rdparty/pcre2/src/pcre2_compile_cgroup.c
../../3rdparty/pcre2/src/pcre2_compile_class.c
../../3rdparty/pcre2/src/pcre2_config.c
../../3rdparty/pcre2/src/pcre2_context.c
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt
index ce30f50616b..c0be3debe49 100644
--- a/src/widgets/CMakeLists.txt
+++ b/src/widgets/CMakeLists.txt
@@ -681,6 +681,7 @@ qt_internal_extend_target(Widgets CONDITION MACOS AND (QT_FEATURE_menu OR QT_FEA
qt_internal_extend_target(Widgets CONDITION QT_FEATURE_colordialog
SOURCES
dialogs/qcolordialog.cpp dialogs/qcolordialog.h
+ dialogs/qcolorwell_p.h
)
qt_internal_extend_target(Widgets CONDITION QT_FEATURE_dialog
diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp
index 608a99b575d..cd28a61f427 100644
--- a/src/widgets/accessible/qaccessiblewidgets.cpp
+++ b/src/widgets/accessible/qaccessiblewidgets.cpp
@@ -958,54 +958,22 @@ QPoint QAccessibleTextWidget::scrollBarPosition() const
QString QAccessibleTextWidget::textBeforeOffset(int offset, QAccessible::TextBoundaryType boundaryType,
int *startOffset, int *endOffset) const
{
- Q_ASSERT(startOffset);
- Q_ASSERT(endOffset);
-
- QTextCursor cursor = textCursor();
- cursor.setPosition(offset);
- std::pair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
- cursor.setPosition(boundaries.first - 1);
- boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
-
- *startOffset = boundaries.first;
- *endOffset = boundaries.second;
-
- return text(boundaries.first, boundaries.second);
- }
-
+ return qt_accTextBeforeOffsetHelper(*this, textCursor(), offset, boundaryType, startOffset,
+ endOffset);
+}
QString QAccessibleTextWidget::textAfterOffset(int offset, QAccessible::TextBoundaryType boundaryType,
int *startOffset, int *endOffset) const
{
- Q_ASSERT(startOffset);
- Q_ASSERT(endOffset);
-
- QTextCursor cursor = textCursor();
- cursor.setPosition(offset);
- std::pair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
- cursor.setPosition(boundaries.second);
- boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
-
- *startOffset = boundaries.first;
- *endOffset = boundaries.second;
-
- return text(boundaries.first, boundaries.second);
+ return qt_accTextAfterOffsetHelper(*this, textCursor(), offset, boundaryType, startOffset,
+ endOffset);
}
QString QAccessibleTextWidget::textAtOffset(int offset, QAccessible::TextBoundaryType boundaryType,
int *startOffset, int *endOffset) const
{
- Q_ASSERT(startOffset);
- Q_ASSERT(endOffset);
-
- QTextCursor cursor = textCursor();
- cursor.setPosition(offset);
- std::pair<int, int> boundaries = QAccessible::qAccessibleTextBoundaryHelper(cursor, boundaryType);
-
- *startOffset = boundaries.first;
- *endOffset = boundaries.second;
-
- return text(boundaries.first, boundaries.second);
+ return qt_accTextAtOffsetHelper(*this, textCursor(), offset, boundaryType, startOffset,
+ endOffset);
}
void QAccessibleTextWidget::setCursorPosition(int position)
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index b4ca17b9f64..25d742039c5 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -39,6 +39,7 @@
#include "qwindow.h"
#include "private/qdialog_p.h"
+#include "private/qcolorwell_p.h"
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformservices.h>
@@ -56,16 +57,12 @@ namespace QtPrivate {
class QColorLuminancePicker;
class QColorPicker;
class QColorShower;
-class QWellArray;
-class QColorWell;
class QColorPickingEventFilter;
} // namespace QtPrivate
using QColorLuminancePicker = QtPrivate::QColorLuminancePicker;
using QColorPicker = QtPrivate::QColorPicker;
using QColorShower = QtPrivate::QColorShower;
-using QWellArray = QtPrivate::QWellArray;
-using QColorWell = QtPrivate::QColorWell;
using QColorPickingEventFilter = QtPrivate::QColorPickingEventFilter;
class QColorDialogPrivate : public QDialogPrivate
@@ -162,96 +159,6 @@ private:
//////////// QWellArray BEGIN
-namespace QtPrivate {
-
-class QWellArray : public QWidget
-{
- Q_OBJECT
- Q_PROPERTY(int selectedColumn READ selectedColumn)
- Q_PROPERTY(int selectedRow READ selectedRow)
-
-public:
- QWellArray(int rows, int cols, QWidget* parent=nullptr);
- ~QWellArray() {}
- QString cellContent(int row, int col) const;
-
- int selectedColumn() const { return selCol; }
- int selectedRow() const { return selRow; }
-
- virtual void setCurrent(int row, int col);
- virtual void setSelected(int row, int col);
-
- QSize sizeHint() const override;
-
- inline int cellWidth() const
- { return cellw; }
-
- inline int cellHeight() const
- { return cellh; }
-
- inline int rowAt(int y) const
- { return y / cellh; }
-
- inline int columnAt(int x) const
- { if (isRightToLeft()) return ncols - (x / cellw) - 1; return x / cellw; }
-
- inline int rowY(int row) const
- { return cellh * row; }
-
- inline int columnX(int column) const
- { if (isRightToLeft()) return cellw * (ncols - column - 1); return cellw * column; }
-
- inline int numRows() const
- { return nrows; }
-
- inline int numCols() const
- {return ncols; }
-
- inline QRect cellRect() const
- { return QRect(0, 0, cellw, cellh); }
-
- inline QSize gridSize() const
- { return QSize(ncols * cellw, nrows * cellh); }
-
- QRect cellGeometry(int row, int column)
- {
- QRect r;
- if (row >= 0 && row < nrows && column >= 0 && column < ncols)
- r.setRect(columnX(column), rowY(row), cellw, cellh);
- return r;
- }
-
- inline void updateCell(int row, int column) { update(cellGeometry(row, column)); }
-
-signals:
- void selected(int row, int col);
- void currentChanged(int row, int col);
- void colorChanged(int index, QRgb color);
-
-protected:
- virtual void paintCell(QPainter *, int row, int col, const QRect&);
- virtual void paintCellContents(QPainter *, int row, int col, const QRect&);
-
- void mousePressEvent(QMouseEvent*) override;
- void mouseReleaseEvent(QMouseEvent*) override;
- void keyPressEvent(QKeyEvent*) override;
- void focusInEvent(QFocusEvent*) override;
- void focusOutEvent(QFocusEvent*) override;
- void paintEvent(QPaintEvent *) override;
-
-private:
- Q_DISABLE_COPY(QWellArray)
-
- int nrows;
- int ncols;
- int cellw;
- int cellh;
- int curRow;
- int curCol;
- int selRow;
- int selCol;
-};
-
void QWellArray::paintEvent(QPaintEvent *e)
{
QRect r = e->rect();
@@ -476,11 +383,12 @@ void QWellArray::keyPressEvent(QKeyEvent* e)
e->ignore(); // we don't accept the event
return;
}
-
-} // namespace QtPrivate
+}
//////////// QWellArray END
+namespace QtPrivate {
+
// Event filter to be installed on the dialog while in color-picking mode.
class QColorPickingEventFilter : public QObject {
public:
@@ -511,7 +419,7 @@ private:
QColorDialogPrivate *m_dp;
};
-} // unnamed namespace
+} // namespace QtPrivate
/*!
Returns the number of custom colors supported by QColorDialog. All
@@ -571,35 +479,6 @@ static inline void rgb2hsv(QRgb rgb, int &h, int &s, int &v)
c.getHsv(&h, &s, &v);
}
-namespace QtPrivate {
-
-class QColorWell : public QWellArray
-{
-public:
- QColorWell(QWidget *parent, int r, int c, const QRgb *vals)
- :QWellArray(r, c, parent), values(vals), mousePressed(false), oldCurrent(-1, -1)
- { setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum)); }
-
-protected:
- void paintCellContents(QPainter *, int row, int col, const QRect&) override;
- void mousePressEvent(QMouseEvent *e) override;
- void mouseMoveEvent(QMouseEvent *e) override;
- void mouseReleaseEvent(QMouseEvent *e) override;
-#if QT_CONFIG(draganddrop)
- void dragEnterEvent(QDragEnterEvent *e) override;
- void dragLeaveEvent(QDragLeaveEvent *e) override;
- void dragMoveEvent(QDragMoveEvent *e) override;
- void dropEvent(QDropEvent *e) override;
-#endif
-
-private:
- const QRgb *values;
- bool mousePressed;
- QPoint pressPos;
- QPoint oldCurrent;
-
-};
-
void QColorWell::paintCellContents(QPainter *p, int row, int col, const QRect &r)
{
int i = row + col*numRows();
@@ -687,6 +566,8 @@ void QColorWell::mouseReleaseEvent(QMouseEvent *e)
mousePressed = false;
}
+namespace QtPrivate {
+
class QColorPicker : public QFrame
{
Q_OBJECT
diff --git a/src/widgets/dialogs/qcolorwell_p.h b/src/widgets/dialogs/qcolorwell_p.h
new file mode 100644
index 00000000000..31d69fabb13
--- /dev/null
+++ b/src/widgets/dialogs/qcolorwell_p.h
@@ -0,0 +1,142 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCOLORWELL_P_H
+#define QCOLORWELL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qrect.h>
+#include <QtWidgets/qwidget.h>
+
+QT_REQUIRE_CONFIG(colordialog);
+
+QT_BEGIN_NAMESPACE
+
+class QWellArray : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(int selectedColumn READ selectedColumn)
+ Q_PROPERTY(int selectedRow READ selectedRow)
+
+public:
+ QWellArray(int rows, int cols, QWidget *parent = nullptr);
+ ~QWellArray() { }
+
+ int selectedColumn() const { return selCol; }
+ int selectedRow() const { return selRow; }
+
+ virtual void setCurrent(int row, int col);
+ virtual void setSelected(int row, int col);
+
+ QSize sizeHint() const override;
+
+ inline int cellWidth() const { return cellw; }
+
+ inline int cellHeight() const { return cellh; }
+
+ inline int rowAt(int y) const { return y / cellh; }
+
+ inline int columnAt(int x) const
+ {
+ if (isRightToLeft())
+ return ncols - (x / cellw) - 1;
+ return x / cellw;
+ }
+
+ inline int rowY(int row) const { return cellh * row; }
+
+ inline int columnX(int column) const
+ {
+ if (isRightToLeft())
+ return cellw * (ncols - column - 1);
+ return cellw * column;
+ }
+
+ inline int numRows() const { return nrows; }
+
+ inline int numCols() const { return ncols; }
+
+ inline QRect cellRect() const { return QRect(0, 0, cellw, cellh); }
+
+ inline QSize gridSize() const { return QSize(ncols * cellw, nrows * cellh); }
+
+ QRect cellGeometry(int row, int column)
+ {
+ QRect r;
+ if (row >= 0 && row < nrows && column >= 0 && column < ncols)
+ r.setRect(columnX(column), rowY(row), cellw, cellh);
+ return r;
+ }
+
+ inline void updateCell(int row, int column) { update(cellGeometry(row, column)); }
+
+signals:
+ void selected(int row, int col);
+ void currentChanged(int row, int col);
+ void colorChanged(int index, QRgb color);
+
+protected:
+ virtual void paintCell(QPainter *, int row, int col, const QRect &);
+ virtual void paintCellContents(QPainter *, int row, int col, const QRect &);
+
+ void mousePressEvent(QMouseEvent *) override;
+ void mouseReleaseEvent(QMouseEvent *) override;
+ void keyPressEvent(QKeyEvent *) override;
+ void focusInEvent(QFocusEvent *) override;
+ void focusOutEvent(QFocusEvent *) override;
+ void paintEvent(QPaintEvent *) override;
+
+private:
+ Q_DISABLE_COPY(QWellArray)
+
+ int nrows;
+ int ncols;
+ int cellw;
+ int cellh;
+ int curRow;
+ int curCol;
+ int selRow;
+ int selCol;
+};
+
+class QColorWell : public QWellArray
+{
+public:
+ QColorWell(QWidget *parent, int r, int c, const QRgb *vals)
+ : QWellArray(r, c, parent), values(vals), mousePressed(false), oldCurrent(-1, -1)
+ {
+ setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
+ }
+
+protected:
+ void paintCellContents(QPainter *, int row, int col, const QRect &) override;
+ void mousePressEvent(QMouseEvent *e) override;
+ void mouseMoveEvent(QMouseEvent *e) override;
+ void mouseReleaseEvent(QMouseEvent *e) override;
+#if QT_CONFIG(draganddrop)
+ void dragEnterEvent(QDragEnterEvent *e) override;
+ void dragLeaveEvent(QDragLeaveEvent *e) override;
+ void dragMoveEvent(QDragMoveEvent *e) override;
+ void dropEvent(QDropEvent *e) override;
+#endif
+
+private:
+ const QRgb *values;
+ bool mousePressed;
+ QPoint pressPos;
+ QPoint oldCurrent;
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOLORWELL_P_H
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index d964c9667e6..1ed9dd06e3c 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -3008,7 +3008,6 @@ void QFileDialogPrivate::createWidgets()
qFileDialogUi->lookInCombo->setDuplicatesEnabled(false);
// filename
- qFileDialogUi->fileNameEdit->setFileDialogPrivate(this);
#ifndef QT_NO_SHORTCUT
qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
#endif
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
index 15044cfd291..dd4a2505def 100644
--- a/src/widgets/dialogs/qfiledialog_p.h
+++ b/src/widgets/dialogs/qfiledialog_p.h
@@ -266,12 +266,9 @@ private:
class QFileDialogLineEdit : public QLineEdit
{
public:
- QFileDialogLineEdit(QWidget *parent = nullptr) : QLineEdit(parent), d_ptr(nullptr){}
- void setFileDialogPrivate(QFileDialogPrivate *d_pointer) {d_ptr = d_pointer; }
+ QFileDialogLineEdit(QWidget *parent = nullptr) : QLineEdit(parent) {}
void keyPressEvent(QKeyEvent *e) override;
bool hideOnEsc;
-private:
- QFileDialogPrivate *d_ptr;
};
class QFileDialogComboBox : public QComboBox
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 9b06822c218..b9143a59ee7 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -851,6 +851,12 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
}
#ifndef QT_NO_FRAME
case PE_Frame:
+ if (w && w->inherits("QComboBoxPrivateContainer")){
+ QStyleOption copy = *opt;
+ copy.state |= State_Raised;
+ proxy()->drawPrimitive(PE_PanelMenu, &copy, p, w);
+ break;
+ }
case PE_FrameMenu:
if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
if (frame->lineWidth == 2 || pe == PE_Frame) {
@@ -873,6 +879,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
}
} else {
QPalette popupPal = opt->palette;
+ p->drawRect(opt->rect);
popupPal.setColor(QPalette::Light, opt->palette.window().color());
popupPal.setColor(QPalette::Midlight, opt->palette.light().color());
qDrawWinPanel(p, opt->rect, popupPal, opt->state & State_Sunken);
@@ -899,6 +906,12 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
p->drawRect(opt->rect);
}
break; }
+ case PE_PanelMenu:
+ if (w && w->inherits("QComboBoxPrivateContainer")){
+ const QBrush menuBackground = opt->palette.base().color();
+ QColor borderColor = opt->palette.window().color();
+ qDrawPlainRect(p, opt->rect, borderColor, 1, &menuBackground);
+ }
case PE_FrameWindow: {
QPalette popupPal = opt->palette;
popupPal.setColor(QPalette::Light, opt->palette.window().color());
diff --git a/tests/auto/corelib/animation/qparallelanimationgroup/tst_qparallelanimationgroup.cpp b/tests/auto/corelib/animation/qparallelanimationgroup/tst_qparallelanimationgroup.cpp
index d8da8ecc03b..c2c09a234c8 100644
--- a/tests/auto/corelib/animation/qparallelanimationgroup/tst_qparallelanimationgroup.cpp
+++ b/tests/auto/corelib/animation/qparallelanimationgroup/tst_qparallelanimationgroup.cpp
@@ -74,13 +74,13 @@ class TestAnimation : public QVariantAnimation
{
Q_OBJECT
public:
- virtual void updateCurrentValue(const QVariant &value) override { Q_UNUSED(value)};
+ virtual void updateCurrentValue(const QVariant &value) override { Q_UNUSED(value)}
virtual void updateState(QAbstractAnimation::State newState,
QAbstractAnimation::State oldState) override
{
Q_UNUSED(oldState);
Q_UNUSED(newState);
- };
+ }
};
class TestAnimation2 : public QVariantAnimation
@@ -90,13 +90,13 @@ public:
TestAnimation2(QAbstractAnimation *animation) : QVariantAnimation(animation) {}
TestAnimation2(int duration, QAbstractAnimation *animation) : QVariantAnimation(animation), m_duration(duration) {}
- virtual void updateCurrentValue(const QVariant &value) override { Q_UNUSED(value)};
+ virtual void updateCurrentValue(const QVariant &value) override { Q_UNUSED(value)}
virtual void updateState(QAbstractAnimation::State newState,
QAbstractAnimation::State oldState) override
{
Q_UNUSED(oldState);
Q_UNUSED(newState);
- };
+ }
virtual int duration() const override {
return m_duration;
@@ -463,8 +463,9 @@ void tst_QParallelAnimationGroup::deleteChildrenWithRunningGroup()
QCOMPARE(group.state(), QAnimationGroup::Running);
QCOMPARE(anim1->state(), QAnimationGroup::Running);
- QTest::qWait(80);
- QVERIFY(group.currentLoopTime() > 0);
+ QTest::qWaitFor([&]{
+ return group.currentLoopTime() > 0;
+ }, 200ms);
delete anim1;
QCOMPARE(group.animationCount(), 0);
diff --git a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
index 0fd62d40f62..9aa99a1b653 100644
--- a/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
+++ b/tests/auto/corelib/io/qloggingregistry/tst_qloggingregistry.cpp
@@ -186,6 +186,12 @@ private slots:
Q_ASSERT(!qApp); // Rules should not require an app to resolve
+ static bool calledOnce = false;
+ if (calledOnce)
+ QSKIP("QLoggingRegistry_environment can only run once");
+
+ calledOnce = true;
+
qputenv("QT_LOGGING_RULES", "qt.foo.bar=true");
QLoggingCategory qtEnabledByLoggingRule("qt.foo.bar");
QCOMPARE(qtEnabledByLoggingRule.isDebugEnabled(), true);
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index 683025fd409..3cf16367777 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -528,11 +528,25 @@ void tst_QMetaType::qMetaTypeId()
QCOMPARE(::qMetaTypeId<qint8>(), QMetaType::fromType<qint8>().id());
}
+class QPropObject : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<QVariant> prop READ prop WRITE setProp)
+
+public:
+ QPropObject() { propList << 42 << "Hello"; }
+
+ QList<QVariant> prop() const { return propList; }
+ void setProp(const QList<QVariant> &list) { propList = list; }
+ QList<QVariant> propList;
+};
+
void tst_QMetaType::properties()
{
qRegisterMetaType<QList<QVariant> >("QList<QVariant>");
+ QPropObject sut;
- QVariant v = property("prop");
+ QVariant v = sut.property("prop");
QCOMPARE(v.typeName(), "QVariantList");
@@ -542,8 +556,8 @@ void tst_QMetaType::properties()
values << 43 << "world";
- QVERIFY(setProperty("prop", values));
- v = property("prop");
+ QVERIFY(sut.setProperty("prop", values));
+ v = sut.property("prop");
QCOMPARE(v.toList().size(), 4);
}
@@ -1450,6 +1464,11 @@ void tst_QMetaType::defaultConstructTrivial_QTBUG_109594()
void tst_QMetaType::typedConstruct()
{
+ static bool calledOnce = false;
+ if (calledOnce)
+ QSKIP("tst_QMetaType::typedConstruct can only run once");
+ calledOnce = true;
+
auto testMetaObjectWriteOnGadget = [](QVariant &gadget, const QList<GadgetPropertyType> &properties)
{
auto metaObject = QMetaType(gadget.userType()).metaObject();
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
index 6f218bb0651..e9a177356e6 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
@@ -25,7 +25,6 @@ struct MessageHandlerCustom : public MessageHandler
class tst_QMetaType: public QObject
{
Q_OBJECT
- Q_PROPERTY(QList<QVariant> prop READ prop WRITE setProp)
public:
struct GadgetPropertyType {
@@ -34,14 +33,8 @@ public:
QVariant testData;
};
- tst_QMetaType() { propList << 42 << "Hello"; }
-
- QList<QVariant> prop() const { return propList; }
- void setProp(const QList<QVariant> &list) { propList = list; }
-
private:
void registerGadget(const char * name, const QList<GadgetPropertyType> &gadgetProperties);
- QList<QVariant> propList;
private slots:
#if QT_CONFIG(thread)
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp
index 661c1f6072b..93f23259745 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype2.cpp
@@ -148,6 +148,11 @@ void registerCustomTypeConversions()
void tst_QMetaType::convertCustomType_data()
{
+ static bool calledOnce = false;
+ if (calledOnce)
+ QSKIP("convertCustomType can only run once");
+ calledOnce = true;
+
customTypeNotYetConvertible();
registerCustomTypeConversions();
@@ -363,6 +368,11 @@ void tst_QMetaType::compareCustomEqualOnlyType()
void tst_QMetaType::customDebugStream()
{
+ static bool calledOnce = false;
+ if (calledOnce)
+ QSKIP("customDebugStream can only run once");
+ calledOnce = true;
+
MessageHandlerCustom handler(::qMetaTypeId<CustomDebugStreamableType>());
QVariant v1 = QVariant::fromValue(CustomDebugStreamableType());
handler.expectedMessage = "QVariant(CustomDebugStreamableType, string-content)";
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index bef43091277..e713901101c 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -455,7 +455,6 @@ private:
};
const qlonglong intMax1 = (qlonglong)INT_MAX + 1;
-const qulonglong uintMax1 = (qulonglong)UINT_MAX + 1;
void tst_QVariant::constructor()
{
@@ -5737,22 +5736,24 @@ void tst_QVariant::sequentialIterableAppend()
void tst_QVariant::preferDirectConversionOverInterfaces()
{
using namespace QtMetaTypePrivate;
- bool calledCorrectConverter = false;
+ static bool calledCorrectConverter = false;
+ calledCorrectConverter = false;
+
QMetaType::registerConverter<MyType, QSequentialIterable>([](const MyType &) {
return QSequentialIterable {};
});
- QMetaType::registerConverter<MyType, QVariantList>([&calledCorrectConverter](const MyType &) {
+ QMetaType::registerConverter<MyType, QVariantList>([&](const MyType &) {
calledCorrectConverter = true;
return QVariantList {};
});
QMetaType::registerConverter<MyType, QAssociativeIterable>([](const MyType &) {
return QAssociativeIterable {};
});
- QMetaType::registerConverter<MyType, QVariantHash>([&calledCorrectConverter](const MyType &) {
+ QMetaType::registerConverter<MyType, QVariantHash>([&](const MyType &) {
calledCorrectConverter = true;
return QVariantHash {};
});
- QMetaType::registerConverter<MyType, QVariantMap>([&calledCorrectConverter](const MyType &) {
+ QMetaType::registerConverter<MyType, QVariantMap>([&](const MyType &) {
calledCorrectConverter = true;
return QVariantMap {};
});
@@ -5783,6 +5784,11 @@ struct MyTypeView
void tst_QVariant::mutableView()
{
+ static bool calledOnce = false;
+ if (calledOnce)
+ QSKIP("This test can only be run once per test execution because of QMetaType registration");
+ calledOnce = true;
+
bool calledView = false;
const bool success = QMetaType::registerMutableView<MyType, MyTypeView>([&](MyType &data) {
calledView = true;
@@ -5906,6 +5912,11 @@ void tst_QVariant::moveOperations()
class NoMetaObject : public QObject {};
void tst_QVariant::equalsWithoutMetaObject()
{
+ static bool calledOnce = false;
+ if (calledOnce)
+ QSKIP("This test can only be run once per test execution because of QMetaType registration");
+ calledOnce = true;
+
using T = NoMetaObject*;
QtPrivate::QMetaTypeInterface d = {
/*.revision=*/ 0,
@@ -6021,6 +6032,12 @@ void tst_QVariant::constructFromIncompatibleMetaType()
void tst_QVariant::constructFromQtLT65MetaType()
{
+ static bool calledOnce = false;
+ if (calledOnce)
+ QSKIP("This test can only be run once per test execution because of QMetaType registration");
+ calledOnce = true;
+
+
auto qsizeIface = QtPrivate::qMetaTypeInterfaceForType<QSize>();
QtPrivate::QMetaTypeInterface qsize64Iface = {
diff --git a/tests/auto/corelib/plugin/CMakeLists.txt b/tests/auto/corelib/plugin/CMakeLists.txt
index 5518231ace2..82fa9d18749 100644
--- a/tests/auto/corelib/plugin/CMakeLists.txt
+++ b/tests/auto/corelib/plugin/CMakeLists.txt
@@ -7,7 +7,9 @@ endif()
add_subdirectory(quuid)
if(QT_FEATURE_library)
add_subdirectory(qpluginloader)
- add_subdirectory(qlibrary)
+ if(QT_FEATURE_private_tests)
+ add_subdirectory(qlibrary)
+ endif()
endif()
if(QT_BUILD_SHARED_LIBS AND QT_FEATURE_library)
add_subdirectory(qplugin)
diff --git a/tests/auto/corelib/plugin/qlibrary/tst/CMakeLists.txt b/tests/auto/corelib/plugin/qlibrary/tst/CMakeLists.txt
index fc452f37f53..62dd4a06c17 100644
--- a/tests/auto/corelib/plugin/qlibrary/tst/CMakeLists.txt
+++ b/tests/auto/corelib/plugin/qlibrary/tst/CMakeLists.txt
@@ -13,7 +13,7 @@ qt_internal_add_test(tst_qlibrary
SOURCES
../tst_qlibrary.cpp
TESTDATA ${test_data}
- LIBRARIES mylib mylib2
+ LIBRARIES mylib mylib2 Qt::CorePrivate
)
add_dependencies(tst_qlibrary mylib mylib2)
diff --git a/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp b/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp
index 5ae49ff1707..d708f6def1c 100644
--- a/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp
+++ b/tests/auto/corelib/plugin/qlibrary/tst_qlibrary.cpp
@@ -6,6 +6,7 @@
#include <qdir.h>
#include <qlibrary.h>
#include <QtCore/QRegularExpression>
+#include <QtCore/private/qlibrary_p.h>
// Helper macros to let us know if some suffixes and prefixes are valid
@@ -162,7 +163,12 @@ void tst_QLibrary::cleanup()
};
for (const auto &entry : libs) {
- do {} while (QLibrary(entry.name, entry.version).unload());
+ bool unloaded = false;
+ do {
+ QLibrary lib(entry.name, entry.version);
+ auto libPrivate = QLibraryPrivate::get(&lib);
+ unloaded = libPrivate->unload();
+ } while (unloaded);
}
}
diff --git a/tests/auto/corelib/tools/collections/tst_collections.cpp b/tests/auto/corelib/tools/collections/tst_collections.cpp
index 463f600e36d..cbe04ae39f7 100644
--- a/tests/auto/corelib/tools/collections/tst_collections.cpp
+++ b/tests/auto/corelib/tools/collections/tst_collections.cpp
@@ -650,14 +650,14 @@ QT_WARNING_POP
{
QList<int *> list;
QVERIFY(list.value(0) == 0);
- int i;
+ int i = 42;
list.append(&i);
QVERIFY(list.value(0) == &i);
}
{
QList<const int *> list;
QVERIFY(list.value(0) == 0);
- int i;
+ int i = 42;
list.append(&i);
QVERIFY(list.value(0) == &i);
}
diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
index 51edf7a1ea7..b671c419b2b 100644
--- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
+++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp
@@ -17,6 +17,7 @@ class tst_QCommandLineParser : public QObject
public slots:
void initTestCase();
+ void cleanupTestCase();
private slots:
void parsingModes_data();
@@ -71,6 +72,11 @@ void tst_QCommandLineParser::initTestCase()
empty_argv[0] = const_cast<char*>(QTest::currentAppName());
}
+void tst_QCommandLineParser::cleanupTestCase()
+{
+ empty_argv[0] = nullptr;
+}
+
Q_DECLARE_METATYPE(QCommandLineParser::SingleDashWordOptionMode)
void tst_QCommandLineParser::parsingModes_data()
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index a067ac541b0..2e92cdffada 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -1904,6 +1904,20 @@ void tst_QAccessibility::textEditTest()
QCOMPARE(textIface->textAtOffset(15, QAccessible::LineBoundary, &startOffset, &endOffset), QString("How are you today?"));
QCOMPARE(startOffset, 13);
QCOMPARE(endOffset, 31);
+
+ QCOMPARE(textIface->textAfterOffset(3, QAccessible::WordBoundary, &startOffset, &endOffset),
+ QString("world"));
+ QCOMPARE(
+ textIface->textBeforeOffset(8, QAccessible::WordBoundary, &startOffset, &endOffset),
+ QString("hello"));
+ // no more word before or after the last one
+ QCOMPARE(
+ textIface->textBeforeOffset(1, QAccessible::WordBoundary, &startOffset, &endOffset),
+ QString());
+ QCOMPARE(textIface->textAfterOffset(textIface->characterCount() - 1,
+ QAccessible::WordBoundary, &startOffset, &endOffset),
+ QString());
+
QCOMPARE(textIface->characterCount(), 48);
QFontMetrics fm(edit.document()->defaultFont());
QCOMPARE(textIface->characterRect(0).size(), QSize(fm.horizontalAdvance("h"), fm.height()));
@@ -2321,6 +2335,12 @@ void tst_QAccessibility::lineEditTest()
QCOMPARE(textIface->textAtOffset(5, QAccessible::LineBoundary,&start,&end), cite);
QCOMPARE(textIface->textAtOffset(5, QAccessible::NoBoundary,&start,&end), cite);
+ le3->setText("Hello");
+ QCOMPARE(textIface->textAtOffset(1, QAccessible::WordBoundary, &start, &end),
+ QString::fromLatin1("Hello"));
+ QCOMPARE(textIface->textBeforeOffset(1, QAccessible::WordBoundary, &start, &end), QString());
+ QCOMPARE(textIface->textAfterOffset(1, QAccessible::WordBoundary, &start, &end), QString());
+
QTestAccessibility::clearEvents();
}
diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
index a79d3454724..e8a3e8c046d 100644
--- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp
@@ -47,6 +47,7 @@ Q_GUI_EXPORT void qt_test_resetFetchedRoot();
QT_END_NAMESPACE
#endif
+[[maybe_unused]]
static QByteArray msgDoesNotExist(const QString &name)
{
return (QLatin1Char('"') + QDir::toNativeSeparators(name)
diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
index b651668cabd..526081b2f19 100644
--- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
+++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -2842,15 +2842,6 @@ const bool block_some_signals = true; // The test should also work with this set
const int rowcount = 500;
const int colcount = 10;
-static inline QString istr(int n, bool comma = true)
-{
- QString s;
- s.setNum(n);
- if (comma)
- s += ", ";
- return s;
-}
-
void tst_QHeaderView::setupTestData()
{
QTest::addColumn<bool>("updates_enabled");