diff options
Diffstat (limited to 'thirdparty')
278 files changed, 22949 insertions, 26675 deletions
diff --git a/thirdparty/README.md b/thirdparty/README.md index dd937dcfec..6dca29e856 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -3,7 +3,6 @@ Please keep categories (`##` level) listed alphabetically and matching their respective folder names. Use two empty lines to separate categories for readability. -Subcategories (`###` level) where needed are separated by a single empty line. ## basis_universal @@ -46,7 +45,7 @@ as it's generated on the user's system.) ## cvtt - Upstream: https://github.com/elasota/cvtt -- Version: 1.0.0-beta4 (2018) +- Version: 1.0.0-beta4 (cc8472a04ba110fe999c686d07af40f7839051fd, 2018) - License: MIT Files extracted from upstream source: @@ -55,16 +54,18 @@ Files extracted from upstream source: ## doctest + - Upstream: https://github.com/onqtam/doctest -- Version: 8424be5 (2.4.1) +- Version: 2.4.4 (97d5a9447e66cd5e107b7a6c463be4a468a40496, 2020) - License: MIT Extracted from .zip provided. Extracted license and header only. + ## enet - Upstream: http://enet.bespin.org -- Version: 1.3.15 (224f31101fc60939c02f6bbe8e8fc810a7db306b, 2020) +- Version: 1.3.17 (e0e7045b7e056b454b5093cb34df49dc4cee0bee, 2020) - License: MIT Files extracted from upstream source: @@ -74,11 +75,11 @@ Files extracted from upstream source: - LICENSE file Important: enet.h, host.c, protocol.c have been slightly modified -to be usable by godot socket implementation and allow IPv6 and DTLS. +to be usable by Godot's socket implementation and allow IPv6 and DTLS. Apply the patches in the `patches/` folder when syncing on newer upstream commits. -Two files (godot.cpp and enet/godot.h) have been added to provide +Three files (godot.cpp, enet/godot.h, enet/godot_ext.h) have been added to provide enet socket implementation using Godot classes. It is still possible to build against a system wide ENet but doing so @@ -103,37 +104,31 @@ comments. ## fonts -### Noto Sans - -- Upstream: https://github.com/googlei18n/noto-fonts -- Version: 1.06 (2017) -- License: OFL-1.1 - -Use UI font variant if available, because it has tight vertical metrics and good for UI. - -### Hack Regular - -- Upstream: https://github.com/source-foundry/Hack -- Version: 3.003 (2018) -- License: MIT + Bitstream Vera License - -### DroidSans*.ttf - -- Upstream: https://android.googlesource.com/platform/frameworks/base/+/master/data/fonts/ -- Version: ? (pre-2014 commit when DroidSansJapanese.ttf was obsoleted) -- License: Apache 2.0 - -### Tamsyn -- Upstream: http://www.fial.com/~scott/tamsyn-font/ -- Version: 1.11 -- License: Tamsyn +- `NotoSans*.ttf`, `NotoNaskhArabicUI_Regular.ttf`: + * Upstream: https://github.com/googlei18n/noto-fonts + * Version: 1.06 (2017) + * License: OFL-1.1 + * Comment: Use UI font variant if available, because it has tight vertical metrics and + good for UI. +- `Hack_Regular.ttf`: + * Upstream: https://github.com/source-foundry/Hack + * Version: 3.003 (2018) + * License: MIT + Bitstream Vera License +- `DroidSans*.ttf`: + * Upstream: https://android.googlesource.com/platform/frameworks/base/+/master/data/fonts/ + * Version: ? (pre-2014 commit when DroidSansJapanese.ttf was obsoleted) + * License: Apache 2.0 +- `Tamsyn*.png`: + * Upstream: http://www.fial.com/~scott/tamsyn-font/ + * Version: 1.11 (2015) + * License: Tamsyn + * Comment: Extracted "0..9,A..F" characters for hex code printing. -Extracted "0..9,A..F" characters for hex code printing. ## freetype - Upstream: https://www.freetype.org -- Version: 2.10.4 (2020) +- Version: 2.10.4 (6a2b3e4007e794bfc6c91030d0ed987f925164a8, 2020) - License: FreeType License (BSD-like) Files extracted from upstream source: @@ -162,45 +157,55 @@ Files extracted from upstream source: - `LICENSE.txt` - Unnecessary files like `CMakeLists.txt` and `updateGrammar` removed. -## Graphite engine + +## graphite - Upstream: https://github.com/silnrsi/graphite -- Version: 1.3.14 +- Version: 1.3.14 (92f59dcc52f73ce747f1cdc831579ed2546884aa, 2020) - License: MPL-2.0 Files extracted from upstream source: + - the `include` folder - the `src` folder - `COPYING`, `ChangeLog` -## HarfBuzz + +## harfbuzz - Upstream: https://github.com/harfbuzz/harfbuzz -- Version: 2.7.4 -- License: HarfBuzz +- Version: 2.8.0 (03538e872a0610a65fad692b33d3646f387cf578, 2021) +- License: MIT Files extracted from upstream source: + - the `src` folder - `AUTHORS`, `COPYING`, `NEWS`, `THANKS` -## International Components for Unicode + +## icu4c - Upstream: https://github.com/unicode-org/icu -- Version: 68.2 +- Version: 68.2 (84e1f26ea77152936e70d53178a816dbfbf69989, 2020) - License: Unicode Files extracted from upstream source: + - the `common` folder - `APIChangeReport.md`, `LICENSE` Files generated from upstream source: -- the `icudt68l.dat` built with the provided `godot_data.json` config file (see https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md for instructions) + +- the `icudt68l.dat` built with the provided `godot_data.json` config file (see + https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md + for instructions) + ## jpeg-compressor - Upstream: https://github.com/richgel999/jpeg-compressor - Version: 2.00 (aeb7d3b463aa8228b87a28013c15ee50a7e6fcf3, 2020) -- License: Public domain +- License: Public domain or MIT Files extracted from upstream source: @@ -223,7 +228,7 @@ Files extracted from upstream source: ## libpng - Upstream: http://libpng.org/pub/png/libpng.html -- Version: 1.6.37 (2019) +- Version: 1.6.37 (a40189cf881e9f0db80511c382292a5604c3c3d1, 2019) - License: libpng/zlib Files extracted from upstream source: @@ -303,7 +308,7 @@ from the Android NDK r18. ## libwebp - Upstream: https://chromium.googlesource.com/webm/libwebp/ -- Version: 1.1.0 (2020) +- Version: 1.1.0 (d7844e9762b61c9638c263657bd49e1690184832, 2020) - License: BSD-3-Clause Files extracted from upstream source: @@ -319,7 +324,7 @@ changes are marked with `// -- GODOT --` comments. ## mbedtls - Upstream: https://tls.mbed.org/ -- Version: 2.16.9 (2020) +- Version: 2.16.10 (d61fa61bef06b64132e3490543c81b8ee40fbee3, 2021) - License: Apache 2.0 File extracted from upstream release tarball: @@ -339,26 +344,34 @@ File extracted from upstream release tarball: ## meshoptimizer - Upstream: https://github.com/zeux/meshoptimizer -- Version: git (e4e43fe36e7a8705e602e7ca2f9fb795ded1d0b9, 2020) +- Version: git (e3f53f66e7a35b9b8764bee478589d79e34fa698, 2021) - License: MIT -- File extracted from upstream tarball: +Files extracted from upstream repository: + - All files in `src/`. +- `LICENSE.md`. + ## miniupnpc -- Upstream: https://github.com/miniupnp/miniupnp/tree/master/miniupnpc -- Version: git (44366328661826603982d1e0d7ebb4062c5f2bfc, 2020) +- Upstream: https://github.com/miniupnp/miniupnp +- Version: 2.2.2 (81029a860baf1f727903e5b85307903b3f40cbc8, 2021) - License: BSD-3-Clause Files extracted from upstream source: - All `*.c` and `*.h` files from `miniupnpc` to `thirdparty/miniupnpc/miniupnpc` -- Remove `test*`, `minihttptestserver.c` and `wingenminiupnpcstrings.c` +- Remove the following test or sample files: + `listdevices.c minihttptestserver.c miniupnpcmodule.c upnpc.c upnperrors.* test* wingenminiupnpcstrings.c` +- `LICENSE` -The patch `windows_fix.diff` is applied to `minissdpc.c` to fix an upstream issue. -The only modified file is miniupnpcstrings.h, which was created for Godot -(it is usually autogenerated by cmake). +The only modified file is `miniupnpcstrings.h`, which was created for Godot +(it is usually autogenerated by cmake). Bump the version number for miniupnpc in that +file when upgrading. + +Note: The following upstream patch has been applied, remove this notice on next update. +https://github.com/miniupnp/miniupnp/commit/3a08dd4b89af2e9effa22a136bac86f2f306fd79 ## minizip @@ -380,8 +393,6 @@ comments and a patch is provided in the minizip/ folder. Collection of single-file libraries used in Godot components. -### core - - `clipper.{cpp,hpp}` * Upstream: https://sourceforge.net/projects/polyclipping * Version: 6.4.2 (2017) + Godot changes (added optional exceptions handling) @@ -390,6 +401,10 @@ Collection of single-file libraries used in Godot components. * Upstream: https://research.activision.com/publications/archives/fast-filtering-of-reflection-probes File coeffs_const_8.txt (retrieved April 2020) * License: MIT +- `easing_equations.cpp` + * Upstream: http://robertpenner.com/easing/ via https://github.com/jesusgollonet/ofpennereasing (modified to fit Godot types) + * Version: git (af72c147c3a74e7e872aa28c7e2abfcced04fdce, 2008) + Godot types and style changes + * License: BSD-3-Clause - `fastlz.{c,h}` * Upstream: https://github.com/ariya/FastLZ * Version: 0.5.0 (4f20f54d46f5a6dd4fae4def134933369b7602d2, 2020) @@ -398,61 +413,49 @@ Collection of single-file libraries used in Godot components. * Upstream: https://github.com/brunexgeek/hqx * Version: TBD, file structure differs * License: Apache 2.0 +- `ifaddrs-android.{cc,h}` + * Upstream: https://chromium.googlesource.com/external/webrtc/stable/talk/+/master/base/ifaddrs-android.h + * Version: git (5976650443d68ccfadf1dea24999ee459dd2819d, 2013) + * License: BSD-3-Clause +- `mikktspace.{c,h}` + * Upstream: https://archive.blender.org/wiki/index.php/Dev:Shading/Tangent_Space_Normal_Maps/ + * Version: 1.0 (2011) + * License: zlib - `open-simplex-noise.{c,h}` * Upstream: https://github.com/smcameron/open-simplex-noise-in-c * Version: git (826f1dd1724e6fb3ff45f58e48c0fbae864c3403, 2020) + custom changes - * License: Unlicense + * License: Public Domain or Unlicense - `pcg.{cpp,h}` * Upstream: http://www.pcg-random.org * Version: minimal C implementation, http://www.pcg-random.org/download.html * License: Apache 2.0 +- `polypartition.{cpp,h}` + * Upstream: https://github.com/ivanfratric/polypartition (`src/polypartition.{cpp,h}`) + * Version: git (7bdffb428b2b19ad1c43aa44c714dcc104177e84, 2021) + * Modifications: Change from STL to Godot types (see provided patch). + * License: MIT - `r128.h` * Upstream: https://github.com/fahickman/r128 - * Version: git (423f693617faafd01de21e92818add4208eb8bd1, 2020) - * License: Public Domain + * Version: 1.4.4 (cf2e88fc3e7d7dfe99189686f914874cd0bda15e, 2020) + * License: Public Domain or Unlicense - `smaz.{c,h}` * Upstream: https://github.com/antirez/smaz - * Version: git (150e125cbae2e8fd20dd332432776ce13395d4d4, 2009) + * Version: git (2f625846a775501fb69456567409a8b12f10ea25, 2012) * License: BSD-3-Clause * Modifications: use `const char*` instead of `char*` for input string - `stb_rect_pack.h` * Upstream: https://github.com/nothings/stb - * Version: 1.00 (2019) - * License: Public Domain (Unlicense) or MIT -- `triangulator.{cpp,h}` - * Upstream: https://github.com/ivanfratric/polypartition (`src/polypartition.cpp`) - * Version: TBD, class was renamed - * License: MIT - -### modules - + * Version: 1.00 (2bb4a0accd4003c1db4c24533981e01b1adfd656, 2019) + * License: Public Domain or Unlicense or MIT +- `stb_vorbis.c` + * Upstream: https://github.com/nothings/stb + * Version: 1.20 (314d0a6f9af5af27e585336eecea333e95c5a2d8, 2020) + * License: Public Domain or Unlicense or MIT - `yuv2rgb.h` * Upstream: http://wss.co.uk/pinknoise/yuv2rgb/ (to check) * Version: ? * License: BSD -### platform - -- `ifaddrs-android.{cc,h}` - * Upstream: https://chromium.googlesource.com/external/webrtc/stable/talk/+/master/base/ifaddrs-android.h - * Version: git (5976650443d68ccfadf1dea24999ee459dd2819d, 2013) - * License: BSD-3-Clause - -### scene - -- `easing_equations.cpp` - * Upstream: http://robertpenner.com/easing/ via https://github.com/jesusgollonet/ofpennereasing (modified to fit Godot types) - * Version: git (af72c147c3a74e7e872aa28c7e2abfcced04fdce, 2008) + Godot types and style changes - * License: BSD-3-Clause -- `mikktspace.{c,h}` - * Upstream: https://archive.blender.org/wiki/index.php/Dev:Shading/Tangent_Space_Normal_Maps/ - * Version: 1.0 (2011) - * License: zlib -- `stb_vorbis.c` - * Upstream: https://github.com/nothings/stb - * Version: 1.20 - * License: Public Domain (Unlicense) or MIT - ## nanosvg @@ -474,27 +477,27 @@ Files extracted from the upstream source: Files extracted from upstream source: -common/* (except tasking.* and CMakeLists.txt) -core/* -include/OpenImageDenoise/* (except version.h.in) -LICENSE.txt -mkl-dnn/include/* -mkl-dnn/src/* (except CMakeLists.txt) -weights/rtlightmap_hdr.tza -scripts/resource_to_cpp.py +- common/* (except tasking.* and CMakeLists.txt) +- core/* +- include/OpenImageDenoise/* (except version.h.in) +- LICENSE.txt +- mkl-dnn/include/* +- mkl-dnn/src/* (except CMakeLists.txt) +- weights/rtlightmap_hdr.tza +- scripts/resource_to_cpp.py Modified files: Modifications are marked with `// -- GODOT start --` and `// -- GODOT end --`. Patch files are provided in `oidn/patches/`. -core/autoencoder.cpp -core/autoencoder.h -core/common.h -core/device.cpp -core/device.h -core/transfer_function.cpp +- core/autoencoder.cpp +- core/autoencoder.h +- core/common.h +- core/device.cpp +- core/device.h +- core/transfer_function.cpp -scripts/resource_to_cpp.py (used in modules/denoise/resource_to_cpp.py) +- scripts/resource_to_cpp.py (used in modules/denoise/resource_to_cpp.py) ## opus @@ -517,7 +520,7 @@ Files extracted from upstream source: ## pcre2 - Upstream: http://www.pcre.org -- Version: 10.34 (2019) +- Version: 10.36 (r1288, 2020) - License: BSD-3-Clause Files extracted from upstream source: @@ -526,13 +529,14 @@ Files extracted from upstream source: - All .h files in src/ apart from pcre2posix.h - src/pcre2_jit_match.c - src/pcre2_jit_misc.c -- src/sljit/* +- src/sljit/ - AUTHORS and LICENCE ## pvrtccompressor -- Upstream: https://bitbucket.org/jthlim/pvrtccompressor +- Upstream: https://bitbucket.org/jthlim/pvrtccompressor (dead link) + Unofficial backup fork: https://github.com/LibreGamesArchive/PVRTCCompressor - Version: hg (cf7177748ee0dcdccfe89716dc11a47d2dc81af5, 2015) - License: BSD-3-Clause @@ -556,8 +560,8 @@ Files extracted from upstream source: ## rvo2 -- Upstream: http://gamma.cs.unc.edu/RVO2/ -- Version: 3D - 1.0.1 (2016) +- Upstream: https://github.com/snape/RVO2-3D +- Version: 1.0.1 (e3883f288a9e55ecfed3633a01af3e12778c6acf, 2016) - License: Apache 2.0 Files extracted from upstream source: @@ -570,10 +574,23 @@ originally proposed by this library and better integrate this library with Godot. Please check the file to know what's new. +## spirv-reflect + +- Upstream: https://github.com/KhronosGroup/SPIRV-Reflect +- Version: git (c0ce03a43ca77fedb5abfd1976ae2fd0eeb0e611, 2021) +- License: Apache 2.0 + +Files extracted from upstream source: + +- `spirv_reflect.{c,h}` +- `include` folder +- `LICENSE` + + ## squish - Upstream: https://sourceforge.net/projects/libsquish -- Version: 1.15 (2017) +- Version: 1.15 (r104, 2017) - License: MIT Files extracted from upstream source: @@ -616,7 +633,7 @@ folder. ## vulkan - Upstream: https://github.com/KhronosGroup/Vulkan-Loader -- Version: sdk-1.2.162.0 (2020) +- Version: sdk-1.2.162.0 (7a313093b5c4af964d50a5a64e73d7df6152ea3f, 2020) - License: Apache 2.0 Unless there is a specific reason to package a more recent version, please stick @@ -645,7 +662,7 @@ Patches in the `patches` directory should be re-applied after updates. ## wslay - Upstream: https://github.com/tatsuhiro-t/wslay -- Version: 1.1.1 (2020) +- Version: 1.1.1 (c9a84aa6df8512584c77c8cd15be9536b89c35aa, 2020) - License: MIT File extracted from upstream release tarball: @@ -681,7 +698,7 @@ Files extracted from upstream source: ## zstd - Upstream: https://github.com/facebook/zstd -- Version: 1.4.5 (2020) +- Version: 1.4.8 (97a3da1df009d4dc67251de0c4b1c9d7fe286fc1, 2020) - License: BSD-3-Clause Files extracted from upstream source: diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp index cac5302a73..cac5302a73 100755..100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h index 75ca34e978..75ca34e978 100755..100644 --- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h +++ b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h diff --git a/thirdparty/doctest/doctest.h b/thirdparty/doctest/doctest.h index acbe6cd321..7712dd6b63 100644 --- a/thirdparty/doctest/doctest.h +++ b/thirdparty/doctest/doctest.h @@ -48,8 +48,8 @@ #define DOCTEST_VERSION_MAJOR 2 #define DOCTEST_VERSION_MINOR 4 -#define DOCTEST_VERSION_PATCH 1 -#define DOCTEST_VERSION_STR "2.4.1" +#define DOCTEST_VERSION_PATCH 4 +#define DOCTEST_VERSION_STR "2.4.4" #define DOCTEST_VERSION \ (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) @@ -368,7 +368,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum' #define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP) #endif #elif defined(DOCTEST_PLATFORM_MAC) -#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) +#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386) #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) #else #define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); @@ -747,6 +747,7 @@ struct ContextOptions //!OCLINT too many fields bool gnu_file_line; // if line numbers should be surrounded with :x: and not (x): bool no_path_in_filenames; // if the path to files should be removed from the output bool no_line_numbers; // if source code line numbers should be omitted from the output + bool no_debug_output; // no output in the debug console when a debugger is attached bool no_skipped_summary; // don't print "skipped" in the summary !!! UNDOCUMENTED !!! bool no_time_in_output; // omit any time/timestamps from output !!! UNDOCUMENTED !!! @@ -806,7 +807,7 @@ namespace detail { } // namespace has_insertion_operator_impl template<class T> - using has_insertion_operator = has_insertion_operator_impl::check<T>; + using has_insertion_operator = has_insertion_operator_impl::check<const T>; DOCTEST_INTERFACE void my_memcpy(void* dest, const void* src, unsigned num); @@ -1035,6 +1036,7 @@ namespace detail { template <typename L, typename R> String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op, const DOCTEST_REF_WRAP(R) rhs) { + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) return toString(lhs) + op + toString(rhs); } @@ -1122,6 +1124,7 @@ namespace detail { #define DOCTEST_COMPARISON_RETURN_TYPE bool #else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING #define DOCTEST_COMPARISON_RETURN_TYPE typename enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); } inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); } inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); } @@ -1541,12 +1544,24 @@ namespace detail { MessageBuilder() = delete; ~MessageBuilder(); + // the preferred way of chaining parameters for stringification template <typename T> - MessageBuilder& operator<<(const T& in) { + MessageBuilder& operator,(const T& in) { toStream(m_stream, in); return *this; } + // kept here just for backwards-compatibility - the comma operator should be preferred now + template <typename T> + MessageBuilder& operator<<(const T& in) { return this->operator,(in); } + + // the `,` operator has the lowest operator precedence - if `<<` is used by the user then + // the `,` operator will be called last which is not what we want and thus the `*` operator + // is used first (has higher operator precedence compared to `<<`) so that we guarantee that + // an operator of the MessageBuilder class is called first before the rest of the parameters + template <typename T> + MessageBuilder& operator*(const T& in) { return this->operator,(in); } + bool log(); void react(); }; @@ -1962,38 +1977,38 @@ int registerReporter(const char* name, int priority, bool isReporter) { DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) // for logging -#define DOCTEST_INFO(expression) \ +#define DOCTEST_INFO(...) \ DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), \ - DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), expression) + DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), __VA_ARGS__) -#define DOCTEST_INFO_IMPL(lambda_name, mb_name, s_name, expression) \ +#define DOCTEST_INFO_IMPL(lambda_name, mb_name, s_name, ...) \ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4626) \ auto lambda_name = [&](std::ostream* s_name) { \ doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \ mb_name.m_stream = s_name; \ - mb_name << expression; \ + mb_name * __VA_ARGS__; \ }; \ DOCTEST_MSVC_SUPPRESS_WARNING_POP \ auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope(lambda_name) -#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := " << x) +#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x) -#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, x) \ +#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \ do { \ doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \ - mb << x; \ + mb * __VA_ARGS__; \ DOCTEST_ASSERT_LOG_AND_REACT(mb); \ } while(false) // clang-format off -#define DOCTEST_ADD_MESSAGE_AT(file, line, x) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), x) -#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, x) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), x) -#define DOCTEST_ADD_FAIL_AT(file, line, x) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), x) +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), __VA_ARGS__) +#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), __VA_ARGS__) +#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), __VA_ARGS__) // clang-format on -#define DOCTEST_MESSAGE(x) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, x) -#define DOCTEST_FAIL_CHECK(x) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, x) -#define DOCTEST_FAIL(x) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, x) +#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL_CHECK(...) DOCTEST_ADD_FAIL_CHECK_AT(__FILE__, __LINE__, __VA_ARGS__) +#define DOCTEST_FAIL(...) DOCTEST_ADD_FAIL_AT(__FILE__, __LINE__, __VA_ARGS__) #define DOCTEST_TO_LVALUE(...) __VA_ARGS__ // Not removed to keep backwards compatibility. @@ -2036,12 +2051,12 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__) // clang-format off -#define DOCTEST_WARN_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } while(false) -#define DOCTEST_CHECK_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } while(false) -#define DOCTEST_REQUIRE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } while(false) -#define DOCTEST_WARN_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } while(false) -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } while(false) -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) do { DOCTEST_INFO(msg); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } while(false) +#define DOCTEST_WARN_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } while(false) +#define DOCTEST_CHECK_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } while(false) +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } while(false) +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } while(false) +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } while(false) +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } while(false) // clang-format on #define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \ @@ -2051,8 +2066,8 @@ int registerReporter(const char* name, int priority, bool isReporter) { __LINE__, #expr, #__VA_ARGS__, message); \ try { \ DOCTEST_CAST_TO_VOID(expr) \ - } catch(const doctest::detail::remove_const< \ - doctest::detail::remove_reference<__VA_ARGS__>::type>::type&) { \ + } catch(const typename doctest::detail::remove_const< \ + typename doctest::detail::remove_reference<__VA_ARGS__>::type>::type&) { \ _DOCTEST_RB.translateException(); \ _DOCTEST_RB.m_threw_as = true; \ } catch(...) { _DOCTEST_RB.translateException(); } \ @@ -2103,21 +2118,21 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__) #define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__) -#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS(expr); } while(false) -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS(expr); } while(false) -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS(expr); } while(false) -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_AS(expr, ex); } while(false) -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_AS(expr, ex); } while(false) -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } while(false) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH(expr, with); } while(false) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH(expr, with); } while(false) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } while(false) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } while(false) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } while(false) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } while(false) -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_WARN_NOTHROW(expr); } while(false) -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_CHECK_NOTHROW(expr); } while(false) -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) do { DOCTEST_INFO(msg); DOCTEST_REQUIRE_NOTHROW(expr); } while(false) +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } while(false) +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } while(false) +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } while(false) +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } while(false) +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } while(false) +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } while(false) +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } while(false) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } while(false) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } while(false) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } while(false) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } while(false) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } while(false) +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } while(false) +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } while(false) +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } while(false) // clang-format on #ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS @@ -2230,21 +2245,21 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_CHECK_NOTHROW(...) (static_cast<void>(0)) #define DOCTEST_REQUIRE_NOTHROW(...) (static_cast<void>(0)) -#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) (static_cast<void>(0)) -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast<void>(0)) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast<void>(0)) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast<void>(0)) -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) (static_cast<void>(0)) +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) (static_cast<void>(0)) +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0)) +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0)) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0)) +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0)) #else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS @@ -2335,14 +2350,14 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_REGISTER_REPORTER(name, priority, reporter) #define DOCTEST_REGISTER_LISTENER(name, priority, reporter) -#define DOCTEST_INFO(x) (static_cast<void>(0)) +#define DOCTEST_INFO(...) (static_cast<void>(0)) #define DOCTEST_CAPTURE(x) (static_cast<void>(0)) -#define DOCTEST_ADD_MESSAGE_AT(file, line, x) (static_cast<void>(0)) -#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, x) (static_cast<void>(0)) -#define DOCTEST_ADD_FAIL_AT(file, line, x) (static_cast<void>(0)) -#define DOCTEST_MESSAGE(x) (static_cast<void>(0)) -#define DOCTEST_FAIL_CHECK(x) (static_cast<void>(0)) -#define DOCTEST_FAIL(x) (static_cast<void>(0)) +#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) (static_cast<void>(0)) +#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) (static_cast<void>(0)) +#define DOCTEST_ADD_FAIL_AT(file, line, ...) (static_cast<void>(0)) +#define DOCTEST_MESSAGE(...) (static_cast<void>(0)) +#define DOCTEST_FAIL_CHECK(...) (static_cast<void>(0)) +#define DOCTEST_FAIL(...) (static_cast<void>(0)) #define DOCTEST_WARN(...) (static_cast<void>(0)) #define DOCTEST_CHECK(...) (static_cast<void>(0)) @@ -2351,12 +2366,12 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_CHECK_FALSE(...) (static_cast<void>(0)) #define DOCTEST_REQUIRE_FALSE(...) (static_cast<void>(0)) -#define DOCTEST_WARN_MESSAGE(cond, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_MESSAGE(cond, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_MESSAGE(cond, msg) (static_cast<void>(0)) -#define DOCTEST_WARN_FALSE_MESSAGE(cond, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_FALSE_MESSAGE(cond, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, msg) (static_cast<void>(0)) +#define DOCTEST_WARN_MESSAGE(cond, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_MESSAGE(cond, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_MESSAGE(cond, ...) (static_cast<void>(0)) +#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) (static_cast<void>(0)) #define DOCTEST_WARN_THROWS(...) (static_cast<void>(0)) #define DOCTEST_CHECK_THROWS(...) (static_cast<void>(0)) @@ -2374,21 +2389,21 @@ int registerReporter(const char* name, int priority, bool isReporter) { #define DOCTEST_CHECK_NOTHROW(...) (static_cast<void>(0)) #define DOCTEST_REQUIRE_NOTHROW(...) (static_cast<void>(0)) -#define DOCTEST_WARN_THROWS_MESSAGE(expr, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_THROWS_MESSAGE(expr, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, msg) (static_cast<void>(0)) -#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, msg) (static_cast<void>(0)) -#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, msg) (static_cast<void>(0)) -#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, msg) (static_cast<void>(0)) -#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, msg) (static_cast<void>(0)) -#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, msg) (static_cast<void>(0)) -#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, msg) (static_cast<void>(0)) +#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) (static_cast<void>(0)) +#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0)) +#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0)) +#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0)) +#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0)) +#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0)) +#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0)) #define DOCTEST_WARN_EQ(...) (static_cast<void>(0)) #define DOCTEST_CHECK_EQ(...) (static_cast<void>(0)) @@ -2754,9 +2769,7 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN #include <map> #include <exception> #include <stdexcept> -#ifdef DOCTEST_CONFIG_POSIX_SIGNALS #include <csignal> -#endif // DOCTEST_CONFIG_POSIX_SIGNALS #include <cfloat> #include <cctype> #include <cstdint> @@ -3071,6 +3084,7 @@ String::String() { String::~String() { if(!isOnStack()) delete[] data.ptr; + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) } String::String(const char* in) @@ -3112,6 +3126,7 @@ String& String::operator+=(const String& other) { if(total_size < len) { // append to the current stack space memcpy(buf + my_old_size, other.c_str(), other_size + 1); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) setLast(last - total_size); } else { // alloc new chunk @@ -3153,6 +3168,7 @@ String& String::operator+=(const String& other) { return *this; } +// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) String String::operator+(const String& other) const { return String(*this) += other; } String::String(String&& other) { @@ -3307,6 +3323,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wnull-dereference") // depending on the current options this will remove the path of filenames const char* skipPathFromFilename(const char* file) { +#ifndef DOCTEST_CONFIG_DISABLE if(getContextOptions()->no_path_in_filenames) { auto back = std::strrchr(file, '\\'); auto forward = std::strrchr(file, '/'); @@ -3316,6 +3333,7 @@ const char* skipPathFromFilename(const char* file) { return forward + 1; } } +#endif // DOCTEST_CONFIG_DISABLE return file; } DOCTEST_CLANG_SUPPRESS_WARNING_POP @@ -3334,6 +3352,7 @@ IContextScope::~IContextScope() = default; #ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING String toString(char* in) { return toString(static_cast<const char*>(in)); } +// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; } #endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING String toString(bool in) { return in ? "true" : "false"; } @@ -3406,6 +3425,7 @@ bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; } String toString(const Approx& in) { + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) return String("Approx( ") + doctest::toString(in.m_value) + " )"; } const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); } @@ -3698,11 +3718,15 @@ namespace detail { } bool TestCase::operator<(const TestCase& other) const { + // this will be used only to differentiate between test cases - not relevant for sorting if(m_line != other.m_line) return m_line < other.m_line; const int file_cmp = m_file.compare(other.m_file); if(file_cmp != 0) return file_cmp < 0; + const int name_cmp = strcmp(m_name, other.m_name); + if(name_cmp != 0) + return name_cmp < 0; return m_template_id < other.m_template_id; } } // namespace detail @@ -4009,24 +4033,40 @@ namespace { // Windows can easily distinguish between SO and SigSegV, // but SigInt, SigTerm, etc are handled differently. SignalDefs signalDefs[] = { - {EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal"}, - {EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow"}, - {EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal"}, - {EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error"}, + {static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION), + "SIGILL - Illegal instruction signal"}, + {static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"}, + {static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), + "SIGSEGV - Segmentation violation signal"}, + {static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"}, }; struct FatalConditionHandler { static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) { - for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { - if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { - reportFatal(signalDefs[i].name); - break; + // Multiple threads may enter this filter/handler at once. We want the error message to be printed on the + // console just once no matter how many threads have crashed. + static std::mutex mutex; + static bool execute = true; + { + std::lock_guard<std::mutex> lock(mutex); + if(execute) { + bool reported = false; + for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) { + if(ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { + reportFatal(signalDefs[i].name); + reported = true; + break; + } + } + if(reported == false) + reportFatal("Unhandled SEH exception caught"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); } + execute = false; } - // If its not an exception we care about, pass it along. - // This stops us from eating debugger breaks etc. - return EXCEPTION_CONTINUE_SEARCH; + std::exit(EXIT_FAILURE); } FatalConditionHandler() { @@ -4038,6 +4078,51 @@ namespace { previousTop = SetUnhandledExceptionFilter(handleException); // Pass in guarantee size to be filled SetThreadStackGuarantee(&guaranteeSize); + + // On Windows uncaught exceptions from another thread, exceptions from + // destructors, or calls to std::terminate are not a SEH exception + + // The terminal handler gets called when: + // - std::terminate is called FROM THE TEST RUNNER THREAD + // - an exception is thrown from a destructor FROM THE TEST RUNNER THREAD + original_terminate_handler = std::get_terminate(); + std::set_terminate([]() noexcept { + reportFatal("Terminate handler called"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); // explicitly exit - otherwise the SIGABRT handler may be called as well + }); + + // SIGABRT is raised when: + // - std::terminate is called FROM A DIFFERENT THREAD + // - an exception is thrown from a destructor FROM A DIFFERENT THREAD + // - an uncaught exception is thrown FROM A DIFFERENT THREAD + prev_sigabrt_handler = std::signal(SIGABRT, [](int signal) noexcept { + if(signal == SIGABRT) { + reportFatal("SIGABRT - Abort (abnormal termination) signal"); + if(isDebuggerActive() && !g_cs->no_breaks) + DOCTEST_BREAK_INTO_DEBUGGER(); + std::exit(EXIT_FAILURE); + } + }); + + // The following settings are taken from google test, and more + // specifically from UnitTest::Run() inside of gtest.cc + + // the user does not want to see pop-up dialogs about crashes + prev_error_mode_1 = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | + SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + // This forces the abort message to go to stderr in all circumstances. + prev_error_mode_2 = _set_error_mode(_OUT_TO_STDERR); + // In the debug version, Visual Studio pops up a separate dialog + // offering a choice to debug the aborted program - we want to disable that. + prev_abort_behavior = _set_abort_behavior(0x0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + // In debug mode, the Windows CRT can crash with an assertion over invalid + // input (e.g. passing an invalid file descriptor). The default handling + // for these assertions is to pop up a dialog and wait for user input. + // Instead ask the CRT to dump such assertions to stderr non-interactively. + prev_report_mode = _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + prev_report_file = _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); } static void reset() { @@ -4045,7 +4130,13 @@ namespace { // Unregister handler and restore the old guarantee SetUnhandledExceptionFilter(previousTop); SetThreadStackGuarantee(&guaranteeSize); - previousTop = nullptr; + std::set_terminate(original_terminate_handler); + std::signal(SIGABRT, prev_sigabrt_handler); + SetErrorMode(prev_error_mode_1); + _set_error_mode(prev_error_mode_2); + _set_abort_behavior(prev_abort_behavior, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); + _CrtSetReportMode(_CRT_ASSERT, prev_report_mode); + _CrtSetReportFile(_CRT_ASSERT, prev_report_file); isSet = false; } } @@ -4053,11 +4144,25 @@ namespace { ~FatalConditionHandler() { reset(); } private: + static UINT prev_error_mode_1; + static int prev_error_mode_2; + static unsigned int prev_abort_behavior; + static int prev_report_mode; + static _HFILE prev_report_file; + static void (*prev_sigabrt_handler)(int); + static std::terminate_handler original_terminate_handler; static bool isSet; static ULONG guaranteeSize; static LPTOP_LEVEL_EXCEPTION_FILTER previousTop; }; + UINT FatalConditionHandler::prev_error_mode_1; + int FatalConditionHandler::prev_error_mode_2; + unsigned int FatalConditionHandler::prev_abort_behavior; + int FatalConditionHandler::prev_report_mode; + _HFILE FatalConditionHandler::prev_report_file; + void (*FatalConditionHandler::prev_sigabrt_handler)(int); + std::terminate_handler FatalConditionHandler::original_terminate_handler; bool FatalConditionHandler::isSet = false; ULONG FatalConditionHandler::guaranteeSize = 0; LPTOP_LEVEL_EXCEPTION_FILTER FatalConditionHandler::previousTop = nullptr; @@ -4257,6 +4362,7 @@ namespace detail { // ################################################################################### DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp); DOCTEST_ASSERT_IN_TESTS(result.m_decomp); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) } MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) { @@ -4979,7 +5085,6 @@ namespace { } // TODO: - // - log_contexts() // - log_message() // - respond to queries // - honor remaining options @@ -4993,7 +5098,6 @@ namespace { struct JUnitTestCaseData { -DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") // gmtime static std::string getCurrentTimestamp() { // Beware, this is not reentrant because of backward compatibility issues // Also, UTC only, again because of backward compatibility (%z is C++11) @@ -5001,16 +5105,19 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations") // gmtime std::time(&rawtime); auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); - std::tm* timeInfo; - timeInfo = std::gmtime(&rawtime); + std::tm timeInfo; +#ifdef DOCTEST_PLATFORM_WINDOWS + gmtime_s(&timeInfo, &rawtime); +#else // DOCTEST_PLATFORM_WINDOWS + gmtime_r(&rawtime, &timeInfo); +#endif // DOCTEST_PLATFORM_WINDOWS char timeStamp[timeStampSize]; const char* const fmt = "%Y-%m-%dT%H:%M:%SZ"; - std::strftime(timeStamp, timeStampSize, fmt, timeInfo); + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); return std::string(timeStamp); } -DOCTEST_CLANG_SUPPRESS_WARNING_POP struct JUnitTestMessage { @@ -5175,12 +5282,27 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP << line(rb.m_line) << (opt.gnu_file_line ? ":" : "):") << std::endl; fulltext_log_assert_to_stream(os, rb); + log_contexts(os); testCaseData.addFailure(rb.m_decomp.c_str(), assertString(rb.m_at), os.str()); } void log_message(const MessageData&) override {} void test_case_skipped(const TestCaseData&) override {} + + void log_contexts(std::ostringstream& s) { + int num_contexts = get_num_active_contexts(); + if(num_contexts) { + auto contexts = get_active_contexts(); + + s << " logged: "; + for(int i = 0; i < num_contexts; ++i) { + s << (i == 0 ? "" : " "); + contexts[i]->stringify(&s); + s << std::endl; + } + } + } }; DOCTEST_REGISTER_REPORTER("junit", 0, JUnitReporter); @@ -5894,6 +6016,7 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { DOCTEST_PARSE_AS_BOOL_OR_FLAG("gnu-file-line", "gfl", gnu_file_line, !bool(DOCTEST_MSVC)); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-path-filenames", "npf", no_path_in_filenames, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-line-numbers", "nln", no_line_numbers, false); + DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-debug-output", "ndo", no_debug_output, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-skipped-summary", "nss", no_skipped_summary, false); DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-time-in-output", "ntio", no_time_in_output, false); // clang-format on @@ -5951,6 +6074,7 @@ void Context::clearFilters() { // allows the user to override procedurally the int/bool options from the command line void Context::setOption(const char* option, int value) { setOption(option, toString(value).c_str()); + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) } // allows the user to override procedurally the string options from the command line @@ -6026,7 +6150,7 @@ int Context::run() { p->reporters_currently_used.insert(p->reporters_currently_used.begin(), curr.second(*g_cs)); #ifdef DOCTEST_PLATFORM_WINDOWS - if(isDebuggerActive()) + if(isDebuggerActive() && p->no_debug_output == false) p->reporters_currently_used.push_back(new DebugOutputWindowReporter(*g_cs)); #endif // DOCTEST_PLATFORM_WINDOWS diff --git a/thirdparty/enet/enet/enet.h b/thirdparty/enet/enet/enet.h index 24d36647d9..77f8004b80 100644 --- a/thirdparty/enet/enet/enet.h +++ b/thirdparty/enet/enet/enet.h @@ -31,7 +31,7 @@ extern "C" #define ENET_VERSION_MAJOR 1 #define ENET_VERSION_MINOR 3 -#define ENET_VERSION_PATCH 15 +#define ENET_VERSION_PATCH 17 #define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch)) #define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF) #define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF) @@ -323,12 +323,10 @@ typedef struct _ENetPeer ENetList acknowledgements; ENetList sentReliableCommands; ENetList sentUnreliableCommands; - ENetList outgoingReliableCommands; - ENetList outgoingUnreliableCommands; + ENetList outgoingCommands; ENetList dispatchedCommands; enet_uint16 flags; - enet_uint8 roundTripTimeRemainder; - enet_uint8 roundTripTimeVarianceRemainder; + enet_uint16 reserved; enet_uint16 incomingUnsequencedGroup; enet_uint16 outgoingUnsequencedGroup; enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32]; @@ -604,8 +602,8 @@ extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetO extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16); extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32); extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16); -extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *); -extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *); +extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *); +extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *); extern void enet_peer_on_connect (ENetPeer *); extern void enet_peer_on_disconnect (ENetPeer *); diff --git a/thirdparty/enet/host.c b/thirdparty/enet/host.c index fc4da4ca67..21ab27e247 100644 --- a/thirdparty/enet/host.c +++ b/thirdparty/enet/host.c @@ -124,8 +124,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL enet_list_clear (& currentPeer -> acknowledgements); enet_list_clear (& currentPeer -> sentReliableCommands); enet_list_clear (& currentPeer -> sentUnreliableCommands); - enet_list_clear (& currentPeer -> outgoingReliableCommands); - enet_list_clear (& currentPeer -> outgoingUnreliableCommands); + enet_list_clear (& currentPeer -> outgoingCommands); enet_list_clear (& currentPeer -> dispatchedCommands); enet_peer_reset (currentPeer); diff --git a/thirdparty/enet/patches/godot.patch b/thirdparty/enet/patches/godot_socket.patch index c8b4a5225d..364b3536be 100644 --- a/thirdparty/enet/patches/godot.patch +++ b/thirdparty/enet/patches/godot_socket.patch @@ -1,5 +1,5 @@ diff --git a/thirdparty/enet/enet/enet.h b/thirdparty/enet/enet/enet.h -index 54d91b5603..24d36647d9 100644 +index fc45cbd0c9..77f8004b80 100644 --- a/thirdparty/enet/enet/enet.h +++ b/thirdparty/enet/enet/enet.h @@ -10,13 +10,19 @@ extern "C" @@ -38,7 +38,7 @@ index 54d91b5603..24d36647d9 100644 /** * Packet flag bit constants. -@@ -606,6 +616,10 @@ ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, +@@ -604,6 +614,10 @@ ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, extern size_t enet_protocol_command_size (enet_uint8); @@ -50,7 +50,7 @@ index 54d91b5603..24d36647d9 100644 } #endif diff --git a/thirdparty/enet/host.c b/thirdparty/enet/host.c -index 3be6c0922c..fc4da4ca67 100644 +index 3b2180f7fd..21ab27e247 100644 --- a/thirdparty/enet/host.c +++ b/thirdparty/enet/host.c @@ -87,7 +87,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL @@ -63,10 +63,10 @@ index 3be6c0922c..fc4da4ca67 100644 host -> receivedData = NULL; host -> receivedDataLength = 0; diff --git a/thirdparty/enet/protocol.c b/thirdparty/enet/protocol.c -index 0a60253173..fefc0e6f0a 100644 +index 9d654f1d96..d7fe80f117 100644 --- a/thirdparty/enet/protocol.c +++ b/thirdparty/enet/protocol.c -@@ -307,7 +307,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet +@@ -309,7 +309,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet } else if (currentPeer -> state != ENET_PEER_STATE_CONNECTING && @@ -75,7 +75,7 @@ index 0a60253173..fefc0e6f0a 100644 { if (currentPeer -> address.port == host -> receivedAddress.port && currentPeer -> connectID == command -> connect.connectID) -@@ -1027,9 +1027,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) +@@ -1031,9 +1031,8 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) if (peer -> state == ENET_PEER_STATE_DISCONNECTED || peer -> state == ENET_PEER_STATE_ZOMBIE || @@ -87,7 +87,7 @@ index 0a60253173..fefc0e6f0a 100644 (peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID && sessionID != peer -> incomingSessionID)) return 0; -@@ -1071,7 +1070,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) +@@ -1075,7 +1074,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event) if (peer != NULL) { diff --git a/thirdparty/enet/peer.c b/thirdparty/enet/peer.c index 1278b85a80..9370ef4be1 100644 --- a/thirdparty/enet/peer.c +++ b/thirdparty/enet/peer.c @@ -76,7 +76,7 @@ enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt) return 1; } else - if (rtt >= peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance) + if (rtt > peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance) { if (peer -> packetThrottle > peer -> packetThrottleDeceleration) peer -> packetThrottle -= peer -> packetThrottleDeceleration; @@ -268,7 +268,7 @@ enet_peer_reset_outgoing_commands (ENetList * queue) } static void -enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand) +enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand, ENetIncomingCommand * excludeCommand) { ENetListIterator currentCommand; @@ -278,6 +278,9 @@ enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startComm currentCommand = enet_list_next (currentCommand); + if (incomingCommand == excludeCommand) + continue; + enet_list_remove (& incomingCommand -> incomingCommandList); if (incomingCommand -> packet != NULL) @@ -298,7 +301,7 @@ enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startComm static void enet_peer_reset_incoming_commands (ENetList * queue) { - enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue)); + enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue), NULL); } void @@ -318,8 +321,7 @@ enet_peer_reset_queues (ENetPeer * peer) enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands); enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands); - enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands); - enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands); + enet_peer_reset_outgoing_commands (& peer -> outgoingCommands); enet_peer_reset_incoming_commands (& peer -> dispatchedCommands); if (peer -> channels != NULL && peer -> channelCount > 0) @@ -419,8 +421,6 @@ enet_peer_reset (ENetPeer * peer) peer -> eventData = 0; peer -> totalWaitingData = 0; peer -> flags = 0; - peer -> roundTripTimeRemainder = 0; - peer -> roundTripTimeVarianceRemainder = 0; memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow)); @@ -573,8 +573,7 @@ void enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data) { if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) && - ! (enet_list_empty (& peer -> outgoingReliableCommands) && - enet_list_empty (& peer -> outgoingUnreliableCommands) && + ! (enet_list_empty (& peer -> outgoingCommands) && enet_list_empty (& peer -> sentReliableCommands))) { peer -> state = ENET_PEER_STATE_DISCONNECT_LATER; @@ -676,10 +675,7 @@ enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoin break; } - if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) - enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand); - else - enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand); + enet_list_insert (enet_list_end (& peer -> outgoingCommands), outgoingCommand); } ENetOutgoingCommand * @@ -702,7 +698,7 @@ enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, } void -enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel) +enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand) { ENetListIterator droppedCommand, startCommand, currentCommand; @@ -781,11 +777,11 @@ enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * droppedCommand = currentCommand; } - enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand); + enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand, queuedCommand); } void -enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel) +enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand) { ENetListIterator currentCommand; @@ -820,7 +816,7 @@ enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * ch } if (! enet_list_empty (& channel -> incomingUnreliableCommands)) - enet_peer_dispatch_incoming_unreliable_commands (peer, channel); + enet_peer_dispatch_incoming_unreliable_commands (peer, channel, queuedCommand); } ENetIncomingCommand * @@ -978,11 +974,11 @@ enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, { case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: - enet_peer_dispatch_incoming_reliable_commands (peer, channel); + enet_peer_dispatch_incoming_reliable_commands (peer, channel, incomingCommand); break; default: - enet_peer_dispatch_incoming_unreliable_commands (peer, channel); + enet_peer_dispatch_incoming_unreliable_commands (peer, channel, incomingCommand); break; } diff --git a/thirdparty/enet/protocol.c b/thirdparty/enet/protocol.c index fefc0e6f0a..d7fe80f117 100644 --- a/thirdparty/enet/protocol.c +++ b/thirdparty/enet/protocol.c @@ -188,8 +188,7 @@ enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer) } while (! enet_list_empty (& peer -> sentUnreliableCommands)); if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER && - enet_list_empty (& peer -> outgoingReliableCommands) && - enet_list_empty (& peer -> outgoingUnreliableCommands) && + enet_list_empty (& peer -> outgoingCommands) && enet_list_empty (& peer -> sentReliableCommands)) enet_peer_disconnect (peer, peer -> eventData); } @@ -215,12 +214,15 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl if (currentCommand == enet_list_end (& peer -> sentReliableCommands)) { - for (currentCommand = enet_list_begin (& peer -> outgoingReliableCommands); - currentCommand != enet_list_end (& peer -> outgoingReliableCommands); + for (currentCommand = enet_list_begin (& peer -> outgoingCommands); + currentCommand != enet_list_end (& peer -> outgoingCommands); currentCommand = enet_list_next (currentCommand)) { outgoingCommand = (ENetOutgoingCommand *) currentCommand; + if (! (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)) + continue; + if (outgoingCommand -> sendAttempts < 1) return ENET_PROTOCOL_COMMAND_NONE; if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber && @@ -228,7 +230,7 @@ enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliabl break; } - if (currentCommand == enet_list_end (& peer -> outgoingReliableCommands)) + if (currentCommand == enet_list_end (& peer -> outgoingCommands)) return ENET_PROTOCOL_COMMAND_NONE; wasSent = 0; @@ -623,7 +625,7 @@ enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENet fragmentLength); if (startCommand -> fragmentsRemaining <= 0) - enet_peer_dispatch_incoming_reliable_commands (peer, channel); + enet_peer_dispatch_incoming_reliable_commands (peer, channel, NULL); } return 0; @@ -741,7 +743,7 @@ enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, fragmentLength); if (startCommand -> fragmentsRemaining <= 0) - enet_peer_dispatch_incoming_unreliable_commands (peer, channel); + enet_peer_dispatch_incoming_unreliable_commands (peer, channel, NULL); } return 0; @@ -856,19 +858,22 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * if (peer -> lastReceiveTime > 0) { - enet_uint32 accumRoundTripTime = (peer -> roundTripTime << 8) + peer -> roundTripTimeRemainder; - enet_uint32 accumRoundTripTimeVariance = (peer -> roundTripTimeVariance << 8) + peer -> roundTripTimeVarianceRemainder; - enet_peer_throttle (peer, roundTripTime); - roundTripTime <<= 8; - accumRoundTripTimeVariance = (accumRoundTripTimeVariance * 3 + ENET_DIFFERENCE (roundTripTime, accumRoundTripTime)) / 4; - accumRoundTripTime = (accumRoundTripTime * 7 + roundTripTime) / 8; + peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4; - peer -> roundTripTime = accumRoundTripTime >> 8; - peer -> roundTripTimeRemainder = accumRoundTripTime & 0xFF; - peer -> roundTripTimeVariance = accumRoundTripTimeVariance >> 8; - peer -> roundTripTimeVarianceRemainder = accumRoundTripTimeVariance & 0xFF; + if (roundTripTime >= peer -> roundTripTime) + { + enet_uint32 diff = roundTripTime - peer -> roundTripTime; + peer -> roundTripTimeVariance += diff / 4; + peer -> roundTripTime += diff / 8; + } + else + { + enet_uint32 diff = peer -> roundTripTime - roundTripTime; + peer -> roundTripTimeVariance += diff / 4; + peer -> roundTripTime -= diff / 8; + } } else { @@ -879,14 +884,14 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * if (peer -> roundTripTime < peer -> lowestRoundTripTime) peer -> lowestRoundTripTime = peer -> roundTripTime; - if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance) + if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance) peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance; if (peer -> packetThrottleEpoch == 0 || ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval) { peer -> lastRoundTripTime = peer -> lowestRoundTripTime; - peer -> lastRoundTripTimeVariance = ENET_MAX (peer -> highestRoundTripTimeVariance, 2); + peer -> lastRoundTripTimeVariance = ENET_MAX (peer -> highestRoundTripTimeVariance, 1); peer -> lowestRoundTripTime = peer -> roundTripTime; peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance; peer -> packetThrottleEpoch = host -> serviceTime; @@ -916,8 +921,7 @@ enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * break; case ENET_PEER_STATE_DISCONNECT_LATER: - if (enet_list_empty (& peer -> outgoingReliableCommands) && - enet_list_empty (& peer -> outgoingUnreliableCommands) && + if (enet_list_empty (& peer -> outgoingCommands) && enet_list_empty (& peer -> sentReliableCommands)) enet_peer_disconnect (peer, peer -> eventData); break; @@ -1325,108 +1329,6 @@ enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer) host -> bufferCount = buffer - host -> buffers; } -static void -enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer) -{ - ENetProtocol * command = & host -> commands [host -> commandCount]; - ENetBuffer * buffer = & host -> buffers [host -> bufferCount]; - ENetOutgoingCommand * outgoingCommand; - ENetListIterator currentCommand; - - currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands); - - while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands)) - { - size_t commandSize; - - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK]; - - if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] || - buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] || - peer -> mtu - host -> packetSize < commandSize || - (outgoingCommand -> packet != NULL && - peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> fragmentLength)) - { - host -> continueSending = 1; - - break; - } - - currentCommand = enet_list_next (currentCommand); - - if (outgoingCommand -> packet != NULL && outgoingCommand -> fragmentOffset == 0) - { - peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER; - peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE; - - if (peer -> packetThrottleCounter > peer -> packetThrottle) - { - enet_uint16 reliableSequenceNumber = outgoingCommand -> reliableSequenceNumber, - unreliableSequenceNumber = outgoingCommand -> unreliableSequenceNumber; - for (;;) - { - -- outgoingCommand -> packet -> referenceCount; - - if (outgoingCommand -> packet -> referenceCount == 0) - enet_packet_destroy (outgoingCommand -> packet); - - enet_list_remove (& outgoingCommand -> outgoingCommandList); - enet_free (outgoingCommand); - - if (currentCommand == enet_list_end (& peer -> outgoingUnreliableCommands)) - break; - - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - if (outgoingCommand -> reliableSequenceNumber != reliableSequenceNumber || - outgoingCommand -> unreliableSequenceNumber != unreliableSequenceNumber) - break; - - currentCommand = enet_list_next (currentCommand); - } - - continue; - } - } - - buffer -> data = command; - buffer -> dataLength = commandSize; - - host -> packetSize += buffer -> dataLength; - - * command = outgoingCommand -> command; - - enet_list_remove (& outgoingCommand -> outgoingCommandList); - - if (outgoingCommand -> packet != NULL) - { - ++ buffer; - - buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset; - buffer -> dataLength = outgoingCommand -> fragmentLength; - - host -> packetSize += buffer -> dataLength; - - enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand); - } - else - enet_free (outgoingCommand); - - ++ command; - ++ buffer; - } - - host -> commandCount = command - host -> commands; - host -> bufferCount = buffer - host -> buffers; - - if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER && - enet_list_empty (& peer -> outgoingReliableCommands) && - enet_list_empty (& peer -> outgoingUnreliableCommands) && - enet_list_empty (& peer -> sentReliableCommands) && - enet_list_empty (& peer -> sentUnreliableCommands)) - enet_peer_disconnect (peer, peer -> eventData); -} - static int enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event) { @@ -1434,7 +1336,7 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even ENetListIterator currentCommand, insertPosition; currentCommand = enet_list_begin (& peer -> sentReliableCommands); - insertPosition = enet_list_begin (& peer -> outgoingReliableCommands); + insertPosition = enet_list_begin (& peer -> outgoingCommands); while (currentCommand != enet_list_end (& peer -> sentReliableCommands)) { @@ -1481,7 +1383,7 @@ enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * even } static int -enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) +enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer) { ENetProtocol * command = & host -> commands [host -> commandCount]; ENetBuffer * buffer = & host -> buffers [host -> bufferCount]; @@ -1492,49 +1394,52 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) size_t commandSize; int windowExceeded = 0, windowWrap = 0, canPing = 1; - currentCommand = enet_list_begin (& peer -> outgoingReliableCommands); + currentCommand = enet_list_begin (& peer -> outgoingCommands); - while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands)) + while (currentCommand != enet_list_end (& peer -> outgoingCommands)) { outgoingCommand = (ENetOutgoingCommand *) currentCommand; - channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL; - reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - if (channel != NULL) + if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { - if (! windowWrap && - outgoingCommand -> sendAttempts < 1 && - ! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) && - (channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE || - channel -> usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow) | - (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow))))) - windowWrap = 1; - if (windowWrap) + channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL; + reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + if (channel != NULL) { - currentCommand = enet_list_next (currentCommand); + if (! windowWrap && + outgoingCommand -> sendAttempts < 1 && + ! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) && + (channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE || + channel -> usedReliableWindows & ((((1 << (ENET_PEER_FREE_RELIABLE_WINDOWS + 2)) - 1) << reliableWindow) | + (((1 << (ENET_PEER_FREE_RELIABLE_WINDOWS + 2)) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow))))) + windowWrap = 1; + if (windowWrap) + { + currentCommand = enet_list_next (currentCommand); - continue; + continue; + } } - } - if (outgoingCommand -> packet != NULL) - { - if (! windowExceeded) + if (outgoingCommand -> packet != NULL) { - enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE; + if (! windowExceeded) + { + enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE; - if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu)) - windowExceeded = 1; - } - if (windowExceeded) - { - currentCommand = enet_list_next (currentCommand); + if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu)) + windowExceeded = 1; + } + if (windowExceeded) + { + currentCommand = enet_list_next (currentCommand); - continue; + continue; + } } - } - canPing = 0; + canPing = 0; + } commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK]; if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] || @@ -1550,33 +1455,80 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) currentCommand = enet_list_next (currentCommand); - if (channel != NULL && outgoingCommand -> sendAttempts < 1) + if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { - channel -> usedReliableWindows |= 1 << reliableWindow; - ++ channel -> reliableWindows [reliableWindow]; - } + if (channel != NULL && outgoingCommand -> sendAttempts < 1) + { + channel -> usedReliableWindows |= 1 << reliableWindow; + ++ channel -> reliableWindows [reliableWindow]; + } - ++ outgoingCommand -> sendAttempts; + ++ outgoingCommand -> sendAttempts; - if (outgoingCommand -> roundTripTimeout == 0) - { - outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance; - outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout; + if (outgoingCommand -> roundTripTimeout == 0) + { + outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance; + outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout; + } + + if (enet_list_empty (& peer -> sentReliableCommands)) + peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout; + + enet_list_insert (enet_list_end (& peer -> sentReliableCommands), + enet_list_remove (& outgoingCommand -> outgoingCommandList)); + + outgoingCommand -> sentTime = host -> serviceTime; + + host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME; + + peer -> reliableDataInTransit += outgoingCommand -> fragmentLength; } + else + { + if (outgoingCommand -> packet != NULL && outgoingCommand -> fragmentOffset == 0) + { + peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER; + peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE; + + if (peer -> packetThrottleCounter > peer -> packetThrottle) + { + enet_uint16 reliableSequenceNumber = outgoingCommand -> reliableSequenceNumber, + unreliableSequenceNumber = outgoingCommand -> unreliableSequenceNumber; + for (;;) + { + -- outgoingCommand -> packet -> referenceCount; + + if (outgoingCommand -> packet -> referenceCount == 0) + enet_packet_destroy (outgoingCommand -> packet); - if (enet_list_empty (& peer -> sentReliableCommands)) - peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout; + enet_list_remove (& outgoingCommand -> outgoingCommandList); + enet_free (outgoingCommand); - enet_list_insert (enet_list_end (& peer -> sentReliableCommands), - enet_list_remove (& outgoingCommand -> outgoingCommandList)); + if (currentCommand == enet_list_end (& peer -> outgoingCommands)) + break; - outgoingCommand -> sentTime = host -> serviceTime; + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + if (outgoingCommand -> reliableSequenceNumber != reliableSequenceNumber || + outgoingCommand -> unreliableSequenceNumber != unreliableSequenceNumber) + break; + + currentCommand = enet_list_next (currentCommand); + } + + continue; + } + } + + enet_list_remove (& outgoingCommand -> outgoingCommandList); + + if (outgoingCommand -> packet != NULL) + enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand); + } buffer -> data = command; buffer -> dataLength = commandSize; host -> packetSize += buffer -> dataLength; - host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME; * command = outgoingCommand -> command; @@ -1588,9 +1540,10 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) buffer -> dataLength = outgoingCommand -> fragmentLength; host -> packetSize += outgoingCommand -> fragmentLength; - - peer -> reliableDataInTransit += outgoingCommand -> fragmentLength; } + else + if (! (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)) + enet_free (outgoingCommand); ++ peer -> packetsSent; @@ -1601,6 +1554,12 @@ enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer) host -> commandCount = command - host -> commands; host -> bufferCount = buffer - host -> buffers; + if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER && + enet_list_empty (& peer -> outgoingCommands) && + enet_list_empty (& peer -> sentReliableCommands) && + enet_list_empty (& peer -> sentUnreliableCommands)) + enet_peer_disconnect (peer, peer -> eventData); + return canPing; } @@ -1644,18 +1603,15 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch continue; } - if ((enet_list_empty (& currentPeer -> outgoingReliableCommands) || - enet_protocol_send_reliable_outgoing_commands (host, currentPeer)) && + if ((enet_list_empty (& currentPeer -> outgoingCommands) || + enet_protocol_check_outgoing_commands (host, currentPeer)) && enet_list_empty (& currentPeer -> sentReliableCommands) && ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= currentPeer -> pingInterval && currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing)) { enet_peer_ping (currentPeer); - enet_protocol_send_reliable_outgoing_commands (host, currentPeer); + enet_protocol_check_outgoing_commands (host, currentPeer); } - - if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands)) - enet_protocol_send_unreliable_outgoing_commands (host, currentPeer); if (host -> commandCount == 0) continue; @@ -1669,7 +1625,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent; #ifdef ENET_DEBUG - printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0); + printf ("peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0); #endif currentPeer -> packetLossVariance = (currentPeer -> packetLossVariance * 3 + ENET_DIFFERENCE (packetLoss, currentPeer -> packetLoss)) / 4; diff --git a/thirdparty/harfbuzz/NEWS b/thirdparty/harfbuzz/NEWS index f09c2fafd1..321c550188 100644 --- a/thirdparty/harfbuzz/NEWS +++ b/thirdparty/harfbuzz/NEWS @@ -1,3 +1,18 @@ +Overview of changes leading to 2.8.0 +Tuesday, March 16, 2021 +==================================== +- Shape joining scripts other than Arabic/Syriac using the Universal Shaping Engine. + Previously these were shaped using the generalized Arabic shaper. (David Corbett) +- Fix regression in shaping of U+0B55 ORIYA SIGN OVERLINE. (David Corbett) +- Update language tags. (David Corbett) +- Variations: reduce error: do not round each interpolated delta. (Just van Rossum) +- Documentation improvements. (Khaled Hosny, Nathan Willis) +- Subsetter improvements: subsets most, if not all, lookup types now. (Garret Rieger, Qunxin Liu) +- Fuzzer-found fixes and other improvements when memory failures happen. (Behdad) +- Removed most atomic implementations now that we have C++11 atomic impl. (Behdad) +- General codebase upkeep; using more C++11 features: constexpr constructors, etc. (Behdad) + + Overview of changes leading to 2.7.4 Sunday, December 27, 2020 ==================================== diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh index 75d523f5fc..98ed20d8eb 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh @@ -510,7 +510,7 @@ struct StateTable const Entry<Extra> &get_entry (int state, unsigned int klass) const { if (unlikely (klass >= nClasses)) - klass = StateTable<Types, Entry<Extra>>::CLASS_OUT_OF_BOUNDS; + klass = StateTable::CLASS_OUT_OF_BOUNDS; const HBUSHORT *states = (this+stateArrayTable).arrayZ; const Entry<Extra> *entries = (this+entryTable).arrayZ; @@ -576,7 +576,7 @@ struct StateTable if (unlikely (stop > states)) return_trace (false); for (const HBUSHORT *p = states; stop < p; p--) - num_entries = hb_max (num_entries, *(p - 1) + 1); + num_entries = hb_max (num_entries, *(p - 1) + 1u); state_neg = min_state; } } @@ -597,7 +597,7 @@ struct StateTable if (unlikely (stop < states)) return_trace (false); for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++) - num_entries = hb_max (num_entries, *p + 1); + num_entries = hb_max (num_entries, *p + 1u); state_pos = max_state + 1; } } @@ -729,7 +729,10 @@ struct ExtendedTypes template <typename Types, typename EntryData> struct StateTableDriver { - StateTableDriver (const StateTable<Types, EntryData> &machine_, + using StateTableT = StateTable<Types, EntryData>; + using EntryT = Entry<EntryData>; + + StateTableDriver (const StateTableT &machine_, hb_buffer_t *buffer_, hb_face_t *face_) : machine (machine_), @@ -742,59 +745,101 @@ struct StateTableDriver if (!c->in_place) buffer->clear_output (); - int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT; + int state = StateTableT::STATE_START_OF_TEXT; for (buffer->idx = 0; buffer->successful;) { unsigned int klass = buffer->idx < buffer->len ? machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) : - (unsigned) StateTable<Types, EntryData>::CLASS_END_OF_TEXT; + (unsigned) StateTableT::CLASS_END_OF_TEXT; DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx); - const Entry<EntryData> &entry = machine.get_entry (state, klass); + const EntryT &entry = machine.get_entry (state, klass); + const int next_state = machine.new_state (entry.newState); - /* Unsafe-to-break before this if not in state 0, as things might - * go differently if we start from state 0 here. + /* Conditions under which it's guaranteed safe-to-break before current glyph: * - * Ugh. The indexing here is ugly... */ - if (state && buffer->backtrack_len () && buffer->idx < buffer->len) - { - /* If there's no action and we're just epsilon-transitioning to state 0, - * safe to break. */ - if (c->is_actionable (this, entry) || - !(entry.newState == StateTable<Types, EntryData>::STATE_START_OF_TEXT && - entry.flags == context_t::DontAdvance)) - buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1); - } - - /* Unsafe-to-break if end-of-text would kick in here. */ - if (buffer->idx + 2 <= buffer->len) - { - const Entry<EntryData> &end_entry = machine.get_entry (state, StateTable<Types, EntryData>::CLASS_END_OF_TEXT); - if (c->is_actionable (this, end_entry)) - buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); - } + * 1. There was no action in this transition; and + * + * 2. If we break before current glyph, the results will be the same. That + * is guaranteed if: + * + * 2a. We were already in start-of-text state; or + * + * 2b. We are epsilon-transitioning to start-of-text state; or + * + * 2c. Starting from start-of-text state seeing current glyph: + * + * 2c'. There won't be any actions; and + * + * 2c". We would end up in the same state that we were going to end up + * in now, including whether epsilon-transitioning. + * + * and + * + * 3. If we break before current glyph, there won't be any end-of-text action + * after previous glyph. + * + * This triples the transitions we need to look up, but is worth returning + * granular unsafe-to-break results. See eg.: + * + * https://github.com/harfbuzz/harfbuzz/issues/2860 + */ + const EntryT *wouldbe_entry; + bool safe_to_break = + /* 1. */ + !c->is_actionable (this, entry) + && + /* 2. */ + ( + /* 2a. */ + state == StateTableT::STATE_START_OF_TEXT + || + /* 2b. */ + ( + (entry.flags & context_t::DontAdvance) && + next_state == StateTableT::STATE_START_OF_TEXT + ) + || + /* 2c. */ + ( + wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass) + , + /* 2c'. */ + !c->is_actionable (this, *wouldbe_entry) + && + /* 2c". */ + ( + next_state == machine.new_state (wouldbe_entry->newState) + && + (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance) + ) + ) + ) + && + /* 3. */ + !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT)) + ; + + if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len) + buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1); c->transition (this, entry); - state = machine.new_state (entry.newState); + state = next_state; DEBUG_MSG (APPLY, nullptr, "s%d", state); - if (buffer->idx == buffer->len) + if (buffer->idx == buffer->len || unlikely (!buffer->successful)) break; if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0) - buffer->next_glyph (); + (void) buffer->next_glyph (); } if (!c->in_place) - { - for (; buffer->successful && buffer->idx < buffer->len;) - buffer->next_glyph (); buffer->swap_buffers (); - } } public: - const StateTable<Types, EntryData> &machine; + const StateTableT &machine; hb_buffer_t *buffer; unsigned int num_glyphs; }; diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh index 04027a61be..e3bc268d26 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh +++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh @@ -337,9 +337,9 @@ struct ContextualSubtable const EntryData &data = entries[i].data; if (data.markIndex != 0xFFFF) - num_lookups = hb_max (num_lookups, 1 + data.markIndex); + num_lookups = hb_max (num_lookups, 1u + data.markIndex); if (data.currentIndex != 0xFFFF) - num_lookups = hb_max (num_lookups, 1 + data.currentIndex); + num_lookups = hb_max (num_lookups, 1u + data.currentIndex); } return_trace (substitutionTables.sanitize (c, this, num_lookups)); @@ -499,7 +499,7 @@ struct LigatureSubtable } DEBUG_MSG (APPLY, nullptr, "Moving to stack position %u", cursor - 1); - buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]); + if (unlikely (!buffer->move_to (match_positions[--cursor % ARRAY_LENGTH (match_positions)]))) return; if (unlikely (!actionData->sanitize (&c->sanitizer))) break; action = *actionData; @@ -525,25 +525,25 @@ struct LigatureSubtable hb_codepoint_t lig = ligatureData; DEBUG_MSG (APPLY, nullptr, "Produced ligature %u", lig); - buffer->replace_glyph (lig); + if (unlikely (!buffer->replace_glyph (lig))) return; unsigned int lig_end = match_positions[(match_length - 1u) % ARRAY_LENGTH (match_positions)] + 1u; /* Now go and delete all subsequent components. */ while (match_length - 1u > cursor) { DEBUG_MSG (APPLY, nullptr, "Skipping ligature component"); - buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]); - buffer->replace_glyph (DELETED_GLYPH); + if (unlikely (!buffer->move_to (match_positions[--match_length % ARRAY_LENGTH (match_positions)]))) return; + if (unlikely (!buffer->replace_glyph (DELETED_GLYPH))) return; } - buffer->move_to (lig_end); + if (unlikely (!buffer->move_to (lig_end))) return; buffer->merge_out_clusters (match_positions[cursor % ARRAY_LENGTH (match_positions)], buffer->out_len); } actionData++; } while (!(action & LigActionLast)); - buffer->move_to (end); + if (unlikely (!buffer->move_to (end))) return; } } @@ -733,17 +733,16 @@ struct InsertionSubtable bool before = flags & MarkedInsertBefore; unsigned int end = buffer->out_len; - buffer->move_to (mark); + if (unlikely (!buffer->move_to (mark))) return; if (buffer->idx < buffer->len && !before) - buffer->copy_glyph (); + if (unlikely (!buffer->copy_glyph ())) return; /* TODO We ignore KashidaLike setting. */ - for (unsigned int i = 0; i < count; i++) - buffer->output_glyph (glyphs[i]); + if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; if (buffer->idx < buffer->len && !before) buffer->skip_glyph (); - buffer->move_to (end + count); + if (unlikely (!buffer->move_to (end + count))) return; buffer->unsafe_to_break_from_outbuffer (mark, hb_min (buffer->idx + 1, buffer->len)); } @@ -764,10 +763,9 @@ struct InsertionSubtable unsigned int end = buffer->out_len; if (buffer->idx < buffer->len && !before) - buffer->copy_glyph (); + if (unlikely (!buffer->copy_glyph ())) return; /* TODO We ignore KashidaLike setting. */ - for (unsigned int i = 0; i < count; i++) - buffer->output_glyph (glyphs[i]); + if (unlikely (!buffer->replace_glyphs (0, count, glyphs))) return; if (buffer->idx < buffer->len && !before) buffer->skip_glyph (); @@ -786,7 +784,7 @@ struct InsertionSubtable * * https://github.com/harfbuzz/harfbuzz/issues/1224#issuecomment-427691417 */ - buffer->move_to ((flags & DontAdvance) ? end : end + count); + if (unlikely (!buffer->move_to ((flags & DontAdvance) ? end : end + count))) return; } } diff --git a/thirdparty/harfbuzz/src/hb-aat-layout.cc b/thirdparty/harfbuzz/src/hb-aat-layout.cc index 74ebaa64ec..0e9f2b4954 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout.cc +++ b/thirdparty/harfbuzz/src/hb-aat-layout.cc @@ -227,7 +227,7 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, * * <note>Note: does not examine the `GSUB` table.</note> * - * Return value: true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 2.3.0 */ @@ -294,7 +294,7 @@ hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer) * * <note>Note: does not examine the `GPOS` table.</note> * - * Return value: true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 2.3.0 */ @@ -325,7 +325,7 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan, * Tests whether the specified face includes any tracking information * in the `trak` table. * - * Return value: true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 2.3.0 */ @@ -350,7 +350,7 @@ hb_aat_layout_track (const hb_ot_shape_plan_t *plan, * hb_aat_layout_get_feature_types: * @face: #hb_face_t to work upon * @start_offset: offset of the first feature type to retrieve - * @feature_count: (inout) (allow-none): Input = the maximum number of feature types to return; + * @feature_count: (inout) (optional): Input = the maximum number of feature types to return; * Output = the actual number of feature types returned (may be zero) * @features: (out caller-allocates) (array length=feature_count): Array of feature types found * @@ -374,9 +374,9 @@ hb_aat_layout_get_feature_types (hb_face_t *face, * @face: #hb_face_t to work upon * @feature_type: The #hb_aat_layout_feature_type_t of the requested feature type * - * Fetches the name ID of the specified feature type in the face's `name` table. + * Fetches the name identifier of the specified feature type in the face's `name` table. * - * Return value: Name ID of the requested feature type + * Return value: Name identifier of the requested feature type * * Since: 2.2.0 */ @@ -388,15 +388,15 @@ hb_aat_layout_feature_type_get_name_id (hb_face_t *face, } /** - * hb_aat_layout_feature_type_get_selectors: + * hb_aat_layout_feature_type_get_selector_infos: * @face: #hb_face_t to work upon * @feature_type: The #hb_aat_layout_feature_type_t of the requested feature type * @start_offset: offset of the first feature type to retrieve - * @selector_count: (inout) (allow-none): Input = the maximum number of selectors to return; + * @selector_count: (inout) (optional): Input = the maximum number of selectors to return; * Output = the actual number of selectors returned (may be zero) - * @selectors: (out caller-allocates) (array length=selector_count): A buffer pointer. - * The selectors available for the feature type queries. - * @default_index: (out) (allow-none): The index of the feature's default selector, if any + * @selectors: (out caller-allocates) (array length=selector_count) (optional): + * A buffer pointer. The selectors available for the feature type queries. + * @default_index: (out) (optional): The index of the feature's default selector, if any * * Fetches a list of the selectors available for the specified feature in the given face. * diff --git a/thirdparty/harfbuzz/src/hb-aat-layout.h b/thirdparty/harfbuzz/src/hb-aat-layout.h index dc1bf96573..9af2740088 100644 --- a/thirdparty/harfbuzz/src/hb-aat-layout.h +++ b/thirdparty/harfbuzz/src/hb-aat-layout.h @@ -22,7 +22,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -#ifndef HB_AAT_H_IN +#if !defined(HB_AAT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-aat.h> instead." #endif @@ -38,47 +38,47 @@ HB_BEGIN_DECLS /** * hb_aat_layout_feature_type_t: * @HB_AAT_LAYOUT_FEATURE_TYPE_INVALID: Initial, unset feature type - * @HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC: - * @HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES: - * @HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION: - * @HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION: - * @HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT: - * @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING: - * @HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION: - * @HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS: - * @HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS: - * @HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS: - * @HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES: - * @HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS: - * @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING: - * @HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION: - * @HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA: - * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN: - * @HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT: - * @HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA: - * @HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES: - * @HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES: - * @HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE: - * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE: + * @HB_AAT_LAYOUT_FEATURE_TYPE_ALL_TYPOGRAPHIC: [All Typographic Features](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type0) + * @HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES: [Ligatures](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type1) + * @HB_AAT_LAYOUT_FEATURE_TYPE_CURISVE_CONNECTION: [Cursive Connection](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type2) + * @HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE: [Letter Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type3) + * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION: [Vertical Substitution](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type4) + * @HB_AAT_LAYOUT_FEATURE_TYPE_LINGUISTIC_REARRANGEMENT: [Linguistic Rearrangement](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type5) + * @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING: [Number Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type6) + * @HB_AAT_LAYOUT_FEATURE_TYPE_SMART_SWASH_TYPE: [Smart Swash](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type8) + * @HB_AAT_LAYOUT_FEATURE_TYPE_DIACRITICS_TYPE: [Diacritics](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type9) + * @HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION: [Vertical Position](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type10) + * @HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS: [Fractions](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type11) + * @HB_AAT_LAYOUT_FEATURE_TYPE_OVERLAPPING_CHARACTERS_TYPE: [Overlapping Characters](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type13) + * @HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS: [Typographic Extras](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type14) + * @HB_AAT_LAYOUT_FEATURE_TYPE_MATHEMATICAL_EXTRAS: [Mathematical Extras](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type15) + * @HB_AAT_LAYOUT_FEATURE_TYPE_ORNAMENT_SETS_TYPE: [Ornament Sets](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type16) + * @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES: [Character Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type17) + * @HB_AAT_LAYOUT_FEATURE_TYPE_DESIGN_COMPLEXITY_TYPE: [Design Complexity](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type18) + * @HB_AAT_LAYOUT_FEATURE_TYPE_STYLE_OPTIONS: [Style Options](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type19) + * @HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_SHAPE: [Character Shape](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type20) + * @HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_CASE: [Number Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type21) + * @HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING: [Text Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type22) + * @HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION: [Transliteration](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type23) + * @HB_AAT_LAYOUT_FEATURE_TYPE_ANNOTATION_TYPE: [Annotation](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type24) + * @HB_AAT_LAYOUT_FEATURE_TYPE_KANA_SPACING_TYPE: [Kana Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type25) + * @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_SPACING_TYPE: [Ideographic Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type26) + * @HB_AAT_LAYOUT_FEATURE_TYPE_UNICODE_DECOMPOSITION_TYPE: [Unicode Decomposition](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type27) + * @HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA: [Ruby Kana](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type28) + * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_SYMBOL_ALTERNATIVES_TYPE: [CJK Symbol Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type29) + * @HB_AAT_LAYOUT_FEATURE_TYPE_IDEOGRAPHIC_ALTERNATIVES_TYPE: [Ideographic Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type30) + * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_VERTICAL_ROMAN_PLACEMENT_TYPE: [CJK Vertical Roman Placement](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type31) + * @HB_AAT_LAYOUT_FEATURE_TYPE_ITALIC_CJK_ROMAN: [Italic CJK Roman](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type32) + * @HB_AAT_LAYOUT_FEATURE_TYPE_CASE_SENSITIVE_LAYOUT: [Case Sensitive Layout](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type33) + * @HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA: [Alternate Kana](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type34) + * @HB_AAT_LAYOUT_FEATURE_TYPE_STYLISTIC_ALTERNATIVES: [Stylistic Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type35) + * @HB_AAT_LAYOUT_FEATURE_TYPE_CONTEXTUAL_ALTERNATIVES: [Contextual Alternatives](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type36) + * @HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE: [Lower Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type37) + * @HB_AAT_LAYOUT_FEATURE_TYPE_UPPER_CASE: [Upper Case](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type38) + * @HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE: [Language Tag](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type39) + * @HB_AAT_LAYOUT_FEATURE_TYPE_CJK_ROMAN_SPACING_TYPE: [CJK Roman Spacing](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html#Type103) * - * The possible feature types defined for AAT shaping. + * The possible feature types defined for AAT shaping, from Apple [Font Feature Registry](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html). * * Since: 2.2.0 */ @@ -732,6 +732,14 @@ HB_EXTERN hb_ot_name_id_t hb_aat_layout_feature_type_get_name_id (hb_face_t *face, hb_aat_layout_feature_type_t feature_type); +/** + * hb_aat_layout_feature_selector_info_t: + * @name_id: The selector's name identifier + * @enable: The value to turn the selector on + * @disable: The value to turn the selector off + * + * Structure representing a setting for an #hb_aat_layout_feature_type_t. + */ typedef struct hb_aat_layout_feature_selector_info_t { hb_ot_name_id_t name_id; hb_aat_layout_feature_selector_t enable; diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh index 98de61f3e8..bc170b0546 100644 --- a/thirdparty/harfbuzz/src/hb-algs.hh +++ b/thirdparty/harfbuzz/src/hb-algs.hh @@ -35,6 +35,132 @@ #include "hb-number.hh" +/* + * Flags + */ + +/* Enable bitwise ops on enums marked as flags_t */ +/* To my surprise, looks like the function resolver is happy to silently cast + * one enum to another... So this doesn't provide the type-checking that I + * originally had in mind... :(. + * + * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163 + */ +#ifdef _MSC_VER +# pragma warning(disable:4200) +# pragma warning(disable:4800) +#endif +#define HB_MARK_AS_FLAG_T(T) \ + extern "C++" { \ + static inline constexpr T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \ + static inline constexpr T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \ + static inline constexpr T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \ + static inline constexpr T operator ~ (T r) { return T (~(unsigned int) r); } \ + static inline T& operator |= (T &l, T r) { l = l | r; return l; } \ + static inline T& operator &= (T& l, T r) { l = l & r; return l; } \ + static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \ + } \ + static_assert (true, "") + +/* Useful for set-operations on small enums. + * For example, for testing "x ∈ {x1, x2, x3}" use: + * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) + */ +#define FLAG(x) (static_assert_expr ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x))) +#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0) +#define FLAG_RANGE(x,y) (static_assert_expr ((x) < (y)) + FLAG(y+1) - FLAG(x)) +#define FLAG64(x) (static_assert_expr ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x))) +#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0) + + +/* + * Big-endian integers. + */ + +/* Endian swap, used in Windows related backends */ +static inline constexpr uint16_t hb_uint16_swap (uint16_t v) +{ return (v >> 8) | (v << 8); } +static inline constexpr uint32_t hb_uint32_swap (uint32_t v) +{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); } + +template <typename Type, int Bytes = sizeof (Type)> +struct BEInt; +template <typename Type> +struct BEInt<Type, 1> +{ + public: + BEInt () = default; + constexpr BEInt (Type V) : v {uint8_t (V)} {} + constexpr operator Type () const { return v; } + private: uint8_t v; +}; +template <typename Type> +struct BEInt<Type, 2> +{ + public: + BEInt () = default; + constexpr BEInt (Type V) : v {uint8_t ((V >> 8) & 0xFF), + uint8_t ((V ) & 0xFF)} {} + + struct __attribute__((packed)) packed_uint16_t { uint16_t v; }; + constexpr operator Type () const + { +#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \ + defined(__BYTE_ORDER) && \ + (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN) + /* Spoon-feed the compiler a big-endian integer with alignment 1. + * https://github.com/harfbuzz/harfbuzz/pull/1398 */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + return __builtin_bswap16 (((packed_uint16_t *) this)->v); +#else /* __BYTE_ORDER == __BIG_ENDIAN */ + return ((packed_uint16_t *) this)->v; +#endif +#else + return (v[0] << 8) + + (v[1] ); +#endif + } + private: uint8_t v[2]; +}; +template <typename Type> +struct BEInt<Type, 3> +{ + static_assert (!hb_is_signed (Type), ""); + public: + BEInt () = default; + constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF), + uint8_t ((V >> 8) & 0xFF), + uint8_t ((V ) & 0xFF)} {} + + constexpr operator Type () const { return (v[0] << 16) + + (v[1] << 8) + + (v[2] ); } + private: uint8_t v[3]; +}; +template <typename Type> +struct BEInt<Type, 4> +{ + public: + BEInt () = default; + constexpr BEInt (Type V) : v {uint8_t ((V >> 24) & 0xFF), + uint8_t ((V >> 16) & 0xFF), + uint8_t ((V >> 8) & 0xFF), + uint8_t ((V ) & 0xFF)} {} + constexpr operator Type () const { return (v[0] << 24) + + (v[1] << 16) + + (v[2] << 8) + + (v[3] ); } + private: uint8_t v[4]; +}; + +/* Floats. */ + +/* We want our rounding towards +infinity. */ +static inline float +_hb_roundf (float x) { return floorf (x + .5f); } +#define roundf(x) _hb_roundf(x) + + /* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits, * values will be truncated / overlap, and might not decode exactly. */ #define HB_CODEPOINT_ENCODE3(x,y,z) (((uint64_t) (x) << 42) | ((uint64_t) (y) << 21) | (uint64_t) (z)) @@ -48,6 +174,7 @@ #define HB_CODEPOINT_DECODE3_11_7_14_2(v) ((hb_codepoint_t) (((v) >> 14) & 0x007Fu) | 0x0300) #define HB_CODEPOINT_DECODE3_11_7_14_3(v) ((hb_codepoint_t) (v) & 0x3FFFu) + struct { /* Note. This is dangerous in that if it's passed an rvalue, it returns rvalue-reference. */ @@ -215,7 +342,9 @@ struct template <typename Pred, typename Val> auto impl (Pred&& p, Val &&v, hb_priority<1>) const HB_AUTO_RETURN - (hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v))) + ( + hb_deref (hb_forward<Pred> (p)).has (hb_forward<Val> (v)) + ) template <typename Pred, typename Val> auto impl (Pred&& p, Val &&v, hb_priority<0>) const HB_AUTO_RETURN @@ -269,7 +398,9 @@ struct template <typename Proj, typename Val> auto impl (Proj&& f, Val &&v, hb_priority<2>) const HB_AUTO_RETURN - (hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v))) + ( + hb_deref (hb_forward<Proj> (f)).get (hb_forward<Val> (v)) + ) template <typename Proj, typename Val> auto impl (Proj&& f, Val &&v, hb_priority<1>) const HB_AUTO_RETURN @@ -296,6 +427,40 @@ struct } HB_FUNCOBJ (hb_get); +struct +{ + private: + + template <typename T1, typename T2> auto + impl (T1&& v1, T2 &&v2, hb_priority<2>) const HB_AUTO_RETURN + ( + hb_forward<T2> (v2).cmp (hb_forward<T1> (v1)) == 0 + ) + + template <typename T1, typename T2> auto + impl (T1&& v1, T2 &&v2, hb_priority<1>) const HB_AUTO_RETURN + ( + hb_forward<T1> (v1).cmp (hb_forward<T2> (v2)) == 0 + ) + + template <typename T1, typename T2> auto + impl (T1&& v1, T2 &&v2, hb_priority<0>) const HB_AUTO_RETURN + ( + hb_forward<T1> (v1) == hb_forward<T2> (v2) + ) + + public: + + template <typename T1, typename T2> auto + operator () (T1&& v1, T2 &&v2) const HB_AUTO_RETURN + ( + impl (hb_forward<T1> (v1), + hb_forward<T2> (v2), + hb_prioritize) + ) +} +HB_FUNCOBJ (hb_equal); + template <typename T1, typename T2> struct hb_pair_t @@ -375,7 +540,7 @@ HB_FUNCOBJ (hb_clamp); /* Return the number of 1 bits in v. */ template <typename T> -static inline HB_CONST_FUNC unsigned int +static inline unsigned int hb_popcount (T v) { #if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) @@ -416,7 +581,7 @@ hb_popcount (T v) /* Returns the number of bits needed to store number */ template <typename T> -static inline HB_CONST_FUNC unsigned int +static inline unsigned int hb_bit_storage (T v) { if (unlikely (!v)) return 0; @@ -490,7 +655,7 @@ hb_bit_storage (T v) /* Returns the number of zero bits in the least significant side of v */ template <typename T> -static inline HB_CONST_FUNC unsigned int +static inline unsigned int hb_ctz (T v) { if (unlikely (!v)) return 8 * sizeof (T); @@ -988,32 +1153,24 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o struct hb_bitwise_and { HB_PARTIALIZE(2); - static constexpr bool passthru_left = false; - static constexpr bool passthru_right = false; template <typename T> constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & b) } HB_FUNCOBJ (hb_bitwise_and); struct hb_bitwise_or { HB_PARTIALIZE(2); - static constexpr bool passthru_left = true; - static constexpr bool passthru_right = true; template <typename T> constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a | b) } HB_FUNCOBJ (hb_bitwise_or); struct hb_bitwise_xor { HB_PARTIALIZE(2); - static constexpr bool passthru_left = true; - static constexpr bool passthru_right = true; template <typename T> constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a ^ b) } HB_FUNCOBJ (hb_bitwise_xor); struct hb_bitwise_sub { HB_PARTIALIZE(2); - static constexpr bool passthru_left = true; - static constexpr bool passthru_right = false; template <typename T> constexpr auto operator () (const T &a, const T &b) const HB_AUTO_RETURN (a & ~b) } diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh index 568cd02c79..02bd8d81c2 100644 --- a/thirdparty/harfbuzz/src/hb-array.hh +++ b/thirdparty/harfbuzz/src/hb-array.hh @@ -142,7 +142,7 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&> bool lfind (const T &x, unsigned *pos = nullptr) const { for (unsigned i = 0; i < length; ++i) - if (!this->arrayZ[i].cmp (x)) + if (hb_equal (x, this->arrayZ[i])) { if (pos) *pos = i; diff --git a/thirdparty/harfbuzz/src/hb-atomic.hh b/thirdparty/harfbuzz/src/hb-atomic.hh index b3fb296b4e..93265f655f 100644 --- a/thirdparty/harfbuzz/src/hb-atomic.hh +++ b/thirdparty/harfbuzz/src/hb-atomic.hh @@ -52,7 +52,7 @@ #elif !defined(HB_NO_MT) && defined(__ATOMIC_ACQUIRE) -/* C++11-style GCC primitives. */ +/* C++11-style GCC primitives. We prefer these as they don't require linking to libstdc++ / libc++. */ #define _hb_memory_barrier() __sync_synchronize () @@ -73,7 +73,8 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N) } #define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N)) -#elif !defined(HB_NO_MT) && __cplusplus >= 201103L + +#elif !defined(HB_NO_MT) /* C++11 atomics. */ @@ -101,117 +102,6 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N) #define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N)) -#elif !defined(HB_NO_MT) && defined(_WIN32) - -#include <windows.h> - -static inline void _hb_memory_barrier () -{ -#if !defined(MemoryBarrier) && !defined(__MINGW32_VERSION) - /* MinGW has a convoluted history of supporting MemoryBarrier. */ - LONG dummy = 0; - InterlockedExchange (&dummy, 1); -#else - MemoryBarrier (); -#endif -} -#define _hb_memory_barrier() _hb_memory_barrier () - -#define hb_atomic_int_impl_add(AI, V) InterlockedExchangeAdd ((LONG *) (AI), (V)) -static_assert ((sizeof (LONG) == sizeof (int)), ""); - -#define hb_atomic_ptr_impl_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((P), (N), (O)) == (O)) - - -#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) - -#define _hb_memory_barrier() __sync_synchronize () - -#define hb_atomic_int_impl_add(AI, V) __sync_fetch_and_add ((AI), (V)) - -#define hb_atomic_ptr_impl_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N)) - - -#elif !defined(HB_NO_MT) && defined(HAVE_SOLARIS_ATOMIC_OPS) - -#include <atomic.h> -#include <mbarrier.h> - -#define _hb_memory_r_barrier() __machine_r_barrier () -#define _hb_memory_w_barrier() __machine_w_barrier () -#define _hb_memory_barrier() __machine_rw_barrier () - -static inline int _hb_fetch_and_add (int *AI, int V) -{ - _hb_memory_w_barrier (); - int result = atomic_add_int_nv ((uint_t *) AI, V) - V; - _hb_memory_r_barrier (); - return result; -} -static inline bool _hb_compare_and_swap_ptr (void **P, void *O, void *N) -{ - _hb_memory_w_barrier (); - bool result = atomic_cas_ptr (P, O, N) == O; - _hb_memory_r_barrier (); - return result; -} - -#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V)) - -#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swap_ptr ((P), (O), (N)) - - -#elif !defined(HB_NO_MT) && defined(__APPLE__) - -#include <libkern/OSAtomic.h> -#ifdef __MAC_OS_X_MIN_REQUIRED -#include <AvailabilityMacros.h> -#elif defined(__IPHONE_OS_MIN_REQUIRED) -#include <Availability.h> -#endif - -#define _hb_memory_barrier() OSMemoryBarrier () - -#define hb_atomic_int_impl_add(AI, V) (OSAtomicAdd32Barrier ((V), (AI)) - (V)) - -#if (MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4 || __IPHONE_VERSION_MIN_REQUIRED >= 20100) -#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((O), (N), (P)) -#else -#if __ppc64__ || __x86_64__ || __aarch64__ -#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap64Barrier ((int64_t) (O), (int64_t) (N), (int64_t*) (P)) -#else -#define hb_atomic_ptr_impl_cmpexch(P,O,N) OSAtomicCompareAndSwap32Barrier ((int32_t) (O), (int32_t) (N), (int32_t*) (P)) -#endif -#endif - - -#elif !defined(HB_NO_MT) && defined(_AIX) && (defined(__IBMCPP__) || defined(__ibmxl__)) - -#include <builtins.h> - -#define _hb_memory_barrier() __lwsync () - -static inline int _hb_fetch_and_add (int *AI, int V) -{ - _hb_memory_barrier (); - int result = __fetch_and_add (AI, V); - _hb_memory_barrier (); - return result; -} -static inline bool _hb_compare_and_swaplp (long *P, long O, long N) -{ - _hb_memory_barrier (); - bool result = __compare_and_swaplp (P, &O, N); - _hb_memory_barrier (); - return result; -} - -#define hb_atomic_int_impl_add(AI, V) _hb_fetch_and_add ((AI), (V)) - -#define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_compare_and_swaplp ((long *) (P), (long) (O), (long) (N)) -static_assert ((sizeof (long) == sizeof (void *)), ""); - - #elif defined(HB_NO_MT) #define hb_atomic_int_impl_add(AI, V) ((*(AI) += (V)) - (V)) @@ -259,9 +149,11 @@ inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory #endif -#define HB_ATOMIC_INT_INIT(V) {V} struct hb_atomic_int_t { + hb_atomic_int_t () = default; + constexpr hb_atomic_int_t (int v) : v (v) {} + void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); } void set (int v_) { hb_atomic_int_impl_set (&v, v_); } int get_relaxed () const { return hb_atomic_int_impl_get_relaxed (&v); } @@ -269,16 +161,17 @@ struct hb_atomic_int_t int inc () { return hb_atomic_int_impl_add (&v, 1); } int dec () { return hb_atomic_int_impl_add (&v, -1); } - int v; + int v = 0; }; - -#define HB_ATOMIC_PTR_INIT(V) {V} template <typename P> struct hb_atomic_ptr_t { typedef hb_remove_pointer<P> T; + hb_atomic_ptr_t () = default; + constexpr hb_atomic_ptr_t (T* v) : v (v) {} + void init (T* v_ = nullptr) { set_relaxed (v_); } void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); } T *get_relaxed () const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); } @@ -288,7 +181,7 @@ struct hb_atomic_ptr_t T * operator -> () const { return get (); } template <typename C> operator C * () const { return get (); } - T *v; + T *v = nullptr; }; diff --git a/thirdparty/harfbuzz/src/hb-blob.cc b/thirdparty/harfbuzz/src/hb-blob.cc index e340bc346d..71b1b1fc4f 100644 --- a/thirdparty/harfbuzz/src/hb-blob.cc +++ b/thirdparty/harfbuzz/src/hb-blob.cc @@ -35,9 +35,6 @@ #include <sys/mman.h> #endif /* HAVE_SYS_MMAN_H */ -#include <stdio.h> -#include <stdlib.h> - /** * SECTION: hb-blob @@ -58,7 +55,7 @@ * @length: Length of @data in bytes. * @mode: Memory mode for @data. * @user_data: Data parameter to pass to @destroy. - * @destroy: (optional): Callback to call when @data is not needed anymore. + * @destroy: (nullable): Callback to call when @data is not needed anymore. * * Creates a new "blob" object wrapping @data. The @mode parameter is used * to negotiate ownership and lifecycle of @data. @@ -116,7 +113,7 @@ _hb_blob_destroy (void *data) * @length: Length of sub-blob. * * Returns a blob that represents a range of bytes in @parent. The new - * blob is always created with %HB_MEMORY_MODE_READONLY, meaning that it + * blob is always created with #HB_MEMORY_MODE_READONLY, meaning that it * will never modify data in the parent blob. The parent data is not * expected to be modified, and will result in undefined behavior if it * is. @@ -237,7 +234,7 @@ hb_blob_destroy (hb_blob_t *blob) * @blob: An #hb_blob_t * @key: The user-data key to set * @data: A pointer to the user data to set - * @destroy: (optional): A callback to call when @data is not needed anymore + * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * * Attaches a user-data key/data pair to the specified blob. @@ -299,7 +296,7 @@ hb_blob_make_immutable (hb_blob_t *blob) * * Tests whether a blob is immutable. * - * Return value: %true if @blob is immutable, false otherwise + * Return value: %true if @blob is immutable, %false otherwise * * Since: 0.9.2 **/ @@ -365,16 +362,14 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length) char * hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) { - if (!blob->try_make_writable ()) { - if (length) - *length = 0; - + if (hb_object_is_immutable (blob) || + !blob->try_make_writable ()) + { + if (length) *length = 0; return nullptr; } - if (length) - *length = blob->length; - + if (length) *length = blob->length; return const_cast<char *> (blob->data); } @@ -440,8 +435,8 @@ hb_blob_t::try_make_writable_inplace () bool hb_blob_t::try_make_writable () { - if (hb_object_is_immutable (this)) - return false; + if (unlikely (!length)) + mode = HB_MEMORY_MODE_WRITABLE; if (this->mode == HB_MEMORY_MODE_WRITABLE) return true; diff --git a/thirdparty/harfbuzz/src/hb-blob.h b/thirdparty/harfbuzz/src/hb-blob.h index 00e41f3ce3..86f12788d2 100644 --- a/thirdparty/harfbuzz/src/hb-blob.h +++ b/thirdparty/harfbuzz/src/hb-blob.h @@ -24,7 +24,7 @@ * Red Hat Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif @@ -38,10 +38,12 @@ HB_BEGIN_DECLS /** * hb_memory_mode_t: - * @HB_MEMORY_MODE_DUPLICATE - * @HB_MEMORY_MODE_READONLY - * @HB_MEMORY_MODE_WRITABLE - * @HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE + * @HB_MEMORY_MODE_DUPLICATE: HarfBuzz immediately makes a copy of the data. + * @HB_MEMORY_MODE_READONLY: HarfBuzz client will never modify the data, + * and HarfBuzz will never modify the data. + * @HB_MEMORY_MODE_WRITABLE: HarfBuzz client made a copy of the data solely + * for HarfBuzz, so HarfBuzz may modify the data. + * @HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE: See above * * Data type holding the memory modes available to * client programs. diff --git a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc index f65bad45bb..6539b89640 100644 --- a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc +++ b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc @@ -400,8 +400,8 @@ _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer, * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * write serialized buffer into. * @buf_size: the size of @buf. - * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf. - * @font: (allow-none): the #hb_font_t used to shape this buffer, needed to + * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf. + * @font: (nullable): the #hb_font_t used to shape this buffer, needed to * read glyph names and extents. If %NULL, and empty font will be used. * @format: the #hb_buffer_serialize_format_t to use for formatting the output. * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties @@ -514,8 +514,10 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer, * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * write serialized buffer into. * @buf_size: the size of @buf. - * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf. + * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf. * @format: the #hb_buffer_serialize_format_t to use for formatting the output. + * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties + * to serialize. * * Serializes @buffer into a textual representation of its content, * when the buffer contains Unicode codepoints (i.e., before shaping). This is @@ -635,8 +637,8 @@ _hb_buffer_serialize_invalid (hb_buffer_t *buffer, * @buf: (out) (array length=buf_size) (element-type uint8_t): output string to * write serialized buffer into. * @buf_size: the size of @buf. - * @buf_consumed: (out) (allow-none): if not %NULL, will be set to the number of byes written into @buf. - * @font: (allow-none): the #hb_font_t used to shape this buffer, needed to + * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf. + * @font: (nullable): the #hb_font_t used to shape this buffer, needed to * read glyph names and extents. If %NULL, and empty font will be used. * @format: the #hb_buffer_serialize_format_t to use for formatting the output. * @flags: the #hb_buffer_serialize_flags_t that control what glyph properties @@ -724,15 +726,17 @@ parse_hex (const char *pp, const char *end, uint32_t *pv) /** * hb_buffer_deserialize_glyphs: * @buffer: an #hb_buffer_t buffer. - * @buf: (array length=buf_len): - * @buf_len: - * @end_ptr: (out): - * @font: - * @format: - * + * @buf: (array length=buf_len): string to deserialize + * @buf_len: the size of @buf, or -1 if it is %NULL-terminated + * @end_ptr: (out) (optional): output pointer to the character after last + * consumed one. + * @font: (nullable): font for getting glyph IDs + * @format: the #hb_buffer_serialize_format_t of the input @buf * + * Deserializes glyphs @buffer from textual representation in the format + * produced by hb_buffer_serialize_glyphs(). * - * Return value: + * Return value: %true if @buf is not fully consumed, %false otherwise. * * Since: 0.9.7 **/ @@ -795,14 +799,16 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer, /** * hb_buffer_deserialize_unicode: * @buffer: an #hb_buffer_t buffer. - * @buf: (array length=buf_len): - * @buf_len: - * @end_ptr: (out): - * @format: - * + * @buf: (array length=buf_len): string to deserialize + * @buf_len: the size of @buf, or -1 if it is %NULL-terminated + * @end_ptr: (out) (optional): output pointer to the character after last + * consumed one. + * @format: the #hb_buffer_serialize_format_t of the input @buf * + * Deserializes Unicode @buffer from textual representation in the format + * produced by hb_buffer_serialize_unicode(). * - * Return value: + * Return value: %true if @buf is not fully consumed, %false otherwise. * * Since: 2.7.3 **/ diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc index 10063db050..8cad6ab8e6 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.cc +++ b/thirdparty/harfbuzz/src/hb-buffer.cc @@ -218,9 +218,6 @@ hb_buffer_t::get_scratch_buffer (unsigned int *size) void hb_buffer_t::reset () { - if (unlikely (hb_object_is_immutable (this))) - return; - hb_unicode_funcs_destroy (unicode); unicode = hb_unicode_funcs_reference (hb_unicode_funcs_get_default ()); flags = HB_BUFFER_FLAG_DEFAULT; @@ -233,9 +230,6 @@ hb_buffer_t::reset () void hb_buffer_t::clear () { - if (unlikely (hb_object_is_immutable (this))) - return; - hb_segment_properties_t default_props = HB_SEGMENT_PROPERTIES_DEFAULT; props = default_props; scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; @@ -290,9 +284,6 @@ hb_buffer_t::add_info (const hb_glyph_info_t &glyph_info) void hb_buffer_t::remove_output () { - if (unlikely (hb_object_is_immutable (this))) - return; - have_output = false; have_positions = false; @@ -303,9 +294,6 @@ hb_buffer_t::remove_output () void hb_buffer_t::clear_output () { - if (unlikely (hb_object_is_immutable (this))) - return; - have_output = true; have_positions = false; @@ -316,9 +304,6 @@ hb_buffer_t::clear_output () void hb_buffer_t::clear_positions () { - if (unlikely (hb_object_is_immutable (this))) - return; - have_output = false; have_positions = true; @@ -333,15 +318,19 @@ hb_buffer_t::swap_buffers () { if (unlikely (!successful)) return; + assert (idx <= len); + if (unlikely (!next_glyphs (len - idx))) return; + assert (have_output); have_output = false; if (out_info != info) { - hb_glyph_info_t *tmp_string; - tmp_string = info; + hb_glyph_info_t *tmp; + tmp = info; info = out_info; - out_info = tmp_string; + out_info = tmp; + pos = (hb_glyph_position_t *) out_info; } @@ -353,31 +342,6 @@ hb_buffer_t::swap_buffers () idx = 0; } - -void -hb_buffer_t::replace_glyphs (unsigned int num_in, - unsigned int num_out, - const uint32_t *glyph_data) -{ - if (unlikely (!make_room_for (num_in, num_out))) return; - - assert (idx + num_in <= len); - - merge_clusters (idx, idx + num_in); - - hb_glyph_info_t orig_info = info[idx]; - hb_glyph_info_t *pinfo = &out_info[out_len]; - for (unsigned int i = 0; i < num_out; i++) - { - *pinfo = orig_info; - pinfo->codepoint = glyph_data[i]; - pinfo++; - } - - idx += num_in; - out_len += num_out; -} - bool hb_buffer_t::move_to (unsigned int i) { @@ -768,7 +732,7 @@ hb_buffer_destroy (hb_buffer_t *buffer) * @buffer: An #hb_buffer_t * @key: The user-data key * @data: A pointer to the user data - * @destroy: (optional): A callback to call when @data is not needed anymore + * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * * Attaches a user-data key/data pair to the specified buffer. @@ -795,7 +759,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer, * Fetches the user data associated with the specified key, * attached to the specified buffer. * - * Return value: (transfer-none): A pointer to the user data + * Return value: (transfer none): A pointer to the user data * * Since: 0.9.2 **/ @@ -1137,7 +1101,7 @@ hb_buffer_get_cluster_level (hb_buffer_t *buffer) * Sets the #hb_codepoint_t that replaces invalid entries for a given encoding * when adding text to @buffer. * - * Default is %HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT. + * Default is #HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT. * * Since: 0.9.31 **/ @@ -1222,6 +1186,9 @@ hb_buffer_get_invisible_glyph (hb_buffer_t *buffer) void hb_buffer_reset (hb_buffer_t *buffer) { + if (unlikely (hb_object_is_immutable (buffer))) + return; + buffer->reset (); } @@ -1237,6 +1204,9 @@ hb_buffer_reset (hb_buffer_t *buffer) void hb_buffer_clear_contents (hb_buffer_t *buffer) { + if (unlikely (hb_object_is_immutable (buffer))) + return; + buffer->clear (); } @@ -1321,7 +1291,7 @@ hb_buffer_set_length (hb_buffer_t *buffer, if (unlikely (hb_object_is_immutable (buffer))) return length == 0; - if (!buffer->ensure (length)) + if (unlikely (!buffer->ensure (length))) return false; /* Wipe the new space */ @@ -1501,20 +1471,20 @@ hb_buffer_reverse_clusters (hb_buffer_t *buffer) * * Sets unset buffer segment properties based on buffer Unicode * contents. If buffer is not empty, it must have content type - * %HB_BUFFER_CONTENT_TYPE_UNICODE. + * #HB_BUFFER_CONTENT_TYPE_UNICODE. * - * If buffer script is not set (ie. is %HB_SCRIPT_INVALID), it + * If buffer script is not set (ie. is #HB_SCRIPT_INVALID), it * will be set to the Unicode script of the first character in - * the buffer that has a script other than %HB_SCRIPT_COMMON, - * %HB_SCRIPT_INHERITED, and %HB_SCRIPT_UNKNOWN. + * the buffer that has a script other than #HB_SCRIPT_COMMON, + * #HB_SCRIPT_INHERITED, and #HB_SCRIPT_UNKNOWN. * - * Next, if buffer direction is not set (ie. is %HB_DIRECTION_INVALID), + * Next, if buffer direction is not set (ie. is #HB_DIRECTION_INVALID), * it will be set to the natural horizontal direction of the * buffer script as returned by hb_script_get_horizontal_direction(). - * If hb_script_get_horizontal_direction() returns %HB_DIRECTION_INVALID, - * then %HB_DIRECTION_LTR is used. + * If hb_script_get_horizontal_direction() returns #HB_DIRECTION_INVALID, + * then #HB_DIRECTION_LTR is used. * - * Finally, if buffer language is not set (ie. is %HB_LANGUAGE_INVALID), + * Finally, if buffer language is not set (ie. is #HB_LANGUAGE_INVALID), * it will be set to the process's default language as returned by * hb_language_get_default(). This may change in the future by * taking buffer script into consideration when choosing a language. @@ -1551,7 +1521,10 @@ hb_buffer_add_utf (hb_buffer_t *buffer, if (item_length == -1) item_length = text_length - item_offset; - buffer->ensure (buffer->len + item_length * sizeof (T) / 4); + if (unlikely (item_length < 0 || + item_length > INT_MAX / 8 || + !buffer->ensure (buffer->len + item_length * sizeof (T) / 4))) + return; /* If buffer is empty and pre-context provided, install it. * This check is written this way, to make sure people can @@ -1768,11 +1741,6 @@ hb_buffer_append (hb_buffer_t *buffer, if (start == end) return; - if (!buffer->len) - buffer->content_type = source->content_type; - if (!buffer->have_positions && source->have_positions) - buffer->clear_positions (); - if (buffer->len + (end - start) < buffer->len) /* Overflows. */ { buffer->successful = false; @@ -1784,6 +1752,11 @@ hb_buffer_append (hb_buffer_t *buffer, if (unlikely (!buffer->successful)) return; + if (!orig_len) + buffer->content_type = source->content_type; + if (!buffer->have_positions && source->have_positions) + buffer->clear_positions (); + memcpy (buffer->info + orig_len, source->info + start, (end - start) * sizeof (buffer->info[0])); if (buffer->have_positions) memcpy (buffer->pos + orig_len, source->pos + start, (end - start) * sizeof (buffer->pos[0])); @@ -1902,8 +1875,8 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g * @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1. * @position_fuzz: allowed absolute difference in position values. * - * If dottedcircle_glyph is (hb_codepoint_t) -1 then %HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT - * and %HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most + * If dottedcircle_glyph is (hb_codepoint_t) -1 then #HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT + * and #HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT are never returned. This should be used by most * callers if just comparing two buffers is needed. * * Since: 1.5.0 @@ -1994,11 +1967,11 @@ hb_buffer_diff (hb_buffer_t *buffer, /** * hb_buffer_set_message_func: * @buffer: An #hb_buffer_t - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: - * + * @func: (closure user_data) (destroy destroy) (scope notified): Callback function + * @user_data: (nullable): Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore * + * Sets the implementation function for #hb_buffer_message_func_t. * * Since: 1.1.3 **/ diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h index b13757e68f..865ccb2273 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.h +++ b/thirdparty/harfbuzz/src/hb-buffer.h @@ -27,7 +27,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif @@ -90,6 +90,8 @@ typedef struct hb_glyph_info_t { * breaking point only. * @HB_GLYPH_FLAG_DEFINED: All the currently defined flags. * + * Flags for #hb_glyph_info_t. + * * Since: 1.5.0 */ typedef enum { /*< flags >*/ @@ -150,6 +152,11 @@ typedef struct hb_segment_properties_t { void *reserved2; } hb_segment_properties_t; +/** + * HB_SEGMENT_PROPERTIES_DEFAULT: + * + * The default #hb_segment_properties_t of of freshly created #hb_buffer_t. + */ #define HB_SEGMENT_PROPERTIES_DEFAULT {HB_DIRECTION_INVALID, \ HB_SCRIPT_INVALID, \ HB_LANGUAGE_INVALID, \ @@ -203,6 +210,8 @@ hb_buffer_get_user_data (hb_buffer_t *buffer, * @HB_BUFFER_CONTENT_TYPE_INVALID: Initial value for new buffer. * @HB_BUFFER_CONTENT_TYPE_UNICODE: The buffer contains input characters (before shaping). * @HB_BUFFER_CONTENT_TYPE_GLYPHS: The buffer contains output glyphs (after shaping). + * + * The type of #hb_buffer_t contents. */ typedef enum { HB_BUFFER_CONTENT_TYPE_INVALID = 0, @@ -288,6 +297,8 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer); * not be inserted in the rendering of incorrect * character sequences (such at <0905 093E>). Since: 2.4 * + * Flags for #hb_buffer_t. + * * Since: 0.9.20 */ typedef enum { /*< flags >*/ @@ -579,6 +590,35 @@ hb_buffer_deserialize_unicode (hb_buffer_t *buffer, * Compare buffers */ +/** + * hb_buffer_diff_flags_t: + * @HB_BUFFER_DIFF_FLAG_EQUAL: equal buffers. + * @HB_BUFFER_DIFF_FLAG_CONTENT_TYPE_MISMATCH: buffers with different + * #hb_buffer_content_type_t. + * @HB_BUFFER_DIFF_FLAG_LENGTH_MISMATCH: buffers with differing length. + * @HB_BUFFER_DIFF_FLAG_NOTDEF_PRESENT: `.notdef` glyph is present in the + * reference buffer. + * @HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT: dotted circle glyph is present + * in the reference buffer. + * @HB_BUFFER_DIFF_FLAG_CODEPOINT_MISMATCH: difference in #hb_glyph_info_t.codepoint + * @HB_BUFFER_DIFF_FLAG_CLUSTER_MISMATCH: difference in #hb_glyph_info_t.cluster + * @HB_BUFFER_DIFF_FLAG_GLYPH_FLAGS_MISMATCH: difference in #hb_glyph_flags_t. + * @HB_BUFFER_DIFF_FLAG_POSITION_MISMATCH: difference in #hb_glyph_position_t. + * + * Flags from comparing two #hb_buffer_t's. + * + * Buffer with different #hb_buffer_content_type_t cannot be meaningfully + * compared in any further detail. + * + * For buffers with differing length, the per-glyph comparison is not + * attempted, though we do still scan reference buffer for dotted circle and + * `.notdef` glyphs. + * + * If the buffers have the same length, we compare them glyph-by-glyph and + * report which aspect(s) of the glyph info/position are different. + * + * Since: 1.5.0 + */ typedef enum { /*< flags >*/ HB_BUFFER_DIFF_FLAG_EQUAL = 0x0000, @@ -618,6 +658,23 @@ hb_buffer_diff (hb_buffer_t *buffer, * Debugging. */ +/** + * hb_buffer_message_func_t: + * @buffer: An #hb_buffer_t to work upon + * @font: The #hb_font_t the @buffer is shaped with + * @message: %NULL-terminated message passed to the function + * @user_data: User data pointer passed by the caller + * + * A callback method for #hb_buffer_t. The method gets called with the + * #hb_buffer_t it was set on, the #hb_font_t the buffer is shaped with and a + * message describing what step of the shaping process will be performed. + * Returning %false from this method will skip this shaping step and move to + * the next one. + * + * Return value: %true to perform the shaping step, %false to skip it. + * + * Since: 1.1.3 + */ typedef hb_bool_t (*hb_buffer_message_func_t) (hb_buffer_t *buffer, hb_font_t *font, const char *message, diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh index 9cad5206e2..8b432b5f96 100644 --- a/thirdparty/harfbuzz/src/hb-buffer.hh +++ b/thirdparty/harfbuzz/src/hb-buffer.hh @@ -139,7 +139,7 @@ struct hb_buffer_t /* Methods */ - bool in_error () const { return !successful; } + HB_NODISCARD bool in_error () const { return !successful; } void allocate_var (unsigned int start, unsigned int count) { @@ -186,7 +186,7 @@ struct hb_buffer_t hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; } hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; } - bool has_separate_output () const { return info != out_info; } + HB_NODISCARD bool has_separate_output () const { return info != out_info; } HB_INTERNAL void reset (); @@ -210,86 +210,89 @@ struct hb_buffer_t HB_INTERNAL void clear_output (); HB_INTERNAL void clear_positions (); - HB_INTERNAL void replace_glyphs (unsigned int num_in, - unsigned int num_out, - const hb_codepoint_t *glyph_data); - - void replace_glyph (hb_codepoint_t glyph_index) + template <typename T> + HB_NODISCARD bool replace_glyphs (unsigned int num_in, + unsigned int num_out, + const T *glyph_data) { - if (unlikely (out_info != info || out_len != idx)) { - if (unlikely (!make_room_for (1, 1))) return; - out_info[out_len] = info[idx]; - } - out_info[out_len].codepoint = glyph_index; + if (unlikely (!make_room_for (num_in, num_out))) return false; - idx++; - out_len++; - } - /* Makes a copy of the glyph at idx to output and replace glyph_index */ - hb_glyph_info_t & output_glyph (hb_codepoint_t glyph_index) - { - if (unlikely (!make_room_for (0, 1))) return Crap (hb_glyph_info_t); + assert (idx + num_in <= len); - if (unlikely (idx == len && !out_len)) - return Crap (hb_glyph_info_t); + merge_clusters (idx, idx + num_in); - out_info[out_len] = idx < len ? info[idx] : out_info[out_len - 1]; - out_info[out_len].codepoint = glyph_index; + hb_glyph_info_t &orig_info = idx < len ? cur() : prev(); - out_len++; + hb_glyph_info_t *pinfo = &out_info[out_len]; + for (unsigned int i = 0; i < num_out; i++) + { + *pinfo = orig_info; + pinfo->codepoint = glyph_data[i]; + pinfo++; + } - return out_info[out_len - 1]; + idx += num_in; + out_len += num_out; + return true; } - void output_info (const hb_glyph_info_t &glyph_info) + + HB_NODISCARD bool replace_glyph (hb_codepoint_t glyph_index) + { return replace_glyphs (1, 1, &glyph_index); } + + /* Makes a copy of the glyph at idx to output and replace glyph_index */ + HB_NODISCARD bool output_glyph (hb_codepoint_t glyph_index) + { return replace_glyphs (0, 1, &glyph_index); } + + HB_NODISCARD bool output_info (const hb_glyph_info_t &glyph_info) { - if (unlikely (!make_room_for (0, 1))) return; + if (unlikely (!make_room_for (0, 1))) return false; out_info[out_len] = glyph_info; out_len++; + return true; } /* Copies glyph at idx to output but doesn't advance idx */ - void copy_glyph () + HB_NODISCARD bool copy_glyph () { - if (unlikely (!make_room_for (0, 1))) return; - - out_info[out_len] = info[idx]; - - out_len++; + /* Extra copy because cur()'s return can be freed within + * output_info() call if buffer reallocates. */ + return output_info (hb_glyph_info_t (cur())); } + /* Copies glyph at idx to output and advance idx. * If there's no output, just advance idx. */ - void - next_glyph () + HB_NODISCARD bool next_glyph () { if (have_output) { if (out_info != info || out_len != idx) { - if (unlikely (!make_room_for (1, 1))) return; + if (unlikely (!make_room_for (1, 1))) return false; out_info[out_len] = info[idx]; } out_len++; } idx++; + return true; } /* Copies n glyphs at idx to output and advance idx. * If there's no output, just advance idx. */ - void - next_glyphs (unsigned int n) + HB_NODISCARD bool next_glyphs (unsigned int n) { if (have_output) { if (out_info != info || out_len != idx) { - if (unlikely (!make_room_for (n, n))) return; + if (unlikely (!make_room_for (n, n))) return false; memmove (out_info + out_len, info + idx, n * sizeof (out_info[0])); } out_len += n; } idx += n; + return true; } /* Advance idx without copying to output. */ void skip_glyph () { idx++; } @@ -329,14 +332,14 @@ struct hb_buffer_t /* Internal methods */ - HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */ + HB_NODISCARD HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */ - HB_INTERNAL bool enlarge (unsigned int size); + HB_NODISCARD HB_INTERNAL bool enlarge (unsigned int size); - bool ensure (unsigned int size) + HB_NODISCARD bool ensure (unsigned int size) { return likely (!size || size < allocated) ? true : enlarge (size); } - bool ensure_inplace (unsigned int size) + HB_NODISCARD bool ensure_inplace (unsigned int size) { return likely (!size || size < allocated); } void assert_glyphs () @@ -349,7 +352,7 @@ struct hb_buffer_t assert ((content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) || (!len && (content_type == HB_BUFFER_CONTENT_TYPE_INVALID))); } - bool ensure_glyphs () + HB_NODISCARD bool ensure_glyphs () { if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS)) { @@ -360,7 +363,7 @@ struct hb_buffer_t } return true; } - bool ensure_unicode () + HB_NODISCARD bool ensure_unicode () { if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_UNICODE)) { @@ -372,8 +375,8 @@ struct hb_buffer_t return true; } - HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out); - HB_INTERNAL bool shift_forward (unsigned int count); + HB_NODISCARD HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out); + HB_NODISCARD HB_INTERNAL bool shift_forward (unsigned int count); typedef long scratch_buffer_t; HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size); diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc index ddbcaa064c..7bb878b217 100644 --- a/thirdparty/harfbuzz/src/hb-common.cc +++ b/thirdparty/harfbuzz/src/hb-common.cc @@ -675,8 +675,8 @@ hb_version_string () * Tests the library version against a minimum value, * as three integer components. * - * Return value: True if the library is equal to or greater than - * the test value, false otherwise + * Return value: %true if the library is equal to or greater than + * the test value, %false otherwise * * Since: 0.9.30 **/ @@ -1003,6 +1003,21 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation /** * hb_variation_from_string: + * @str: (array length=len) (element-type uint8_t): a string to parse + * @len: length of @str, or -1 if string is %NULL terminated + * @variation: (out): the #hb_variation_t to initialize with the parsed values + * + * Parses a string into a #hb_variation_t. + * + * The format for specifying variation settings follows. All valid CSS + * font-variation-settings values other than 'normal' and 'inherited' are also + * accepted, though, not documented below. + * + * The format is a tag, optionally followed by an equals sign, followed by a + * number. For example `wght=500`, or `slnt=-7.5`. + * + * Return value: + * %true if @str is successfully parsed, %false otherwise * * Since: 1.4.2 */ @@ -1029,6 +1044,13 @@ hb_variation_from_string (const char *str, int len, /** * hb_variation_to_string: + * @variation: an #hb_variation_t to convert + * @buf: (array length=size) (out): output string + * @size: the allocated size of @buf + * + * Converts an #hb_variation_t into a %NULL-terminated string in the format + * understood by hb_variation_from_string(). The client in responsible for + * allocating big enough size for @buf, 128 bytes is more than enough. * * Since: 1.4.2 */ @@ -1055,9 +1077,11 @@ hb_variation_to_string (hb_variation_t *variation, /** * hb_color_get_alpha: - * color: a #hb_color_t we are interested in its channels. + * @color: an #hb_color_t we are interested in its channels. * - * Return value: Alpha channel value of the given color + * Fetches the alpha channel of the given @color. + * + * Return value: Alpha channel value * * Since: 2.1.0 */ @@ -1069,9 +1093,11 @@ uint8_t /** * hb_color_get_red: - * color: a #hb_color_t we are interested in its channels. + * @color: an #hb_color_t we are interested in its channels. + * + * Fetches the red channel of the given @color. * - * Return value: Red channel value of the given color + * Return value: Red channel value * * Since: 2.1.0 */ @@ -1083,9 +1109,11 @@ uint8_t /** * hb_color_get_green: - * color: a #hb_color_t we are interested in its channels. + * @color: an #hb_color_t we are interested in its channels. * - * Return value: Green channel value of the given color + * Fetches the green channel of the given @color. + * + * Return value: Green channel value * * Since: 2.1.0 */ @@ -1097,9 +1125,11 @@ uint8_t /** * hb_color_get_blue: - * color: a #hb_color_t we are interested in its channels. + * @color: an #hb_color_t we are interested in its channels. + * + * Fetches the blue channel of the given @color. * - * Return value: Blue channel value of the given color + * Return value: Blue channel value * * Since: 2.1.0 */ diff --git a/thirdparty/harfbuzz/src/hb-common.h b/thirdparty/harfbuzz/src/hb-common.h index efe185cdfd..532fd428cb 100644 --- a/thirdparty/harfbuzz/src/hb-common.h +++ b/thirdparty/harfbuzz/src/hb-common.h @@ -26,7 +26,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif @@ -135,7 +135,7 @@ typedef union _hb_var_int_t { /** * hb_tag_t: - * + * * Data type for tag identifiers. Tags are four * byte integers, each byte representing a character. * @@ -148,22 +148,48 @@ typedef uint32_t hb_tag_t; /** * HB_TAG: + * @c1: 1st character of the tag + * @c2: 2nd character of the tag + * @c3: 3rd character of the tag + * @c4: 4th character of the tag * - * Constructs an #hb_tag_t from four characters. + * Constructs an #hb_tag_t from four character literals. * **/ #define HB_TAG(c1,c2,c3,c4) ((hb_tag_t)((((uint32_t)(c1)&0xFF)<<24)|(((uint32_t)(c2)&0xFF)<<16)|(((uint32_t)(c3)&0xFF)<<8)|((uint32_t)(c4)&0xFF))) /** * HB_UNTAG: + * @tag: an #hb_tag_t + * + * Extracts four character literals from an #hb_tag_t. * - * Extracts the characters from an #hb_tag_t. + * Since: 0.6.0 * **/ #define HB_UNTAG(tag) (uint8_t)(((tag)>>24)&0xFF), (uint8_t)(((tag)>>16)&0xFF), (uint8_t)(((tag)>>8)&0xFF), (uint8_t)((tag)&0xFF) +/** + * HB_TAG_NONE: + * + * Unset #hb_tag_t. + */ #define HB_TAG_NONE HB_TAG(0,0,0,0) +/** + * HB_TAG_MAX: + * + * Maximum possible unsigned #hb_tag_t. + * + * Since: 0.9.26 + */ #define HB_TAG_MAX HB_TAG(0xff,0xff,0xff,0xff) +/** + * HB_TAG_MAX_SIGNED: + * + * Maximum possible signed #hb_tag_t. + * + * Since: 0.9.33 + */ #define HB_TAG_MAX_SIGNED HB_TAG(0x7f,0xff,0xff,0xff) /* len=-1 means str is NUL-terminated. */ @@ -263,6 +289,13 @@ hb_direction_to_string (hb_direction_t direction); /* hb_language_t */ +/** + * hb_language_t: + * + * Data type for languages. Each #hb_language_t corresponds to a BCP 47 + * language tag. + * + */ typedef const struct hb_language_impl_t *hb_language_t; HB_EXTERN hb_language_t @@ -271,6 +304,13 @@ hb_language_from_string (const char *str, int len); HB_EXTERN const char * hb_language_to_string (hb_language_t language); +/** + * HB_LANGUAGE_INVALID: + * + * An unset #hb_language_t. + * + * Since: 0.6.0 + */ #define HB_LANGUAGE_INVALID ((hb_language_t) 0) HB_EXTERN hb_language_t @@ -279,160 +319,164 @@ hb_language_get_default (void); /** * hb_script_t: - * @HB_SCRIPT_COMMON: HB_TAG ('Z','y','y','y') - * @HB_SCRIPT_INHERITED: HB_TAG ('Z','i','n','h') - * @HB_SCRIPT_UNKNOWN: HB_TAG ('Z','z','z','z') - * @HB_SCRIPT_ARABIC - * @HB_SCRIPT_ARMENIAN - * @HB_SCRIPT_BENGALI - * @HB_SCRIPT_CYRILLIC - * @HB_SCRIPT_DEVANAGARI - * @HB_SCRIPT_GEORGIAN - * @HB_SCRIPT_GREEK - * @HB_SCRIPT_GUJARATI - * @HB_SCRIPT_GURMUKHI - * @HB_SCRIPT_HANGUL - * @HB_SCRIPT_HAN - * @HB_SCRIPT_HEBREW - * @HB_SCRIPT_HIRAGANA - * @HB_SCRIPT_KANNADA - * @HB_SCRIPT_KATAKANA - * @HB_SCRIPT_LAO - * @HB_SCRIPT_LATIN - * @HB_SCRIPT_MALAYALAM - * @HB_SCRIPT_ORIYA - * @HB_SCRIPT_TAMIL - * @HB_SCRIPT_TELUGU - * @HB_SCRIPT_THAI - * @HB_SCRIPT_TIBETAN - * @HB_SCRIPT_BOPOMOFO - * @HB_SCRIPT_BRAILLE - * @HB_SCRIPT_CANADIAN_SYLLABICS - * @HB_SCRIPT_CHEROKEE - * @HB_SCRIPT_ETHIOPIC - * @HB_SCRIPT_KHMER - * @HB_SCRIPT_MONGOLIAN - * @HB_SCRIPT_MYANMAR - * @HB_SCRIPT_OGHAM - * @HB_SCRIPT_RUNIC - * @HB_SCRIPT_SINHALA - * @HB_SCRIPT_SYRIAC - * @HB_SCRIPT_THAANA - * @HB_SCRIPT_YI - * @HB_SCRIPT_DESERET - * @HB_SCRIPT_GOTHIC - * @HB_SCRIPT_OLD_ITALIC - * @HB_SCRIPT_BUHID - * @HB_SCRIPT_HANUNOO - * @HB_SCRIPT_TAGALOG - * @HB_SCRIPT_TAGBANWA - * @HB_SCRIPT_CYPRIOT - * @HB_SCRIPT_LIMBU - * @HB_SCRIPT_LINEAR_B - * @HB_SCRIPT_OSMANYA - * @HB_SCRIPT_SHAVIAN - * @HB_SCRIPT_TAI_LE - * @HB_SCRIPT_UGARITIC - * @HB_SCRIPT_BUGINESE - * @HB_SCRIPT_COPTIC - * @HB_SCRIPT_GLAGOLITIC - * @HB_SCRIPT_KHAROSHTHI - * @HB_SCRIPT_NEW_TAI_LUE - * @HB_SCRIPT_OLD_PERSIAN - * @HB_SCRIPT_SYLOTI_NAGRI - * @HB_SCRIPT_TIFINAGH - * @HB_SCRIPT_BALINESE - * @HB_SCRIPT_CUNEIFORM - * @HB_SCRIPT_NKO - * @HB_SCRIPT_PHAGS_PA - * @HB_SCRIPT_PHOENICIAN - * @HB_SCRIPT_CARIAN - * @HB_SCRIPT_CHAM - * @HB_SCRIPT_KAYAH_LI - * @HB_SCRIPT_LEPCHA - * @HB_SCRIPT_LYCIAN - * @HB_SCRIPT_LYDIAN - * @HB_SCRIPT_OL_CHIKI - * @HB_SCRIPT_REJANG - * @HB_SCRIPT_SAURASHTRA - * @HB_SCRIPT_SUNDANESE - * @HB_SCRIPT_VAI - * @HB_SCRIPT_AVESTAN - * @HB_SCRIPT_BAMUM - * @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS - * @HB_SCRIPT_IMPERIAL_ARAMAIC - * @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI - * @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN - * @HB_SCRIPT_JAVANESE - * @HB_SCRIPT_KAITHI - * @HB_SCRIPT_LISU - * @HB_SCRIPT_MEETEI_MAYEK - * @HB_SCRIPT_OLD_SOUTH_ARABIAN - * @HB_SCRIPT_OLD_TURKIC - * @HB_SCRIPT_SAMARITAN - * @HB_SCRIPT_TAI_THAM - * @HB_SCRIPT_TAI_VIET - * @HB_SCRIPT_BATAK - * @HB_SCRIPT_BRAHMI - * @HB_SCRIPT_MANDAIC - * @HB_SCRIPT_CHAKMA - * @HB_SCRIPT_MEROITIC_CURSIVE - * @HB_SCRIPT_MEROITIC_HIEROGLYPHS - * @HB_SCRIPT_MIAO - * @HB_SCRIPT_SHARADA - * @HB_SCRIPT_SORA_SOMPENG - * @HB_SCRIPT_TAKRI - * @HB_SCRIPT_BASSA_VAH - * @HB_SCRIPT_CAUCASIAN_ALBANIAN - * @HB_SCRIPT_DUPLOYAN - * @HB_SCRIPT_ELBASAN - * @HB_SCRIPT_GRANTHA - * @HB_SCRIPT_KHOJKI - * @HB_SCRIPT_KHUDAWADI - * @HB_SCRIPT_LINEAR_A - * @HB_SCRIPT_MAHAJANI - * @HB_SCRIPT_MANICHAEAN - * @HB_SCRIPT_MENDE_KIKAKUI - * @HB_SCRIPT_MODI - * @HB_SCRIPT_MRO - * @HB_SCRIPT_NABATAEAN - * @HB_SCRIPT_OLD_NORTH_ARABIAN - * @HB_SCRIPT_OLD_PERMIC - * @HB_SCRIPT_PAHAWH_HMONG - * @HB_SCRIPT_PALMYRENE - * @HB_SCRIPT_PAU_CIN_HAU - * @HB_SCRIPT_PSALTER_PAHLAVI - * @HB_SCRIPT_SIDDHAM - * @HB_SCRIPT_TIRHUTA - * @HB_SCRIPT_WARANG_CITI - * @HB_SCRIPT_AHOM - * @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS - * @HB_SCRIPT_HATRAN - * @HB_SCRIPT_MULTANI - * @HB_SCRIPT_OLD_HUNGARIAN - * @HB_SCRIPT_SIGNWRITING - * @HB_SCRIPT_ADLAM - * @HB_SCRIPT_BHAIKSUKI - * @HB_SCRIPT_MARCHEN - * @HB_SCRIPT_OSAGE - * @HB_SCRIPT_TANGUT - * @HB_SCRIPT_NEWA - * @HB_SCRIPT_MASARAM_GONDI - * @HB_SCRIPT_NUSHU - * @HB_SCRIPT_SOYOMBO - * @HB_SCRIPT_ZANABAZAR_SQUARE - * @HB_SCRIPT_DOGRA - * @HB_SCRIPT_GUNJALA_GONDI - * @HB_SCRIPT_HANIFI_ROHINGYA - * @HB_SCRIPT_MAKASAR - * @HB_SCRIPT_MEDEFAIDRIN - * @HB_SCRIPT_OLD_SOGDIAN - * @HB_SCRIPT_SOGDIAN - * @HB_SCRIPT_ELYMAIC - * @HB_SCRIPT_NANDINAGARI - * @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG - * @HB_SCRIPT_WANCHO - * @HB_SCRIPT_INVALID: #HB_TAG_NONE + * @HB_SCRIPT_COMMON: `Zyyy` + * @HB_SCRIPT_INHERITED: `Zinh` + * @HB_SCRIPT_UNKNOWN: `Zzzz` + * @HB_SCRIPT_ARABIC: `Arab` + * @HB_SCRIPT_ARMENIAN: `Armn` + * @HB_SCRIPT_BENGALI: `Beng` + * @HB_SCRIPT_CYRILLIC: `Cyrl` + * @HB_SCRIPT_DEVANAGARI: `Deva` + * @HB_SCRIPT_GEORGIAN: `Geor` + * @HB_SCRIPT_GREEK: `Grek` + * @HB_SCRIPT_GUJARATI: `Gujr` + * @HB_SCRIPT_GURMUKHI: `Guru` + * @HB_SCRIPT_HANGUL: `Hang` + * @HB_SCRIPT_HAN: `Hani` + * @HB_SCRIPT_HEBREW: `Hebr` + * @HB_SCRIPT_HIRAGANA: `Hira` + * @HB_SCRIPT_KANNADA: `Knda` + * @HB_SCRIPT_KATAKANA: `Kana` + * @HB_SCRIPT_LAO: `Laoo` + * @HB_SCRIPT_LATIN: `Latn` + * @HB_SCRIPT_MALAYALAM: `Mlym` + * @HB_SCRIPT_ORIYA: `Orya` + * @HB_SCRIPT_TAMIL: `Taml` + * @HB_SCRIPT_TELUGU: `Telu` + * @HB_SCRIPT_THAI: `Thai` + * @HB_SCRIPT_TIBETAN: `Tibt` + * @HB_SCRIPT_BOPOMOFO: `Bopo` + * @HB_SCRIPT_BRAILLE: `Brai` + * @HB_SCRIPT_CANADIAN_SYLLABICS: `Cans` + * @HB_SCRIPT_CHEROKEE: `Cher` + * @HB_SCRIPT_ETHIOPIC: `Ethi` + * @HB_SCRIPT_KHMER: `Khmr` + * @HB_SCRIPT_MONGOLIAN: `Mong` + * @HB_SCRIPT_MYANMAR: `Mymr` + * @HB_SCRIPT_OGHAM: `Ogam` + * @HB_SCRIPT_RUNIC: `Runr` + * @HB_SCRIPT_SINHALA: `Sinh` + * @HB_SCRIPT_SYRIAC: `Syrc` + * @HB_SCRIPT_THAANA: `Thaa` + * @HB_SCRIPT_YI: `Yiii` + * @HB_SCRIPT_DESERET: `Dsrt` + * @HB_SCRIPT_GOTHIC: `Goth` + * @HB_SCRIPT_OLD_ITALIC: `Ital` + * @HB_SCRIPT_BUHID: `Buhd` + * @HB_SCRIPT_HANUNOO: `Hano` + * @HB_SCRIPT_TAGALOG: `Tglg` + * @HB_SCRIPT_TAGBANWA: `Tagb` + * @HB_SCRIPT_CYPRIOT: `Cprt` + * @HB_SCRIPT_LIMBU: `Limb` + * @HB_SCRIPT_LINEAR_B: `Linb` + * @HB_SCRIPT_OSMANYA: `Osma` + * @HB_SCRIPT_SHAVIAN: `Shaw` + * @HB_SCRIPT_TAI_LE: `Tale` + * @HB_SCRIPT_UGARITIC: `Ugar` + * @HB_SCRIPT_BUGINESE: `Bugi` + * @HB_SCRIPT_COPTIC: `Copt` + * @HB_SCRIPT_GLAGOLITIC: `Glag` + * @HB_SCRIPT_KHAROSHTHI: `Khar` + * @HB_SCRIPT_NEW_TAI_LUE: `Talu` + * @HB_SCRIPT_OLD_PERSIAN: `Xpeo` + * @HB_SCRIPT_SYLOTI_NAGRI: `Sylo` + * @HB_SCRIPT_TIFINAGH: `Tfng` + * @HB_SCRIPT_BALINESE: `Bali` + * @HB_SCRIPT_CUNEIFORM: `Xsux` + * @HB_SCRIPT_NKO: `Nkoo` + * @HB_SCRIPT_PHAGS_PA: `Phag` + * @HB_SCRIPT_PHOENICIAN: `Phnx` + * @HB_SCRIPT_CARIAN: `Cari` + * @HB_SCRIPT_CHAM: `Cham` + * @HB_SCRIPT_KAYAH_LI: `Kali` + * @HB_SCRIPT_LEPCHA: `Lepc` + * @HB_SCRIPT_LYCIAN: `Lyci` + * @HB_SCRIPT_LYDIAN: `Lydi` + * @HB_SCRIPT_OL_CHIKI: `Olck` + * @HB_SCRIPT_REJANG: `Rjng` + * @HB_SCRIPT_SAURASHTRA: `Saur` + * @HB_SCRIPT_SUNDANESE: `Sund` + * @HB_SCRIPT_VAI: `Vaii` + * @HB_SCRIPT_AVESTAN: `Avst` + * @HB_SCRIPT_BAMUM: `Bamu` + * @HB_SCRIPT_EGYPTIAN_HIEROGLYPHS: `Egyp` + * @HB_SCRIPT_IMPERIAL_ARAMAIC: `Armi` + * @HB_SCRIPT_INSCRIPTIONAL_PAHLAVI: `Phli` + * @HB_SCRIPT_INSCRIPTIONAL_PARTHIAN: `Prti` + * @HB_SCRIPT_JAVANESE: `Java` + * @HB_SCRIPT_KAITHI: `Kthi` + * @HB_SCRIPT_LISU: `Lisu` + * @HB_SCRIPT_MEETEI_MAYEK: `Mtei` + * @HB_SCRIPT_OLD_SOUTH_ARABIAN: `Sarb` + * @HB_SCRIPT_OLD_TURKIC: `Orkh` + * @HB_SCRIPT_SAMARITAN: `Samr` + * @HB_SCRIPT_TAI_THAM: `Lana` + * @HB_SCRIPT_TAI_VIET: `Tavt` + * @HB_SCRIPT_BATAK: `Batk` + * @HB_SCRIPT_BRAHMI: `Brah` + * @HB_SCRIPT_MANDAIC: `Mand` + * @HB_SCRIPT_CHAKMA: `Cakm` + * @HB_SCRIPT_MEROITIC_CURSIVE: `Merc` + * @HB_SCRIPT_MEROITIC_HIEROGLYPHS: `Mero` + * @HB_SCRIPT_MIAO: `Plrd` + * @HB_SCRIPT_SHARADA: `Shrd` + * @HB_SCRIPT_SORA_SOMPENG: `Sora` + * @HB_SCRIPT_TAKRI: `Takr` + * @HB_SCRIPT_BASSA_VAH: `Bass`, Since: 0.9.30 + * @HB_SCRIPT_CAUCASIAN_ALBANIAN: `Aghb`, Since: 0.9.30 + * @HB_SCRIPT_DUPLOYAN: `Dupl`, Since: 0.9.30 + * @HB_SCRIPT_ELBASAN: `Elba`, Since: 0.9.30 + * @HB_SCRIPT_GRANTHA: `Gran`, Since: 0.9.30 + * @HB_SCRIPT_KHOJKI: `Khoj`, Since: 0.9.30 + * @HB_SCRIPT_KHUDAWADI: `Sind`, Since: 0.9.30 + * @HB_SCRIPT_LINEAR_A: `Lina`, Since: 0.9.30 + * @HB_SCRIPT_MAHAJANI: `Mahj`, Since: 0.9.30 + * @HB_SCRIPT_MANICHAEAN: `Mani`, Since: 0.9.30 + * @HB_SCRIPT_MENDE_KIKAKUI: `Mend`, Since: 0.9.30 + * @HB_SCRIPT_MODI: `Modi`, Since: 0.9.30 + * @HB_SCRIPT_MRO: `Mroo`, Since: 0.9.30 + * @HB_SCRIPT_NABATAEAN: `Nbat`, Since: 0.9.30 + * @HB_SCRIPT_OLD_NORTH_ARABIAN: `Narb`, Since: 0.9.30 + * @HB_SCRIPT_OLD_PERMIC: `Perm`, Since: 0.9.30 + * @HB_SCRIPT_PAHAWH_HMONG: `Hmng`, Since: 0.9.30 + * @HB_SCRIPT_PALMYRENE: `Palm`, Since: 0.9.30 + * @HB_SCRIPT_PAU_CIN_HAU: `Pauc`, Since: 0.9.30 + * @HB_SCRIPT_PSALTER_PAHLAVI: `Phlp`, Since: 0.9.30 + * @HB_SCRIPT_SIDDHAM: `Sidd`, Since: 0.9.30 + * @HB_SCRIPT_TIRHUTA: `Tirh`, Since: 0.9.30 + * @HB_SCRIPT_WARANG_CITI: `Wara`, Since: 0.9.30 + * @HB_SCRIPT_AHOM: `Ahom`, Since: 0.9.30 + * @HB_SCRIPT_ANATOLIAN_HIEROGLYPHS: `Hluw`, Since: 0.9.30 + * @HB_SCRIPT_HATRAN: `Hatr`, Since: 0.9.30 + * @HB_SCRIPT_MULTANI: `Mult`, Since: 0.9.30 + * @HB_SCRIPT_OLD_HUNGARIAN: `Hung`, Since: 0.9.30 + * @HB_SCRIPT_SIGNWRITING: `Sgnw`, Since: 0.9.30 + * @HB_SCRIPT_ADLAM: `Adlm`, Since: 1.3.0 + * @HB_SCRIPT_BHAIKSUKI: `Bhks`, Since: 1.3.0 + * @HB_SCRIPT_MARCHEN: `Marc`, Since: 1.3.0 + * @HB_SCRIPT_OSAGE: `Osge`, Since: 1.3.0 + * @HB_SCRIPT_TANGUT: `Tang`, Since: 1.3.0 + * @HB_SCRIPT_NEWA: `Newa`, Since: 1.3.0 + * @HB_SCRIPT_MASARAM_GONDI: `Gonm`, Since: 1.6.0 + * @HB_SCRIPT_NUSHU: `Nshu`, Since: 1.6.0 + * @HB_SCRIPT_SOYOMBO: `Soyo`, Since: 1.6.0 + * @HB_SCRIPT_ZANABAZAR_SQUARE: `Zanb`, Since: 1.6.0 + * @HB_SCRIPT_DOGRA: `Dogr`, Since: 1.8.0 + * @HB_SCRIPT_GUNJALA_GONDI: `Gong`, Since: 1.8.0 + * @HB_SCRIPT_HANIFI_ROHINGYA: `Rohg`, Since: 1.8.0 + * @HB_SCRIPT_MAKASAR: `Maka`, Since: 1.8.0 + * @HB_SCRIPT_MEDEFAIDRIN: `Medf`, Since: 1.8.0 + * @HB_SCRIPT_OLD_SOGDIAN: `Sogo`, Since: 1.8.0 + * @HB_SCRIPT_SOGDIAN: `Sogd`, Since: 1.8.0 + * @HB_SCRIPT_ELYMAIC: `Elym`, Since: 2.4.0 + * @HB_SCRIPT_NANDINAGARI: `Nand`, Since: 2.4.0 + * @HB_SCRIPT_NYIAKENG_PUACHUE_HMONG: `Hmnp`, Since: 2.4.0 + * @HB_SCRIPT_WANCHO: `Wcho`, Since: 2.4.0 + * @HB_SCRIPT_CHORASMIAN: `Chrs`, Since: 2.6.7 + * @HB_SCRIPT_DIVES_AKURU: `Diak`, Since: 2.6.7 + * @HB_SCRIPT_KHITAN_SMALL_SCRIPT: `Kits`, Since: 2.6.7 + * @HB_SCRIPT_YEZIDI: `Yezi`, Since: 2.6.7 + * @HB_SCRIPT_INVALID: No script set * * Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding * to the four-letter values defined by [ISO 15924](https://unicode.org/iso15924/). @@ -441,208 +485,208 @@ hb_language_get_default (void); * **/ -/* https://unicode.org/iso15924/ */ /* https://docs.google.com/spreadsheets/d/1Y90M0Ie3MUJ6UVCRDOypOtijlMDLNNyyLk36T6iMu0o */ -/* Unicode Character Database property: Script (sc) */ typedef enum { - /*1.1*/ HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), - /*1.1*/ HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), - /*5.0*/ HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), - - /*1.1*/ HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), - /*1.1*/ HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), - /*1.1*/ HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), - /*1.1*/ HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), - /*1.1*/ HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), - /*1.1*/ HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), - /*1.1*/ HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), - /*1.1*/ HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), - /*1.1*/ HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), - /*1.1*/ HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), - /*1.1*/ HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), - /*1.1*/ HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), - /*1.1*/ HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), - /*1.1*/ HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), - /*1.1*/ HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), - /*1.1*/ HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), - /*1.1*/ HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), - /*1.1*/ HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), - /*1.1*/ HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), - /*1.1*/ HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), - /*1.1*/ HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), - /*1.1*/ HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), - - /*2.0*/ HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), - - /*3.0*/ HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), - /*3.0*/ HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), - /*3.0*/ HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), - /*3.0*/ HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), - /*3.0*/ HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), - /*3.0*/ HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), - /*3.0*/ HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), - /*3.0*/ HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), - /*3.0*/ HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), - /*3.0*/ HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), - /*3.0*/ HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), - /*3.0*/ HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), - /*3.0*/ HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), - /*3.0*/ HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), - - /*3.1*/ HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), - /*3.1*/ HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), - /*3.1*/ HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), - - /*3.2*/ HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), - /*3.2*/ HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), - /*3.2*/ HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), - /*3.2*/ HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), - - /*4.0*/ HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), - /*4.0*/ HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), - /*4.0*/ HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), - /*4.0*/ HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), - /*4.0*/ HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), - /*4.0*/ HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), - /*4.0*/ HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), - - /*4.1*/ HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), - /*4.1*/ HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), - /*4.1*/ HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), - /*4.1*/ HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), - /*4.1*/ HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), - /*4.1*/ HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), - /*4.1*/ HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), - /*4.1*/ HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), - - /*5.0*/ HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), - /*5.0*/ HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), - /*5.0*/ HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), - /*5.0*/ HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), - /*5.0*/ HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), - - /*5.1*/ HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), - /*5.1*/ HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), - /*5.1*/ HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), - /*5.1*/ HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), - /*5.1*/ HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), - /*5.1*/ HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), - /*5.1*/ HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), - /*5.1*/ HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), - /*5.1*/ HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), - /*5.1*/ HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), - /*5.1*/ HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), - - /*5.2*/ HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), - /*5.2*/ HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), - /*5.2*/ HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), - /*5.2*/ HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), - /*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), - /*5.2*/ HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), - /*5.2*/ HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), - /*5.2*/ HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), - /*5.2*/ HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), - /*5.2*/ HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), - /*5.2*/ HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), - /*5.2*/ HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), - /*5.2*/ HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), - /*5.2*/ HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), - /*5.2*/ HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), - - /*6.0*/ HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), - /*6.0*/ HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), - /*6.0*/ HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), - - /*6.1*/ HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), - /*6.1*/ HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), - /*6.1*/ HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), - /*6.1*/ HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), - /*6.1*/ HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), - /*6.1*/ HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), - /*6.1*/ HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), + HB_SCRIPT_COMMON = HB_TAG ('Z','y','y','y'), /*1.1*/ + HB_SCRIPT_INHERITED = HB_TAG ('Z','i','n','h'), /*1.1*/ + HB_SCRIPT_UNKNOWN = HB_TAG ('Z','z','z','z'), /*5.0*/ + + HB_SCRIPT_ARABIC = HB_TAG ('A','r','a','b'), /*1.1*/ + HB_SCRIPT_ARMENIAN = HB_TAG ('A','r','m','n'), /*1.1*/ + HB_SCRIPT_BENGALI = HB_TAG ('B','e','n','g'), /*1.1*/ + HB_SCRIPT_CYRILLIC = HB_TAG ('C','y','r','l'), /*1.1*/ + HB_SCRIPT_DEVANAGARI = HB_TAG ('D','e','v','a'), /*1.1*/ + HB_SCRIPT_GEORGIAN = HB_TAG ('G','e','o','r'), /*1.1*/ + HB_SCRIPT_GREEK = HB_TAG ('G','r','e','k'), /*1.1*/ + HB_SCRIPT_GUJARATI = HB_TAG ('G','u','j','r'), /*1.1*/ + HB_SCRIPT_GURMUKHI = HB_TAG ('G','u','r','u'), /*1.1*/ + HB_SCRIPT_HANGUL = HB_TAG ('H','a','n','g'), /*1.1*/ + HB_SCRIPT_HAN = HB_TAG ('H','a','n','i'), /*1.1*/ + HB_SCRIPT_HEBREW = HB_TAG ('H','e','b','r'), /*1.1*/ + HB_SCRIPT_HIRAGANA = HB_TAG ('H','i','r','a'), /*1.1*/ + HB_SCRIPT_KANNADA = HB_TAG ('K','n','d','a'), /*1.1*/ + HB_SCRIPT_KATAKANA = HB_TAG ('K','a','n','a'), /*1.1*/ + HB_SCRIPT_LAO = HB_TAG ('L','a','o','o'), /*1.1*/ + HB_SCRIPT_LATIN = HB_TAG ('L','a','t','n'), /*1.1*/ + HB_SCRIPT_MALAYALAM = HB_TAG ('M','l','y','m'), /*1.1*/ + HB_SCRIPT_ORIYA = HB_TAG ('O','r','y','a'), /*1.1*/ + HB_SCRIPT_TAMIL = HB_TAG ('T','a','m','l'), /*1.1*/ + HB_SCRIPT_TELUGU = HB_TAG ('T','e','l','u'), /*1.1*/ + HB_SCRIPT_THAI = HB_TAG ('T','h','a','i'), /*1.1*/ + + HB_SCRIPT_TIBETAN = HB_TAG ('T','i','b','t'), /*2.0*/ + + HB_SCRIPT_BOPOMOFO = HB_TAG ('B','o','p','o'), /*3.0*/ + HB_SCRIPT_BRAILLE = HB_TAG ('B','r','a','i'), /*3.0*/ + HB_SCRIPT_CANADIAN_SYLLABICS = HB_TAG ('C','a','n','s'), /*3.0*/ + HB_SCRIPT_CHEROKEE = HB_TAG ('C','h','e','r'), /*3.0*/ + HB_SCRIPT_ETHIOPIC = HB_TAG ('E','t','h','i'), /*3.0*/ + HB_SCRIPT_KHMER = HB_TAG ('K','h','m','r'), /*3.0*/ + HB_SCRIPT_MONGOLIAN = HB_TAG ('M','o','n','g'), /*3.0*/ + HB_SCRIPT_MYANMAR = HB_TAG ('M','y','m','r'), /*3.0*/ + HB_SCRIPT_OGHAM = HB_TAG ('O','g','a','m'), /*3.0*/ + HB_SCRIPT_RUNIC = HB_TAG ('R','u','n','r'), /*3.0*/ + HB_SCRIPT_SINHALA = HB_TAG ('S','i','n','h'), /*3.0*/ + HB_SCRIPT_SYRIAC = HB_TAG ('S','y','r','c'), /*3.0*/ + HB_SCRIPT_THAANA = HB_TAG ('T','h','a','a'), /*3.0*/ + HB_SCRIPT_YI = HB_TAG ('Y','i','i','i'), /*3.0*/ + + HB_SCRIPT_DESERET = HB_TAG ('D','s','r','t'), /*3.1*/ + HB_SCRIPT_GOTHIC = HB_TAG ('G','o','t','h'), /*3.1*/ + HB_SCRIPT_OLD_ITALIC = HB_TAG ('I','t','a','l'), /*3.1*/ + + HB_SCRIPT_BUHID = HB_TAG ('B','u','h','d'), /*3.2*/ + HB_SCRIPT_HANUNOO = HB_TAG ('H','a','n','o'), /*3.2*/ + HB_SCRIPT_TAGALOG = HB_TAG ('T','g','l','g'), /*3.2*/ + HB_SCRIPT_TAGBANWA = HB_TAG ('T','a','g','b'), /*3.2*/ + + HB_SCRIPT_CYPRIOT = HB_TAG ('C','p','r','t'), /*4.0*/ + HB_SCRIPT_LIMBU = HB_TAG ('L','i','m','b'), /*4.0*/ + HB_SCRIPT_LINEAR_B = HB_TAG ('L','i','n','b'), /*4.0*/ + HB_SCRIPT_OSMANYA = HB_TAG ('O','s','m','a'), /*4.0*/ + HB_SCRIPT_SHAVIAN = HB_TAG ('S','h','a','w'), /*4.0*/ + HB_SCRIPT_TAI_LE = HB_TAG ('T','a','l','e'), /*4.0*/ + HB_SCRIPT_UGARITIC = HB_TAG ('U','g','a','r'), /*4.0*/ + + HB_SCRIPT_BUGINESE = HB_TAG ('B','u','g','i'), /*4.1*/ + HB_SCRIPT_COPTIC = HB_TAG ('C','o','p','t'), /*4.1*/ + HB_SCRIPT_GLAGOLITIC = HB_TAG ('G','l','a','g'), /*4.1*/ + HB_SCRIPT_KHAROSHTHI = HB_TAG ('K','h','a','r'), /*4.1*/ + HB_SCRIPT_NEW_TAI_LUE = HB_TAG ('T','a','l','u'), /*4.1*/ + HB_SCRIPT_OLD_PERSIAN = HB_TAG ('X','p','e','o'), /*4.1*/ + HB_SCRIPT_SYLOTI_NAGRI = HB_TAG ('S','y','l','o'), /*4.1*/ + HB_SCRIPT_TIFINAGH = HB_TAG ('T','f','n','g'), /*4.1*/ + + HB_SCRIPT_BALINESE = HB_TAG ('B','a','l','i'), /*5.0*/ + HB_SCRIPT_CUNEIFORM = HB_TAG ('X','s','u','x'), /*5.0*/ + HB_SCRIPT_NKO = HB_TAG ('N','k','o','o'), /*5.0*/ + HB_SCRIPT_PHAGS_PA = HB_TAG ('P','h','a','g'), /*5.0*/ + HB_SCRIPT_PHOENICIAN = HB_TAG ('P','h','n','x'), /*5.0*/ + + HB_SCRIPT_CARIAN = HB_TAG ('C','a','r','i'), /*5.1*/ + HB_SCRIPT_CHAM = HB_TAG ('C','h','a','m'), /*5.1*/ + HB_SCRIPT_KAYAH_LI = HB_TAG ('K','a','l','i'), /*5.1*/ + HB_SCRIPT_LEPCHA = HB_TAG ('L','e','p','c'), /*5.1*/ + HB_SCRIPT_LYCIAN = HB_TAG ('L','y','c','i'), /*5.1*/ + HB_SCRIPT_LYDIAN = HB_TAG ('L','y','d','i'), /*5.1*/ + HB_SCRIPT_OL_CHIKI = HB_TAG ('O','l','c','k'), /*5.1*/ + HB_SCRIPT_REJANG = HB_TAG ('R','j','n','g'), /*5.1*/ + HB_SCRIPT_SAURASHTRA = HB_TAG ('S','a','u','r'), /*5.1*/ + HB_SCRIPT_SUNDANESE = HB_TAG ('S','u','n','d'), /*5.1*/ + HB_SCRIPT_VAI = HB_TAG ('V','a','i','i'), /*5.1*/ + + HB_SCRIPT_AVESTAN = HB_TAG ('A','v','s','t'), /*5.2*/ + HB_SCRIPT_BAMUM = HB_TAG ('B','a','m','u'), /*5.2*/ + HB_SCRIPT_EGYPTIAN_HIEROGLYPHS = HB_TAG ('E','g','y','p'), /*5.2*/ + HB_SCRIPT_IMPERIAL_ARAMAIC = HB_TAG ('A','r','m','i'), /*5.2*/ + HB_SCRIPT_INSCRIPTIONAL_PAHLAVI = HB_TAG ('P','h','l','i'), /*5.2*/ + HB_SCRIPT_INSCRIPTIONAL_PARTHIAN = HB_TAG ('P','r','t','i'), /*5.2*/ + HB_SCRIPT_JAVANESE = HB_TAG ('J','a','v','a'), /*5.2*/ + HB_SCRIPT_KAITHI = HB_TAG ('K','t','h','i'), /*5.2*/ + HB_SCRIPT_LISU = HB_TAG ('L','i','s','u'), /*5.2*/ + HB_SCRIPT_MEETEI_MAYEK = HB_TAG ('M','t','e','i'), /*5.2*/ + HB_SCRIPT_OLD_SOUTH_ARABIAN = HB_TAG ('S','a','r','b'), /*5.2*/ + HB_SCRIPT_OLD_TURKIC = HB_TAG ('O','r','k','h'), /*5.2*/ + HB_SCRIPT_SAMARITAN = HB_TAG ('S','a','m','r'), /*5.2*/ + HB_SCRIPT_TAI_THAM = HB_TAG ('L','a','n','a'), /*5.2*/ + HB_SCRIPT_TAI_VIET = HB_TAG ('T','a','v','t'), /*5.2*/ + + HB_SCRIPT_BATAK = HB_TAG ('B','a','t','k'), /*6.0*/ + HB_SCRIPT_BRAHMI = HB_TAG ('B','r','a','h'), /*6.0*/ + HB_SCRIPT_MANDAIC = HB_TAG ('M','a','n','d'), /*6.0*/ + + HB_SCRIPT_CHAKMA = HB_TAG ('C','a','k','m'), /*6.1*/ + HB_SCRIPT_MEROITIC_CURSIVE = HB_TAG ('M','e','r','c'), /*6.1*/ + HB_SCRIPT_MEROITIC_HIEROGLYPHS = HB_TAG ('M','e','r','o'), /*6.1*/ + HB_SCRIPT_MIAO = HB_TAG ('P','l','r','d'), /*6.1*/ + HB_SCRIPT_SHARADA = HB_TAG ('S','h','r','d'), /*6.1*/ + HB_SCRIPT_SORA_SOMPENG = HB_TAG ('S','o','r','a'), /*6.1*/ + HB_SCRIPT_TAKRI = HB_TAG ('T','a','k','r'), /*6.1*/ /* * Since: 0.9.30 */ - /*7.0*/ HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), - /*7.0*/ HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), - /*7.0*/ HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), - /*7.0*/ HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), - /*7.0*/ HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), - /*7.0*/ HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), - /*7.0*/ HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), - /*7.0*/ HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), - /*7.0*/ HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), - /*7.0*/ HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), - /*7.0*/ HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), - /*7.0*/ HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), - /*7.0*/ HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), - /*7.0*/ HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), - /*7.0*/ HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), - /*7.0*/ HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), - /*7.0*/ HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), - /*7.0*/ HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), - /*7.0*/ HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), - /*7.0*/ HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), - /*7.0*/ HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), - /*7.0*/ HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), - /*7.0*/ HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), - - /*8.0*/ HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), - /*8.0*/ HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), - /*8.0*/ HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), - /*8.0*/ HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), - /*8.0*/ HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), - /*8.0*/ HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), + HB_SCRIPT_BASSA_VAH = HB_TAG ('B','a','s','s'), /*7.0*/ + HB_SCRIPT_CAUCASIAN_ALBANIAN = HB_TAG ('A','g','h','b'), /*7.0*/ + HB_SCRIPT_DUPLOYAN = HB_TAG ('D','u','p','l'), /*7.0*/ + HB_SCRIPT_ELBASAN = HB_TAG ('E','l','b','a'), /*7.0*/ + HB_SCRIPT_GRANTHA = HB_TAG ('G','r','a','n'), /*7.0*/ + HB_SCRIPT_KHOJKI = HB_TAG ('K','h','o','j'), /*7.0*/ + HB_SCRIPT_KHUDAWADI = HB_TAG ('S','i','n','d'), /*7.0*/ + HB_SCRIPT_LINEAR_A = HB_TAG ('L','i','n','a'), /*7.0*/ + HB_SCRIPT_MAHAJANI = HB_TAG ('M','a','h','j'), /*7.0*/ + HB_SCRIPT_MANICHAEAN = HB_TAG ('M','a','n','i'), /*7.0*/ + HB_SCRIPT_MENDE_KIKAKUI = HB_TAG ('M','e','n','d'), /*7.0*/ + HB_SCRIPT_MODI = HB_TAG ('M','o','d','i'), /*7.0*/ + HB_SCRIPT_MRO = HB_TAG ('M','r','o','o'), /*7.0*/ + HB_SCRIPT_NABATAEAN = HB_TAG ('N','b','a','t'), /*7.0*/ + HB_SCRIPT_OLD_NORTH_ARABIAN = HB_TAG ('N','a','r','b'), /*7.0*/ + HB_SCRIPT_OLD_PERMIC = HB_TAG ('P','e','r','m'), /*7.0*/ + HB_SCRIPT_PAHAWH_HMONG = HB_TAG ('H','m','n','g'), /*7.0*/ + HB_SCRIPT_PALMYRENE = HB_TAG ('P','a','l','m'), /*7.0*/ + HB_SCRIPT_PAU_CIN_HAU = HB_TAG ('P','a','u','c'), /*7.0*/ + HB_SCRIPT_PSALTER_PAHLAVI = HB_TAG ('P','h','l','p'), /*7.0*/ + HB_SCRIPT_SIDDHAM = HB_TAG ('S','i','d','d'), /*7.0*/ + HB_SCRIPT_TIRHUTA = HB_TAG ('T','i','r','h'), /*7.0*/ + HB_SCRIPT_WARANG_CITI = HB_TAG ('W','a','r','a'), /*7.0*/ + + HB_SCRIPT_AHOM = HB_TAG ('A','h','o','m'), /*8.0*/ + HB_SCRIPT_ANATOLIAN_HIEROGLYPHS = HB_TAG ('H','l','u','w'), /*8.0*/ + HB_SCRIPT_HATRAN = HB_TAG ('H','a','t','r'), /*8.0*/ + HB_SCRIPT_MULTANI = HB_TAG ('M','u','l','t'), /*8.0*/ + HB_SCRIPT_OLD_HUNGARIAN = HB_TAG ('H','u','n','g'), /*8.0*/ + HB_SCRIPT_SIGNWRITING = HB_TAG ('S','g','n','w'), /*8.0*/ /* * Since 1.3.0 */ - /*9.0*/ HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), - /*9.0*/ HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), - /*9.0*/ HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), - /*9.0*/ HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), - /*9.0*/ HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), - /*9.0*/ HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), + HB_SCRIPT_ADLAM = HB_TAG ('A','d','l','m'), /*9.0*/ + HB_SCRIPT_BHAIKSUKI = HB_TAG ('B','h','k','s'), /*9.0*/ + HB_SCRIPT_MARCHEN = HB_TAG ('M','a','r','c'), /*9.0*/ + HB_SCRIPT_OSAGE = HB_TAG ('O','s','g','e'), /*9.0*/ + HB_SCRIPT_TANGUT = HB_TAG ('T','a','n','g'), /*9.0*/ + HB_SCRIPT_NEWA = HB_TAG ('N','e','w','a'), /*9.0*/ /* * Since 1.6.0 */ - /*10.0*/HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), - /*10.0*/HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), - /*10.0*/HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), - /*10.0*/HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), + HB_SCRIPT_MASARAM_GONDI = HB_TAG ('G','o','n','m'), /*10.0*/ + HB_SCRIPT_NUSHU = HB_TAG ('N','s','h','u'), /*10.0*/ + HB_SCRIPT_SOYOMBO = HB_TAG ('S','o','y','o'), /*10.0*/ + HB_SCRIPT_ZANABAZAR_SQUARE = HB_TAG ('Z','a','n','b'), /*10.0*/ /* * Since 1.8.0 */ - /*11.0*/HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), - /*11.0*/HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), - /*11.0*/HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), - /*11.0*/HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), - /*11.0*/HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), - /*11.0*/HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), - /*11.0*/HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), + HB_SCRIPT_DOGRA = HB_TAG ('D','o','g','r'), /*11.0*/ + HB_SCRIPT_GUNJALA_GONDI = HB_TAG ('G','o','n','g'), /*11.0*/ + HB_SCRIPT_HANIFI_ROHINGYA = HB_TAG ('R','o','h','g'), /*11.0*/ + HB_SCRIPT_MAKASAR = HB_TAG ('M','a','k','a'), /*11.0*/ + HB_SCRIPT_MEDEFAIDRIN = HB_TAG ('M','e','d','f'), /*11.0*/ + HB_SCRIPT_OLD_SOGDIAN = HB_TAG ('S','o','g','o'), /*11.0*/ + HB_SCRIPT_SOGDIAN = HB_TAG ('S','o','g','d'), /*11.0*/ /* * Since 2.4.0 */ - /*12.0*/HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), - /*12.0*/HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), - /*12.0*/HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), - /*12.0*/HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), + HB_SCRIPT_ELYMAIC = HB_TAG ('E','l','y','m'), /*12.0*/ + HB_SCRIPT_NANDINAGARI = HB_TAG ('N','a','n','d'), /*12.0*/ + HB_SCRIPT_NYIAKENG_PUACHUE_HMONG = HB_TAG ('H','m','n','p'), /*12.0*/ + HB_SCRIPT_WANCHO = HB_TAG ('W','c','h','o'), /*12.0*/ /* * Since 2.6.7 */ - /*13.0*/HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), - /*13.0*/HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), - /*13.0*/HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), - /*13.0*/HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), + HB_SCRIPT_CHORASMIAN = HB_TAG ('C','h','r','s'), /*13.0*/ + HB_SCRIPT_DIVES_AKURU = HB_TAG ('D','i','a','k'), /*13.0*/ + HB_SCRIPT_KHITAN_SMALL_SCRIPT = HB_TAG ('K','i','t','s'), /*13.0*/ + HB_SCRIPT_YEZIDI = HB_TAG ('Y','e','z','i'), /*13.0*/ /* No script set. */ - HB_SCRIPT_INVALID = HB_TAG_NONE, + HB_SCRIPT_INVALID = HB_TAG_NONE, + + /*< private >*/ /* Dummy values to ensure any hb_tag_t value can be passed/stored as hb_script_t * without risking undefined behavior. We have two, for historical reasons. @@ -687,19 +731,33 @@ typedef struct hb_user_data_key_t { char unused; } hb_user_data_key_t; +/** + * hb_destroy_func_t: + * @user_data: the data to be destroyed + * + * A virtual method for destroy user-data callbacks. + * + */ typedef void (*hb_destroy_func_t) (void *user_data); /* Font features and variations. */ /** - * HB_FEATURE_GLOBAL_START + * HB_FEATURE_GLOBAL_START: + * + * Special setting for #hb_feature_t.start to apply the feature from the start + * of the buffer. * * Since: 2.0.0 */ #define HB_FEATURE_GLOBAL_START 0 + /** - * HB_FEATURE_GLOBAL_END + * HB_FEATURE_GLOBAL_END: + * + * Special setting for #hb_feature_t.end to apply the feature from to the end + * of the buffer. * * Since: 2.0.0 */ @@ -717,7 +775,7 @@ typedef void (*hb_destroy_func_t) (void *user_data); * The #hb_feature_t is the structure that holds information about requested * feature application. The feature will be applied with the given value to all * glyphs which are in clusters between @start (inclusive) and @end (exclusive). - * Setting start to @HB_FEATURE_GLOBAL_START and end to @HB_FEATURE_GLOBAL_END + * Setting start to #HB_FEATURE_GLOBAL_START and end to #HB_FEATURE_GLOBAL_END * specifies that the feature always applies to the entire buffer. */ typedef struct hb_feature_t { @@ -741,8 +799,8 @@ hb_feature_to_string (hb_feature_t *feature, * @value: The value of the variation axis * * Data type for holding variation data. Registered OpenType - * variation-axis tags are listed at - * https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg + * variation-axis tags are listed in + * [OpenType Axis Tag Registry](https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg). * * Since: 1.4.2 */ @@ -769,6 +827,17 @@ hb_variation_to_string (hb_variation_t *variation, */ typedef uint32_t hb_color_t; +/** + * HB_COLOR: + * @b: blue channel value + * @g: green channel value + * @r: red channel value + * @a: alpha channel value + * + * Constructs an #hb_color_t from four integers. + * + * Since: 2.1.0 + */ #define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a))) HB_EXTERN uint8_t diff --git a/thirdparty/harfbuzz/src/hb-coretext.cc b/thirdparty/harfbuzz/src/hb-coretext.cc index 7b6b2bd5ef..461bd20e65 100644 --- a/thirdparty/harfbuzz/src/hb-coretext.cc +++ b/thirdparty/harfbuzz/src/hb-coretext.cc @@ -34,7 +34,6 @@ #include "hb-coretext.h" #include "hb-aat-layout.hh" -#include <math.h> /** @@ -190,7 +189,10 @@ create_ct_font (CGFontRef cg_font, CGFloat font_size) * reconfiguring the cascade list causes CoreText crashes. For details, see * crbug.com/549610 */ // 0x00070000 stands for "kCTVersionNumber10_10", see CoreText.h +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" if (&CTGetCoreTextVersion != nullptr && CTGetCoreTextVersion() < 0x00070000) { +#pragma GCC diagnostic pop CFStringRef fontName = CTFontCopyPostScriptName (ct_font); bool isEmojiFont = CFStringCompare (fontName, CFSTR("AppleColorEmoji"), 0) == kCFCompareEqualTo; CFRelease (fontName); @@ -346,7 +348,7 @@ retry: const hb_coretext_font_data_t *data = font->data.coretext; if (unlikely (!data)) return nullptr; - if (fabs (CTFontGetSize ((CTFontRef) data) - (CGFloat) font->ptem) > .5) + if (fabs (CTFontGetSize ((CTFontRef) data) - (CGFloat) font->ptem) > (CGFloat) .5) { /* XXX-MT-bug * Note that evaluating condition above can be dangerous if another thread @@ -402,7 +404,7 @@ hb_coretext_font_create (CTFontRef ct_font) } /** - * hb_coretext_face_get_ct_font: + * hb_coretext_font_get_ct_font: * @font: #hb_font_t to work upon * * Fetches the CTFontRef associated with the specified @@ -858,7 +860,7 @@ resize_and_retry: buffer->len = 0; uint32_t status_and = ~0, status_or = 0; - double advances_so_far = 0; + CGFloat advances_so_far = 0; /* For right-to-left runs, CoreText returns the glyphs positioned such that * any trailing whitespace is to the left of (0,0). Adjust coordinate system * to fix for that. Test with any RTL string with trailing spaces. @@ -880,10 +882,10 @@ resize_and_retry: status_or |= run_status; status_and &= run_status; DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status); - double run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr); + CGFloat run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr); if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction)) run_advance = -run_advance; - DEBUG_MSG (CORETEXT, run, "Run advance: %g", run_advance); + DEBUG_MSG (CORETEXT, run, "Run advance: %g", (double) run_advance); /* CoreText does automatic font fallback (AKA "cascading") for characters * not supported by the requested font, and provides no way to turn it off, @@ -1062,7 +1064,7 @@ resize_and_retry: hb_position_t x_offset = (positions[0].x - advances_so_far) * x_mult; for (unsigned int j = 0; j < num_glyphs; j++) { - double advance; + CGFloat advance; if (likely (j + 1 < num_glyphs)) advance = positions[j + 1].x - positions[j].x; else /* last glyph */ @@ -1078,7 +1080,7 @@ resize_and_retry: hb_position_t y_offset = (positions[0].y - advances_so_far) * y_mult; for (unsigned int j = 0; j < num_glyphs; j++) { - double advance; + CGFloat advance; if (likely (j + 1 < num_glyphs)) advance = positions[j + 1].y - positions[j].y; else /* last glyph */ diff --git a/thirdparty/harfbuzz/src/hb-deprecated.h b/thirdparty/harfbuzz/src/hb-deprecated.h index 43f89a4c4e..5f19125789 100644 --- a/thirdparty/harfbuzz/src/hb-deprecated.h +++ b/thirdparty/harfbuzz/src/hb-deprecated.h @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif @@ -53,11 +53,50 @@ HB_BEGIN_DECLS #ifndef HB_DISABLE_DEPRECATED +/** + * HB_SCRIPT_CANADIAN_ABORIGINAL: + * + * Use #HB_SCRIPT_CANADIAN_SYLLABICS instead: + * + * Deprecated: 0.9.20 + */ #define HB_SCRIPT_CANADIAN_ABORIGINAL HB_SCRIPT_CANADIAN_SYLLABICS +/** + * HB_BUFFER_FLAGS_DEFAULT: + * + * Use #HB_BUFFER_FLAG_DEFAULT instead. + * + * Deprecated: 0.9.20 + */ #define HB_BUFFER_FLAGS_DEFAULT HB_BUFFER_FLAG_DEFAULT +/** + * HB_BUFFER_SERIALIZE_FLAGS_DEFAULT: + * + * Use #HB_BUFFER_SERIALIZE_FLAG_DEFAULT instead. + * + * Deprecated: 0.9.20 + */ #define HB_BUFFER_SERIALIZE_FLAGS_DEFAULT HB_BUFFER_SERIALIZE_FLAG_DEFAULT +/** + * hb_font_get_glyph_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @unicode: The Unicode code point to query + * @variation_selector: The variation-selector code point to query + * @glyph: (out): The glyph ID retrieved + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * This method should retrieve the glyph ID for a specified Unicode code point + * font, with an optional variation selector. + * + * Return value: %true if data found, %false otherwise + * Deprecated: 1.2.3 + * + **/ typedef hb_bool_t (*hb_font_get_glyph_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t *glyph, @@ -73,6 +112,11 @@ hb_set_invert (hb_set_t *set); /** * hb_unicode_eastasian_width_func_t: + * @ufuncs: A Unicode-functions structure + * @unicode: The code point to query + * @user_data: User data pointer passed by the caller + * + * A virtual method for the #hb_unicode_funcs_t structure. * * Deprecated: 2.0.0 */ @@ -82,12 +126,12 @@ typedef unsigned int (*hb_unicode_eastasian_width_func_t) (hb_unicode_funcs_t /** * hb_unicode_funcs_set_eastasian_width_func: - * @ufuncs: a Unicode function structure - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: + * @ufuncs: a Unicode-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore * - * + * Sets the implementation function for #hb_unicode_eastasian_width_func_t. * * Since: 0.9.2 * Deprecated: 2.0.0 @@ -99,6 +143,10 @@ hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs, /** * hb_unicode_eastasian_width: + * @ufuncs: a Unicode-function structure + * @unicode: The code point to query + * + * Don't use. Not used by HarfBuzz. * * Since: 0.9.2 * Deprecated: 2.0.0 @@ -112,7 +160,7 @@ hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs, * hb_unicode_decompose_compatibility_func_t: * @ufuncs: a Unicode function structure * @u: codepoint to decompose - * @decomposed: address of codepoint array (of length %HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into + * @decomposed: address of codepoint array (of length #HB_UNICODE_MAX_DECOMPOSITION_LEN) to write decomposition into * @user_data: user data pointer as passed to hb_unicode_funcs_set_decompose_compatibility_func() * * Fully decompose @u to its Unicode compatibility decomposition. The codepoints of the decomposition will be written to @decomposed. @@ -120,7 +168,7 @@ hb_unicode_eastasian_width (hb_unicode_funcs_t *ufuncs, * * If @u has no compatibility decomposition, zero should be returned. * - * The Unicode standard guarantees that a buffer of length %HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any + * The Unicode standard guarantees that a buffer of length #HB_UNICODE_MAX_DECOMPOSITION_LEN codepoints will always be sufficient for any * compatibility decomposition plus an terminating value of 0. Consequently, @decompose must be allocated by the caller to be at least this length. Implementations * of this function type must ensure that they do not write past the provided array. * @@ -144,10 +192,12 @@ typedef unsigned int (*hb_unicode_decompose_compatibility_func_t) (hb_unicode_ /** * hb_unicode_funcs_set_decompose_compatibility_func: - * @ufuncs: a Unicode function structure - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: + * @ufuncs: A Unicode-functions structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore + * + * Sets the implementation function for #hb_unicode_decompose_compatibility_func_t. * * * @@ -165,16 +215,25 @@ hb_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs, hb_codepoint_t *decomposed); +/** + * hb_font_get_glyph_v_kerning_func_t: + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * This method should retrieve the kerning-adjustment value for a glyph-pair in + * the specified font, for vertical text segments. + * + **/ typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_v_kerning_func_t; /** * hb_font_funcs_set_glyph_v_kerning_func: - * @ffuncs: font functions. - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: + * @ffuncs: A font-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore * - * + * Sets the implementation function for #hb_font_get_glyph_v_kerning_func_t. * * Since: 0.9.2 * Deprecated: 2.0.0 diff --git a/thirdparty/harfbuzz/src/hb-directwrite.cc b/thirdparty/harfbuzz/src/hb-directwrite.cc index 92c956c032..a07302159c 100644 --- a/thirdparty/harfbuzz/src/hb-directwrite.cc +++ b/thirdparty/harfbuzz/src/hb-directwrite.cc @@ -957,6 +957,8 @@ _hb_directwrite_font_release (void *data) * hb_directwrite_face_create: * @font_face: a DirectWrite IDWriteFontFace object. * + * Constructs a new face object from the specified DirectWrite IDWriteFontFace. + * * Return value: #hb_face_t object corresponding to the given input * * Since: 2.4.0 @@ -974,6 +976,8 @@ hb_directwrite_face_create (IDWriteFontFace *font_face) * hb_directwrite_face_get_font_face: * @face: a #hb_face_t object * +* Gets the DirectWrite IDWriteFontFace associated with @face. +* * Return value: DirectWrite IDWriteFontFace object corresponding to the given input * * Since: 2.5.0 diff --git a/thirdparty/harfbuzz/src/hb-dispatch.hh b/thirdparty/harfbuzz/src/hb-dispatch.hh index 7eace86e54..4b2b65a8de 100644 --- a/thirdparty/harfbuzz/src/hb-dispatch.hh +++ b/thirdparty/harfbuzz/src/hb-dispatch.hh @@ -38,7 +38,6 @@ template <typename Context, typename Return=hb_empty_t, unsigned int MaxDebugDepth=0> struct hb_dispatch_context_t { - hb_dispatch_context_t () : debug_depth (0) {} private: /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ const Context* thiz () const { return static_cast<const Context *> (this); } @@ -54,7 +53,7 @@ struct hb_dispatch_context_t { return obj.dispatch (thiz (), hb_forward<Ts> (ds)...); } static return_t no_dispatch_return_value () { return Context::default_return_value (); } static bool stop_sublookup_iteration (const return_t r HB_UNUSED) { return false; } - unsigned debug_depth; + unsigned debug_depth = 0; }; diff --git a/thirdparty/harfbuzz/src/hb-draw.h b/thirdparty/harfbuzz/src/hb-draw.h index 98eccf4c0c..bddc876399 100644 --- a/thirdparty/harfbuzz/src/hb-draw.h +++ b/thirdparty/harfbuzz/src/hb-draw.h @@ -22,7 +22,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif diff --git a/thirdparty/harfbuzz/src/hb-face.cc b/thirdparty/harfbuzz/src/hb-face.cc index 33a788e7c5..61bd4af7b1 100644 --- a/thirdparty/harfbuzz/src/hb-face.cc +++ b/thirdparty/harfbuzz/src/hb-face.cc @@ -89,8 +89,8 @@ DEFINE_NULL_INSTANCE (hb_face_t) = nullptr, /* destroy */ 0, /* index */ - HB_ATOMIC_INT_INIT (1000), /* upem */ - HB_ATOMIC_INT_INIT (0), /* num_glyphs */ + 1000, /* upem */ + 0, /* num_glyphs */ /* Zero for the rest is fine. */ }; @@ -100,7 +100,7 @@ DEFINE_NULL_INSTANCE (hb_face_t) = * hb_face_create_for_tables: * @reference_table_func: (closure user_data) (destroy destroy) (scope notified): Table-referencing function * @user_data: A pointer to the user data - * @destroy: (optional): A callback to call when @data is not needed anymore + * @destroy: (nullable): A callback to call when @data is not needed anymore * * Variant of hb_face_create(), built for those cases where it is more * convenient to provide data for individual tables instead of the whole font @@ -235,7 +235,7 @@ hb_face_create (hb_blob_t *blob, * * Fetches the singleton empty face object. * - * Return value: (transfer full) The empty face object + * Return value: (transfer full): The empty face object * * Since: 0.9.2 **/ @@ -299,7 +299,7 @@ hb_face_destroy (hb_face_t *face) * @face: A face object * @key: The user-data key to set * @data: A pointer to the user data - * @destroy: (optional): A callback to call when @data is not needed anymore + * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * * Attaches a user-data key/data pair to the given face object. @@ -360,7 +360,7 @@ hb_face_make_immutable (hb_face_t *face) * * Tests whether the given face object is immutable. * - * Return value: True is @face is immutable, false otherwise + * Return value: %true is @face is immutable, %false otherwise * * Since: 0.9.2 **/ @@ -756,7 +756,7 @@ hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob) hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data; hb_face_builder_data_t::table_entry_t *entry = data->tables.push (); - if (data->tables.in_error()) + if (unlikely (data->tables.in_error())) return false; entry->tag = tag; diff --git a/thirdparty/harfbuzz/src/hb-face.h b/thirdparty/harfbuzz/src/hb-face.h index 3b18f7eef9..6ef2f8b886 100644 --- a/thirdparty/harfbuzz/src/hb-face.h +++ b/thirdparty/harfbuzz/src/hb-face.h @@ -24,7 +24,7 @@ * Red Hat Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif @@ -58,6 +58,19 @@ HB_EXTERN hb_face_t * hb_face_create (hb_blob_t *blob, unsigned int index); +/** + * hb_reference_table_func_t: + * @face: an #hb_face_t to reference table for + * @tag: the tag of the table to reference + * @user_data: User data pointer passed by the caller + * + * Callback function for hb_face_create_for_tables(). + * + * Return value: (transfer full): A pointer to the @tag table within @face + * + * Since: 0.9.2 + */ + typedef hb_blob_t * (*hb_reference_table_func_t) (hb_face_t *face, hb_tag_t tag, void *user_data); /* calls destroy() when not needing user_data anymore */ diff --git a/thirdparty/harfbuzz/src/hb-face.hh b/thirdparty/harfbuzz/src/hb-face.hh index f1b472ccf3..765f272858 100644 --- a/thirdparty/harfbuzz/src/hb-face.hh +++ b/thirdparty/harfbuzz/src/hb-face.hh @@ -81,7 +81,7 @@ struct hb_face_t return blob; } - HB_PURE_FUNC unsigned int get_upem () const + unsigned int get_upem () const { unsigned int ret = upem.get_relaxed (); if (unlikely (!ret)) diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc index 5c8357ff28..37a0e7fe85 100644 --- a/thirdparty/harfbuzz/src/hb-font.cc +++ b/thirdparty/harfbuzz/src/hb-font.cc @@ -628,7 +628,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs) * @ffuncs: The font-functions structure * @key: The user-data key to set * @data: A pointer to the user data set - * @destroy: (optional): A callback to call when @data is not needed anymore + * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * * Attaches a user-data key/data pair to the specified font-functions structure. @@ -690,7 +690,7 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs) * * Tests whether a font-functions structure is immutable. * - * Return value: %true if @ffuncs is immutable, false otherwise + * Return value: %true if @ffuncs is immutable, %false otherwise * * Since: 0.9.2 **/ @@ -753,10 +753,10 @@ hb_font_t::has_func (unsigned int i) * @font: #hb_font_t to work upon * @extents: (out): The font extents retrieved * - * Fetches the extents for a specified font, in horizontal + * Fetches the extents for a specified font, for horizontal * text segments. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 1.1.3 **/ @@ -772,10 +772,10 @@ hb_font_get_h_extents (hb_font_t *font, * @font: #hb_font_t to work upon * @extents: (out): The font extents retrieved * - * Fetches the extents for a specified font, in vertical + * Fetches the extents for a specified font, for vertical * text segments. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 1.1.3 **/ @@ -790,7 +790,7 @@ hb_font_get_v_extents (hb_font_t *font, * hb_font_get_glyph: * @font: #hb_font_t to work upon * @unicode: The Unicode code point to query - * @variation_selector: (optional): A variation-selector code point + * @variation_selector: A variation-selector code point * @glyph: (out): The glyph ID retrieved * * Fetches the glyph ID for a Unicode code point in the specified @@ -799,7 +799,7 @@ hb_font_get_v_extents (hb_font_t *font, * If @variation_selector is 0, calls hb_font_get_nominal_glyph(); * otherwise calls hb_font_get_variation_glyph(). * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 0.9.2 **/ @@ -827,7 +827,7 @@ hb_font_get_glyph (hb_font_t *font, * for code points modified by variation selectors. For variation-selector * support, user hb_font_get_variation_glyph() or use hb_font_get_glyph(). * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 1.2.3 **/ @@ -841,11 +841,17 @@ hb_font_get_nominal_glyph (hb_font_t *font, /** * hb_font_get_nominal_glyphs: - * @font: a font. - * + * @font: #hb_font_t to work upon + * @count: number of code points to query + * @first_unicode: The first Unicode code point to query + * @unicode_stride: The stride between successive code points + * @first_glyph: (out): The first glyph ID retrieved + * @glyph_stride: The stride between successive glyph IDs * + * Fetches the nominal glyph IDs for a sequence of Unicode code points. Glyph + * IDs must be returned in a #hb_codepoint_t output parameter. * - * Return value: + * Return value: the number of code points processed * * Since: 2.6.3 **/ @@ -873,7 +879,7 @@ hb_font_get_nominal_glyphs (hb_font_t *font, * by the specified variation-selector code point, in the specified * font. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 1.2.3 **/ @@ -931,7 +937,7 @@ hb_font_get_glyph_v_advance (hb_font_t *font, * @first_glyph: The first glyph ID to query * @glyph_stride: The stride between successive glyph IDs * @first_advance: (out): The first advance retrieved - * @advance_stride: (out): The stride between successive advances + * @advance_stride: The stride between successive advances * * Fetches the advances for a sequence of glyph IDs in the specified * font, for horizontal text segments. @@ -983,7 +989,7 @@ hb_font_get_glyph_v_advances (hb_font_t* font, * Fetches the (X,Y) coordinates of the origin for a glyph ID * in the specified font, for horizontal text segments. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 0.9.2 **/ @@ -1006,7 +1012,7 @@ hb_font_get_glyph_h_origin (hb_font_t *font, * Fetches the (X,Y) coordinates of the origin for a glyph ID * in the specified font, for vertical text segments. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 0.9.2 **/ @@ -1026,7 +1032,7 @@ hb_font_get_glyph_v_origin (hb_font_t *font, * @right_glyph: The glyph ID of the right glyph in the glyph pair * * Fetches the kerning-adjustment value for a glyph-pair in - * the specified font, in horizontal text segments. + * the specified font, for horizontal text segments. * * <note>It handles legacy kerning only (as returned by the corresponding * #hb_font_funcs_t function).</note> @@ -1051,7 +1057,7 @@ hb_font_get_glyph_h_kerning (hb_font_t *font, * @bottom_glyph: The glyph ID of the bottom glyph in the glyph pair * * Fetches the kerning-adjustment value for a glyph-pair in - * the specified font, in vertical text segments. + * the specified font, for vertical text segments. * * <note>It handles legacy kerning only (as returned by the corresponding * #hb_font_funcs_t function).</note> @@ -1079,7 +1085,7 @@ hb_font_get_glyph_v_kerning (hb_font_t *font, * Fetches the #hb_glyph_extents_t data for a glyph ID * in the specified font. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 0.9.2 **/ @@ -1102,7 +1108,7 @@ hb_font_get_glyph_extents (hb_font_t *font, * Fetches the (x,y) coordinates of a specified contour-point index * in the specified glyph, within the specified font. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 0.9.2 **/ @@ -1125,7 +1131,7 @@ hb_font_get_glyph_contour_point (hb_font_t *font, * * Fetches the glyph-name string for a glyph ID in the specified @font. * - * Return value: %true if data found, zero otherwise + * Return value: %true if data found, %false otherwise * * Since: 0.9.2 **/ @@ -1149,7 +1155,7 @@ hb_font_get_glyph_name (hb_font_t *font, * * <note>Note: @len == -1 means the name string is null-terminated.</note> * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 0.9.2 **/ @@ -1169,7 +1175,7 @@ hb_font_get_glyph_from_name (hb_font_t *font, * hb_font_get_extents_for_direction: * @font: #hb_font_t to work upon * @direction: The direction of the text segment - * @extents: (out): The #hb_glyph_extents_t retrieved + * @extents: (out): The #hb_font_extents_t retrieved * * Fetches the extents for a font in a text segment of the * specified direction. @@ -1364,7 +1370,7 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font, * Calls the appropriate direction-specific variant (horizontal * or vertical) depending on the value of @direction. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 0.9.2 **/ @@ -1393,7 +1399,7 @@ hb_font_get_glyph_extents_for_origin (hb_font_t *font, * Calls the appropriate direction-specific variant (horizontal * or vertical) depending on the value of @direction. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 0.9.2 **/ @@ -1444,7 +1450,7 @@ hb_font_glyph_to_string (hb_font_t *font, * * <note>Note: @len == -1 means the string is null-terminated.</note> * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 0.9.2 **/ @@ -1664,12 +1670,12 @@ hb_font_destroy (hb_font_t *font) * @font: #hb_font_t to work upon * @key: The user-data key * @data: A pointer to the user data - * @destroy: (optional): A callback to call when @data is not needed anymore + * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * * Attaches a user-data key/data pair to the specified font object. * - * Return value: + * Return value: %true if success, %false otherwise * * Since: 0.9.2 **/ @@ -1728,7 +1734,7 @@ hb_font_make_immutable (hb_font_t *font) * * Tests whether a font object is immutable. * - * Return value: %true if @font is immutable, false otherwise + * Return value: %true if @font is immutable, %false otherwise * * Since: 0.9.2 **/ @@ -1828,9 +1834,9 @@ hb_font_get_face (hb_font_t *font) /** * hb_font_set_funcs: * @font: #hb_font_t to work upon - * @klass: (closure font_data) (destroy destroy) (scope notified): + * @klass: (closure font_data) (destroy destroy) (scope notified): The font-functions structure. * @font_data: Data to attach to @font - * @destroy: (optional): The function to call when @font_data is not needed anymore + * @destroy: (nullable): The function to call when @font_data is not needed anymore * * Replaces the font-functions structure attached to a font, updating * the font's user-data with @font-data and the @destroy callback. @@ -1867,7 +1873,7 @@ hb_font_set_funcs (hb_font_t *font, * hb_font_set_funcs_data: * @font: #hb_font_t to work upon * @font_data: (destroy destroy) (scope notified): Data to attach to @font - * @destroy: (optional): The function to call when @font_data is not needed anymore + * @destroy: (nullable): The function to call when @font_data is not needed anymore * * Replaces the user data attached to a font, updating the font's * @destroy callback. @@ -2212,10 +2218,14 @@ hb_font_get_var_coords_normalized (hb_font_t *font, #ifdef HB_EXPERIMENTAL_API /** * hb_font_get_var_coords_design: + * @font: #hb_font_t to work upon + * @length: (out): number of coordinates * * Return value is valid as long as variation coordinates of the font * are not modified. * + * Return value: coordinates array + * * Since: EXPERIMENTAL */ const float * @@ -2319,7 +2329,7 @@ hb_font_get_variation_glyph_trampoline (hb_font_t *font, * @ffuncs: The font-functions structure * @func: (closure user_data) (destroy destroy) (scope notified): callback function * @user_data: data to pass to @func - * @destroy: (optional): function to call when @user_data is not needed anymore + * @destroy: (nullable): function to call when @user_data is not needed anymore * * Deprecated. Use hb_font_funcs_set_nominal_glyph_func() and * hb_font_funcs_set_variation_glyph_func() instead. diff --git a/thirdparty/harfbuzz/src/hb-font.h b/thirdparty/harfbuzz/src/hb-font.h index 05f6c03f47..15dc126523 100644 --- a/thirdparty/harfbuzz/src/hb-font.h +++ b/thirdparty/harfbuzz/src/hb-font.h @@ -24,7 +24,7 @@ * Red Hat Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif @@ -37,7 +37,12 @@ HB_BEGIN_DECLS - +/** + * hb_font_t: + * + * Data type for holding fonts. + * + */ typedef struct hb_font_t hb_font_t; @@ -141,6 +146,16 @@ typedef struct hb_glyph_extents_t { /* func types */ +/** + * hb_font_get_font_extents_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @extents: (out): The font extents retrieved + * @user_data: User data pointer passed by the caller + * + * This method should retrieve the extents for a font. + * + **/ typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data, hb_font_extents_t *extents, void *user_data); @@ -150,7 +165,7 @@ typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *fon * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * - * This method should retrieve the extents for a font, in horizontal-direction + * This method should retrieve the extents for a font, for horizontal-direction * text segments. Extents must be returned in an #hb_glyph_extents output * parameter. * @@ -162,7 +177,7 @@ typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t; * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * - * This method should retrieve the extents for a font, in vertical-direction + * This method should retrieve the extents for a font, for vertical-direction * text segments. Extents must be returned in an #hb_glyph_extents output * parameter. * @@ -172,12 +187,19 @@ typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t; /** * hb_font_get_nominal_glyph_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @unicode: The Unicode code point to query + * @glyph: (out): The glyph ID retrieved + * @user_data: User data pointer passed by the caller * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * * This method should retrieve the nominal glyph ID for a specified Unicode code * point. Glyph IDs must be returned in a #hb_codepoint_t output parameter. * + * Return value: %true if data found, %false otherwise + * **/ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t unicode, @@ -186,6 +208,12 @@ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *fo /** * hb_font_get_variation_glyph_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @unicode: The Unicode code point to query + * @variation_selector: The variation-selector code point to query + * @glyph: (out): The glyph ID retrieved + * @user_data: User data pointer passed by the caller * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * @@ -193,6 +221,8 @@ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *fo * followed by a specified Variation Selector code point. Glyph IDs must be * returned in a #hb_codepoint_t output parameter. * + * Return value: %true if data found, %false otherwise + * **/ typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t unicode, hb_codepoint_t variation_selector, @@ -202,12 +232,22 @@ typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void * /** * hb_font_get_nominal_glyphs_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @count: number of code points to query + * @first_unicode: The first Unicode code point to query + * @unicode_stride: The stride between successive code points + * @first_glyph: (out): The first glyph ID retrieved + * @glyph_stride: The stride between successive glyph IDs + * @user_data: User data pointer passed by the caller * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * * This method should retrieve the nominal glyph IDs for a sequence of * Unicode code points. Glyph IDs must be returned in a #hb_codepoint_t * output parameter. + * + * Return value: the number of code points processed * **/ typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void *font_data, @@ -220,12 +260,18 @@ typedef unsigned int (*hb_font_get_nominal_glyphs_func_t) (hb_font_t *font, void /** * hb_font_get_glyph_advance_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @user_data: User data pointer passed by the caller * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * * This method should retrieve the advance for a specified glyph. The * method must return an #hb_position_t. * + * Return value: The advance of @glyph within @font + * **/ typedef hb_position_t (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t glyph, @@ -257,6 +303,14 @@ typedef hb_font_get_glyph_advance_func_t hb_font_get_glyph_v_advance_func_t; /** * hb_font_get_glyph_advances_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @count: The number of glyph IDs in the sequence queried + * @first_glyph: The first glyph ID to query + * @glyph_stride: The stride between successive glyph IDs + * @first_advance: (out): The first advance retrieved + * @advance_stride: The stride between successive advances + * @user_data: User data pointer passed by the caller * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * @@ -295,12 +349,20 @@ typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t; /** * hb_font_get_glyph_origin_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @x: (out): The X coordinate of the origin + * @y: (out): The Y coordinate of the origin + * @user_data: User data pointer passed by the caller * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * * This method should retrieve the (X,Y) coordinates (in font units) of the * origin for a glyph. Each coordinate must be returned in an #hb_position_t * output parameter. + * + * Return value: %true if data found, %false otherwise * **/ typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data, @@ -314,7 +376,7 @@ typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *fon * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * * This method should retrieve the (X,Y) coordinates (in font units) of the - * origin for a glyph, in horizontal-direction text segments. Each + * origin for a glyph, for horizontal-direction text segments. Each * coordinate must be returned in an #hb_position_t output parameter. * **/ @@ -326,25 +388,53 @@ typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t; * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * * This method should retrieve the (X,Y) coordinates (in font units) of the - * origin for a glyph, in vertical-direction text segments. Each coordinate + * origin for a glyph, for vertical-direction text segments. Each coordinate * must be returned in an #hb_position_t output parameter. * **/ typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t; +/** + * hb_font_get_glyph_kerning_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @first_glyph: The glyph ID of the first glyph in the glyph pair + * @second_glyph: The glyph ID of the second glyph in the glyph pair + * @user_data: User data pointer passed by the caller + * + * This method should retrieve the kerning-adjustment value for a glyph-pair in + * the specified font, for horizontal text segments. + * + **/ typedef hb_position_t (*hb_font_get_glyph_kerning_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t first_glyph, hb_codepoint_t second_glyph, void *user_data); +/** + * hb_font_get_glyph_h_kerning_func_t: + * + * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. + * + * This method should retrieve the kerning-adjustment value for a glyph-pair in + * the specified font, for horizontal text segments. + * + **/ typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t; /** * hb_font_get_glyph_extents_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @extents: (out): The #hb_glyph_extents_t retrieved + * @user_data: User data pointer passed by the caller * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * * This method should retrieve the extents for a specified glyph. Extents must be * returned in an #hb_glyph_extents output parameter. + * + * Return value: %true if data found, %false otherwise * **/ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data, @@ -354,6 +444,13 @@ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *fo /** * hb_font_get_glyph_contour_point_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @point_index: The contour-point index to query + * @x: (out): The X value retrieved for the contour point + * @y: (out): The Y value retrieved for the contour point + * @user_data: User data pointer passed by the caller * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * @@ -361,6 +458,8 @@ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *fo * specified contour point in a glyph. Each coordinate must be returned as * an #hb_position_t output parameter. * + * Return value: %true if data found, %false otherwise + * **/ typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t glyph, unsigned int point_index, @@ -370,12 +469,20 @@ typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, vo /** * hb_font_get_glyph_name_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @glyph: The glyph ID to query + * @name: (out) (array length=size): Name string retrieved for the glyph ID + * @size: Length of the glyph-name string retrieved + * @user_data: User data pointer passed by the caller * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * * This method should retrieve the glyph name that corresponds to a * glyph ID. The name should be returned in a string output parameter. * + * Return value: %true if data found, %false otherwise + * **/ typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data, hb_codepoint_t glyph, @@ -384,12 +491,20 @@ typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_ /** * hb_font_get_glyph_from_name_func_t: + * @font: #hb_font_t to work upon + * @font_data: @font user data pointer + * @name: (array length=len): The name string to query + * @len: The length of the name queried + * @glyph: (out): The glyph ID retrieved + * @user_data: User data pointer passed by the caller * * A virtual method for the #hb_font_funcs_t of an #hb_font_t object. * * This method should retrieve the glyph ID that corresponds to a glyph-name * string. * + * Return value: %true if data found, %false otherwise + * **/ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data, const char *name, int len, /* -1 means nul-terminated */ @@ -404,7 +519,7 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void * * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_font_h_extents_func_t. * @@ -420,7 +535,7 @@ hb_font_funcs_set_font_h_extents_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_font_v_extents_func_t. * @@ -436,7 +551,7 @@ hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_nominal_glyph_func_t. * @@ -452,7 +567,7 @@ hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_nominal_glyphs_func_t. * @@ -468,7 +583,7 @@ hb_font_funcs_set_nominal_glyphs_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_variation_glyph_func_t. * @@ -484,7 +599,7 @@ hb_font_funcs_set_variation_glyph_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_glyph_h_advance_func_t. * @@ -500,7 +615,7 @@ hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_glyph_v_advance_func_t. * @@ -516,7 +631,7 @@ hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_glyph_h_advances_func_t. * @@ -532,7 +647,7 @@ hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_glyph_v_advances_func_t. * @@ -548,7 +663,7 @@ hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_glyph_h_origin_func_t. * @@ -564,7 +679,7 @@ hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_glyph_v_origin_func_t. * @@ -577,12 +692,12 @@ hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs, /** * hb_font_funcs_set_glyph_h_kerning_func: - * @ffuncs: font functions. - * @func: (closure user_data) (destroy destroy) (scope notified): - * @user_data: - * @destroy: - * + * @ffuncs: A font-function structure + * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign + * @user_data: Data to pass to @func + * @destroy: (nullable): The function to call when @user_data is not needed anymore * + * Sets the implementation function for #hb_font_get_glyph_h_kerning_func_t. * * Since: 0.9.2 **/ @@ -596,7 +711,7 @@ hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_glyph_extents_func_t. * @@ -612,7 +727,7 @@ hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_glyph_contour_point_func_t. * @@ -628,7 +743,7 @@ hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_glyph_name_func_t. * @@ -644,7 +759,7 @@ hb_font_funcs_set_glyph_name_func (hb_font_funcs_t *ffuncs, * @ffuncs: A font-function structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_font_get_glyph_from_name_func_t. * diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc index ab7d6146ce..b82c1a67bd 100644 --- a/thirdparty/harfbuzz/src/hb-ft.cc +++ b/thirdparty/harfbuzz/src/hb-ft.cc @@ -84,7 +84,7 @@ struct hb_ft_font_t bool symbol; /* Whether selected cmap is symbol cmap. */ bool unref; /* Whether to destroy ft_face when done. */ - mutable hb_atomic_int_t cached_x_scale; + mutable int cached_x_scale; mutable hb_advance_cache_t advance_cache; }; @@ -101,7 +101,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref) ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; - ft_font->cached_x_scale.set_relaxed (0); + ft_font->cached_x_scale = 0; ft_font->advance_cache.init (); return ft_font; @@ -179,13 +179,13 @@ hb_ft_font_get_load_flags (hb_font_t *font) } /** - * hb_ft_get_face: + * hb_ft_font_get_face: * @font: #hb_font_t to work upon * * Fetches the FT_Face associated with the specified #hb_font_t * font object. * - * Return value: the FT_Face found + * Return value: (nullable): the FT_Face found or %NULL * * Since: 0.9.2 **/ @@ -202,11 +202,12 @@ hb_ft_font_get_face (hb_font_t *font) /** * hb_ft_font_lock_face: - * @font: - * + * @font: #hb_font_t to work upon * + * Gets the FT_Face associated with @font, This face will be kept around until + * you call hb_ft_font_unlock_face(). * - * Return value: + * Return value: (nullable): the FT_Face associated with @font or %NULL * Since: 2.6.5 **/ FT_Face @@ -224,11 +225,10 @@ hb_ft_font_lock_face (hb_font_t *font) /** * hb_ft_font_unlock_face: - * @font: - * + * @font: #hb_font_t to work upon * + * Releases an FT_Face previously obtained with hb_ft_font_lock_face(). * - * Return value: * Since: 2.6.5 **/ void @@ -335,10 +335,10 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data, int load_flags = ft_font->load_flags; int mult = font->x_scale < 0 ? -1 : +1; - if (font->x_scale != ft_font->cached_x_scale.get ()) + if (font->x_scale != ft_font->cached_x_scale) { ft_font->advance_cache.clear (); - ft_font->cached_x_scale.set (font->x_scale); + ft_font->cached_x_scale = font->x_scale; } for (unsigned int i = 0; i < count; i++) @@ -661,7 +661,7 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data /** * hb_ft_face_create: * @ft_face: (destroy destroy) (scope notified): FT_Face to work upon - * @destroy: (optional): A callback to call when the face object is not needed anymore + * @destroy: (nullable): A callback to call when the face object is not needed anymore * * Creates an #hb_face_t face object from the specified FT_Face. * @@ -771,13 +771,13 @@ hb_ft_face_create_cached (FT_Face ft_face) /** * hb_ft_font_create: * @ft_face: (destroy destroy) (scope notified): FT_Face to work upon - * @destroy: (optional): A callback to call when the font object is not needed anymore + * @destroy: (nullable): A callback to call when the font object is not needed anymore * * Creates an #hb_font_t font object from the specified FT_Face. * * <note>Note: You must set the face size on @ft_face before calling - * hb_ft_font_create() on it. Otherwise, HarfBuzz will not pick up - * the face size.</note> + * hb_ft_font_create() on it. HarfBuzz assumes size is always set and will + * access `size` member of FT_Face unconditionally.</note> * * This variant of the function does not provide any life-cycle management. * @@ -814,7 +814,7 @@ hb_ft_font_create (FT_Face ft_face, } /** - * hb_ft_font_has_changed: + * hb_ft_font_changed: * @font: #hb_font_t to work upon * * Refreshes the state of @font when the underlying FT_Face has changed. @@ -884,8 +884,8 @@ hb_ft_font_changed (hb_font_t *font) * Creates an #hb_font_t font object from the specified FT_Face. * * <note>Note: You must set the face size on @ft_face before calling - * hb_ft_font_create_references() on it. Otherwise, HarfBuzz will not pick up - * the face size.</note> + * hb_ft_font_create_referenced() on it. HarfBuzz assumes size is always set + * and will access `size` member of FT_Face unconditionally.</note> * * This is the preferred variant of the hb_ft_font_create* * function family, because it calls FT_Reference_Face() on @ft_face, diff --git a/thirdparty/harfbuzz/src/hb-gdi.cc b/thirdparty/harfbuzz/src/hb-gdi.cc index 3a67cef160..dc4659c7f6 100644 --- a/thirdparty/harfbuzz/src/hb-gdi.cc +++ b/thirdparty/harfbuzz/src/hb-gdi.cc @@ -70,6 +70,8 @@ fail: * hb_gdi_face_create: * @hfont: a HFONT object. * + * Constructs a new face object from the specified GDI HFONT. + * * Return value: #hb_face_t object corresponding to the given input * * Since: 2.6.0 diff --git a/thirdparty/harfbuzz/src/hb-gobject-structs.h b/thirdparty/harfbuzz/src/hb-gobject-structs.h index 6fad8d7019..63467f80df 100644 --- a/thirdparty/harfbuzz/src/hb-gobject-structs.h +++ b/thirdparty/harfbuzz/src/hb-gobject-structs.h @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifndef HB_GOBJECT_H_IN +#if !defined(HB_GOBJECT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-gobject.h> instead." #endif @@ -40,47 +40,22 @@ HB_BEGIN_DECLS /* Object types */ -/** - * hb_gobject_blob_get_type: - * - * Since: 0.9.2 - **/ HB_EXTERN GType hb_gobject_blob_get_type (void); #define HB_GOBJECT_TYPE_BLOB (hb_gobject_blob_get_type ()) -/** - * hb_gobject_buffer_get_type: - * - * Since: 0.9.2 - **/ HB_EXTERN GType hb_gobject_buffer_get_type (void); #define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ()) -/** - * hb_gobject_face_get_type: - * - * Since: 0.9.2 - **/ HB_EXTERN GType hb_gobject_face_get_type (void); #define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ()) -/** - * hb_gobject_font_get_type: - * - * Since: 0.9.2 - **/ HB_EXTERN GType hb_gobject_font_get_type (void); #define HB_GOBJECT_TYPE_FONT (hb_gobject_font_get_type ()) -/** - * hb_gobject_font_funcs_get_type: - * - * Since: 0.9.2 - **/ HB_EXTERN GType hb_gobject_font_funcs_get_type (void); #define HB_GOBJECT_TYPE_FONT_FUNCS (hb_gobject_font_funcs_get_type ()) @@ -97,11 +72,6 @@ HB_EXTERN GType hb_gobject_shape_plan_get_type (void); #define HB_GOBJECT_TYPE_SHAPE_PLAN (hb_gobject_shape_plan_get_type ()) -/** - * hb_gobject_unicode_funcs_get_type: - * - * Since: 0.9.2 - **/ HB_EXTERN GType hb_gobject_unicode_funcs_get_type (void); #define HB_GOBJECT_TYPE_UNICODE_FUNCS (hb_gobject_unicode_funcs_get_type ()) diff --git a/thirdparty/harfbuzz/src/hb-graphite2.cc b/thirdparty/harfbuzz/src/hb-graphite2.cc index d8a72dc2f1..9dafe654c8 100644 --- a/thirdparty/harfbuzz/src/hb-graphite2.cc +++ b/thirdparty/harfbuzz/src/hb-graphite2.cc @@ -195,6 +195,11 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED #ifndef HB_DISABLE_DEPRECATED /** * hb_graphite2_font_get_gr_font: + * @font: An #hb_font_t + * + * Always returns %NULL. Use hb_graphite2_face_get_gr_face() instead. + * + * Return value: (nullable): Graphite2 font associated with @font. * * Since: 0.9.10 * Deprecated: 1.4.2 @@ -284,7 +289,7 @@ _hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED, return true; } - buffer->ensure (glyph_count); + (void) buffer->ensure (glyph_count); scratch = buffer->get_scratch_buffer (&scratch_size); while ((DIV_CEIL (sizeof (hb_graphite2_cluster_t) * buffer->len, sizeof (*scratch)) + DIV_CEIL (sizeof (hb_codepoint_t) * glyph_count, sizeof (*scratch))) > scratch_size) diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh index 981c5c218c..f7018150e4 100644 --- a/thirdparty/harfbuzz/src/hb-iter.hh +++ b/thirdparty/harfbuzz/src/hb-iter.hh @@ -922,7 +922,7 @@ HB_FUNCOBJ (hb_none); template <typename C, typename V, hb_requires (hb_is_iterable (C))> inline void -hb_fill (C& c, const V &v) +hb_fill (C&& c, const V &v) { for (auto i = hb_iter (c); i; i++) *i = v; diff --git a/thirdparty/harfbuzz/src/hb-machinery.hh b/thirdparty/harfbuzz/src/hb-machinery.hh index 54bc60d4c8..3bd5a979b0 100644 --- a/thirdparty/harfbuzz/src/hb-machinery.hh +++ b/thirdparty/harfbuzz/src/hb-machinery.hh @@ -80,6 +80,11 @@ static inline Type& StructAfter(TObject &X) * Size checking */ +/* Size signifying variable-sized array */ +#ifndef HB_VAR_ARRAY +#define HB_VAR_ARRAY 1 +#endif + /* Check _assertion in a method environment */ #define _DEFINE_INSTANCE_ASSERTION1(_line, _assertion) \ void _instance_assertion_on_line_##_line () const \ diff --git a/thirdparty/harfbuzz/src/hb-map.cc b/thirdparty/harfbuzz/src/hb-map.cc index f898bd8f92..f115da2bb8 100644 --- a/thirdparty/harfbuzz/src/hb-map.cc +++ b/thirdparty/harfbuzz/src/hb-map.cc @@ -117,7 +117,7 @@ hb_map_destroy (hb_map_t *map) * @map: A map * @key: The user-data key to set * @data: A pointer to the user data to set - * @destroy: (optional): A callback to call when @data is not needed anymore + * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * * Attaches a user-data key/data pair to the specified map. @@ -162,7 +162,7 @@ hb_map_get_user_data (hb_map_t *map, * * Tests whether memory allocation for a set was successful. * - * Return value: %true if allocation succeeded, false otherwise + * Return value: %true if allocation succeeded, %false otherwise * * Since: 1.7.7 **/ @@ -230,7 +230,7 @@ hb_map_del (hb_map_t *map, * * Tests whether @key is an element of @map. * - * Return value: %true if @key is found in @map, false otherwise + * Return value: %true if @key is found in @map, %false otherwise * * Since: 1.7.7 **/ @@ -253,6 +253,9 @@ hb_map_has (const hb_map_t *map, void hb_map_clear (hb_map_t *map) { + if (unlikely (hb_object_is_immutable (map))) + return; + return map->clear (); } diff --git a/thirdparty/harfbuzz/src/hb-map.h b/thirdparty/harfbuzz/src/hb-map.h index 0c19ac8fb5..6a45a7bdd5 100644 --- a/thirdparty/harfbuzz/src/hb-map.h +++ b/thirdparty/harfbuzz/src/hb-map.h @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif @@ -36,7 +36,11 @@ HB_BEGIN_DECLS -/* +/** + * HB_MAP_VALUE_INVALID: + * + * Unset #hb_map_t value. + * * Since: 1.7.7 */ #define HB_MAP_VALUE_INVALID ((hb_codepoint_t) -1) diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh index 92c1bd67e5..84fe1d549b 100644 --- a/thirdparty/harfbuzz/src/hb-map.hh +++ b/thirdparty/harfbuzz/src/hb-map.hh @@ -97,8 +97,6 @@ struct hb_hashmap_t void reset () { - if (unlikely (hb_object_is_immutable (this))) - return; successful = true; clear (); } @@ -171,8 +169,6 @@ struct hb_hashmap_t void clear () { - if (unlikely (hb_object_is_immutable (this))) - return; if (items) for (auto &_ : hb_iter (items, mask + 1)) _.clear (); @@ -181,6 +177,7 @@ struct hb_hashmap_t } bool is_empty () const { return population == 0; } + explicit operator bool () const { return !is_empty (); } unsigned int get_population () const { return population; } diff --git a/thirdparty/harfbuzz/src/hb-meta.hh b/thirdparty/harfbuzz/src/hb-meta.hh index 4c0898b1b7..e40d9fd178 100644 --- a/thirdparty/harfbuzz/src/hb-meta.hh +++ b/thirdparty/harfbuzz/src/hb-meta.hh @@ -49,6 +49,10 @@ template <bool b> using hb_bool_constant = hb_integral_constant<bool, b>; using hb_true_type = hb_bool_constant<true>; using hb_false_type = hb_bool_constant<false>; +/* Static-assert as expression. */ +template <bool cond> struct static_assert_expr; +template <> struct static_assert_expr<true> : hb_false_type {}; +#define static_assert_expr(C) static_assert_expr<C>::value /* Basic type SFINAE. */ @@ -220,6 +224,8 @@ struct hb_reference_wrapper<T&> }; +/* Type traits */ + template <typename T> using hb_is_integral = hb_bool_constant< hb_is_same (hb_decay<T>, char) || @@ -292,6 +298,15 @@ template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigne #define hb_int_max(T) hb_int_max<T>::value +/* Class traits. */ + +#define HB_DELETE_COPY_ASSIGN(TypeName) \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete +#define HB_DELETE_CREATE_COPY_ASSIGN(TypeName) \ + TypeName() = delete; \ + TypeName(const TypeName&) = delete; \ + void operator=(const TypeName&) = delete template <typename T, typename> struct _hb_is_destructible : hb_false_type {}; diff --git a/thirdparty/harfbuzz/src/hb-mutex.hh b/thirdparty/harfbuzz/src/hb-mutex.hh index 56392d049b..2fc8d7ee58 100644 --- a/thirdparty/harfbuzz/src/hb-mutex.hh +++ b/thirdparty/harfbuzz/src/hb-mutex.hh @@ -73,24 +73,6 @@ typedef CRITICAL_SECTION hb_mutex_impl_t; #define hb_mutex_impl_finish(M) DeleteCriticalSection (M) -#elif !defined(HB_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES) - -#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD) -# include <sched.h> -# define HB_SCHED_YIELD() sched_yield () -#else -# define HB_SCHED_YIELD() HB_STMT_START {} HB_STMT_END -#endif - -/* This actually is not a totally awful implementation. */ -typedef volatile int hb_mutex_impl_t; -#define HB_MUTEX_IMPL_INIT 0 -#define hb_mutex_impl_init(M) *(M) = 0 -#define hb_mutex_impl_lock(M) HB_STMT_START { while (__sync_lock_test_and_set((M), 1)) HB_SCHED_YIELD (); } HB_STMT_END -#define hb_mutex_impl_unlock(M) __sync_lock_release (M) -#define hb_mutex_impl_finish(M) HB_STMT_START {} HB_STMT_END - - #elif defined(HB_NO_MT) typedef int hb_mutex_impl_t; diff --git a/thirdparty/harfbuzz/src/hb-object.hh b/thirdparty/harfbuzz/src/hb-object.hh index 39845a70e7..f3048b1c3e 100644 --- a/thirdparty/harfbuzz/src/hb-object.hh +++ b/thirdparty/harfbuzz/src/hb-object.hh @@ -140,9 +140,7 @@ struct hb_lockable_set_t * Reference-count. */ -#define HB_REFERENCE_COUNT_INERT_VALUE 0 -#define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD -#define HB_REFERENCE_COUNT_INIT {HB_ATOMIC_INT_INIT (HB_REFERENCE_COUNT_INERT_VALUE)} +#define HB_REFERENCE_COUNT_INIT {0} struct hb_reference_count_t { @@ -152,9 +150,9 @@ struct hb_reference_count_t int get_relaxed () const { return ref_count.get_relaxed (); } int inc () const { return ref_count.inc (); } int dec () const { return ref_count.dec (); } - void fini () { ref_count.set_relaxed (HB_REFERENCE_COUNT_POISON_VALUE); } + void fini () { ref_count.set_relaxed (-0x0000DEAD); } - bool is_inert () const { return ref_count.get_relaxed () == HB_REFERENCE_COUNT_INERT_VALUE; } + bool is_inert () const { return !ref_count.get_relaxed (); } bool is_valid () const { return ref_count.get_relaxed () > 0; } }; @@ -197,15 +195,10 @@ struct hb_user_data_array_t struct hb_object_header_t { hb_reference_count_t ref_count; - mutable hb_atomic_int_t writable; + mutable hb_atomic_int_t writable = 0; hb_atomic_ptr_t<hb_user_data_array_t> user_data; }; -#define HB_OBJECT_HEADER_STATIC \ - { \ - HB_REFERENCE_COUNT_INIT, \ - HB_ATOMIC_INT_INIT (false), \ - HB_ATOMIC_PTR_INIT (nullptr) \ - } +#define HB_OBJECT_HEADER_STATIC {} /* diff --git a/thirdparty/harfbuzz/src/hb-open-file.hh b/thirdparty/harfbuzz/src/hb-open-file.hh index ac13dd23c3..54c07ff13c 100644 --- a/thirdparty/harfbuzz/src/hb-open-file.hh +++ b/thirdparty/harfbuzz/src/hb-open-file.hh @@ -48,7 +48,7 @@ namespace OT { */ struct OpenTypeFontFile; -struct OffsetTable; +struct OpenTypeOffsetTable; struct TTCHeader; @@ -78,7 +78,7 @@ typedef struct TableRecord DEFINE_SIZE_STATIC (16); } OpenTypeTable; -typedef struct OffsetTable +typedef struct OpenTypeOffsetTable { friend struct OpenTypeFontFile; @@ -218,7 +218,7 @@ struct TTCHeaderVersion1 Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */ FixedVersion<>version; /* Version of the TTC Header (1.0), * 0x00010000u */ - LArrayOf<LOffsetTo<OffsetTable>> + LArrayOf<LOffsetTo<OpenTypeOffsetTable>> table; /* Array of offsets to the OffsetTable for each font * from the beginning of the file */ public: diff --git a/thirdparty/harfbuzz/src/hb-open-type.hh b/thirdparty/harfbuzz/src/hb-open-type.hh index 99634b76f0..dc0ae1d989 100644 --- a/thirdparty/harfbuzz/src/hb-open-type.hh +++ b/thirdparty/harfbuzz/src/hb-open-type.hh @@ -53,14 +53,19 @@ namespace OT { */ /* Integer types in big-endian order and no alignment requirement */ -template <typename Type, unsigned int Size> +template <typename Type, + unsigned int Size = sizeof (Type)> struct IntType { typedef Type type; - typedef hb_conditional<hb_is_signed (Type), signed, unsigned> wide_type; - IntType& operator = (wide_type i) { v = i; return *this; } - operator wide_type () const { return v; } + IntType () = default; + explicit constexpr IntType (Type V) : v {V} {} + IntType& operator = (Type i) { v = i; return *this; } + /* For reason we define cast out operator for signed/unsigned, instead of Type, see: + * https://github.com/harfbuzz/harfbuzz/pull/2875/commits/09836013995cab2b9f07577a179ad7b024130467 */ + operator hb_conditional<hb_is_signed (Type), signed, unsigned> () const { return v; } + bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } bool operator != (const IntType &o) const { return !(*this == o); } @@ -80,14 +85,21 @@ struct IntType return pb->cmp (*pa); } - template <typename Type2> + template <typename Type2, + hb_enable_if (hb_is_integral (Type2) && + sizeof (Type2) < sizeof (int) && + sizeof (Type) < sizeof (int))> int cmp (Type2 a) const { Type b = v; - if (sizeof (Type) < sizeof (int) && sizeof (Type2) < sizeof (int)) - return (int) a - (int) b; - else - return a < b ? -1 : a == b ? 0 : +1; + return (int) a - (int) b; + } + template <typename Type2, + hb_enable_if (hb_is_convertible (Type2, Type))> + int cmp (Type2 a) const + { + Type b = v; + return a < b ? -1 : a == b ? 0 : +1; } bool sanitize (hb_sanitize_context_t *c) const { @@ -100,12 +112,12 @@ struct IntType DEFINE_SIZE_STATIC (Size); }; -typedef IntType<uint8_t, 1> HBUINT8; /* 8-bit unsigned integer. */ -typedef IntType<int8_t, 1> HBINT8; /* 8-bit signed integer. */ -typedef IntType<uint16_t, 2> HBUINT16; /* 16-bit unsigned integer. */ -typedef IntType<int16_t, 2> HBINT16; /* 16-bit signed integer. */ -typedef IntType<uint32_t, 4> HBUINT32; /* 32-bit unsigned integer. */ -typedef IntType<int32_t, 4> HBINT32; /* 32-bit signed integer. */ +typedef IntType<uint8_t> HBUINT8; /* 8-bit unsigned integer. */ +typedef IntType<int8_t> HBINT8; /* 8-bit signed integer. */ +typedef IntType<uint16_t> HBUINT16; /* 16-bit unsigned integer. */ +typedef IntType<int16_t> HBINT16; /* 16-bit signed integer. */ +typedef IntType<uint32_t> HBUINT32; /* 32-bit unsigned integer. */ +typedef IntType<int32_t> HBINT32; /* 32-bit signed integer. */ /* Note: we cannot defined a signed HBINT24 because there's no corresponding C type. * Works for unsigned, but not signed, since we rely on compiler for sign-extension. */ typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */ @@ -163,8 +175,8 @@ struct Tag : HBUINT32 { Tag& operator = (hb_tag_t i) { HBUINT32::operator= (i); return *this; } /* What the char* converters return is NOT nul-terminated. Print using "%.4s" */ - operator const char* () const { return reinterpret_cast<const char *> (&this->v); } - operator char* () { return reinterpret_cast<char *> (&this->v); } + operator const char* () const { return reinterpret_cast<const char *> (this); } + operator char* () { return reinterpret_cast<char *> (this); } public: DEFINE_SIZE_STATIC (4); }; diff --git a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh index e5286cd792..864a27f458 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh @@ -183,7 +183,7 @@ struct CFFIndex else { serialize_header(c, + it | hb_map ([] (const byte_str_t &_) { return _.length; })); - for (const byte_str_t &_ : +it) + for (const auto &_ : +it) _.copy (c); } return_trace (true); diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc b/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc index 66b9c8c907..3298fa35ae 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc +++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc @@ -426,7 +426,7 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph else { extents->x_bearing = font->em_scalef_x (bounds.min.x.to_real ()); - extents->width = font->em_scalef_x (bounds.max.x.to_real () - bounds.min.x.to_real ()); + extents->width = font->em_scalef_x (bounds.max.x.to_real ()) - extents->x_bearing; } if (bounds.min.y >= bounds.max.y) { @@ -436,7 +436,7 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph else { extents->y_bearing = font->em_scalef_y (bounds.max.y.to_real ()); - extents->height = font->em_scalef_y (bounds.min.y.to_real () - bounds.max.y.to_real ()); + extents->height = font->em_scalef_y (bounds.min.y.to_real ()) - extents->y_bearing; } return true; diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc index ac0feeee21..879b7cdb23 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc +++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc @@ -127,7 +127,7 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, else { extents->x_bearing = font->em_scalef_x (param.min_x.to_real ()); - extents->width = font->em_scalef_x (param.max_x.to_real () - param.min_x.to_real ()); + extents->width = font->em_scalef_x (param.max_x.to_real ()) - extents->x_bearing; } if (param.min_y >= param.max_y) { @@ -137,7 +137,7 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font, else { extents->y_bearing = font->em_scalef_y (param.max_y.to_real ()); - extents->height = font->em_scalef_y (param.min_y.to_real () - param.max_y.to_real ()); + extents->height = font->em_scalef_y (param.min_y.to_real ()) - extents->y_bearing; } return true; diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh index cc48379bb8..878e02ff17 100644 --- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh @@ -95,7 +95,7 @@ struct CmapSubtableFormat4 HBUINT16 *endCode = c->start_embed<HBUINT16> (); hb_codepoint_t prev_endcp = 0xFFFF; - for (const hb_item_type<Iterator> _ : +it) + for (const auto& _ : +it) { if (prev_endcp != 0xFFFF && prev_endcp + 1u != _.first) { @@ -131,7 +131,7 @@ struct CmapSubtableFormat4 HBUINT16 *startCode = c->start_embed<HBUINT16> (); hb_codepoint_t prev_cp = 0xFFFF; - for (const hb_item_type<Iterator> _ : +it) + for (const auto& _ : +it) { if (prev_cp == 0xFFFF || prev_cp + 1u != _.first) { @@ -170,7 +170,7 @@ struct CmapSubtableFormat4 if ((char *)idDelta - (char *)startCode != (int) segcount * (int) HBINT16::static_size) return nullptr; - for (const hb_item_type<Iterator> _ : +it) + for (const auto& _ : +it) { if (_.first == startCode[i]) { @@ -696,7 +696,7 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12> hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF; hb_codepoint_t glyphID = 0; - for (const hb_item_type<Iterator> _ : +it) + for (const auto& _ : +it) { if (startCharCode == 0xFFFF) { diff --git a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh index aaa1c37c64..e285acec3d 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-cbdt-table.hh @@ -455,8 +455,8 @@ struct IndexSubtableRecord unsigned int old_cbdt_prime_length = bitmap_size_context->cbdt_prime->length; // Set to invalid state to indicate filling glyphs is not yet started. - if (unlikely (!records->resize (records->length + 1))) - return_trace (c->serializer->check_success (false)); + if (unlikely (!c->serializer->check_success (records->resize (records->length + 1)))) + return_trace (false); (*records)[records->length - 1].firstGlyphIndex = 1; (*records)[records->length - 1].lastGlyphIndex = 0; @@ -567,8 +567,8 @@ struct IndexSubtableArray hb_vector_t<hb_pair_t<hb_codepoint_t, const IndexSubtableRecord*>> lookup; build_lookup (c, bitmap_size_context, &lookup); - if (unlikely (lookup.in_error ())) - return c->serializer->check_success (false); + if (unlikely (!c->serializer->propagate_error (lookup))) + return false; bitmap_size_context->size = 0; bitmap_size_context->num_tables = 0; diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh index 92a49bb4f4..e2a1ff4662 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh @@ -214,7 +214,7 @@ struct COLR if (unlikely (!old_record)) return hb_pair_t<bool, BaseGlyphRecord> (false, Null (BaseGlyphRecord)); - BaseGlyphRecord new_record; + BaseGlyphRecord new_record = {}; new_record.glyphId = new_gid; new_record.numLayers = old_record->numLayers; return hb_pair_t<bool, BaseGlyphRecord> (true, new_record); diff --git a/thirdparty/harfbuzz/src/hb-ot-color.cc b/thirdparty/harfbuzz/src/hb-ot-color.cc index 0e7203a88b..4170b71317 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color.cc +++ b/thirdparty/harfbuzz/src/hb-ot-color.cc @@ -37,9 +37,6 @@ #include "hb-ot-color-sbix-table.hh" #include "hb-ot-color-svg-table.hh" -#include <stdlib.h> -#include <string.h> - /** * SECTION:hb-ot-color @@ -64,7 +61,7 @@ * * Tests whether a face includes a `CPAL` color-palette table. * - * Return value: true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 2.1.0 */ @@ -195,7 +192,7 @@ hb_ot_color_palette_get_colors (hb_face_t *face, * * Tests whether a face includes any `COLR` color layers. * - * Return value: true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 2.1.0 */ @@ -242,7 +239,7 @@ hb_ot_color_glyph_get_layers (hb_face_t *face, * * Tests whether a face includes any `SVG` glyph images. * - * Return value: true if data found, false otherwise. + * Return value: %true if data found, %false otherwise. * * Since: 2.1.0 */ @@ -280,7 +277,7 @@ hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph) * * Tests whether a face has PNG glyph images (either in `CBDT` or `sbix` tables). * - * Return value: true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 2.1.0 */ diff --git a/thirdparty/harfbuzz/src/hb-ot-color.h b/thirdparty/harfbuzz/src/hb-ot-color.h index 4f37a4386f..c23ce4de44 100644 --- a/thirdparty/harfbuzz/src/hb-ot-color.h +++ b/thirdparty/harfbuzz/src/hb-ot-color.h @@ -26,7 +26,7 @@ * Google Author(s): Sascha Brawer, Behdad Esfahbod */ -#ifndef HB_OT_H_IN +#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-ot.h> instead." #endif @@ -66,6 +66,8 @@ hb_ot_color_palette_color_get_name_id (hb_face_t *face, * @HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND: Flag indicating that the color * palette is appropriate to use when displaying the font on a dark background such as black. * + * Flags that describe the properties of color palette. + * * Since: 2.1.0 */ typedef enum { /*< flags >*/ @@ -95,6 +97,8 @@ hb_ot_color_has_layers (hb_face_t *face); /** * hb_ot_color_layer_t: + * @glyph: the glyph ID of the layer + * @color_index: the palette color index of the layer * * Pairs of glyph and color index. * diff --git a/thirdparty/harfbuzz/src/hb-ot-deprecated.h b/thirdparty/harfbuzz/src/hb-ot-deprecated.h index 2e75deef2d..ce6b6fef11 100644 --- a/thirdparty/harfbuzz/src/hb-ot-deprecated.h +++ b/thirdparty/harfbuzz/src/hb-ot-deprecated.h @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifndef HB_OT_H_IN +#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-ot.h> instead." #endif @@ -41,6 +41,13 @@ HB_BEGIN_DECLS /* https://github.com/harfbuzz/harfbuzz/issues/1734 */ +/** + * HB_MATH_GLYPH_PART_FLAG_EXTENDER: + * + * Use #HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER instead. + * + * Deprecated: 2.5.1 + */ #define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER @@ -71,6 +78,8 @@ hb_ot_tag_from_language (hb_language_t language); /** * HB_OT_VAR_NO_AXIS_INDEX: * + * Do not use. + * * Since: 1.4.2 * Deprecated: 2.2.0 */ @@ -78,6 +87,13 @@ hb_ot_tag_from_language (hb_language_t language); /** * hb_ot_var_axis_t: + * @tag: axis tag + * @name_id: axis name identifier + * @min_value: minimum value of the axis + * @default_value: default value of the axis + * @max_value: maximum value of the axis + * + * Use #hb_ot_var_axis_info_t instead. * * Since: 1.4.2 * Deprecated: 2.2.0 diff --git a/thirdparty/harfbuzz/src/hb-ot-font.h b/thirdparty/harfbuzz/src/hb-ot-font.h index 80eaa54b1a..e7959d1ae2 100644 --- a/thirdparty/harfbuzz/src/hb-ot-font.h +++ b/thirdparty/harfbuzz/src/hb-ot-font.h @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod, Roozbeh Pournader */ -#ifndef HB_OT_H_IN +#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-ot.h> instead." #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh index 5470bd96da..5352156f02 100644 --- a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh @@ -186,7 +186,7 @@ struct glyf | hb_map (&SubsetGlyph::padded_size) ; - if (c->serializer->in_error ()) return_trace (false); + if (unlikely (c->serializer->in_error ())) return_trace (false); return_trace (c->serializer->check_success (_add_loca_and_head (c->plan, padded_offsets))); } @@ -944,9 +944,9 @@ struct glyf return; } extents->x_bearing = font->em_scalef_x (min_x); - extents->width = font->em_scalef_x (max_x - min_x); + extents->width = font->em_scalef_x (max_x) - extents->x_bearing; extents->y_bearing = font->em_scalef_y (max_y); - extents->height = font->em_scalef_y (min_y - max_y); + extents->height = font->em_scalef_y (min_y) - extents->y_bearing; } protected: diff --git a/thirdparty/harfbuzz/src/hb-ot-head-table.hh b/thirdparty/harfbuzz/src/hb-ot-head-table.hh index 5613a96dbf..ac588e3af6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-head-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-head-table.hh @@ -43,7 +43,7 @@ namespace OT { struct head { - friend struct OffsetTable; + friend struct OpenTypeOffsetTable; static constexpr hb_tag_t tableTag = HB_OT_TAG_head; diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh index 6ab950a322..0ba7e3c061 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh @@ -1128,7 +1128,7 @@ struct Lookup out->lookupType = lookupType; out->lookupFlag = lookupFlag; - const hb_set_t *glyphset = c->plan->glyphset (); + const hb_set_t *glyphset = c->plan->glyphset_gsub (); unsigned int lookup_type = get_type (); + hb_iter (get_subtables <TSubTable> ()) | hb_filter ([this, glyphset, lookup_type] (const OffsetTo<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); }) @@ -1251,8 +1251,9 @@ struct CoverageFormat1 { /* TODO Speed up, using hb_set_next() and bsearch()? */ unsigned int count = glyphArray.len; + const HBGlyphID *arr = glyphArray.arrayZ; for (unsigned int i = 0; i < count; i++) - if (glyphs->has (glyphArray[i])) + if (glyphs->has (arr[i])) return true; return false; } @@ -1356,18 +1357,21 @@ struct CoverageFormat2 bool intersects (const hb_set_t *glyphs) const { /* TODO Speed up, using hb_set_next() and bsearch()? */ - unsigned int count = rangeRecord.len; - for (unsigned int i = 0; i < count; i++) - if (rangeRecord[i].intersects (glyphs)) + /* TODO(iter) Rewrite as dagger. */ + unsigned count = rangeRecord.len; + const RangeRecord *arr = rangeRecord.arrayZ; + for (unsigned i = 0; i < count; i++) + if (arr[i].intersects (glyphs)) return true; return false; } bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const { - unsigned int i; - unsigned int count = rangeRecord.len; - for (i = 0; i < count; i++) { - const RangeRecord &range = rangeRecord[i]; + /* TODO(iter) Rewrite as dagger. */ + unsigned count = rangeRecord.len; + const RangeRecord *arr = rangeRecord.arrayZ; + for (unsigned i = 0; i < count; i++) { + const RangeRecord &range = arr[i]; if (range.value <= index && index < (unsigned int) range.value + (range.last - range.first) && range.intersects (glyphs)) @@ -1502,7 +1506,7 @@ struct Coverage bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto it = @@ -1729,7 +1733,7 @@ struct ClassDefFormat1 hb_map_t *klass_map = nullptr /*OUT*/) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->_glyphset_gsub; + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; hb_sorted_vector_t<HBGlyphID> glyphs; @@ -1784,7 +1788,7 @@ struct ClassDefFormat1 } template <typename set_t> - bool collect_class (set_t *glyphs, unsigned int klass) const + bool collect_class (set_t *glyphs, unsigned klass) const { unsigned int count = classValue.len; for (unsigned int i = 0; i < count; i++) @@ -1802,7 +1806,7 @@ struct ClassDefFormat1 if (classValue[iter - start]) return true; return false; } - bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const + bool intersects_class (const hb_set_t *glyphs, uint16_t klass) const { unsigned int count = classValue.len; if (klass == 0) @@ -1815,8 +1819,12 @@ struct ClassDefFormat1 if (hb_set_next (glyphs, &g)) return true; /* Fall through. */ } + /* TODO Speed up, using set overlap first? */ + /* TODO(iter) Rewrite as dagger. */ + HBUINT16 k {klass}; + const HBUINT16 *arr = classValue.arrayZ; for (unsigned int i = 0; i < count; i++) - if (classValue[i] == klass && glyphs->has (startGlyph + i)) + if (arr[i] == k && glyphs->has (startGlyph + i)) return true; return false; } @@ -1898,7 +1906,7 @@ struct ClassDefFormat2 hb_map_t *klass_map = nullptr /*OUT*/) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->_glyphset_gsub; + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; hb_sorted_vector_t<HBGlyphID> glyphs; @@ -1961,11 +1969,14 @@ struct ClassDefFormat2 /* TODO Speed up, using hb_set_next() and bsearch()? */ unsigned int count = rangeRecord.len; for (unsigned int i = 0; i < count; i++) - if (rangeRecord[i].intersects (glyphs)) + { + const auto& range = rangeRecord[i]; + if (range.intersects (glyphs) && range.value) return true; + } return false; } - bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const + bool intersects_class (const hb_set_t *glyphs, uint16_t klass) const { unsigned int count = rangeRecord.len; if (klass == 0) @@ -1984,8 +1995,12 @@ struct ClassDefFormat2 return true; /* Fall through. */ } + /* TODO Speed up, using set overlap first? */ + /* TODO(iter) Rewrite as dagger. */ + HBUINT16 k {klass}; + const RangeRecord *arr = rangeRecord.arrayZ; for (unsigned int i = 0; i < count; i++) - if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs)) + if (arr[i].value == k && arr[i].intersects (glyphs)) return true; return false; } diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh index 2217d298fb..f523e35c00 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh @@ -566,6 +566,26 @@ struct AnchorMatrix return_trace (true); } + bool subset (hb_subset_context_t *c, + unsigned cols, + const hb_map_t *klass_mapping) const + { + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + + auto indexes = + + hb_range (rows * cols) + | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % cols); }) + ; + + out->serialize (c->serializer, + (unsigned) rows, + this, + c->plan->layout_variation_idx_map, + indexes); + return_trace (true); + } + bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const { TRACE_SANITIZE (this); @@ -755,7 +775,7 @@ struct SinglePosFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto it = @@ -870,7 +890,7 @@ struct SinglePosFormat2 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; unsigned sub_length = valueFormat.get_len (); @@ -1129,7 +1149,7 @@ struct PairSet if (unlikely (!c->serializer->extend_min (out))) return_trace (false); out->len = 0; - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; unsigned len1 = valueFormats[0].get_len (); @@ -1250,7 +1270,7 @@ struct PairPosFormat1 { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); @@ -1441,7 +1461,7 @@ struct PairPosFormat2 }) ; - const hb_set_t &glyphset = *c->plan->_glyphset_gsub; + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto it = @@ -1728,7 +1748,7 @@ struct CursivePosFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); @@ -1904,7 +1924,7 @@ struct MarkBasePosFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); @@ -2025,10 +2045,37 @@ typedef AnchorMatrix LigatureAttach; /* component-major-- * mark-minor-- * ordered by class--zero-based. */ -typedef OffsetListOf<LigatureAttach> LigatureArray; - /* Array of LigatureAttach - * tables ordered by - * LigatureCoverage Index */ +/* Array of LigatureAttach tables ordered by LigatureCoverage Index */ +struct LigatureArray : OffsetListOf<LigatureAttach> +{ + template <typename Iterator, + hb_requires (hb_is_iterator (Iterator))> + bool subset (hb_subset_context_t *c, + Iterator coverage, + unsigned class_count, + const hb_map_t *klass_mapping) const + { + TRACE_SUBSET (this); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + + auto *out = c->serializer->start_embed (this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + + for (const auto _ : + hb_zip (coverage, *this) + | hb_filter (glyphset, hb_first)) + { + auto *matrix = out->serialize_append (c->serializer); + if (unlikely (!matrix)) return_trace (false); + + matrix->serialize_subset (c, + _.second, + this, + class_count, + klass_mapping); + } + return_trace (this->len); + } +}; struct MarkLigPosFormat1 { @@ -2130,8 +2177,56 @@ struct MarkLigPosFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - // TODO(subset) - return_trace (false); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); + const hb_map_t &glyph_map = *c->plan->glyph_map; + + auto *out = c->serializer->start_embed (*this); + if (unlikely (!c->serializer->extend_min (out))) return_trace (false); + out->format = format; + + hb_map_t klass_mapping; + Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping); + + if (!klass_mapping.get_population ()) return_trace (false); + out->classCount = klass_mapping.get_population (); + + auto mark_iter = + + hb_zip (this+markCoverage, this+markArray) + | hb_filter (glyphset, hb_first) + ; + + auto new_mark_coverage = + + mark_iter + | hb_map_retains_sorting (hb_first) + | hb_map_retains_sorting (glyph_map) + ; + + if (!out->markCoverage.serialize (c->serializer, out) + .serialize (c->serializer, new_mark_coverage)) + return_trace (false); + + out->markArray.serialize (c->serializer, out) + .serialize (c->serializer, + &klass_mapping, + c->plan->layout_variation_idx_map, + &(this+markArray), + + mark_iter + | hb_map (hb_second)); + + auto new_ligature_coverage = + + hb_iter (this + ligatureCoverage) + | hb_filter (glyphset) + | hb_map_retains_sorting (glyph_map) + ; + + if (!out->ligatureCoverage.serialize (c->serializer, out) + .serialize (c->serializer, new_ligature_coverage)) + return_trace (false); + + out->ligatureArray.serialize_subset (c, ligatureArray, this, + hb_iter (this+ligatureCoverage), classCount, &klass_mapping); + + return_trace (true); } bool sanitize (hb_sanitize_context_t *c) const @@ -2164,6 +2259,7 @@ struct MarkLigPosFormat1 DEFINE_SIZE_STATIC (12); }; + struct MarkLigPos { template <typename context_t, typename ...Ts> @@ -2288,7 +2384,7 @@ struct MarkMarkPosFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh index 2f41d67819..5f10ecb7ee 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh @@ -356,7 +356,7 @@ struct Sequence bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; if (!intersects (&glyphset)) return_trace (false); @@ -447,7 +447,7 @@ struct MultipleSubstFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); @@ -582,7 +582,7 @@ struct AlternateSet bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto it = @@ -682,7 +682,7 @@ struct AlternateSubstFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); @@ -840,7 +840,7 @@ struct Ligature bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false); @@ -1058,7 +1058,7 @@ struct LigatureSubstFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh index cb95e6dcd5..36a95ead15 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh @@ -89,7 +89,7 @@ struct hb_closure_context_t : bool is_lookup_done (unsigned int lookup_index) { - if (done_lookups->in_error ()) + if (unlikely (done_lookups->in_error ())) return true; /* Have we visited this lookup with the current set of glyphs? */ @@ -146,7 +146,6 @@ struct hb_closure_lookups_context_t : if (is_lookup_visited (lookup_index)) return; - set_lookup_visited (lookup_index); nesting_level_left--; recurse_func (this, lookup_index); nesting_level_left++; @@ -163,10 +162,10 @@ struct hb_closure_lookups_context_t : bool is_lookup_visited (unsigned lookup_index) { - if (lookup_count++ > HB_MAX_LOOKUP_INDICES) + if (unlikely (lookup_count++ > HB_MAX_LOOKUP_INDICES)) return true; - if (visited_lookups->in_error ()) + if (unlikely (visited_lookups->in_error ())) return true; return visited_lookups->has (lookup_index); @@ -660,7 +659,7 @@ struct hb_ot_apply_context_t : void replace_glyph (hb_codepoint_t glyph_index) const { _set_glyph_props (glyph_index); - buffer->replace_glyph (glyph_index); + (void) buffer->replace_glyph (glyph_index); } void replace_glyph_inplace (hb_codepoint_t glyph_index) const { @@ -671,13 +670,13 @@ struct hb_ot_apply_context_t : unsigned int class_guess) const { _set_glyph_props (glyph_index, class_guess, true); - buffer->replace_glyph (glyph_index); + (void) buffer->replace_glyph (glyph_index); } void output_glyph_for_component (hb_codepoint_t glyph_index, unsigned int class_guess) const { _set_glyph_props (glyph_index, class_guess, false, true); - buffer->output_glyph (glyph_index); + (void) buffer->output_glyph (glyph_index); } }; @@ -1044,7 +1043,7 @@ static inline bool ligate_input (hb_ot_apply_context_t *c, hb_min (this_comp, last_num_components); _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp); } - buffer->next_glyph (); + (void) buffer->next_glyph (); } last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur()); @@ -1188,7 +1187,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c, /* Don't recurse to ourself at same position. * Note that this test is too naive, it doesn't catch longer loops. */ - if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index) + if (unlikely (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)) continue; if (unlikely (!buffer->move_to (match_positions[idx]))) @@ -1226,7 +1225,8 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c, * mean that n match positions where removed, as there might * have been marks and default-ignorables in the sequence. We * should instead drop match positions between current-position - * and current-position + n instead. + * and current-position + n instead. Though, am not sure which + * one is better. Both cases have valid uses. Sigh. * * It should be possible to construct tests for both of these cases. */ @@ -1272,7 +1272,7 @@ static inline bool apply_lookup (hb_ot_apply_context_t *c, match_positions[next] += delta; } - buffer->move_to (end); + (void) buffer->move_to (end); return_trace (true); } @@ -1389,9 +1389,11 @@ struct Rule lookup_context); } - void closure_lookups (hb_closure_lookups_context_t *c) const + void closure_lookups (hb_closure_lookups_context_t *c, + ContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; + if (!intersects (c->glyphs, lookup_context)) return; const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (inputZ.as_array (inputCount ? inputCount - 1 : 0)); @@ -1521,14 +1523,13 @@ struct RuleSet ; } - void closure_lookups (hb_closure_lookups_context_t *c) const + void closure_lookups (hb_closure_lookups_context_t *c, + ContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; - - return + hb_iter (rule) | hb_map (hb_add (this)) - | hb_apply ([&] (const Rule &_) { _.closure_lookups (c); }) + | hb_apply ([&] (const Rule &_) { _.closure_lookups (c, lookup_context); }) ; } @@ -1647,9 +1648,16 @@ struct ContextFormat1 void closure_lookups (hb_closure_lookups_context_t *c) const { - + hb_iter (ruleSet) + struct ContextClosureLookupContext lookup_context = { + {intersects_glyph}, + nullptr + }; + + + hb_zip (this+coverage, ruleSet) + | hb_filter (*c->glyphs, hb_first) + | hb_map (hb_second) | hb_map (hb_add (this)) - | hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); }) + | hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c, lookup_context); }) ; } @@ -1700,7 +1708,7 @@ struct ContextFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); @@ -1791,10 +1799,24 @@ struct ContextFormat2 void closure_lookups (hb_closure_lookups_context_t *c) const { + if (!(this+coverage).intersects (c->glyphs)) + return; + + const ClassDef &class_def = this+classDef; + + struct ContextClosureLookupContext lookup_context = { + {intersects_class}, + &class_def + }; + + hb_iter (ruleSet) | hb_map (hb_add (this)) - | hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c); }) - ; + | hb_enumerate + | hb_filter ([&] (const hb_pair_t<unsigned, const RuleSet &> p) + { return class_def.intersects_class (c->glyphs, p.first); }) + | hb_map (hb_second) + | hb_apply ([&] (const RuleSet & _) + { _.closure_lookups (c, lookup_context); }); } void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {} @@ -1860,8 +1882,8 @@ struct ContextFormat2 const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; bool ret = true; int non_zero_index = 0, index = 0; - for (const hb_pair_t<unsigned, const OffsetTo<RuleSet>&> _ : + hb_enumerate (ruleSet) - | hb_filter (klass_map, hb_first)) + for (const auto& _ : + hb_enumerate (ruleSet) + | hb_filter (klass_map, hb_first)) { auto *o = out->ruleSet.serialize_append (c->serializer); if (unlikely (!o)) @@ -1945,6 +1967,8 @@ struct ContextFormat3 void closure_lookups (hb_closure_lookups_context_t *c) const { + if (!intersects (c->glyphs)) + return; const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount)); recurse_lookups (c, lookupCount, lookupRecord); } @@ -2010,6 +2034,7 @@ struct ContextFormat3 for (const OffsetTo<Coverage>& offset : coverages) { + /* TODO(subset) This looks like should not be necessary to write this way. */ auto *o = c->serializer->allocate_size<OffsetTo<Coverage>> (OffsetTo<Coverage>::static_size); if (unlikely (!o)) return_trace (false); if (!o->serialize_subset (c, offset, this)) return_trace (false); @@ -2238,9 +2263,11 @@ struct ChainRule lookup_context); } - void closure_lookups (hb_closure_lookups_context_t *c) const + void closure_lookups (hb_closure_lookups_context_t *c, + ChainContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; + if (!intersects (c->glyphs, lookup_context)) return; const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack); const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16>> (input); @@ -2296,11 +2323,7 @@ struct ChainRule { c->copy (len); for (const auto g : it) - { - HBUINT16 gid; - gid = g; - c->copy (gid); - } + c->copy ((HBUINT16) g); } ChainRule* copy (hb_serialize_context_t *c, @@ -2328,12 +2351,19 @@ struct ChainRule | hb_map (mapping)); const ArrayOf<LookupRecord> &lookupRecord = StructAfter<ArrayOf<LookupRecord>> (lookahead); - HBUINT16 lookupCount; - lookupCount = lookupRecord.len; - if (!c->copy (lookupCount)) return_trace (nullptr); - for (unsigned i = 0; i < (unsigned) lookupCount; i++) + HBUINT16* lookupCount = c->embed (&(lookupRecord.len)); + if (!lookupCount) return_trace (nullptr); + + for (unsigned i = 0; i < lookupRecord.len; i++) + { + if (!lookup_map->has (lookupRecord[i].lookupListIndex)) + { + (*lookupCount)--; + continue; + } if (!c->copy (lookupRecord[i], lookup_map)) return_trace (nullptr); + } return_trace (out); } @@ -2351,7 +2381,7 @@ struct ChainRule if (!backtrack_map) { - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); if (!hb_all (backtrack, glyphset) || !hb_all (input, glyphset) || !hb_all (lookahead, glyphset)) @@ -2424,14 +2454,14 @@ struct ChainRuleSet ; } - void closure_lookups (hb_closure_lookups_context_t *c) const + void closure_lookups (hb_closure_lookups_context_t *c, + ChainContextClosureLookupContext &lookup_context) const { if (unlikely (c->lookup_limit_exceeded ())) return; - return + hb_iter (rule) | hb_map (hb_add (this)) - | hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c); }) + | hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c, lookup_context); }) ; } @@ -2552,9 +2582,16 @@ struct ChainContextFormat1 void closure_lookups (hb_closure_lookups_context_t *c) const { - + hb_iter (ruleSet) + struct ChainContextClosureLookupContext lookup_context = { + {intersects_glyph}, + {nullptr, nullptr, nullptr} + }; + + + hb_zip (this+coverage, ruleSet) + | hb_filter (*c->glyphs, hb_first) + | hb_map (hb_second) | hb_map (hb_add (this)) - | hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); }) + | hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c, lookup_context); }) ; } @@ -2604,7 +2641,7 @@ struct ChainContextFormat1 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - const hb_set_t &glyphset = *c->plan->glyphset (); + const hb_set_t &glyphset = *c->plan->glyphset_gsub (); const hb_map_t &glyph_map = *c->plan->glyph_map; auto *out = c->serializer->start_embed (*this); @@ -2701,9 +2738,28 @@ struct ChainContextFormat2 void closure_lookups (hb_closure_lookups_context_t *c) const { + if (!(this+coverage).intersects (c->glyphs)) + return; + + const ClassDef &backtrack_class_def = this+backtrackClassDef; + const ClassDef &input_class_def = this+inputClassDef; + const ClassDef &lookahead_class_def = this+lookaheadClassDef; + + struct ChainContextClosureLookupContext lookup_context = { + {intersects_class}, + {&backtrack_class_def, + &input_class_def, + &lookahead_class_def} + }; + + hb_iter (ruleSet) | hb_map (hb_add (this)) - | hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c); }) + | hb_enumerate + | hb_filter([&] (unsigned klass) + { return input_class_def.intersects_class (c->glyphs, klass); }, hb_first) + | hb_map (hb_second) + | hb_apply ([&] (const ChainRuleSet &_) + { _.closure_lookups (c, lookup_context); }) ; } @@ -2779,24 +2835,23 @@ struct ChainContextFormat2 out->coverage.serialize_subset (c, coverage, this); hb_map_t backtrack_klass_map; - out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, &backtrack_klass_map); - if (unlikely (!c->serializer->check_success (!backtrack_klass_map.in_error ()))) - return_trace (false); - - // subset inputClassDef based on glyphs survived in Coverage subsetting hb_map_t input_klass_map; - out->inputClassDef.serialize_subset (c, inputClassDef, this, &input_klass_map); - if (unlikely (!c->serializer->check_success (!input_klass_map.in_error ()))) - return_trace (false); - hb_map_t lookahead_klass_map; + + out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, &backtrack_klass_map); + // TODO: subset inputClassDef based on glyphs survived in Coverage subsetting + out->inputClassDef.serialize_subset (c, inputClassDef, this, &input_klass_map); out->lookaheadClassDef.serialize_subset (c, lookaheadClassDef, this, &lookahead_klass_map); - if (unlikely (!c->serializer->check_success (!lookahead_klass_map.in_error ()))) + + if (unlikely (!c->serializer->propagate_error (backtrack_klass_map, + input_klass_map, + lookahead_klass_map))) return_trace (false); - unsigned non_zero_index = 0, index = 0; + int non_zero_index = -1, index = 0; bool ret = true; const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups; + auto last_non_zero = c->serializer->snapshot (); for (const OffsetTo<ChainRuleSet>& _ : + hb_enumerate (ruleSet) | hb_filter (input_klass_map, hb_first) | hb_map (hb_second)) @@ -2812,19 +2867,20 @@ struct ChainContextFormat2 &backtrack_klass_map, &input_klass_map, &lookahead_klass_map)) + { + last_non_zero = c->serializer->snapshot (); non_zero_index = index; + } index++; } if (!ret) return_trace (ret); - //prune empty trailing ruleSets - --index; - while (index > non_zero_index) - { - out->ruleSet.pop (); - index--; + // prune empty trailing ruleSets + if (index > non_zero_index) { + c->serializer->revert (last_non_zero); + out->ruleSet.len = non_zero_index + 1; } return_trace (bool (out->ruleSet)); @@ -2908,6 +2964,9 @@ struct ChainContextFormat3 void closure_lookups (hb_closure_lookups_context_t *c) const { + if (!intersects (c->glyphs)) + return; + const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage>> (backtrack); const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage>> (input); const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead); @@ -2986,13 +3045,16 @@ struct ChainContextFormat3 TRACE_SERIALIZE (this); auto *out = c->serializer->start_embed<OffsetArrayOf<Coverage>> (); - if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size))) return_trace (false); + if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size))) + return_trace (false); - + it - | hb_apply (subset_offset_array (c, *out, base)) - ; + for (auto& offset : it) { + auto *o = out->serialize_append (c->serializer); + if (unlikely (!o) || !o->serialize_subset (c, offset, base)) + return_trace (false); + } - return_trace (out->len); + return_trace (true); } bool subset (hb_subset_context_t *c) const @@ -3113,6 +3175,24 @@ struct ExtensionFormat1 extensionLookupType != T::SubTable::Extension); } + bool subset (hb_subset_context_t *c) const + { + TRACE_SUBSET (this); + + auto *out = c->serializer->start_embed (this); + if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false); + + out->format = format; + out->extensionLookupType = extensionLookupType; + + const auto& src_offset = + reinterpret_cast<const LOffsetTo<typename T::SubTable> &> (extensionOffset); + auto& dest_offset = + reinterpret_cast<LOffsetTo<typename T::SubTable> &> (out->extensionOffset); + + return_trace (dest_offset.serialize_subset (c, src_offset, this, get_type ())); + } + protected: HBUINT16 format; /* Format identifier. Set to 1. */ HBUINT16 extensionLookupType; /* Lookup type of subtable referenced @@ -3143,6 +3223,18 @@ struct Extension } } + // Specialization of dispatch for subset. dispatch() normally just + // dispatches to the sub table this points too, but for subset + // we need to run subset on this subtable too. + template <typename ...Ts> + typename hb_subset_context_t::return_t dispatch (hb_subset_context_t *c, Ts&&... ds) const + { + switch (u.format) { + case 1: return u.format1.subset (c); + default: return c->default_return_value (); + } + } + template <typename context_t, typename ...Ts> typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { @@ -3320,20 +3412,34 @@ struct GSUBGPOS return_trace (true); } - void closure_features (const hb_map_t *lookup_indexes, /* IN */ - hb_set_t *feature_indexes /* OUT */) const + void prune_features (const hb_map_t *lookup_indices, /* IN */ + hb_set_t *feature_indices /* IN/OUT */) const { - unsigned int feature_count = hb_min (get_feature_count (), (unsigned) HB_MAX_FEATURES); - for (unsigned i = 0; i < feature_count; i++) +#ifndef HB_NO_VAR + // This is the set of feature indices which have alternate versions defined + // if the FeatureVariation's table and the alternate version(s) intersect the + // set of lookup indices. + hb_set_t alternate_feature_indices; + if (version.to_int () >= 0x00010001u) + (this+featureVars).closure_features (lookup_indices, &alternate_feature_indices); + if (unlikely (alternate_feature_indices.in_error())) { + feature_indices->successful = false; + return; + } +#endif + + for (unsigned i : feature_indices->iter()) { const Feature& f = get_feature (i); - if ((!f.featureParams.is_null ()) || f.intersects_lookup_indexes (lookup_indexes)) - feature_indexes->add (i); - } + + if (f.featureParams.is_null () + && !f.intersects_lookup_indexes (lookup_indices) #ifndef HB_NO_VAR - if (version.to_int () >= 0x00010001u) - (this+featureVars).closure_features (lookup_indexes, feature_indexes); + && !alternate_feature_indices.has (i) #endif + ) + feature_indices->del (i); + } } unsigned int get_size () const diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc index f25f0f9e23..89df949b26 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.cc +++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc @@ -76,7 +76,7 @@ * Tests whether a face includes any kerning data in the 'kern' table. * Does NOT test for kerning lookups in the GPOS table. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * **/ bool @@ -92,7 +92,7 @@ hb_ot_layout_has_kerning (hb_face_t *face) * Tests whether a face includes any state-machine kerning in the 'kern' table. * Does NOT examine the GPOS table. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * **/ bool @@ -112,7 +112,7 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face) * * Does NOT examine the GPOS table. * - * Return value: %true is data found, false otherwise + * Return value: %true is data found, %false otherwise * **/ bool @@ -268,7 +268,7 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font, * * Tests whether a face has any glyph classes defined in its GDEF table. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * **/ hb_bool_t @@ -322,7 +322,7 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face, * @face: The #hb_face_t to work on * @glyph: The #hb_codepoint_t code point to query * @start_offset: offset of the first attachment point to retrieve - * @point_count: (inout) (allow-none): Input = the maximum number of attachment points to return; + * @point_count: (inout) (optional): Input = the maximum number of attachment points to return; * Output = the actual number of attachment points returned (may be zero) * @point_array: (out) (array length=point_count): The array of attachment points found for the query * @@ -350,7 +350,7 @@ hb_ot_layout_get_attach_points (hb_face_t *face, * @direction: The #hb_direction_t text direction to use * @glyph: The #hb_codepoint_t code point to query * @start_offset: offset of the first caret position to retrieve - * @caret_count: (inout) (allow-none): Input = the maximum number of caret positions to return; + * @caret_count: (inout) (optional): Input = the maximum number of caret positions to return; * Output = the actual number of caret positions returned (may be zero) * @caret_array: (out) (array length=caret_count): The array of caret positions found for the query * @@ -410,9 +410,9 @@ get_gsubgpos_table (hb_face_t *face, /** * hb_ot_layout_table_get_script_tags: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @start_offset: offset of the first script tag to retrieve - * @script_count: (inout) (allow-none): Input = the maximum number of script tags to return; + * @script_count: (inout) (optional): Input = the maximum number of script tags to return; * Output = the actual number of script tags returned (may be zero) * @script_tags: (out) (array length=script_count): The array of #hb_tag_t script tags found for the query * @@ -437,14 +437,14 @@ hb_ot_layout_table_get_script_tags (hb_face_t *face, /** * hb_ot_layout_table_find_script: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @script_tag: #hb_tag_t of the script tag requested * @script_index: (out): The index of the requested script tag * * Fetches the index if a given script tag in the specified face's GSUB table * or GPOS table. * - * Return value: %true if the script is found, false otherwise + * Return value: %true if the script is found, %false otherwise * **/ hb_bool_t @@ -481,7 +481,7 @@ hb_ot_layout_table_find_script (hb_face_t *face, /** * hb_ot_layout_table_choose_script: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @script_tags: Array of #hb_tag_t script tags * @script_index: (out): The index of the requested script tag * @chosen_script: (out): #hb_tag_t of the script tag requested @@ -504,11 +504,22 @@ hb_ot_layout_table_choose_script (hb_face_t *face, /** * hb_ot_layout_table_select_script: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @script_count: Number of script tags in the array * @script_tags: Array of #hb_tag_t script tags - * @script_index: (out): The index of the requested script - * @chosen_script: (out): #hb_tag_t of the requested script + * @script_index: (out) (optional): The index of the requested script + * @chosen_script: (out) (optional): #hb_tag_t of the requested script + * + * Selects an OpenType script for @table_tag from the @script_tags array. + * + * If the table does not have any of the requested scripts, then `DFLT`, + * `dflt`, and `latn` tags are tried in that order. If the table still does not + * have any of these scripts, @script_index and @chosen_script are set to + * #HB_OT_LAYOUT_NO_SCRIPT_INDEX. + * + * Return value: + * %true if one of the requested scripts is selected, %false if a fallback + * script is selected or if no scripts are selected. * * Since: 2.0.0 **/ @@ -566,9 +577,9 @@ hb_ot_layout_table_select_script (hb_face_t *face, /** * hb_ot_layout_table_get_feature_tags: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @start_offset: offset of the first feature tag to retrieve - * @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return; + * @feature_count: (inout) (optional): Input = the maximum number of feature tags to return; * Output = the actual number of feature tags returned (may be zero) * @feature_tags: (out) (array length=feature_count): Array of feature tags found in the table * @@ -591,14 +602,14 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face, /** * hb_ot_layout_table_find_feature: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @feature_tag: The #hb_tag_t og the requested feature tag * @feature_index: (out): The index of the requested feature * * Fetches the index for a given feature tag in the specified face's GSUB table * or GPOS table. * - * Return value: %true if the feature is found, false otherwise + * Return value: %true if the feature is found, %false otherwise **/ bool hb_ot_layout_table_find_feature (hb_face_t *face, @@ -626,10 +637,10 @@ hb_ot_layout_table_find_feature (hb_face_t *face, /** * hb_ot_layout_script_get_language_tags: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @script_index: The index of the requested script tag * @start_offset: offset of the first language tag to retrieve - * @language_count: (inout) (allow-none): Input = the maximum number of language tags to return; + * @language_count: (inout) (optional): Input = the maximum number of language tags to return; * Output = the actual number of language tags returned (may be zero) * @language_tags: (out) (array length=language_count): Array of language tags found in the table * @@ -655,7 +666,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face, /** * hb_ot_layout_script_find_language: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @script_index: The index of the requested script tag * @language_tag: The #hb_tag_t of the requested language * @language_index: The index of the requested language @@ -663,7 +674,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face, * Fetches the index of a given language tag in the specified face's GSUB table * or GPOS table, underneath the specified script tag. * - * Return value: %true if the language tag is found, false otherwise + * Return value: %true if the language tag is found, %false otherwise * * Since: ?? * Deprecated: ?? @@ -688,7 +699,7 @@ hb_ot_layout_script_find_language (hb_face_t *face, /** * hb_ot_layout_script_select_language: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @script_index: The index of the requested script tag * @language_count: The number of languages in the specified script * @language_tags: The array of language tags @@ -697,7 +708,7 @@ hb_ot_layout_script_find_language (hb_face_t *face, * Fetches the index of a given language tag in the specified face's GSUB table * or GPOS table, underneath the specified script index. * - * Return value: %true if the language tag is found, false otherwise + * Return value: %true if the language tag is found, %false otherwise * * Since: 2.0.0 **/ @@ -731,7 +742,7 @@ hb_ot_layout_script_select_language (hb_face_t *face, /** * hb_ot_layout_language_get_required_feature_index: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @script_index: The index of the requested script tag * @language_index: The index of the requested language tag * @feature_index: (out): The index of the requested feature @@ -739,7 +750,7 @@ hb_ot_layout_script_select_language (hb_face_t *face, * Fetches the index of a requested feature in the given face's GSUB or GPOS table, * underneath the specified script and language. * - * Return value: %true if the feature is found, false otherwise + * Return value: %true if the feature is found, %false otherwise * **/ hb_bool_t @@ -761,7 +772,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face, /** * hb_ot_layout_language_get_required_feature: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @script_index: The index of the requested script tag * @language_index: The index of the requested language tag * @feature_index: (out): The index of the requested feature @@ -770,7 +781,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face, * Fetches the tag of a requested feature index in the given face's GSUB or GPOS table, * underneath the specified script and language. * - * Return value: %true if the feature is found, false otherwise + * Return value: %true if the feature is found, %false otherwise * * Since: 0.9.30 **/ @@ -796,11 +807,11 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face, /** * hb_ot_layout_language_get_feature_indexes: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @script_index: The index of the requested script tag * @language_index: The index of the requested language tag * @start_offset: offset of the first feature tag to retrieve - * @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return; + * @feature_count: (inout) (optional): Input = the maximum number of feature tags to return; * Output: the actual number of feature tags returned (may be zero) * @feature_indexes: (out) (array length=feature_count): The array of feature indexes found for the query * @@ -827,11 +838,11 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t *face, /** * hb_ot_layout_language_get_feature_tags: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @script_index: The index of the requested script tag * @language_index: The index of the requested language tag * @start_offset: offset of the first feature tag to retrieve - * @feature_count: (inout) (allow-none): Input = the maximum number of feature tags to return; + * @feature_count: (inout) (optional): Input = the maximum number of feature tags to return; * Output = the actual number of feature tags returned (may be zero) * @feature_tags: (out) (array length=feature_count): The array of #hb_tag_t feature tags found for the query * @@ -868,7 +879,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face, /** * hb_ot_layout_language_find_feature: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @script_index: The index of the requested script tag * @language_index: The index of the requested language tag * @feature_tag: #hb_tag_t of the feature tag requested @@ -877,7 +888,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face, * Fetches the index of a given feature tag in the specified face's GSUB table * or GPOS table, underneath the specified script and language. * - * Return value: %true if the feature is found, false otherwise + * Return value: %true if the feature is found, %false otherwise * **/ hb_bool_t @@ -910,10 +921,10 @@ hb_ot_layout_language_find_feature (hb_face_t *face, /** * hb_ot_layout_feature_get_lookups: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @feature_index: The index of the requested feature * @start_offset: offset of the first lookup to retrieve - * @lookup_count: (inout) (allow-none): Input = the maximum number of lookups to return; + * @lookup_count: (inout) (optional): Input = the maximum number of lookups to return; * Output = the actual number of lookups returned (may be zero) * @lookup_indexes: (out) (array length=lookup_count): The array of lookup indexes found for the query * @@ -944,7 +955,7 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face, /** * hb_ot_layout_table_get_lookup_count: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * * Fetches the total number of lookups enumerated in the specified * face's GSUB table or GPOS table. @@ -1101,7 +1112,7 @@ script_collect_features (hb_collect_features_context_t *c, /** * hb_ot_layout_collect_features: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @scripts: The array of scripts to collect features for * @languages: The array of languages to collect features for * @features: The array of features to collect @@ -1152,7 +1163,7 @@ hb_ot_layout_collect_features (hb_face_t *face, /** * hb_ot_layout_collect_lookups: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @scripts: The array of scripts to collect lookups for * @languages: The array of languages to collect lookups for * @features: The array of features to collect lookups for @@ -1191,7 +1202,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face, /** * hb_ot_layout_lookup_collect_glyphs: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @lookup_index: The index of the feature lookup to query * @glyphs_before: (out): Array of glyphs preceding the substitution range * @glyphs_input: (out): Array of input glyphs that would be substituted by the lookup @@ -1243,7 +1254,7 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, /** * hb_ot_layout_table_find_feature_variations: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @coords: The variation coordinates to query * @num_coords: The number of variation coordinates * @variations_index: (out): The array of feature variations found for the query @@ -1268,11 +1279,11 @@ hb_ot_layout_table_find_feature_variations (hb_face_t *face, /** * hb_ot_layout_feature_with_variations_get_lookups: * @face: #hb_face_t to work upon - * @table_tag: HB_OT_TAG_GSUB or HB_OT_TAG_GPOS + * @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS * @feature_index: The index of the feature to query * @variations_index: The index of the feature variation to query * @start_offset: offset of the first lookup to retrieve - * @lookup_count: (inout) (allow-none): Input = the maximum number of lookups to return; + * @lookup_count: (inout) (optional): Input = the maximum number of lookups to return; * Output = the actual number of lookups returned (may be zero) * @lookup_indexes: (out) (array length=lookup_count): The array of lookups found for the query * @@ -1310,7 +1321,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face, * * Tests whether the specified face includes any GSUB substitutions. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * **/ hb_bool_t @@ -1331,7 +1342,7 @@ hb_ot_layout_has_substitution (hb_face_t *face) * Tests whether a specified lookup in the specified face would * trigger a substitution on the given glyph sequence. * - * Return value: %true if a substitution would be triggered, false otherwise + * Return value: %true if a substitution would be triggered, %false otherwise * * Since: 0.9.7 **/ @@ -1488,7 +1499,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face, * hb_ot_layout_has_positioning: * @face: #hb_face_t to work upon * - * Return value: %true if the face has GPOS data, false otherwise + * Tests whether the specified face includes any GPOS positioning. + * + * Return value: %true if the face has GPOS data, %false otherwise * **/ hb_bool_t @@ -1561,7 +1574,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) * For more information on this distinction, see the [`size` feature documentation]( * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size). * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 0.9.10 **/ @@ -1610,22 +1623,22 @@ hb_ot_layout_get_size_params (hb_face_t *face, * @face: #hb_face_t to work upon * @table_tag: table tag to query, "GSUB" or "GPOS". * @feature_index: index of feature to query. - * @label_id: (out) (allow-none): The ‘name’ table name ID that specifies a string + * @label_id: (out) (optional): The ‘name’ table name ID that specifies a string * for a user-interface label for this feature. (May be NULL.) - * @tooltip_id: (out) (allow-none): The ‘name’ table name ID that specifies a string + * @tooltip_id: (out) (optional): The ‘name’ table name ID that specifies a string * that an application can use for tooltip text for this * feature. (May be NULL.) - * @sample_id: (out) (allow-none): The ‘name’ table name ID that specifies sample text + * @sample_id: (out) (optional): The ‘name’ table name ID that specifies sample text * that illustrates the effect of this feature. (May be NULL.) - * @num_named_parameters: (out) (allow-none): Number of named parameters. (May be zero.) - * @first_param_id: (out) (allow-none): The first ‘name’ table name ID used to specify + * @num_named_parameters: (out) (optional): Number of named parameters. (May be zero.) + * @first_param_id: (out) (optional): The first ‘name’ table name ID used to specify * strings for user-interface labels for the feature * parameters. (Must be zero if numParameters is zero.) * * Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or * "Character Variant" ('cvXX') features. * - * Return value: %true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 2.0.0 **/ @@ -1685,7 +1698,7 @@ hb_ot_layout_feature_get_name_ids (hb_face_t *face, * @table_tag: table tag to query, "GSUB" or "GPOS". * @feature_index: index of feature to query. * @start_offset: offset of the first character to retrieve - * @char_count: (inout) (allow-none): Input = the maximum number of characters to return; + * @char_count: (inout) (optional): Input = the maximum number of characters to return; * Output = the actual number of characters returned (may be zero) * @characters: (out caller-allocates) (array length=char_count): A buffer pointer. * The Unicode codepoints of the characters for which this feature provides @@ -1769,7 +1782,7 @@ apply_forward (OT::hb_ot_apply_context_t *c, if (applied) ret = true; else - buffer->next_glyph (); + (void) buffer->next_glyph (); } return ret; } @@ -1907,7 +1920,7 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c, * @baseline_tag: a baseline tag * @direction: text direction. * @script_tag: script tag. - * @language_tag: language tag. + * @language_tag: language tag, currently unused. * @coord: (out): baseline value if found. * * Fetches a baseline value from the face. @@ -1964,7 +1977,7 @@ struct hb_get_glyph_alternates_dispatch_t : * @lookup_index: index of the feature lookup to query. * @glyph: a glyph id. * @start_offset: starting offset. - * @alternate_count: (inout) (allow-none): Input = the maximum number of alternate glyphs to return; + * @alternate_count: (inout) (optional): Input = the maximum number of alternate glyphs to return; * Output = the actual number of alternate glyphs returned (may be zero). * @alternate_glyphs: (out caller-allocates) (array length=alternate_count): A glyphs buffer. * Alternate glyphs associated with the glyph id. diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.h b/thirdparty/harfbuzz/src/hb-ot-layout.h index 545d5f7fc4..d47ba0fc92 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.h +++ b/thirdparty/harfbuzz/src/hb-ot-layout.h @@ -24,7 +24,7 @@ * Red Hat Author(s): Behdad Esfahbod */ -#ifndef HB_OT_H_IN +#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-ot.h> instead." #endif @@ -38,10 +38,35 @@ HB_BEGIN_DECLS +/** + * HB_OT_TAG_BASE: + * + * OpenType [Baseline Table](https://docs.microsoft.com/en-us/typography/opentype/spec/base). + */ #define HB_OT_TAG_BASE HB_TAG('B','A','S','E') +/** + * HB_OT_TAG_GDEF: + * + * OpenType [Glyph Definition Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gdef). + */ #define HB_OT_TAG_GDEF HB_TAG('G','D','E','F') +/** + * HB_OT_TAG_GSUB: + * + * OpenType [Glyph Substitution Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gsub). + */ #define HB_OT_TAG_GSUB HB_TAG('G','S','U','B') +/** + * HB_OT_TAG_GPOS: + * + * OpenType [Glyph Positioning Table](https://docs.microsoft.com/en-us/typography/opentype/spec/gpos). + */ #define HB_OT_TAG_GPOS HB_TAG('G','P','O','S') +/** + * HB_OT_TAG_JSTF: + * + * OpenType [Justification Table](https://docs.microsoft.com/en-us/typography/opentype/spec/jstf). + */ #define HB_OT_TAG_JSTF HB_TAG('J','S','T','F') @@ -49,18 +74,34 @@ HB_BEGIN_DECLS * Script & Language tags. */ +/** + * HB_OT_TAG_DEFAULT_SCRIPT: + * + * OpenType script tag, `DFLT`, for features that are not script-specific. + * + */ #define HB_OT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T') +/** + * HB_OT_TAG_DEFAULT_LANGUAGE: + * + * OpenType language tag, `dflt`. Not a valid language tag, but some fonts + * mistakenly use it. + */ #define HB_OT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't') /** * HB_OT_MAX_TAGS_PER_SCRIPT: * + * Maximum number of OpenType tags that can correspond to a give #hb_script_t. + * * Since: 2.0.0 **/ #define HB_OT_MAX_TAGS_PER_SCRIPT 3u /** * HB_OT_MAX_TAGS_PER_LANGUAGE: * + * Maximum number of OpenType tags that can correspond to a give #hb_language_t. + * * Since: 2.0.0 **/ #define HB_OT_MAX_TAGS_PER_LANGUAGE 3u @@ -144,9 +185,29 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, * GSUB/GPOS feature query and enumeration interface */ +/** + * HB_OT_LAYOUT_NO_SCRIPT_INDEX: + * + * Special value for script index indicating unsupported script. + */ #define HB_OT_LAYOUT_NO_SCRIPT_INDEX 0xFFFFu +/** + * HB_OT_LAYOUT_NO_FEATURE_INDEX: + * + * Special value for feature index indicating unsupported feature. + */ #define HB_OT_LAYOUT_NO_FEATURE_INDEX 0xFFFFu +/** + * HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX: + * + * Special value for language index indicating default or unsupported language. + */ #define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX 0xFFFFu +/** + * HB_OT_LAYOUT_NO_VARIATIONS_INDEX: + * + * Special value for variations index indicating unsupported variation. + */ #define HB_OT_LAYOUT_NO_VARIATIONS_INDEX 0xFFFFFFFFu HB_EXTERN unsigned int @@ -433,7 +494,7 @@ hb_ot_layout_feature_get_characters (hb_face_t *face, * @HB_OT_LAYOUT_BASELINE_TAG_MATH: The baseline about which mathematical characters are centered. * In vertical writing mode when mathematical characters rotated 90 degrees clockwise, are centered. * - * Baseline tags from https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags + * Baseline tags from [Baseline Tags](https://docs.microsoft.com/en-us/typography/opentype/spec/baselinetags) registry. * * Since: 2.6.0 */ @@ -446,6 +507,7 @@ typedef enum { HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT = HB_TAG ('i','d','t','p'), HB_OT_LAYOUT_BASELINE_TAG_MATH = HB_TAG ('m','a','t','h'), + /*< private >*/ _HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/ } hb_ot_layout_baseline_tag_t; diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh index f3bb15581a..ac61bc70de 100644 --- a/thirdparty/harfbuzz/src/hb-ot-layout.hh +++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh @@ -315,12 +315,13 @@ _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info) } static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info); +static inline bool _hb_glyph_info_substituted (const hb_glyph_info_t *info); static inline bool _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info) { return (info->unicode_props() & UPROPS_MASK_IGNORABLE) && - !_hb_glyph_info_ligated (info); + !_hb_glyph_info_substituted (info); } static inline bool _hb_glyph_info_is_default_ignorable_and_not_hidden (const hb_glyph_info_t *info) diff --git a/thirdparty/harfbuzz/src/hb-ot-math.cc b/thirdparty/harfbuzz/src/hb-ot-math.cc index 9d8c6e735a..5781d25f2a 100644 --- a/thirdparty/harfbuzz/src/hb-ot-math.cc +++ b/thirdparty/harfbuzz/src/hb-ot-math.cc @@ -56,7 +56,7 @@ * * Tests whether a face has a `MATH` table. * - * Return value: true if the table is found, false otherwise + * Return value: %true if the table is found, %false otherwise * * Since: 1.3.3 **/ @@ -142,7 +142,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font, * * Tests whether the given glyph index is an extended shape in the face. * - * Return value: true if the glyph is an extended shape, false otherwise + * Return value: %true if the glyph is an extended shape, %false otherwise * * Since: 1.3.3 **/ diff --git a/thirdparty/harfbuzz/src/hb-ot-math.h b/thirdparty/harfbuzz/src/hb-ot-math.h index ad864a762d..d3ffa19d85 100644 --- a/thirdparty/harfbuzz/src/hb-ot-math.h +++ b/thirdparty/harfbuzz/src/hb-ot-math.h @@ -24,7 +24,7 @@ * Igalia Author(s): Frédéric Wang */ -#ifndef HB_OT_H_IN +#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-ot.h> instead." #endif @@ -40,18 +40,89 @@ HB_BEGIN_DECLS * MATH */ +/** + * HB_OT_TAG_MATH: + * + * OpenType [Mathematical Typesetting Table](https://docs.microsoft.com/en-us/typography/opentype/spec/math). + * + * Since: 1.3.3 + */ #define HB_OT_TAG_MATH HB_TAG('M','A','T','H') -/* Use with hb_buffer_set_script() for math shaping. */ +/** + * HB_OT_MATH_SCRIPT: + * + * OpenType script tag for math shaping, for use with + * Use with hb_buffer_set_script(). + * + * Since: 1.3.3 + */ #define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h') /* Types */ /** * hb_ot_math_constant_t: + * @HB_OT_MATH_CONSTANT_SCRIPT_PERCENT_SCALE_DOWN: scriptPercentScaleDown + * @HB_OT_MATH_CONSTANT_SCRIPT_SCRIPT_PERCENT_SCALE_DOWN: scriptScriptPercentScaleDown + * @HB_OT_MATH_CONSTANT_DELIMITED_SUB_FORMULA_MIN_HEIGHT: delimitedSubFormulaMinHeight + * @HB_OT_MATH_CONSTANT_DISPLAY_OPERATOR_MIN_HEIGHT: displayOperatorMinHeight + * @HB_OT_MATH_CONSTANT_MATH_LEADING: mathLeading + * @HB_OT_MATH_CONSTANT_AXIS_HEIGHT: axisHeight + * @HB_OT_MATH_CONSTANT_ACCENT_BASE_HEIGHT: accentBaseHeight + * @HB_OT_MATH_CONSTANT_FLATTENED_ACCENT_BASE_HEIGHT: flattenedAccentBaseHeight + * @HB_OT_MATH_CONSTANT_SUBSCRIPT_SHIFT_DOWN: subscriptShiftDown + * @HB_OT_MATH_CONSTANT_SUBSCRIPT_TOP_MAX: subscriptTopMax + * @HB_OT_MATH_CONSTANT_SUBSCRIPT_BASELINE_DROP_MIN: subscriptBaselineDropMin + * @HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP: superscriptShiftUp + * @HB_OT_MATH_CONSTANT_SUPERSCRIPT_SHIFT_UP_CRAMPED: superscriptShiftUpCramped + * @HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MIN: superscriptBottomMin + * @HB_OT_MATH_CONSTANT_SUPERSCRIPT_BASELINE_DROP_MAX: superscriptBaselineDropMax + * @HB_OT_MATH_CONSTANT_SUB_SUPERSCRIPT_GAP_MIN: subSuperscriptGapMin + * @HB_OT_MATH_CONSTANT_SUPERSCRIPT_BOTTOM_MAX_WITH_SUBSCRIPT: superscriptBottomMaxWithSubscript + * @HB_OT_MATH_CONSTANT_SPACE_AFTER_SCRIPT: spaceAfterScript + * @HB_OT_MATH_CONSTANT_UPPER_LIMIT_GAP_MIN: upperLimitGapMin + * @HB_OT_MATH_CONSTANT_UPPER_LIMIT_BASELINE_RISE_MIN: upperLimitBaselineRiseMin + * @HB_OT_MATH_CONSTANT_LOWER_LIMIT_GAP_MIN: lowerLimitGapMin + * @HB_OT_MATH_CONSTANT_LOWER_LIMIT_BASELINE_DROP_MIN: lowerLimitBaselineDropMin + * @HB_OT_MATH_CONSTANT_STACK_TOP_SHIFT_UP: stackTopShiftUp + * @HB_OT_MATH_CONSTANT_STACK_TOP_DISPLAY_STYLE_SHIFT_UP: stackTopDisplayStyleShiftUp + * @HB_OT_MATH_CONSTANT_STACK_BOTTOM_SHIFT_DOWN: stackBottomShiftDown + * @HB_OT_MATH_CONSTANT_STACK_BOTTOM_DISPLAY_STYLE_SHIFT_DOWN: stackBottomDisplayStyleShiftDown + * @HB_OT_MATH_CONSTANT_STACK_GAP_MIN: stackGapMin + * @HB_OT_MATH_CONSTANT_STACK_DISPLAY_STYLE_GAP_MIN: stackDisplayStyleGapMin + * @HB_OT_MATH_CONSTANT_STRETCH_STACK_TOP_SHIFT_UP: stretchStackTopShiftUp + * @HB_OT_MATH_CONSTANT_STRETCH_STACK_BOTTOM_SHIFT_DOWN: stretchStackBottomShiftDown + * @HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_ABOVE_MIN: stretchStackGapAboveMin + * @HB_OT_MATH_CONSTANT_STRETCH_STACK_GAP_BELOW_MIN: stretchStackGapBelowMin + * @HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_SHIFT_UP: fractionNumeratorShiftUp + * @HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_DISPLAY_STYLE_SHIFT_UP: fractionNumeratorDisplayStyleShiftUp + * @HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_SHIFT_DOWN: fractionDenominatorShiftDown + * @HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_DISPLAY_STYLE_SHIFT_DOWN: fractionDenominatorDisplayStyleShiftDown + * @HB_OT_MATH_CONSTANT_FRACTION_NUMERATOR_GAP_MIN: fractionNumeratorGapMin + * @HB_OT_MATH_CONSTANT_FRACTION_NUM_DISPLAY_STYLE_GAP_MIN: fractionNumDisplayStyleGapMin + * @HB_OT_MATH_CONSTANT_FRACTION_RULE_THICKNESS: fractionRuleThickness + * @HB_OT_MATH_CONSTANT_FRACTION_DENOMINATOR_GAP_MIN: fractionDenominatorGapMin + * @HB_OT_MATH_CONSTANT_FRACTION_DENOM_DISPLAY_STYLE_GAP_MIN: fractionDenomDisplayStyleGapMin + * @HB_OT_MATH_CONSTANT_SKEWED_FRACTION_HORIZONTAL_GAP: skewedFractionHorizontalGap + * @HB_OT_MATH_CONSTANT_SKEWED_FRACTION_VERTICAL_GAP: skewedFractionVerticalGap + * @HB_OT_MATH_CONSTANT_OVERBAR_VERTICAL_GAP: overbarVerticalGap + * @HB_OT_MATH_CONSTANT_OVERBAR_RULE_THICKNESS: overbarRuleThickness + * @HB_OT_MATH_CONSTANT_OVERBAR_EXTRA_ASCENDER: overbarExtraAscender + * @HB_OT_MATH_CONSTANT_UNDERBAR_VERTICAL_GAP: underbarVerticalGap + * @HB_OT_MATH_CONSTANT_UNDERBAR_RULE_THICKNESS: underbarRuleThickness + * @HB_OT_MATH_CONSTANT_UNDERBAR_EXTRA_DESCENDER: underbarExtraDescender + * @HB_OT_MATH_CONSTANT_RADICAL_VERTICAL_GAP: radicalVerticalGap + * @HB_OT_MATH_CONSTANT_RADICAL_DISPLAY_STYLE_VERTICAL_GAP: radicalDisplayStyleVerticalGap + * @HB_OT_MATH_CONSTANT_RADICAL_RULE_THICKNESS: radicalRuleThickness + * @HB_OT_MATH_CONSTANT_RADICAL_EXTRA_ASCENDER: radicalExtraAscender + * @HB_OT_MATH_CONSTANT_RADICAL_KERN_BEFORE_DEGREE: radicalKernBeforeDegree + * @HB_OT_MATH_CONSTANT_RADICAL_KERN_AFTER_DEGREE: radicalKernAfterDegree + * @HB_OT_MATH_CONSTANT_RADICAL_DEGREE_BOTTOM_RAISE_PERCENT: radicalDegreeBottomRaisePercent * - * The 'MATH' table constants specified at - * https://docs.microsoft.com/en-us/typography/opentype/spec/math + * The 'MATH' table constants, refer to + * [OpenType documentation](https://docs.microsoft.com/en-us/typography/opentype/spec/math#mathconstants-table) + * For more explanations. * * Since: 1.3.3 */ @@ -116,6 +187,10 @@ typedef enum { /** * hb_ot_math_kern_t: + * @HB_OT_MATH_KERN_TOP_RIGHT: The top right corner of the glyph. + * @HB_OT_MATH_KERN_TOP_LEFT: The top left corner of the glyph. + * @HB_OT_MATH_KERN_BOTTOM_RIGHT: The bottom right corner of the glyph. + * @HB_OT_MATH_KERN_BOTTOM_LEFT: The bottom left corner of the glyph. * * The math kerning-table types defined for the four corners * of a glyph. @@ -145,6 +220,8 @@ typedef struct hb_ot_math_glyph_variant_t { /** * hb_ot_math_glyph_part_flags_t: + * @HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER: This is an extender glyph part that + * can be repeated to reach the desired length. * * Flags for math glyph parts. * diff --git a/thirdparty/harfbuzz/src/hb-ot-meta.cc b/thirdparty/harfbuzz/src/hb-ot-meta.cc index 54a0e10f9b..35c8eb523f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-meta.cc +++ b/thirdparty/harfbuzz/src/hb-ot-meta.cc @@ -41,9 +41,11 @@ * hb_ot_meta_get_entry_tags: * @face: a face object * @start_offset: iteration's start offset - * @entries_count:(inout) (allow-none): buffer size as input, filled size as output + * @entries_count:(inout) (optional): buffer size as input, filled size as output * @entries: (out caller-allocates) (array length=entries_count): entries tags buffer * + * Fetches all available feature types. + * * Return value: Number of all available feature types. * * Since: 2.6.0 diff --git a/thirdparty/harfbuzz/src/hb-ot-meta.h b/thirdparty/harfbuzz/src/hb-ot-meta.h index 0278d84148..7748eb4958 100644 --- a/thirdparty/harfbuzz/src/hb-ot-meta.h +++ b/thirdparty/harfbuzz/src/hb-ot-meta.h @@ -22,7 +22,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -#ifndef HB_OT_H_IN +#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-ot.h> instead." #endif @@ -54,6 +54,7 @@ typedef enum { HB_OT_META_TAG_DESIGN_LANGUAGES = HB_TAG ('d','l','n','g'), HB_OT_META_TAG_SUPPORTED_LANGUAGES = HB_TAG ('s','l','n','g'), + /*< private >*/ _HB_OT_META_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/ } hb_ot_meta_tag_t; diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.cc b/thirdparty/harfbuzz/src/hb-ot-metrics.cc index 3065ea2adf..72aeff82d6 100644 --- a/thirdparty/harfbuzz/src/hb-ot-metrics.cc +++ b/thirdparty/harfbuzz/src/hb-ot-metrics.cc @@ -119,11 +119,11 @@ _get_gasp (hb_face_t *face, float *result, hb_ot_metrics_tag_t metrics_tag) /** * hb_ot_metrics_get_position: - * @font: a #hb_font_t object. + * @font: an #hb_font_t object. * @metrics_tag: tag of metrics value you like to fetch. * @position: (out) (optional): result of metrics value from the font. * - * It fetches metrics value corresponding to a given tag from a font. + * Fetches metrics value corresponding to @metrics_tag from @font. * * Returns: Whether found the requested metrics in the font. * Since: 2.6.0 @@ -193,10 +193,13 @@ hb_ot_metrics_get_position (hb_font_t *font, #ifndef HB_NO_VAR /** * hb_ot_metrics_get_variation: - * @font: - * @metrics_tag: + * @font: an #hb_font_t object. + * @metrics_tag: tag of metrics value you like to fetch. + * + * Fetches metrics value corresponding to @metrics_tag from @font with the + * current font variation settings applied. * - * Returns: + * Returns: The requested metric value. * * Since: 2.6.0 **/ @@ -208,10 +211,13 @@ hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag) /** * hb_ot_metrics_get_x_variation: - * @font: - * @metrics_tag: + * @font: an #hb_font_t object. + * @metrics_tag: tag of metrics value you like to fetch. * - * Returns: + * Fetches horizontal metrics value corresponding to @metrics_tag from @font + * with the current font variation settings applied. + * + * Returns: The requested metric value. * * Since: 2.6.0 **/ @@ -223,10 +229,13 @@ hb_ot_metrics_get_x_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag) /** * hb_ot_metrics_get_y_variation: - * @font: - * @metrics_tag: + * @font: an #hb_font_t object. + * @metrics_tag: tag of metrics value you like to fetch. + * + * Fetches vertical metrics value corresponding to @metrics_tag from @font with + * the current font variation settings applied. * - * Returns: + * Returns: The requested metric value. * * Since: 2.6.0 **/ diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.h b/thirdparty/harfbuzz/src/hb-ot-metrics.h index 42c7363c03..5841fc8b0f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-metrics.h +++ b/thirdparty/harfbuzz/src/hb-ot-metrics.h @@ -22,7 +22,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -#ifndef HB_OT_H_IN +#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-ot.h> instead." #endif @@ -66,7 +66,8 @@ HB_BEGIN_DECLS * @HB_OT_METRICS_TAG_UNDERLINE_SIZE: underline size. * @HB_OT_METRICS_TAG_UNDERLINE_OFFSET: underline offset. * - * From https://docs.microsoft.com/en-us/typography/opentype/spec/mvar#value-tags + * Metric tags corresponding to [MVAR Value + * Tags](https://docs.microsoft.com/en-us/typography/opentype/spec/mvar#value-tags) * * Since: 2.6.0 **/ @@ -100,6 +101,7 @@ typedef enum { HB_OT_METRICS_TAG_UNDERLINE_SIZE = HB_TAG ('u','n','d','s'), HB_OT_METRICS_TAG_UNDERLINE_OFFSET = HB_TAG ('u','n','d','o'), + /*< private >*/ _HB_OT_METRICS_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/ } hb_ot_metrics_tag_t; diff --git a/thirdparty/harfbuzz/src/hb-ot-name.cc b/thirdparty/harfbuzz/src/hb-ot-name.cc index 10122b8c2e..4588226e6e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-name.cc +++ b/thirdparty/harfbuzz/src/hb-ot-name.cc @@ -46,7 +46,7 @@ /** * hb_ot_name_list_names: * @face: font face. - * @num_entries: (out) (allow-none): number of returned entries. + * @num_entries: (out) (optional): number of returned entries. * * Enumerates all available name IDs and language combinations. Returned * array is owned by the @face and should not be modified. It can be @@ -150,7 +150,7 @@ hb_ot_name_get_utf (hb_face_t *face, * @face: font face. * @name_id: OpenType name identifier to fetch. * @language: language to fetch the name for. - * @text_size: (inout) (allow-none): input size of @text buffer, and output size of + * @text_size: (inout) (optional): input size of @text buffer, and output size of * text written to buffer. * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. * @@ -177,7 +177,7 @@ hb_ot_name_get_utf8 (hb_face_t *face, * @face: font face. * @name_id: OpenType name identifier to fetch. * @language: language to fetch the name for. - * @text_size: (inout) (allow-none): input size of @text buffer, and output size of + * @text_size: (inout) (optional): input size of @text buffer, and output size of * text written to buffer. * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. * @@ -203,7 +203,7 @@ hb_ot_name_get_utf16 (hb_face_t *face, * @face: font face. * @name_id: OpenType name identifier to fetch. * @language: language to fetch the name for. - * @text_size: (inout) (allow-none): input size of @text buffer, and output size of + * @text_size: (inout) (optional): input size of @text buffer, and output size of * text written to buffer. * @text: (out caller-allocates) (array length=text_size): buffer to write fetched name into. * diff --git a/thirdparty/harfbuzz/src/hb-ot-name.h b/thirdparty/harfbuzz/src/hb-ot-name.h index 6f3fcd2427..9359014c8a 100644 --- a/thirdparty/harfbuzz/src/hb-ot-name.h +++ b/thirdparty/harfbuzz/src/hb-ot-name.h @@ -22,7 +22,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -#ifndef HB_OT_H_IN +#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-ot.h> instead." #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh index 7d31b712c4..8e98f87f4e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh @@ -177,15 +177,14 @@ struct OS2 if (!c->plan->glyphs_requested->is_empty ()) { hb_map_t unicode_glyphid_map; - + OT::cmap::accelerator_t cmap; cmap.init (c->plan->source); cmap.collect_mapping (&unicodes, &unicode_glyphid_map); cmap.fini (); - - if (c->plan->unicodes->is_empty ()) unicodes.clear (); - else hb_set_set (&unicodes, c->plan->unicodes); - + + hb_set_set (&unicodes, c->plan->unicodes); + + unicode_glyphid_map.iter () | hb_filter (c->plan->glyphs_requested, hb_second) | hb_map (hb_first) diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table.hh b/thirdparty/harfbuzz/src/hb-ot-post-table.hh index 8586331cd4..f22d6e244d 100644 --- a/thirdparty/harfbuzz/src/hb-ot-post-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-post-table.hh @@ -87,7 +87,6 @@ struct post if (unlikely (!post_prime)) return_trace (false); serialize (c->serializer); - if (c->serializer->in_error () || c->serializer->ran_out_of_room) return_trace (false); return_trace (true); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh index b15e145f2f..41e3dd38ab 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh @@ -142,7 +142,7 @@ OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \ ) \ OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \ - /* ASSERT_STATIC_EXPR_ZERO (len(FromGlyphs) == len(ToGlyphs)) */ + /* static_assert_expr (len(FromGlyphs) == len(ToGlyphs)) */ #define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \ OT_SUBLOOKUP(Name, 1, \ @@ -151,7 +151,7 @@ OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \ ) \ OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \ - /* ASSERT_STATIC_EXPR_ZERO (len(FirstGlyphs) == len(LigatureSetOffsets)) */ + /* static_assert_expr (len(FirstGlyphs) == len(LigatureSetOffsets)) */ #define OT_LIGATURE_SET(Name, LigatureSetOffsets) \ OT_UARRAY(Name, OT_LIST(LigatureSetOffsets)) diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc index 1e93f0efd5..1f244f940c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc @@ -33,7 +33,7 @@ /* buffer var allocations */ -#define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */ +#define arabic_shaping_action() complex_var_u8_auxiliary() /* arabic shaping action */ #define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0 diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc index f5915f43ae..dbedd6af0c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc @@ -119,7 +119,7 @@ data_destroy_hangul (void *data) #define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu)) /* buffer var allocations */ -#define hangul_shaping_feature() complex_var_u8_0() /* hangul jamo shaping feature */ +#define hangul_shaping_feature() complex_var_u8_auxiliary() /* hangul jamo shaping feature */ static bool is_zero_width_char (hb_font_t *font, @@ -205,7 +205,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED, { /* Tone mark follows a valid syllable; move it in front, unless it's zero width. */ buffer->unsafe_to_break_from_outbuffer (start, buffer->idx); - buffer->next_glyph (); + if (unlikely (!buffer->next_glyph ())) break; if (!is_zero_width_char (font, u)) { buffer->merge_out_clusters (start, end + 1); @@ -218,23 +218,25 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED, else { /* No valid syllable as base for tone mark; try to insert dotted circle. */ - if (!(buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE) && - font->has_glyph (0x25CCu)) + if (!(buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE) && + font->has_glyph (0x25CCu)) { hb_codepoint_t chars[2]; - if (!is_zero_width_char (font, u)) { + if (!is_zero_width_char (font, u)) + { chars[0] = u; chars[1] = 0x25CCu; - } else { + } else + { chars[0] = 0x25CCu; chars[1] = u; } - buffer->replace_glyphs (1, 2, chars); + (void) buffer->replace_glyphs (1, 2, chars); } else { /* No dotted circle available in the font; just leave tone mark untouched. */ - buffer->next_glyph (); + (void) buffer->next_glyph (); } } start = end = buffer->out_len; @@ -271,9 +273,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_codepoint_t s = SBase + (l - LBase) * NCount + (v - VBase) * TCount + tindex; if (font->has_glyph (s)) { - buffer->replace_glyphs (t ? 3 : 2, 1, &s); - if (unlikely (!buffer->successful)) - return; + (void) buffer->replace_glyphs (t ? 3 : 2, 1, &s); end = start + 1; continue; } @@ -285,17 +285,19 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED, * Set jamo features on the individual glyphs, and advance past them. */ buffer->cur().hangul_shaping_feature() = LJMO; - buffer->next_glyph (); + (void) buffer->next_glyph (); buffer->cur().hangul_shaping_feature() = VJMO; - buffer->next_glyph (); + (void) buffer->next_glyph (); if (t) { buffer->cur().hangul_shaping_feature() = TJMO; - buffer->next_glyph (); + (void) buffer->next_glyph (); end = start + 3; } else end = start + 2; + if (unlikely (!buffer->successful)) + break; if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) buffer->merge_out_clusters (start, end); continue; @@ -321,9 +323,7 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_codepoint_t new_s = s + new_tindex; if (font->has_glyph (new_s)) { - buffer->replace_glyphs (2, 1, &new_s); - if (unlikely (!buffer->successful)) - return; + (void) buffer->replace_glyphs (2, 1, &new_s); end = start + 1; continue; } @@ -347,19 +347,18 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED, (!tindex || font->has_glyph (decomposed[2]))) { unsigned int s_len = tindex ? 3 : 2; - buffer->replace_glyphs (1, s_len, decomposed); + (void) buffer->replace_glyphs (1, s_len, decomposed); /* If we decomposed an LV because of a non-combining T following, * we want to include this T in the syllable. */ if (has_glyph && !tindex) { - buffer->next_glyph (); + (void) buffer->next_glyph (); s_len++; } - if (unlikely (!buffer->successful)) - return; + break; /* We decomposed S: apply jamo features to the individual glyphs * that are now in buffer->out_info. @@ -383,17 +382,15 @@ preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED, if (has_glyph) { - /* We didn't decompose the S, so just advance past it. */ + /* We didn't decompose the S, so just advance past it and fall through. */ end = start + 1; - buffer->next_glyph (); - continue; } } /* Didn't find a recognizable syllable, so we leave end <= start; * this will prevent tone-mark reordering happening. */ - buffer->next_glyph (); + (void) buffer->next_glyph (); } buffer->swap_buffers (); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh index 670b6bf486..74bf3ca0fa 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh @@ -31,8 +31,37 @@ #include "hb.hh" +enum indic_syllable_type_t { + indic_consonant_syllable, + indic_vowel_syllable, + indic_standalone_cluster, + indic_symbol_cluster, + indic_broken_cluster, + indic_non_indic_cluster, +}; + -#line 36 "hb-ot-shape-complex-indic-machine.hh" +#line 45 "hb-ot-shape-complex-indic-machine.hh" +#define indic_syllable_machine_ex_A 10u +#define indic_syllable_machine_ex_C 1u +#define indic_syllable_machine_ex_CM 17u +#define indic_syllable_machine_ex_CS 19u +#define indic_syllable_machine_ex_DOTTEDCIRCLE 12u +#define indic_syllable_machine_ex_H 4u +#define indic_syllable_machine_ex_M 7u +#define indic_syllable_machine_ex_N 3u +#define indic_syllable_machine_ex_PLACEHOLDER 11u +#define indic_syllable_machine_ex_RS 13u +#define indic_syllable_machine_ex_Ra 16u +#define indic_syllable_machine_ex_Repha 15u +#define indic_syllable_machine_ex_SM 8u +#define indic_syllable_machine_ex_Symbol 18u +#define indic_syllable_machine_ex_V 2u +#define indic_syllable_machine_ex_ZWJ 6u +#define indic_syllable_machine_ex_ZWNJ 5u + + +#line 65 "hb-ot-shape-complex-indic-machine.hh" static const unsigned char _indic_syllable_machine_trans_keys[] = { 8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 13u, 4u, 8u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, @@ -384,18 +413,18 @@ static const int indic_syllable_machine_error = -1; static const int indic_syllable_machine_en_main = 39; -#line 36 "hb-ot-shape-complex-indic-machine.rl" +#line 46 "hb-ot-shape-complex-indic-machine.rl" -#line 93 "hb-ot-shape-complex-indic-machine.rl" +#line 102 "hb-ot-shape-complex-indic-machine.rl" #define found_syllable(syllable_type) \ HB_STMT_START { \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | indic_##syllable_type; \ + info[i].syllable() = (syllable_serial << 4) | syllable_type; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END @@ -407,7 +436,7 @@ find_syllables_indic (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 411 "hb-ot-shape-complex-indic-machine.hh" +#line 440 "hb-ot-shape-complex-indic-machine.hh" { cs = indic_syllable_machine_start; ts = 0; @@ -415,7 +444,7 @@ find_syllables_indic (hb_buffer_t *buffer) act = 0; } -#line 113 "hb-ot-shape-complex-indic-machine.rl" +#line 122 "hb-ot-shape-complex-indic-machine.rl" p = 0; @@ -423,7 +452,7 @@ find_syllables_indic (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 427 "hb-ot-shape-complex-indic-machine.hh" +#line 456 "hb-ot-shape-complex-indic-machine.hh" { int _slen; int _trans; @@ -437,7 +466,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 441 "hb-ot-shape-complex-indic-machine.hh" +#line 470 "hb-ot-shape-complex-indic-machine.hh" } _keys = _indic_syllable_machine_trans_keys + (cs<<1); @@ -460,64 +489,64 @@ _eof_trans: {te = p+1;} break; case 11: -#line 89 "hb-ot-shape-complex-indic-machine.rl" - {te = p+1;{ found_syllable (non_indic_cluster); }} +#line 98 "hb-ot-shape-complex-indic-machine.rl" + {te = p+1;{ found_syllable (indic_non_indic_cluster); }} break; case 13: -#line 84 "hb-ot-shape-complex-indic-machine.rl" - {te = p;p--;{ found_syllable (consonant_syllable); }} +#line 93 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (indic_consonant_syllable); }} break; case 14: -#line 85 "hb-ot-shape-complex-indic-machine.rl" - {te = p;p--;{ found_syllable (vowel_syllable); }} +#line 94 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (indic_vowel_syllable); }} break; case 17: -#line 86 "hb-ot-shape-complex-indic-machine.rl" - {te = p;p--;{ found_syllable (standalone_cluster); }} +#line 95 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (indic_standalone_cluster); }} break; case 19: -#line 87 "hb-ot-shape-complex-indic-machine.rl" - {te = p;p--;{ found_syllable (symbol_cluster); }} +#line 96 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (indic_symbol_cluster); }} break; case 15: -#line 88 "hb-ot-shape-complex-indic-machine.rl" - {te = p;p--;{ found_syllable (broken_cluster); }} +#line 97 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (indic_broken_cluster); }} break; case 16: -#line 89 "hb-ot-shape-complex-indic-machine.rl" - {te = p;p--;{ found_syllable (non_indic_cluster); }} +#line 98 "hb-ot-shape-complex-indic-machine.rl" + {te = p;p--;{ found_syllable (indic_non_indic_cluster); }} break; case 1: -#line 84 "hb-ot-shape-complex-indic-machine.rl" - {{p = ((te))-1;}{ found_syllable (consonant_syllable); }} +#line 93 "hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }} break; case 3: -#line 85 "hb-ot-shape-complex-indic-machine.rl" - {{p = ((te))-1;}{ found_syllable (vowel_syllable); }} +#line 94 "hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }} break; case 7: -#line 86 "hb-ot-shape-complex-indic-machine.rl" - {{p = ((te))-1;}{ found_syllable (standalone_cluster); }} +#line 95 "hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }} break; case 8: -#line 87 "hb-ot-shape-complex-indic-machine.rl" - {{p = ((te))-1;}{ found_syllable (symbol_cluster); }} +#line 96 "hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }} break; case 4: -#line 88 "hb-ot-shape-complex-indic-machine.rl" - {{p = ((te))-1;}{ found_syllable (broken_cluster); }} +#line 97 "hb-ot-shape-complex-indic-machine.rl" + {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); }} break; case 6: #line 1 "NONE" { switch( act ) { case 1: - {{p = ((te))-1;} found_syllable (consonant_syllable); } + {{p = ((te))-1;} found_syllable (indic_consonant_syllable); } break; case 5: - {{p = ((te))-1;} found_syllable (broken_cluster); } + {{p = ((te))-1;} found_syllable (indic_broken_cluster); } break; case 6: - {{p = ((te))-1;} found_syllable (non_indic_cluster); } + {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); } break; } } @@ -525,22 +554,22 @@ _eof_trans: case 18: #line 1 "NONE" {te = p+1;} -#line 84 "hb-ot-shape-complex-indic-machine.rl" +#line 93 "hb-ot-shape-complex-indic-machine.rl" {act = 1;} break; case 5: #line 1 "NONE" {te = p+1;} -#line 88 "hb-ot-shape-complex-indic-machine.rl" +#line 97 "hb-ot-shape-complex-indic-machine.rl" {act = 5;} break; case 12: #line 1 "NONE" {te = p+1;} -#line 89 "hb-ot-shape-complex-indic-machine.rl" +#line 98 "hb-ot-shape-complex-indic-machine.rl" {act = 6;} break; -#line 544 "hb-ot-shape-complex-indic-machine.hh" +#line 573 "hb-ot-shape-complex-indic-machine.hh" } _again: @@ -549,7 +578,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 553 "hb-ot-shape-complex-indic-machine.hh" +#line 582 "hb-ot-shape-complex-indic-machine.hh" } if ( ++p != pe ) @@ -565,7 +594,7 @@ _again: } -#line 121 "hb-ot-shape-complex-indic-machine.rl" +#line 130 "hb-ot-shape-complex-indic-machine.rl" } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc index a150fd2486..dd204b23c1 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc @@ -82,7 +82,7 @@ #define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M) -static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { +static const uint16_t indic_table[] = { #define indic_offset_0x0028u 0 @@ -404,7 +404,7 @@ static const INDIC_TABLE_ELEMENT_TYPE indic_table[] = { }; /* Table items: 1792; occupancy: 70% */ -INDIC_TABLE_ELEMENT_TYPE +uint16_t hb_indic_get_categories (hb_codepoint_t u) { switch (u >> 12) diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc index 652ef47040..a4f2d9a847 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc @@ -29,6 +29,7 @@ #ifndef HB_NO_OT_SHAPE #include "hb-ot-shape-complex-indic.hh" +#include "hb-ot-shape-complex-indic-machine.hh" #include "hb-ot-shape-complex-vowel-constraints.hh" #include "hb-ot-layout.hh" @@ -337,19 +338,6 @@ consonant_position_from_face (const indic_shape_plan_t *indic_plan, return POS_BASE_C; } - -enum indic_syllable_type_t { - indic_consonant_syllable, - indic_vowel_syllable, - indic_standalone_cluster, - indic_symbol_cluster, - indic_broken_cluster, - indic_non_indic_cluster, -}; - -#include "hb-ot-shape-complex-indic-machine.hh" - - static void setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, @@ -764,7 +752,28 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, * We could use buffer->sort() for this, if there was no special * reordering of pre-base stuff happening later... * We don't want to merge_clusters all of that, which buffer->sort() - * would. + * would. Here's a concrete example: + * + * Assume there's a pre-base consonant and explicit Halant before base, + * followed by a prebase-reordering (left) Matra: + * + * C,H,ZWNJ,B,M + * + * At this point in reordering we would have: + * + * M,C,H,ZWNJ,B + * + * whereas in final reordering we will bring the Matra closer to Base: + * + * C,H,ZWNJ,M,B + * + * That's why we don't want to merge-clusters anything before the Base + * at this point. But if something moved from after Base to before it, + * we should merge clusters from base to them. In final-reordering, we + * only move things around before base, and merge-clusters up to base. + * These two merge-clusters from the two sides of base will interlock + * to merge things correctly. See: + * https://github.com/harfbuzz/harfbuzz/issues/2272 */ if (indic_plan->is_old_spec || end - start > 127) buffer->merge_clusters (base, end); @@ -774,17 +783,18 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan, for (unsigned int i = base; i < end; i++) if (info[i].syllable() != 255) { + unsigned int min = i; unsigned int max = i; unsigned int j = start + info[i].syllable(); while (j != i) { + min = hb_min (min, j); max = hb_max (max, j); unsigned int next = start + info[j].syllable(); info[j].syllable() = 255; /* So we don't process j later again. */ j = next; } - if (i != max) - buffer->merge_clusters (i, max + 1); + buffer->merge_clusters (hb_max (base, min), max + 1); } } @@ -938,69 +948,6 @@ initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan, } } -static inline void -insert_dotted_circles_indic (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font, - hb_buffer_t *buffer) -{ - if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)) - return; - - /* Note: This loop is extra overhead, but should not be measurable. - * TODO Use a buffer scratch flag to remove the loop. */ - bool has_broken_syllables = false; - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - for (unsigned int i = 0; i < count; i++) - if ((info[i].syllable() & 0x0F) == indic_broken_cluster) - { - has_broken_syllables = true; - break; - } - if (likely (!has_broken_syllables)) - return; - - - hb_codepoint_t dottedcircle_glyph; - if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph)) - return; - - hb_glyph_info_t dottedcircle = {0}; - dottedcircle.codepoint = 0x25CCu; - set_indic_properties (dottedcircle); - dottedcircle.codepoint = dottedcircle_glyph; - - buffer->clear_output (); - - buffer->idx = 0; - unsigned int last_syllable = 0; - while (buffer->idx < buffer->len && buffer->successful) - { - unsigned int syllable = buffer->cur().syllable(); - indic_syllable_type_t syllable_type = (indic_syllable_type_t) (syllable & 0x0F); - if (unlikely (last_syllable != syllable && syllable_type == indic_broken_cluster)) - { - last_syllable = syllable; - - hb_glyph_info_t ginfo = dottedcircle; - ginfo.cluster = buffer->cur().cluster; - ginfo.mask = buffer->cur().mask; - ginfo.syllable() = buffer->cur().syllable(); - - /* Insert dottedcircle after possible Repha. */ - while (buffer->idx < buffer->len && buffer->successful && - last_syllable == buffer->cur().syllable() && - buffer->cur().indic_category() == OT_Repha) - buffer->next_glyph (); - - buffer->output_info (ginfo); - } - else - buffer->next_glyph (); - } - buffer->swap_buffers (); -} - static void initial_reordering_indic (const hb_ot_shape_plan_t *plan, hb_font_t *font, @@ -1008,11 +955,16 @@ initial_reordering_indic (const hb_ot_shape_plan_t *plan, { if (!buffer->message (font, "start reordering indic initial")) return; + update_consonant_positions_indic (plan, font, buffer); - insert_dotted_circles_indic (plan, font, buffer); + hb_syllabic_insert_dotted_circles (font, buffer, + indic_broken_cluster, + OT_DOTTEDCIRCLE, + OT_Repha); foreach_syllable (buffer, start, end) initial_reordering_syllable_indic (plan, font->face, buffer, start, end); + (void) buffer->message (font, "end reordering indic initial"); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh index 41bd8bd6cc..dcb28a4e84 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh @@ -29,16 +29,14 @@ #include "hb.hh" -#include "hb-ot-shape-complex.hh" +#include "hb-ot-shape-complex-syllabic.hh" /* buffer var allocations */ -#define indic_category() complex_var_u8_0() /* indic_category_t */ -#define indic_position() complex_var_u8_1() /* indic_position_t */ +#define indic_category() complex_var_u8_category() /* indic_category_t */ +#define indic_position() complex_var_u8_auxiliary() /* indic_position_t */ -#define INDIC_TABLE_ELEMENT_TYPE uint16_t - /* Cateories used in the OpenType spec: * https://docs.microsoft.com/en-us/typography/script-development/devanagari */ @@ -177,7 +175,7 @@ enum indic_matra_category_t { #define INDIC_COMBINE_CATEGORIES(S,M) \ ( \ - ASSERT_STATIC_EXPR_ZERO (S < 255 && M < 255) + \ + static_assert_expr (S < 255 && M < 255) + \ ( S | \ ( \ ( \ @@ -194,7 +192,7 @@ enum indic_matra_category_t { ) \ ) -HB_INTERNAL INDIC_TABLE_ELEMENT_TYPE +HB_INTERNAL uint16_t hb_indic_get_categories (hb_codepoint_t u); @@ -307,17 +305,12 @@ static const hb_codepoint_t ra_chars[] = { 0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */ 0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */ - - 0x179Au, /* Khmer */ }; static inline bool is_ra (hb_codepoint_t u) { - for (unsigned int i = 0; i < ARRAY_LENGTH (ra_chars); i++) - if (u == ra_chars[i]) - return true; - return false; + return hb_array (ra_chars).lfind (u); } static inline void @@ -325,7 +318,7 @@ set_indic_properties (hb_glyph_info_t &info) { hb_codepoint_t u = info.codepoint; unsigned int type = hb_indic_get_categories (u); - indic_category_t cat = (indic_category_t) (type & 0x7Fu); + indic_category_t cat = (indic_category_t) (type & 0xFFu); indic_position_t pos = (indic_position_t) (type >> 8); @@ -370,6 +363,7 @@ set_indic_properties (hb_glyph_info_t &info) else if (unlikely (u == 0x1133Bu || u == 0x1133Cu)) cat = OT_N; else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */ + else if (unlikely (u == 0x0B55u)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/2849 */ else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */ else if (unlikely (u == 0x09FCu)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/1613 */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh index a040318d34..82ab186a41 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh @@ -1,211 +1,179 @@ - #line 1 "hb-ot-shape-complex-khmer-machine.rl" /* - * Copyright © 2011,2012 Google, Inc. - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Google Author(s): Behdad Esfahbod - */ +* Copyright © 2011,2012 Google, Inc. +* +* This is part of HarfBuzz, a text shaping library. +* +* Permission is hereby granted, without written agreement and without +* license or royalty fees, to use, copy, modify, and distribute this +* software and its documentation for any purpose, provided that the +* above copyright notice and the following two paragraphs appear in +* all copies of this software. +* +* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR +* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN +* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +* DAMAGE. +* +* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, +* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO +* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +* +* Google Author(s): Behdad Esfahbod +*/ #ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH #define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH #include "hb.hh" +enum khmer_syllable_type_t { + khmer_consonant_syllable, + khmer_broken_cluster, + khmer_non_khmer_cluster, +}; + -#line 36 "hb-ot-shape-complex-khmer-machine.hh" +#line 41 "hb-ot-shape-complex-khmer-machine.hh" +#define khmer_syllable_machine_ex_C 1u +#define khmer_syllable_machine_ex_Coeng 14u +#define khmer_syllable_machine_ex_DOTTEDCIRCLE 12u +#define khmer_syllable_machine_ex_PLACEHOLDER 11u +#define khmer_syllable_machine_ex_Ra 16u +#define khmer_syllable_machine_ex_Robatic 20u +#define khmer_syllable_machine_ex_V 2u +#define khmer_syllable_machine_ex_VAbv 26u +#define khmer_syllable_machine_ex_VBlw 27u +#define khmer_syllable_machine_ex_VPre 28u +#define khmer_syllable_machine_ex_VPst 29u +#define khmer_syllable_machine_ex_Xgroup 21u +#define khmer_syllable_machine_ex_Ygroup 22u +#define khmer_syllable_machine_ex_ZWJ 6u +#define khmer_syllable_machine_ex_ZWNJ 5u + + +#line 59 "hb-ot-shape-complex-khmer-machine.hh" static const unsigned char _khmer_syllable_machine_trans_keys[] = { - 5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u, - 5u, 26u, 5u, 21u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, - 5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 29u, 5u, 29u, 5u, 29u, 5u, 29u, - 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 26u, 5u, 29u, - 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u, 5u, 29u, - 0 + 2u, 8u, 2u, 6u, 2u, 8u, 2u, 6u, + 0u, 0u, 2u, 6u, 2u, 8u, 2u, 6u, + 2u, 8u, 2u, 6u, 2u, 6u, 2u, 8u, + 2u, 6u, 0u, 0u, 2u, 6u, 2u, 8u, + 2u, 6u, 2u, 8u, 2u, 6u, 2u, 8u, + 0u, 11u, 2u, 11u, 2u, 11u, 2u, 11u, + 7u, 7u, 2u, 7u, 2u, 11u, 2u, 11u, + 2u, 11u, 0u, 0u, 2u, 8u, 2u, 11u, + 2u, 11u, 7u, 7u, 2u, 7u, 2u, 11u, + 2u, 11u, 0u, 0u, 2u, 11u, 2u, 11u, + 0u }; -static const char _khmer_syllable_machine_key_spans[] = { - 22, 17, 22, 17, 16, 17, 22, 17, - 22, 17, 17, 22, 17, 16, 17, 22, - 17, 22, 17, 22, 29, 25, 25, 25, - 1, 18, 25, 25, 25, 16, 22, 25, - 25, 1, 18, 25, 25, 16, 25, 25 +static const signed char _khmer_syllable_machine_char_class[] = { + 0, 0, 1, 1, 2, 2, 1, 1, + 1, 1, 3, 3, 1, 4, 1, 0, + 1, 1, 1, 5, 6, 7, 1, 1, + 1, 8, 9, 10, 11, 0 }; static const short _khmer_syllable_machine_index_offsets[] = { - 0, 23, 41, 64, 82, 99, 117, 140, - 158, 181, 199, 217, 240, 258, 275, 293, - 316, 334, 357, 375, 398, 428, 454, 480, - 506, 508, 527, 553, 579, 605, 622, 645, - 671, 697, 699, 718, 744, 770, 787, 813 + 0, 7, 12, 19, 24, 25, 30, 37, + 42, 49, 54, 59, 66, 71, 72, 77, + 84, 89, 96, 101, 108, 120, 130, 140, + 150, 151, 157, 167, 177, 187, 188, 195, + 205, 215, 216, 222, 232, 242, 243, 253, + 0 }; -static const char _khmer_syllable_machine_indicies[] = { - 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2, - 3, 0, 0, 0, 0, 4, 0, 1, - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3, - 0, 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3, 0, 0, 0, 0, 4, 0, - 5, 5, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 4, 0, 6, 6, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 6, 0, 7, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 8, 0, 9, 9, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 10, 0, 0, - 0, 0, 4, 0, 9, 9, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 10, 0, 11, 11, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 12, 0, - 0, 0, 0, 4, 0, 11, 11, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 12, 0, 14, - 14, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 15, - 13, 14, 14, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 15, 16, 16, 16, 16, 17, 16, - 18, 18, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 17, 16, 19, 19, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 19, 16, 20, 20, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 21, 16, 22, 22, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 23, 16, 16, - 16, 16, 17, 16, 22, 22, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 23, 16, 24, 24, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 25, 16, - 16, 16, 16, 17, 16, 24, 24, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 25, 16, 14, - 14, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 26, 15, - 16, 16, 16, 16, 17, 16, 28, 28, - 27, 27, 29, 29, 27, 27, 27, 27, - 2, 2, 27, 30, 27, 28, 27, 27, - 27, 27, 15, 19, 27, 27, 27, 17, - 23, 25, 21, 27, 32, 32, 31, 31, - 31, 31, 31, 31, 31, 33, 31, 31, - 31, 31, 31, 2, 3, 6, 31, 31, - 31, 4, 10, 12, 8, 31, 34, 34, - 31, 31, 31, 31, 31, 31, 31, 35, - 31, 31, 31, 31, 31, 31, 3, 6, - 31, 31, 31, 4, 10, 12, 8, 31, - 5, 5, 31, 31, 31, 31, 31, 31, - 31, 35, 31, 31, 31, 31, 31, 31, - 4, 6, 31, 31, 31, 31, 31, 31, - 8, 31, 6, 31, 7, 7, 31, 31, - 31, 31, 31, 31, 31, 35, 31, 31, - 31, 31, 31, 31, 8, 6, 31, 36, - 36, 31, 31, 31, 31, 31, 31, 31, - 35, 31, 31, 31, 31, 31, 31, 10, - 6, 31, 31, 31, 4, 31, 31, 8, - 31, 37, 37, 31, 31, 31, 31, 31, - 31, 31, 35, 31, 31, 31, 31, 31, - 31, 12, 6, 31, 31, 31, 4, 10, - 31, 8, 31, 34, 34, 31, 31, 31, - 31, 31, 31, 31, 33, 31, 31, 31, - 31, 31, 31, 3, 6, 31, 31, 31, - 4, 10, 12, 8, 31, 28, 28, 31, - 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 28, 31, 14, 14, - 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 15, 38, - 38, 38, 38, 17, 38, 40, 40, 39, - 39, 39, 39, 39, 39, 39, 41, 39, - 39, 39, 39, 39, 39, 15, 19, 39, - 39, 39, 17, 23, 25, 21, 39, 18, - 18, 39, 39, 39, 39, 39, 39, 39, - 41, 39, 39, 39, 39, 39, 39, 17, - 19, 39, 39, 39, 39, 39, 39, 21, - 39, 19, 39, 20, 20, 39, 39, 39, - 39, 39, 39, 39, 41, 39, 39, 39, - 39, 39, 39, 21, 19, 39, 42, 42, - 39, 39, 39, 39, 39, 39, 39, 41, - 39, 39, 39, 39, 39, 39, 23, 19, - 39, 39, 39, 17, 39, 39, 21, 39, - 43, 43, 39, 39, 39, 39, 39, 39, - 39, 41, 39, 39, 39, 39, 39, 39, - 25, 19, 39, 39, 39, 17, 23, 39, - 21, 39, 44, 44, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, - 39, 44, 39, 45, 45, 39, 39, 39, - 39, 39, 39, 39, 30, 39, 39, 39, - 39, 39, 26, 15, 19, 39, 39, 39, - 17, 23, 25, 21, 39, 40, 40, 39, - 39, 39, 39, 39, 39, 39, 30, 39, - 39, 39, 39, 39, 39, 15, 19, 39, - 39, 39, 17, 23, 25, 21, 39, 0 +static const signed char _khmer_syllable_machine_indicies[] = { + 1, 0, 0, 2, 3, 0, 4, 1, + 0, 0, 0, 3, 1, 0, 0, 0, + 3, 0, 4, 5, 0, 0, 0, 4, + 6, 7, 0, 0, 0, 8, 9, 0, + 0, 0, 10, 0, 4, 9, 0, 0, + 0, 10, 11, 0, 0, 0, 12, 0, + 4, 11, 0, 0, 0, 12, 14, 13, + 13, 13, 15, 14, 16, 16, 16, 15, + 16, 17, 18, 16, 16, 16, 17, 19, + 20, 16, 16, 16, 21, 22, 16, 16, + 16, 23, 16, 17, 22, 16, 16, 16, + 23, 24, 16, 16, 16, 25, 16, 17, + 24, 16, 16, 16, 25, 14, 16, 16, + 26, 15, 16, 17, 29, 28, 30, 2, + 31, 28, 15, 19, 17, 23, 25, 21, + 33, 32, 34, 2, 3, 6, 4, 10, + 12, 8, 35, 32, 36, 32, 3, 6, + 4, 10, 12, 8, 5, 32, 36, 32, + 4, 6, 32, 32, 32, 8, 6, 7, + 32, 36, 32, 8, 6, 37, 32, 36, + 32, 10, 6, 4, 32, 32, 8, 38, + 32, 36, 32, 12, 6, 4, 10, 32, + 8, 35, 32, 34, 32, 3, 6, 4, + 10, 12, 8, 29, 14, 39, 39, 39, + 15, 39, 17, 41, 40, 42, 40, 15, + 19, 17, 23, 25, 21, 18, 40, 42, + 40, 17, 19, 40, 40, 40, 21, 19, + 20, 40, 42, 40, 21, 19, 43, 40, + 42, 40, 23, 19, 17, 40, 40, 21, + 44, 40, 42, 40, 25, 19, 17, 23, + 40, 21, 45, 46, 40, 31, 26, 15, + 19, 17, 23, 25, 21, 41, 40, 31, + 40, 15, 19, 17, 23, 25, 21, 0 }; -static const char _khmer_syllable_machine_trans_targs[] = { - 20, 1, 28, 22, 23, 3, 24, 5, - 25, 7, 26, 9, 27, 20, 10, 31, - 20, 32, 12, 33, 14, 34, 16, 35, - 18, 36, 39, 20, 21, 30, 37, 20, - 0, 29, 2, 4, 6, 8, 20, 20, - 11, 13, 15, 17, 38, 19 +static const signed char _khmer_syllable_machine_index_defaults[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 13, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 28, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 39, 40, + 40, 40, 40, 40, 40, 40, 40, 40, + 0 }; -static const char _khmer_syllable_machine_trans_actions[] = { - 1, 0, 2, 2, 2, 0, 0, 0, - 2, 0, 2, 0, 2, 3, 0, 4, - 5, 2, 0, 0, 0, 2, 0, 2, - 0, 2, 4, 8, 2, 9, 0, 10, - 0, 0, 0, 0, 0, 0, 11, 12, - 0, 0, 0, 0, 4, 0 +static const signed char _khmer_syllable_machine_cond_targs[] = { + 20, 1, 28, 22, 23, 3, 24, 5, + 25, 7, 26, 9, 27, 20, 10, 31, + 20, 32, 12, 33, 14, 34, 16, 35, + 18, 36, 39, 20, 20, 21, 30, 37, + 20, 0, 29, 2, 4, 6, 8, 20, + 20, 11, 13, 15, 17, 38, 19, 0 }; -static const char _khmer_syllable_machine_to_state_actions[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 6, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 +static const signed char _khmer_syllable_machine_cond_actions[] = { + 1, 0, 2, 2, 2, 0, 0, 0, + 2, 0, 2, 0, 2, 3, 0, 4, + 5, 2, 0, 0, 0, 2, 0, 2, + 0, 2, 4, 0, 8, 2, 9, 0, + 10, 0, 0, 0, 0, 0, 0, 11, + 12, 0, 0, 0, 0, 4, 0, 0 }; -static const char _khmer_syllable_machine_from_state_actions[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 +static const signed char _khmer_syllable_machine_to_state_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0 }; -static const unsigned char _khmer_syllable_machine_eof_trans[] = { - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 14, 17, 17, 17, 17, 17, - 17, 17, 17, 17, 0, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 39, 40, - 40, 40, 40, 40, 40, 40, 40, 40 +static const signed char _khmer_syllable_machine_from_state_actions[] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0 +}; + +static const signed char _khmer_syllable_machine_eof_trans[] = { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 14, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 28, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 40, 41, + 41, 41, 41, 41, 41, 41, 41, 41, + 0 }; static const int khmer_syllable_machine_start = 20; @@ -215,156 +183,271 @@ static const int khmer_syllable_machine_error = -1; static const int khmer_syllable_machine_en_main = 20; -#line 36 "hb-ot-shape-complex-khmer-machine.rl" +#line 43 "hb-ot-shape-complex-khmer-machine.rl" -#line 80 "hb-ot-shape-complex-khmer-machine.rl" +#line 86 "hb-ot-shape-complex-khmer-machine.rl" #define found_syllable(syllable_type) \ - HB_STMT_START { \ - if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ - for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \ - syllable_serial++; \ - if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ - } HB_STMT_END +HB_STMT_START { \ + if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ + for (unsigned int i = ts; i < te; i++) \ + info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + syllable_serial++; \ + if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ + } HB_STMT_END static void find_syllables_khmer (hb_buffer_t *buffer) { - unsigned int p, pe, eof, ts, te, act HB_UNUSED; - int cs; - hb_glyph_info_t *info = buffer->info; - -#line 242 "hb-ot-shape-complex-khmer-machine.hh" + unsigned int p, pe, eof, ts, te, act HB_UNUSED; + int cs; + hb_glyph_info_t *info = buffer->info; + +#line 210 "hb-ot-shape-complex-khmer-machine.hh" { - cs = khmer_syllable_machine_start; - ts = 0; - te = 0; - act = 0; + cs = (int)khmer_syllable_machine_start; + ts = 0; + te = 0; + act = 0; } - -#line 100 "hb-ot-shape-complex-khmer-machine.rl" - - - p = 0; - pe = eof = buffer->len; - - unsigned int syllable_serial = 1; - -#line 258 "hb-ot-shape-complex-khmer-machine.hh" + +#line 106 "hb-ot-shape-complex-khmer-machine.rl" + + + p = 0; + pe = eof = buffer->len; + + unsigned int syllable_serial = 1; + +#line 226 "hb-ot-shape-complex-khmer-machine.hh" { - int _slen; - int _trans; - const unsigned char *_keys; - const char *_inds; - if ( p == pe ) - goto _test_eof; -_resume: - switch ( _khmer_syllable_machine_from_state_actions[cs] ) { - case 7: + unsigned int _trans = 0; + const unsigned char * _keys; + const signed char * _inds; + int _ic; + _resume: {} + if ( p == pe && p != eof ) + goto _out; + switch ( _khmer_syllable_machine_from_state_actions[cs] ) { + case 7: { + { #line 1 "NONE" - {ts = p;} - break; -#line 272 "hb-ot-shape-complex-khmer-machine.hh" - } - - _keys = _khmer_syllable_machine_trans_keys + (cs<<1); - _inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs]; - - _slen = _khmer_syllable_machine_key_spans[cs]; - _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) && - ( info[p].khmer_category()) <= _keys[1] ? - ( info[p].khmer_category()) - _keys[0] : _slen ]; - -_eof_trans: - cs = _khmer_syllable_machine_trans_targs[_trans]; - - if ( _khmer_syllable_machine_trans_actions[_trans] == 0 ) - goto _again; - - switch ( _khmer_syllable_machine_trans_actions[_trans] ) { - case 2: + {ts = p;}} + +#line 241 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + } + + if ( p == eof ) { + if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) { + _trans = (unsigned int)_khmer_syllable_machine_eof_trans[cs] - 1; + } + } + else { + _keys = ( _khmer_syllable_machine_trans_keys + ((cs<<1))); + _inds = ( _khmer_syllable_machine_indicies + (_khmer_syllable_machine_index_offsets[cs])); + + if ( (info[p].khmer_category()) <= 29 && (info[p].khmer_category()) >= 1 ) { + _ic = (int)_khmer_syllable_machine_char_class[(int)(info[p].khmer_category()) - 1]; + if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) ) + _trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) )); + else + _trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs]; + } + else { + _trans = (unsigned int)_khmer_syllable_machine_index_defaults[cs]; + } + + } + cs = (int)_khmer_syllable_machine_cond_targs[_trans]; + + if ( _khmer_syllable_machine_cond_actions[_trans] != 0 ) { + + switch ( _khmer_syllable_machine_cond_actions[_trans] ) { + case 2: { + { #line 1 "NONE" - {te = p+1;} - break; - case 8: -#line 76 "hb-ot-shape-complex-khmer-machine.rl" - {te = p+1;{ found_syllable (non_khmer_cluster); }} - break; - case 10: -#line 74 "hb-ot-shape-complex-khmer-machine.rl" - {te = p;p--;{ found_syllable (consonant_syllable); }} - break; - case 12: -#line 75 "hb-ot-shape-complex-khmer-machine.rl" - {te = p;p--;{ found_syllable (broken_cluster); }} - break; - case 11: -#line 76 "hb-ot-shape-complex-khmer-machine.rl" - {te = p;p--;{ found_syllable (non_khmer_cluster); }} - break; - case 1: -#line 74 "hb-ot-shape-complex-khmer-machine.rl" - {{p = ((te))-1;}{ found_syllable (consonant_syllable); }} - break; - case 5: -#line 75 "hb-ot-shape-complex-khmer-machine.rl" - {{p = ((te))-1;}{ found_syllable (broken_cluster); }} - break; - case 3: + {te = p+1;}} + +#line 279 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + case 8: { + { +#line 82 "hb-ot-shape-complex-khmer-machine.rl" + {te = p+1;{ +#line 82 "hb-ot-shape-complex-khmer-machine.rl" + found_syllable (khmer_non_khmer_cluster); } + }} + +#line 292 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + case 10: { + { +#line 80 "hb-ot-shape-complex-khmer-machine.rl" + {te = p;p = p - 1;{ +#line 80 "hb-ot-shape-complex-khmer-machine.rl" + found_syllable (khmer_consonant_syllable); } + }} + +#line 305 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + case 12: { + { +#line 81 "hb-ot-shape-complex-khmer-machine.rl" + {te = p;p = p - 1;{ +#line 81 "hb-ot-shape-complex-khmer-machine.rl" + found_syllable (khmer_broken_cluster); } + }} + +#line 318 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + case 11: { + { +#line 82 "hb-ot-shape-complex-khmer-machine.rl" + {te = p;p = p - 1;{ +#line 82 "hb-ot-shape-complex-khmer-machine.rl" + found_syllable (khmer_non_khmer_cluster); } + }} + +#line 331 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + case 1: { + { +#line 80 "hb-ot-shape-complex-khmer-machine.rl" + {p = ((te))-1; + { +#line 80 "hb-ot-shape-complex-khmer-machine.rl" + found_syllable (khmer_consonant_syllable); } + }} + +#line 345 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + case 5: { + { +#line 81 "hb-ot-shape-complex-khmer-machine.rl" + {p = ((te))-1; + { +#line 81 "hb-ot-shape-complex-khmer-machine.rl" + found_syllable (khmer_broken_cluster); } + }} + +#line 359 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + case 3: { + { #line 1 "NONE" - { switch( act ) { - case 2: - {{p = ((te))-1;} found_syllable (broken_cluster); } - break; - case 3: - {{p = ((te))-1;} found_syllable (non_khmer_cluster); } - break; - } - } - break; - case 4: + {switch( act ) { + case 2: { + p = ((te))-1; + { +#line 81 "hb-ot-shape-complex-khmer-machine.rl" + found_syllable (khmer_broken_cluster); } + break; + } + case 3: { + p = ((te))-1; + { +#line 82 "hb-ot-shape-complex-khmer-machine.rl" + found_syllable (khmer_non_khmer_cluster); } + break; + } + }} + } + +#line 385 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + case 4: { + { #line 1 "NONE" - {te = p+1;} -#line 75 "hb-ot-shape-complex-khmer-machine.rl" - {act = 2;} - break; - case 9: + {te = p+1;}} + +#line 395 "hb-ot-shape-complex-khmer-machine.hh" + + { +#line 81 "hb-ot-shape-complex-khmer-machine.rl" + {act = 2;}} + +#line 401 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + case 9: { + { #line 1 "NONE" - {te = p+1;} -#line 76 "hb-ot-shape-complex-khmer-machine.rl" - {act = 3;} - break; -#line 342 "hb-ot-shape-complex-khmer-machine.hh" - } - -_again: - switch ( _khmer_syllable_machine_to_state_actions[cs] ) { - case 6: + {te = p+1;}} + +#line 411 "hb-ot-shape-complex-khmer-machine.hh" + + { +#line 82 "hb-ot-shape-complex-khmer-machine.rl" + {act = 3;}} + +#line 417 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + } + + } + + if ( p == eof ) { + if ( cs >= 20 ) + goto _out; + } + else { + switch ( _khmer_syllable_machine_to_state_actions[cs] ) { + case 6: { + { #line 1 "NONE" - {ts = 0;} - break; -#line 351 "hb-ot-shape-complex-khmer-machine.hh" - } - - if ( ++p != pe ) - goto _resume; - _test_eof: {} - if ( p == eof ) - { - if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) { - _trans = _khmer_syllable_machine_eof_trans[cs] - 1; - goto _eof_trans; - } + {ts = 0;}} + +#line 437 "hb-ot-shape-complex-khmer-machine.hh" + + + break; + } + } + + p += 1; + goto _resume; + } + _out: {} } - - } - -#line 108 "hb-ot-shape-complex-khmer-machine.rl" - + +#line 114 "hb-ot-shape-complex-khmer-machine.rl" + } #undef found_syllable diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.rl b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.rl deleted file mode 100644 index e7f14533dd..0000000000 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.rl +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright © 2011,2012 Google, Inc. - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Google Author(s): Behdad Esfahbod - */ - -#ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH -#define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH - -#include "hb.hh" - -%%{ - machine khmer_syllable_machine; - alphtype unsigned char; - write data; -}%% - -%%{ - -# Same order as enum khmer_category_t. Not sure how to avoid duplication. -C = 1; -V = 2; -ZWNJ = 5; -ZWJ = 6; -PLACEHOLDER = 11; -DOTTEDCIRCLE = 12; -Coeng= 14; -Ra = 16; -Robatic = 20; -Xgroup = 21; -Ygroup = 22; -VAbv = 26; -VBlw = 27; -VPre = 28; -VPst = 29; - -c = (C | Ra | V); -cn = c.((ZWJ|ZWNJ)?.Robatic)?; -joiner = (ZWJ | ZWNJ); -xgroup = (joiner*.Xgroup)*; -ygroup = Ygroup*; - -# This grammar was experimentally extracted from what Uniscribe allows. - -matra_group = VPre? xgroup VBlw? xgroup (joiner?.VAbv)? xgroup VPst?; -syllable_tail = xgroup matra_group xgroup (Coeng.c)? ygroup; - - -broken_cluster = (Coeng.cn)* (Coeng | syllable_tail); -consonant_syllable = (cn|PLACEHOLDER|DOTTEDCIRCLE) broken_cluster; -other = any; - -main := |* - consonant_syllable => { found_syllable (consonant_syllable); }; - broken_cluster => { found_syllable (broken_cluster); }; - other => { found_syllable (non_khmer_cluster); }; -*|; - - -}%% - -#define found_syllable(syllable_type) \ - HB_STMT_START { \ - if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ - for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | khmer_##syllable_type; \ - syllable_serial++; \ - if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ - } HB_STMT_END - -static void -find_syllables_khmer (hb_buffer_t *buffer) -{ - unsigned int p, pe, eof, ts, te, act HB_UNUSED; - int cs; - hb_glyph_info_t *info = buffer->info; - %%{ - write init; - getkey info[p].khmer_category(); - }%% - - p = 0; - pe = eof = buffer->len; - - unsigned int syllable_serial = 1; - %%{ - write exec; - }%% -} - -#undef found_syllable - -#endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc index d6fcd7c814..dddba142a3 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc @@ -29,6 +29,7 @@ #ifndef HB_NO_OT_SHAPE #include "hb-ot-shape-complex-khmer.hh" +#include "hb-ot-shape-complex-khmer-machine.hh" #include "hb-ot-layout.hh" @@ -140,27 +141,6 @@ override_features_khmer (hb_ot_shape_planner_t *plan) struct khmer_shape_plan_t { - bool get_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const - { - hb_codepoint_t glyph = virama_glyph; - if (unlikely (virama_glyph == (hb_codepoint_t) -1)) - { - if (!font->get_nominal_glyph (0x17D2u, &glyph)) - glyph = 0; - /* Technically speaking, the spec says we should apply 'locl' to virama too. - * Maybe one day... */ - - /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph - * during shape planning... Instead, overwrite it here. It's safe. Don't worry! */ - virama_glyph = glyph; - } - - *pglyph = glyph; - return glyph != 0; - } - - mutable hb_codepoint_t virama_glyph; - hb_mask_t mask_array[KHMER_NUM_FEATURES]; }; @@ -171,8 +151,6 @@ data_create_khmer (const hb_ot_shape_plan_t *plan) if (unlikely (!khmer_plan)) return nullptr; - khmer_plan->virama_glyph = (hb_codepoint_t) -1; - for (unsigned int i = 0; i < ARRAY_LENGTH (khmer_plan->mask_array); i++) khmer_plan->mask_array[i] = (khmer_features[i].flags & F_GLOBAL) ? 0 : plan->map.get_1_mask (khmer_features[i].tag); @@ -186,15 +164,6 @@ data_destroy_khmer (void *data) free (data); } - -enum khmer_syllable_type_t { - khmer_consonant_syllable, - khmer_broken_cluster, - khmer_non_khmer_cluster, -}; - -#include "hb-ot-shape-complex-khmer-machine.hh" - static void setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, @@ -321,76 +290,17 @@ reorder_syllable_khmer (const hb_ot_shape_plan_t *plan, } } -static inline void -insert_dotted_circles_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font, - hb_buffer_t *buffer) -{ - if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)) - return; - - /* Note: This loop is extra overhead, but should not be measurable. - * TODO Use a buffer scratch flag to remove the loop. */ - bool has_broken_syllables = false; - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - for (unsigned int i = 0; i < count; i++) - if ((info[i].syllable() & 0x0F) == khmer_broken_cluster) - { - has_broken_syllables = true; - break; - } - if (likely (!has_broken_syllables)) - return; - - - hb_codepoint_t dottedcircle_glyph; - if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph)) - return; - - hb_glyph_info_t dottedcircle = {0}; - dottedcircle.codepoint = 0x25CCu; - set_khmer_properties (dottedcircle); - dottedcircle.codepoint = dottedcircle_glyph; - - buffer->clear_output (); - - buffer->idx = 0; - unsigned int last_syllable = 0; - while (buffer->idx < buffer->len && buffer->successful) - { - unsigned int syllable = buffer->cur().syllable(); - khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (syllable & 0x0F); - if (unlikely (last_syllable != syllable && syllable_type == khmer_broken_cluster)) - { - last_syllable = syllable; - - hb_glyph_info_t ginfo = dottedcircle; - ginfo.cluster = buffer->cur().cluster; - ginfo.mask = buffer->cur().mask; - ginfo.syllable() = buffer->cur().syllable(); - - /* Insert dottedcircle after possible Repha. */ - while (buffer->idx < buffer->len && buffer->successful && - last_syllable == buffer->cur().syllable() && - buffer->cur().khmer_category() == OT_Repha) - buffer->next_glyph (); - - buffer->output_info (ginfo); - } - else - buffer->next_glyph (); - } - buffer->swap_buffers (); -} - static void reorder_khmer (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - if (buffer->message (font, "start reordering khmer")) { - insert_dotted_circles_khmer (plan, font, buffer); + if (buffer->message (font, "start reordering khmer")) + { + hb_syllabic_insert_dotted_circles (font, buffer, + khmer_broken_cluster, + OT_DOTTEDCIRCLE, + OT_Repha); foreach_syllable (buffer, start, end) reorder_syllable_khmer (plan, font->face, buffer, start, end); diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh index 11a77bfd4b..e24d68a8b5 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh @@ -54,7 +54,7 @@ set_khmer_properties (hb_glyph_info_t &info) { hb_codepoint_t u = info.codepoint; unsigned int type = hb_indic_get_categories (u); - khmer_category_t cat = (khmer_category_t) (type & 0x7Fu); + khmer_category_t cat = (khmer_category_t) (type & 0xFFu); indic_position_t pos = (indic_position_t) (type >> 8); diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-machine-index.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-machine-index.hh deleted file mode 100644 index 9ec1f3eb7c..0000000000 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-machine-index.hh +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright © 2019,2020 David Corbett - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - */ - -#ifndef HB_OT_SHAPE_COMPLEX_MACHINE_INDEX_HH -#define HB_OT_SHAPE_COMPLEX_MACHINE_INDEX_HH - -#include "hb.hh" - - -template <typename Iter> -struct machine_index_t : - hb_iter_with_fallback_t<machine_index_t<Iter>, - typename Iter::item_t> -{ - machine_index_t (const Iter& it) : it (it) {} - machine_index_t (const machine_index_t& o) : it (o.it) {} - - static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator; - static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator; - - typename Iter::item_t __item__ () const { return *it; } - typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; } - unsigned __len__ () const { return it.len (); } - void __next__ () { ++it; } - void __forward__ (unsigned n) { it += n; } - void __prev__ () { --it; } - void __rewind__ (unsigned n) { it -= n; } - void operator = (unsigned n) - { unsigned index = (*it).first; if (index < n) it += n - index; else if (index > n) it -= index - n; } - void operator = (const machine_index_t& o) { *this = (*o.it).first; } - bool operator == (const machine_index_t& o) const { return (*it).first == (*o.it).first; } - bool operator != (const machine_index_t& o) const { return !(*this == o); } - - private: - Iter it; -}; -struct -{ - template <typename Iter, - hb_requires (hb_is_iterable (Iter))> - machine_index_t<hb_iter_type<Iter>> - operator () (Iter&& it) const - { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); } -} -HB_FUNCOBJ (machine_index); - - -#endif /* HB_OT_SHAPE_COMPLEX_MACHINE_INDEX_HH */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh index c2f4c0045c..c09497896d 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh @@ -31,8 +31,43 @@ #include "hb.hh" +enum myanmar_syllable_type_t { + myanmar_consonant_syllable, + myanmar_punctuation_cluster, + myanmar_broken_cluster, + myanmar_non_myanmar_cluster, +}; + -#line 36 "hb-ot-shape-complex-myanmar-machine.hh" +#line 43 "hb-ot-shape-complex-myanmar-machine.hh" +#define myanmar_syllable_machine_ex_A 10u +#define myanmar_syllable_machine_ex_As 18u +#define myanmar_syllable_machine_ex_C 1u +#define myanmar_syllable_machine_ex_CS 19u +#define myanmar_syllable_machine_ex_D 32u +#define myanmar_syllable_machine_ex_D0 20u +#define myanmar_syllable_machine_ex_DB 3u +#define myanmar_syllable_machine_ex_GB 11u +#define myanmar_syllable_machine_ex_H 4u +#define myanmar_syllable_machine_ex_IV 2u +#define myanmar_syllable_machine_ex_MH 21u +#define myanmar_syllable_machine_ex_MR 22u +#define myanmar_syllable_machine_ex_MW 23u +#define myanmar_syllable_machine_ex_MY 24u +#define myanmar_syllable_machine_ex_P 31u +#define myanmar_syllable_machine_ex_PT 25u +#define myanmar_syllable_machine_ex_Ra 16u +#define myanmar_syllable_machine_ex_V 8u +#define myanmar_syllable_machine_ex_VAbv 26u +#define myanmar_syllable_machine_ex_VBlw 27u +#define myanmar_syllable_machine_ex_VPre 28u +#define myanmar_syllable_machine_ex_VPst 29u +#define myanmar_syllable_machine_ex_VS 30u +#define myanmar_syllable_machine_ex_ZWJ 6u +#define myanmar_syllable_machine_ex_ZWNJ 5u + + +#line 71 "hb-ot-shape-complex-myanmar-machine.hh" static const unsigned char _myanmar_syllable_machine_trans_keys[] = { 1u, 32u, 3u, 30u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 29u, 1u, 16u, 3u, 29u, 3u, 29u, 3u, 29u, @@ -293,18 +328,18 @@ static const int myanmar_syllable_machine_error = -1; static const int myanmar_syllable_machine_en_main = 0; -#line 36 "hb-ot-shape-complex-myanmar-machine.rl" +#line 44 "hb-ot-shape-complex-myanmar-machine.rl" -#line 94 "hb-ot-shape-complex-myanmar-machine.rl" +#line 101 "hb-ot-shape-complex-myanmar-machine.rl" #define found_syllable(syllable_type) \ HB_STMT_START { \ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \ for (unsigned int i = ts; i < te; i++) \ - info[i].syllable() = (syllable_serial << 4) | myanmar_##syllable_type; \ + info[i].syllable() = (syllable_serial << 4) | syllable_type; \ syllable_serial++; \ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ } HB_STMT_END @@ -316,7 +351,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) int cs; hb_glyph_info_t *info = buffer->info; -#line 320 "hb-ot-shape-complex-myanmar-machine.hh" +#line 355 "hb-ot-shape-complex-myanmar-machine.hh" { cs = myanmar_syllable_machine_start; ts = 0; @@ -324,7 +359,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) act = 0; } -#line 114 "hb-ot-shape-complex-myanmar-machine.rl" +#line 121 "hb-ot-shape-complex-myanmar-machine.rl" p = 0; @@ -332,7 +367,7 @@ find_syllables_myanmar (hb_buffer_t *buffer) unsigned int syllable_serial = 1; -#line 336 "hb-ot-shape-complex-myanmar-machine.hh" +#line 371 "hb-ot-shape-complex-myanmar-machine.hh" { int _slen; int _trans; @@ -346,7 +381,7 @@ _resume: #line 1 "NONE" {ts = p;} break; -#line 350 "hb-ot-shape-complex-myanmar-machine.hh" +#line 385 "hb-ot-shape-complex-myanmar-machine.hh" } _keys = _myanmar_syllable_machine_trans_keys + (cs<<1); @@ -365,38 +400,38 @@ _eof_trans: switch ( _myanmar_syllable_machine_trans_actions[_trans] ) { case 6: -#line 86 "hb-ot-shape-complex-myanmar-machine.rl" - {te = p+1;{ found_syllable (consonant_syllable); }} +#line 93 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (myanmar_consonant_syllable); }} break; case 4: -#line 87 "hb-ot-shape-complex-myanmar-machine.rl" - {te = p+1;{ found_syllable (non_myanmar_cluster); }} +#line 94 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }} break; case 10: -#line 88 "hb-ot-shape-complex-myanmar-machine.rl" - {te = p+1;{ found_syllable (punctuation_cluster); }} +#line 95 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (myanmar_punctuation_cluster); }} break; case 8: -#line 89 "hb-ot-shape-complex-myanmar-machine.rl" - {te = p+1;{ found_syllable (broken_cluster); }} +#line 96 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (myanmar_broken_cluster); }} break; case 3: -#line 90 "hb-ot-shape-complex-myanmar-machine.rl" - {te = p+1;{ found_syllable (non_myanmar_cluster); }} +#line 97 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }} break; case 5: -#line 86 "hb-ot-shape-complex-myanmar-machine.rl" - {te = p;p--;{ found_syllable (consonant_syllable); }} +#line 93 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }} break; case 7: -#line 89 "hb-ot-shape-complex-myanmar-machine.rl" - {te = p;p--;{ found_syllable (broken_cluster); }} +#line 96 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p;p--;{ found_syllable (myanmar_broken_cluster); }} break; case 9: -#line 90 "hb-ot-shape-complex-myanmar-machine.rl" - {te = p;p--;{ found_syllable (non_myanmar_cluster); }} +#line 97 "hb-ot-shape-complex-myanmar-machine.rl" + {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }} break; -#line 400 "hb-ot-shape-complex-myanmar-machine.hh" +#line 435 "hb-ot-shape-complex-myanmar-machine.hh" } _again: @@ -405,7 +440,7 @@ _again: #line 1 "NONE" {ts = 0;} break; -#line 409 "hb-ot-shape-complex-myanmar-machine.hh" +#line 444 "hb-ot-shape-complex-myanmar-machine.hh" } if ( ++p != pe ) @@ -421,7 +456,7 @@ _again: } -#line 122 "hb-ot-shape-complex-myanmar-machine.rl" +#line 129 "hb-ot-shape-complex-myanmar-machine.rl" } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc index fe096ef28a..bc5dcb904c 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc @@ -29,6 +29,7 @@ #ifndef HB_NO_OT_SHAPE #include "hb-ot-shape-complex-myanmar.hh" +#include "hb-ot-shape-complex-myanmar-machine.hh" /* @@ -97,17 +98,6 @@ collect_features_myanmar (hb_ot_shape_planner_t *plan) map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ); } - -enum myanmar_syllable_type_t { - myanmar_consonant_syllable, - myanmar_punctuation_cluster, - myanmar_broken_cluster, - myanmar_non_myanmar_cluster, -}; - -#include "hb-ot-shape-complex-myanmar-machine.hh" - - static void setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, hb_buffer_t *buffer, @@ -265,70 +255,16 @@ reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, } } -static inline void -insert_dotted_circles_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font, - hb_buffer_t *buffer) -{ - if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)) - return; - - /* Note: This loop is extra overhead, but should not be measurable. - * TODO Use a buffer scratch flag to remove the loop. */ - bool has_broken_syllables = false; - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - for (unsigned int i = 0; i < count; i++) - if ((info[i].syllable() & 0x0F) == myanmar_broken_cluster) - { - has_broken_syllables = true; - break; - } - if (likely (!has_broken_syllables)) - return; - - - hb_codepoint_t dottedcircle_glyph; - if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph)) - return; - - hb_glyph_info_t dottedcircle = {0}; - dottedcircle.codepoint = 0x25CCu; - set_myanmar_properties (dottedcircle); - dottedcircle.codepoint = dottedcircle_glyph; - - buffer->clear_output (); - - buffer->idx = 0; - unsigned int last_syllable = 0; - while (buffer->idx < buffer->len && buffer->successful) - { - unsigned int syllable = buffer->cur().syllable(); - myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (syllable & 0x0F); - if (unlikely (last_syllable != syllable && syllable_type == myanmar_broken_cluster)) - { - last_syllable = syllable; - - hb_glyph_info_t ginfo = dottedcircle; - ginfo.cluster = buffer->cur().cluster; - ginfo.mask = buffer->cur().mask; - ginfo.syllable() = buffer->cur().syllable(); - - buffer->output_info (ginfo); - } - else - buffer->next_glyph (); - } - buffer->swap_buffers (); -} - static void reorder_myanmar (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - if (buffer->message (font, "start reordering myanmar")) { - insert_dotted_circles_myanmar (plan, font, buffer); + if (buffer->message (font, "start reordering myanmar")) + { + hb_syllabic_insert_dotted_circles (font, buffer, + myanmar_broken_cluster, + OT_GB); foreach_syllable (buffer, start, end) reorder_syllable_myanmar (plan, font->face, buffer, start, end); diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh index 7b9821e6ba..a6d68aae57 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh @@ -64,7 +64,7 @@ set_myanmar_properties (hb_glyph_info_t &info) { hb_codepoint_t u = info.codepoint; unsigned int type = hb_indic_get_categories (u); - unsigned int cat = type & 0x7Fu; + unsigned int cat = type & 0xFFu; indic_position_t pos = (indic_position_t) (type >> 8); /* Myanmar diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc new file mode 100644 index 0000000000..46509abee2 --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc @@ -0,0 +1,100 @@ +/* + * Copyright © 2021 Behdad Esfahbod. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "hb.hh" + +#ifndef HB_NO_OT_SHAPE + +#include "hb-ot-shape-complex-syllabic.hh" + + +void +hb_syllabic_insert_dotted_circles (hb_font_t *font, + hb_buffer_t *buffer, + unsigned int broken_syllable_type, + unsigned int dottedcircle_category, + int repha_category) +{ + if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)) + return; + + /* Note: This loop is extra overhead, but should not be measurable. + * TODO Use a buffer scratch flag to remove the loop. */ + bool has_broken_syllables = false; + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + for (unsigned int i = 0; i < count; i++) + if ((info[i].syllable() & 0x0F) == broken_syllable_type) + { + has_broken_syllables = true; + break; + } + if (likely (!has_broken_syllables)) + return; + + + hb_codepoint_t dottedcircle_glyph; + if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph)) + return; + + hb_glyph_info_t dottedcircle = {0}; + dottedcircle.codepoint = 0x25CCu; + dottedcircle.complex_var_u8_category() = dottedcircle_category; + dottedcircle.codepoint = dottedcircle_glyph; + + buffer->clear_output (); + + buffer->idx = 0; + unsigned int last_syllable = 0; + while (buffer->idx < buffer->len && buffer->successful) + { + unsigned int syllable = buffer->cur().syllable(); + if (unlikely (last_syllable != syllable && (syllable & 0x0F) == broken_syllable_type)) + { + last_syllable = syllable; + + hb_glyph_info_t ginfo = dottedcircle; + ginfo.cluster = buffer->cur().cluster; + ginfo.mask = buffer->cur().mask; + ginfo.syllable() = buffer->cur().syllable(); + + /* Insert dottedcircle after possible Repha. */ + if (repha_category != -1) + { + while (buffer->idx < buffer->len && buffer->successful && + last_syllable == buffer->cur().syllable() && + buffer->cur().complex_var_u8_category() == (unsigned) repha_category) + (void) buffer->next_glyph (); + } + + (void) buffer->output_info (ginfo); + } + else + (void) buffer->next_glyph (); + } + buffer->swap_buffers (); +} + + +#endif diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh new file mode 100644 index 0000000000..c80b8fee1d --- /dev/null +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh @@ -0,0 +1,41 @@ +/* + * Copyright © 2021 Behdad Esfahbod. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#ifndef HB_OT_SHAPE_COMPLEX_SYLLABIC_HH +#define HB_OT_SHAPE_COMPLEX_SYLLABIC_HH + +#include "hb.hh" + +#include "hb-ot-shape-complex.hh" + + +HB_INTERNAL void +hb_syllabic_insert_dotted_circles (hb_font_t *font, + hb_buffer_t *buffer, + unsigned int broken_syllable_type, + unsigned int dottedcircle_category, + int repha_category = -1); + + +#endif /* HB_OT_SHAPE_COMPLEX_SYLLABIC_HH */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc index 347ea2e7ac..4c3068173b 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc @@ -323,20 +323,19 @@ preprocess_text_thai (const hb_ot_shape_plan_t *plan, buffer->clear_output (); unsigned int count = buffer->len; - for (buffer->idx = 0; buffer->idx < count && buffer->successful;) + for (buffer->idx = 0; buffer->idx < count /* No need for: && buffer->successful */;) { hb_codepoint_t u = buffer->cur().codepoint; - if (likely (!IS_SARA_AM (u))) { - buffer->next_glyph (); + if (likely (!IS_SARA_AM (u))) + { + if (unlikely (!buffer->next_glyph ())) break; continue; } /* Is SARA AM. Decompose and reorder. */ - hb_glyph_info_t &nikhahit = buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u)); - _hb_glyph_info_set_continuation (&nikhahit); - buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u)); - if (unlikely (!buffer->successful)) - return; + (void) buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u)); + _hb_glyph_info_set_continuation (&buffer->prev()); + if (unlikely (!buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u)))) break; /* Make Nikhahit be recognized as a ccc=0 mark when zeroing widths. */ unsigned int end = buffer->out_len; diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh index 144e7d3a40..b4b2b75100 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh @@ -1,300 +1,348 @@ - #line 1 "hb-ot-shape-complex-use-machine.rl" /* - * Copyright © 2015 Mozilla Foundation. - * Copyright © 2015 Google, Inc. - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Mozilla Author(s): Jonathan Kew - * Google Author(s): Behdad Esfahbod - */ +* Copyright © 2015 Mozilla Foundation. +* Copyright © 2015 Google, Inc. +* +* This is part of HarfBuzz, a text shaping library. +* +* Permission is hereby granted, without written agreement and without +* license or royalty fees, to use, copy, modify, and distribute this +* software and its documentation for any purpose, provided that the +* above copyright notice and the following two paragraphs appear in +* all copies of this software. +* +* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR +* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN +* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +* DAMAGE. +* +* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, +* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO +* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +* +* Mozilla Author(s): Jonathan Kew +* Google Author(s): Behdad Esfahbod +*/ #ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH #define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH #include "hb.hh" -#include "hb-ot-shape-complex-machine-index.hh" +#include "hb-ot-shape-complex-syllabic.hh" + +/* buffer var allocations */ +#define use_category() complex_var_u8_category() + +#define USE(Cat) use_syllable_machine_ex_##Cat + +enum use_syllable_type_t { + use_independent_cluster, + use_virama_terminated_cluster, + use_sakot_terminated_cluster, + use_standard_cluster, + use_number_joiner_terminated_cluster, + use_numeral_cluster, + use_symbol_cluster, + use_hieroglyph_cluster, + use_broken_cluster, + use_non_cluster, +}; -#line 39 "hb-ot-shape-complex-use-machine.hh" + +#line 57 "hb-ot-shape-complex-use-machine.hh" +#define use_syllable_machine_ex_B 1u +#define use_syllable_machine_ex_CMAbv 31u +#define use_syllable_machine_ex_CMBlw 32u +#define use_syllable_machine_ex_CS 43u +#define use_syllable_machine_ex_FAbv 24u +#define use_syllable_machine_ex_FBlw 25u +#define use_syllable_machine_ex_FMAbv 45u +#define use_syllable_machine_ex_FMBlw 46u +#define use_syllable_machine_ex_FMPst 47u +#define use_syllable_machine_ex_FPst 26u +#define use_syllable_machine_ex_G 49u +#define use_syllable_machine_ex_GB 5u +#define use_syllable_machine_ex_H 12u +#define use_syllable_machine_ex_HN 13u +#define use_syllable_machine_ex_HVM 44u +#define use_syllable_machine_ex_J 50u +#define use_syllable_machine_ex_MAbv 27u +#define use_syllable_machine_ex_MBlw 28u +#define use_syllable_machine_ex_MPre 30u +#define use_syllable_machine_ex_MPst 29u +#define use_syllable_machine_ex_N 4u +#define use_syllable_machine_ex_O 0u +#define use_syllable_machine_ex_R 18u +#define use_syllable_machine_ex_S 19u +#define use_syllable_machine_ex_SB 51u +#define use_syllable_machine_ex_SE 52u +#define use_syllable_machine_ex_SMAbv 41u +#define use_syllable_machine_ex_SMBlw 42u +#define use_syllable_machine_ex_SUB 11u +#define use_syllable_machine_ex_Sk 48u +#define use_syllable_machine_ex_VAbv 33u +#define use_syllable_machine_ex_VBlw 34u +#define use_syllable_machine_ex_VMAbv 37u +#define use_syllable_machine_ex_VMBlw 38u +#define use_syllable_machine_ex_VMPre 23u +#define use_syllable_machine_ex_VMPst 39u +#define use_syllable_machine_ex_VPre 22u +#define use_syllable_machine_ex_VPst 35u +#define use_syllable_machine_ex_ZWNJ 14u + + +#line 99 "hb-ot-shape-complex-use-machine.hh" static const unsigned char _use_syllable_machine_trans_keys[] = { - 1u, 1u, 1u, 1u, 0u, 51u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 23u, 48u, - 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, - 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u, - 11u, 48u, 1u, 48u, 13u, 13u, 4u, 4u, 11u, 48u, 41u, 42u, 42u, 42u, 11u, 48u, - 22u, 48u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, - 24u, 48u, 24u, 48u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, - 22u, 48u, 11u, 48u, 1u, 48u, 1u, 1u, 4u, 4u, 13u, 13u, 1u, 48u, 11u, 48u, - 41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u, 0 + 1u, 1u, 1u, 1u, 0u, 37u, 5u, 34u, + 5u, 34u, 1u, 1u, 10u, 34u, 11u, 34u, + 12u, 33u, 13u, 33u, 14u, 33u, 31u, 32u, + 32u, 32u, 12u, 34u, 12u, 34u, 12u, 34u, + 1u, 1u, 12u, 34u, 11u, 34u, 11u, 34u, + 11u, 34u, 10u, 34u, 10u, 34u, 10u, 34u, + 5u, 34u, 1u, 34u, 7u, 7u, 3u, 3u, + 5u, 34u, 27u, 28u, 28u, 28u, 5u, 34u, + 10u, 34u, 11u, 34u, 12u, 33u, 13u, 33u, + 14u, 33u, 31u, 32u, 32u, 32u, 12u, 34u, + 12u, 34u, 12u, 34u, 12u, 34u, 11u, 34u, + 11u, 34u, 11u, 34u, 10u, 34u, 10u, 34u, + 10u, 34u, 5u, 34u, 1u, 34u, 1u, 1u, + 3u, 3u, 7u, 7u, 1u, 34u, 5u, 34u, + 27u, 28u, 28u, 28u, 1u, 4u, 36u, 38u, + 35u, 38u, 35u, 37u, 0u }; -static const char _use_syllable_machine_key_spans[] = { - 1, 1, 52, 38, 38, 1, 27, 26, - 24, 23, 22, 2, 1, 25, 25, 25, - 1, 25, 26, 26, 26, 27, 27, 27, - 38, 48, 1, 1, 38, 2, 1, 38, - 27, 26, 24, 23, 22, 2, 1, 25, - 25, 25, 25, 26, 26, 26, 27, 27, - 27, 38, 48, 1, 1, 1, 48, 38, - 2, 1, 5, 3, 4, 3 +static const signed char _use_syllable_machine_char_class[] = { + 0, 1, 2, 2, 3, 4, 2, 2, + 2, 2, 2, 5, 6, 7, 2, 2, + 2, 2, 8, 9, 2, 2, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 2, 24, 25, 26, + 2, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 0 }; static const short _use_syllable_machine_index_offsets[] = { - 0, 2, 4, 57, 96, 135, 137, 165, - 192, 217, 241, 264, 267, 269, 295, 321, - 347, 349, 375, 402, 429, 456, 484, 512, - 540, 579, 628, 630, 632, 671, 674, 676, - 715, 743, 770, 795, 819, 842, 845, 847, - 873, 899, 925, 951, 978, 1005, 1032, 1060, - 1088, 1116, 1155, 1204, 1206, 1208, 1210, 1259, - 1298, 1301, 1303, 1309, 1313, 1318 + 0, 1, 2, 40, 70, 100, 101, 126, + 150, 172, 193, 213, 215, 216, 239, 262, + 285, 286, 309, 333, 357, 381, 406, 431, + 456, 486, 520, 521, 522, 552, 554, 555, + 585, 610, 634, 656, 677, 697, 699, 700, + 723, 746, 769, 792, 816, 840, 864, 889, + 914, 939, 969, 1003, 1004, 1005, 1006, 1040, + 1070, 1072, 1073, 1077, 1080, 1084, 0 +}; + +static const signed char _use_syllable_machine_indicies[] = { + 1, 2, 4, 5, 6, 7, 8, 1, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 13, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 9, 36, 6, 37, + 39, 40, 38, 38, 38, 41, 42, 43, + 44, 45, 46, 47, 41, 48, 5, 49, + 50, 51, 52, 53, 54, 55, 38, 38, + 38, 56, 57, 58, 59, 40, 39, 40, + 38, 38, 38, 41, 42, 43, 44, 45, + 46, 47, 41, 48, 49, 49, 50, 51, + 52, 53, 54, 55, 38, 38, 38, 56, + 57, 58, 59, 40, 39, 41, 42, 43, + 44, 45, 38, 38, 38, 38, 38, 38, + 50, 51, 52, 53, 54, 55, 38, 38, + 38, 42, 57, 58, 59, 61, 42, 43, + 44, 45, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 53, 54, 55, 38, 38, + 38, 38, 57, 58, 59, 61, 43, 44, + 45, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 57, 58, 59, 44, 45, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 57, 58, + 59, 45, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 57, 58, 59, 57, 58, 58, + 43, 44, 45, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 53, 54, 55, 38, + 38, 38, 38, 57, 58, 59, 61, 43, + 44, 45, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 54, 55, 38, 38, + 38, 38, 57, 58, 59, 61, 43, 44, + 45, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 55, 38, 38, 38, + 38, 57, 58, 59, 61, 63, 43, 44, + 45, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + 38, 57, 58, 59, 61, 42, 43, 44, + 45, 38, 38, 38, 38, 38, 38, 50, + 51, 52, 53, 54, 55, 38, 38, 38, + 42, 57, 58, 59, 61, 42, 43, 44, + 45, 38, 38, 38, 38, 38, 38, 38, + 51, 52, 53, 54, 55, 38, 38, 38, + 42, 57, 58, 59, 61, 42, 43, 44, + 45, 38, 38, 38, 38, 38, 38, 38, + 38, 52, 53, 54, 55, 38, 38, 38, + 42, 57, 58, 59, 61, 41, 42, 43, + 44, 45, 38, 47, 41, 38, 38, 38, + 50, 51, 52, 53, 54, 55, 38, 38, + 38, 42, 57, 58, 59, 61, 41, 42, + 43, 44, 45, 38, 38, 41, 38, 38, + 38, 50, 51, 52, 53, 54, 55, 38, + 38, 38, 42, 57, 58, 59, 61, 41, + 42, 43, 44, 45, 46, 47, 41, 38, + 38, 38, 50, 51, 52, 53, 54, 55, + 38, 38, 38, 42, 57, 58, 59, 61, + 39, 40, 38, 38, 38, 41, 42, 43, + 44, 45, 46, 47, 41, 48, 38, 49, + 50, 51, 52, 53, 54, 55, 38, 38, + 38, 56, 57, 58, 59, 40, 39, 60, + 60, 60, 60, 60, 60, 60, 60, 60, + 42, 43, 44, 45, 60, 60, 60, 60, + 60, 60, 60, 60, 60, 53, 54, 55, + 60, 60, 60, 60, 57, 58, 59, 61, + 65, 7, 39, 40, 38, 38, 38, 41, + 42, 43, 44, 45, 46, 47, 41, 48, + 5, 49, 50, 51, 52, 53, 54, 55, + 12, 67, 38, 56, 57, 58, 59, 40, + 12, 67, 67, 1, 70, 69, 69, 69, + 13, 14, 15, 16, 17, 18, 19, 13, + 20, 22, 22, 23, 24, 25, 26, 27, + 28, 69, 69, 69, 32, 33, 34, 35, + 70, 13, 14, 15, 16, 17, 69, 69, + 69, 69, 69, 69, 23, 24, 25, 26, + 27, 28, 69, 69, 69, 14, 33, 34, + 35, 71, 14, 15, 16, 17, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 26, + 27, 28, 69, 69, 69, 69, 33, 34, + 35, 71, 15, 16, 17, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 33, 34, 35, + 16, 17, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 33, 34, 35, 17, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 33, 34, + 35, 33, 34, 34, 15, 16, 17, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 26, 27, 28, 69, 69, 69, 69, 33, + 34, 35, 71, 15, 16, 17, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 27, 28, 69, 69, 69, 69, 33, 34, + 35, 71, 15, 16, 17, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 28, 69, 69, 69, 69, 33, 34, 35, + 71, 15, 16, 17, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 33, 34, 35, 71, + 14, 15, 16, 17, 69, 69, 69, 69, + 69, 69, 23, 24, 25, 26, 27, 28, + 69, 69, 69, 14, 33, 34, 35, 71, + 14, 15, 16, 17, 69, 69, 69, 69, + 69, 69, 69, 24, 25, 26, 27, 28, + 69, 69, 69, 14, 33, 34, 35, 71, + 14, 15, 16, 17, 69, 69, 69, 69, + 69, 69, 69, 69, 25, 26, 27, 28, + 69, 69, 69, 14, 33, 34, 35, 71, + 13, 14, 15, 16, 17, 69, 19, 13, + 69, 69, 69, 23, 24, 25, 26, 27, + 28, 69, 69, 69, 14, 33, 34, 35, + 71, 13, 14, 15, 16, 17, 69, 69, + 13, 69, 69, 69, 23, 24, 25, 26, + 27, 28, 69, 69, 69, 14, 33, 34, + 35, 71, 13, 14, 15, 16, 17, 18, + 19, 13, 69, 69, 69, 23, 24, 25, + 26, 27, 28, 69, 69, 69, 14, 33, + 34, 35, 71, 1, 70, 69, 69, 69, + 13, 14, 15, 16, 17, 18, 19, 13, + 20, 69, 22, 23, 24, 25, 26, 27, + 28, 69, 69, 69, 32, 33, 34, 35, + 70, 1, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 14, 15, 16, 17, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 26, 27, 28, 69, 69, 69, 69, 33, + 34, 35, 71, 1, 73, 10, 5, 69, + 69, 5, 1, 70, 10, 69, 69, 13, + 14, 15, 16, 17, 18, 19, 13, 20, + 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 69, 32, 33, 34, 35, 70, + 1, 70, 69, 69, 69, 13, 14, 15, + 16, 17, 18, 19, 13, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 69, 69, + 69, 32, 33, 34, 35, 70, 29, 30, + 30, 5, 72, 72, 5, 75, 74, 36, + 36, 75, 74, 75, 36, 74, 37, 0 }; -static const char _use_syllable_machine_indicies[] = { - 1, 0, 2, 0, 3, 4, 5, 5, - 6, 7, 5, 5, 5, 5, 5, 1, - 8, 9, 5, 5, 5, 5, 10, 11, - 5, 5, 12, 13, 14, 15, 16, 17, - 18, 12, 19, 20, 21, 22, 23, 24, - 5, 25, 26, 27, 5, 28, 29, 30, - 31, 32, 33, 34, 8, 35, 5, 36, - 5, 38, 39, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 40, 41, 42, 43, - 44, 45, 46, 40, 47, 4, 48, 49, - 50, 51, 37, 52, 53, 54, 37, 37, - 37, 37, 55, 56, 57, 58, 39, 37, - 38, 39, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 40, 41, 42, 43, 44, - 45, 46, 40, 47, 48, 48, 49, 50, - 51, 37, 52, 53, 54, 37, 37, 37, - 37, 55, 56, 57, 58, 39, 37, 38, - 59, 40, 41, 42, 43, 44, 37, 37, - 37, 37, 37, 37, 49, 50, 51, 37, - 52, 53, 54, 37, 37, 37, 37, 41, - 56, 57, 58, 60, 37, 41, 42, 43, - 44, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 52, 53, 54, 37, 37, - 37, 37, 37, 56, 57, 58, 60, 37, - 42, 43, 44, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 56, 57, 58, - 37, 43, 44, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 56, 57, 58, - 37, 44, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 56, 57, 58, 37, - 56, 57, 37, 57, 37, 42, 43, 44, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 52, 53, 54, 37, 37, 37, - 37, 37, 56, 57, 58, 60, 37, 42, - 43, 44, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 53, 54, 37, - 37, 37, 37, 37, 56, 57, 58, 60, - 37, 42, 43, 44, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 54, 37, 37, 37, 37, 37, 56, 57, - 58, 60, 37, 62, 61, 42, 43, 44, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 56, 57, 58, 60, 37, 41, - 42, 43, 44, 37, 37, 37, 37, 37, - 37, 49, 50, 51, 37, 52, 53, 54, - 37, 37, 37, 37, 41, 56, 57, 58, - 60, 37, 41, 42, 43, 44, 37, 37, - 37, 37, 37, 37, 37, 50, 51, 37, - 52, 53, 54, 37, 37, 37, 37, 41, - 56, 57, 58, 60, 37, 41, 42, 43, - 44, 37, 37, 37, 37, 37, 37, 37, - 37, 51, 37, 52, 53, 54, 37, 37, - 37, 37, 41, 56, 57, 58, 60, 37, - 40, 41, 42, 43, 44, 37, 46, 40, - 37, 37, 37, 49, 50, 51, 37, 52, - 53, 54, 37, 37, 37, 37, 41, 56, - 57, 58, 60, 37, 40, 41, 42, 43, - 44, 37, 37, 40, 37, 37, 37, 49, - 50, 51, 37, 52, 53, 54, 37, 37, - 37, 37, 41, 56, 57, 58, 60, 37, - 40, 41, 42, 43, 44, 45, 46, 40, - 37, 37, 37, 49, 50, 51, 37, 52, - 53, 54, 37, 37, 37, 37, 41, 56, - 57, 58, 60, 37, 38, 39, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 40, - 41, 42, 43, 44, 45, 46, 40, 47, - 37, 48, 49, 50, 51, 37, 52, 53, - 54, 37, 37, 37, 37, 55, 56, 57, - 58, 39, 37, 38, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, - 59, 41, 42, 43, 44, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 52, - 53, 54, 59, 59, 59, 59, 59, 56, - 57, 58, 60, 59, 64, 63, 6, 65, - 38, 39, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 40, 41, 42, 43, 44, - 45, 46, 40, 47, 4, 48, 49, 50, - 51, 37, 52, 53, 54, 37, 11, 66, - 37, 55, 56, 57, 58, 39, 37, 11, - 66, 67, 66, 67, 1, 69, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 12, - 13, 14, 15, 16, 17, 18, 12, 19, - 21, 21, 22, 23, 24, 68, 25, 26, - 27, 68, 68, 68, 68, 31, 32, 33, - 34, 69, 68, 12, 13, 14, 15, 16, - 68, 68, 68, 68, 68, 68, 22, 23, - 24, 68, 25, 26, 27, 68, 68, 68, - 68, 13, 32, 33, 34, 70, 68, 13, - 14, 15, 16, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 25, 26, 27, - 68, 68, 68, 68, 68, 32, 33, 34, - 70, 68, 14, 15, 16, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 32, - 33, 34, 68, 15, 16, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 32, - 33, 34, 68, 16, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 32, 33, - 34, 68, 32, 33, 68, 33, 68, 14, - 15, 16, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 25, 26, 27, 68, - 68, 68, 68, 68, 32, 33, 34, 70, - 68, 14, 15, 16, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 26, - 27, 68, 68, 68, 68, 68, 32, 33, - 34, 70, 68, 14, 15, 16, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 27, 68, 68, 68, 68, 68, - 32, 33, 34, 70, 68, 14, 15, 16, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 32, 33, 34, 70, 68, 13, - 14, 15, 16, 68, 68, 68, 68, 68, - 68, 22, 23, 24, 68, 25, 26, 27, - 68, 68, 68, 68, 13, 32, 33, 34, - 70, 68, 13, 14, 15, 16, 68, 68, - 68, 68, 68, 68, 68, 23, 24, 68, - 25, 26, 27, 68, 68, 68, 68, 13, - 32, 33, 34, 70, 68, 13, 14, 15, - 16, 68, 68, 68, 68, 68, 68, 68, - 68, 24, 68, 25, 26, 27, 68, 68, - 68, 68, 13, 32, 33, 34, 70, 68, - 12, 13, 14, 15, 16, 68, 18, 12, - 68, 68, 68, 22, 23, 24, 68, 25, - 26, 27, 68, 68, 68, 68, 13, 32, - 33, 34, 70, 68, 12, 13, 14, 15, - 16, 68, 68, 12, 68, 68, 68, 22, - 23, 24, 68, 25, 26, 27, 68, 68, - 68, 68, 13, 32, 33, 34, 70, 68, - 12, 13, 14, 15, 16, 17, 18, 12, - 68, 68, 68, 22, 23, 24, 68, 25, - 26, 27, 68, 68, 68, 68, 13, 32, - 33, 34, 70, 68, 1, 69, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 12, - 13, 14, 15, 16, 17, 18, 12, 19, - 68, 21, 22, 23, 24, 68, 25, 26, - 27, 68, 68, 68, 68, 31, 32, 33, - 34, 69, 68, 1, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 68, - 68, 13, 14, 15, 16, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 68, 25, - 26, 27, 68, 68, 68, 68, 68, 32, - 33, 34, 70, 68, 1, 71, 72, 68, - 9, 68, 4, 68, 68, 68, 4, 68, - 68, 68, 68, 68, 1, 69, 9, 68, - 68, 68, 68, 68, 68, 68, 68, 12, - 13, 14, 15, 16, 17, 18, 12, 19, - 20, 21, 22, 23, 24, 68, 25, 26, - 27, 68, 28, 29, 68, 31, 32, 33, - 34, 69, 68, 1, 69, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 12, 13, - 14, 15, 16, 17, 18, 12, 19, 20, - 21, 22, 23, 24, 68, 25, 26, 27, - 68, 68, 68, 68, 31, 32, 33, 34, - 69, 68, 28, 29, 68, 29, 68, 4, - 71, 71, 71, 4, 71, 74, 73, 35, - 73, 35, 74, 73, 74, 73, 35, 73, - 36, 73, 0 +static const signed char _use_syllable_machine_index_defaults[] = { + 0, 0, 6, 38, 38, 60, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, + 62, 38, 38, 38, 38, 38, 38, 38, + 38, 60, 64, 66, 38, 68, 68, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 72, 69, 69, 69, 69, + 69, 69, 72, 74, 74, 74, 0 }; -static const char _use_syllable_machine_trans_targs[] = { - 2, 31, 42, 2, 3, 2, 26, 28, - 51, 52, 54, 29, 32, 33, 34, 35, - 36, 46, 47, 48, 55, 49, 43, 44, - 45, 39, 40, 41, 56, 57, 58, 50, - 37, 38, 2, 59, 61, 2, 4, 5, - 6, 7, 8, 9, 10, 21, 22, 23, - 24, 18, 19, 20, 13, 14, 15, 25, - 11, 12, 2, 2, 16, 2, 17, 2, - 27, 2, 30, 2, 2, 0, 1, 2, - 53, 2, 60 +static const signed char _use_syllable_machine_cond_targs[] = { + 2, 31, 42, 2, 2, 3, 2, 26, + 28, 51, 52, 54, 29, 32, 33, 34, + 35, 36, 46, 47, 48, 55, 49, 43, + 44, 45, 39, 40, 41, 56, 57, 58, + 50, 37, 38, 2, 59, 61, 2, 4, + 5, 6, 7, 8, 9, 10, 21, 22, + 23, 24, 18, 19, 20, 13, 14, 15, + 25, 11, 12, 2, 2, 16, 2, 17, + 2, 27, 2, 30, 2, 2, 0, 1, + 2, 53, 2, 60, 0 }; -static const char _use_syllable_machine_trans_actions[] = { - 1, 2, 2, 5, 0, 6, 0, 0, - 0, 0, 2, 0, 2, 2, 0, 0, - 0, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 0, 0, 0, 2, - 0, 0, 7, 0, 0, 8, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 9, 10, 0, 11, 0, 12, - 0, 13, 0, 14, 15, 0, 0, 16, - 0, 17, 0 +static const signed char _use_syllable_machine_cond_actions[] = { + 1, 2, 2, 0, 5, 0, 6, 0, + 0, 0, 0, 2, 0, 2, 2, 0, + 0, 0, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 0, 0, 0, + 2, 0, 0, 7, 0, 0, 8, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 10, 0, 11, 0, + 12, 0, 13, 0, 14, 15, 0, 0, + 16, 0, 17, 0, 0 }; -static const char _use_syllable_machine_to_state_actions[] = { - 0, 0, 3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 +static const signed char _use_syllable_machine_to_state_actions[] = { + 0, 0, 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 }; -static const char _use_syllable_machine_from_state_actions[] = { - 0, 0, 4, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 +static const signed char _use_syllable_machine_from_state_actions[] = { + 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 }; -static const short _use_syllable_machine_eof_trans[] = { - 1, 1, 0, 38, 38, 60, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, - 62, 38, 38, 38, 38, 38, 38, 38, - 38, 60, 64, 66, 38, 68, 68, 69, - 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 72, 69, 69, 69, 69, - 69, 69, 72, 74, 74, 74 +static const signed char _use_syllable_machine_eof_trans[] = { + 1, 1, 4, 39, 39, 61, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, + 63, 39, 39, 39, 39, 39, 39, 39, + 39, 61, 65, 67, 39, 69, 69, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 73, 70, 70, 70, 70, + 70, 70, 73, 75, 75, 75, 0 }; static const int use_syllable_machine_start = 2; @@ -304,185 +352,376 @@ static const int use_syllable_machine_error = -1; static const int use_syllable_machine_en_main = 2; -#line 39 "hb-ot-shape-complex-use-machine.rl" +#line 59 "hb-ot-shape-complex-use-machine.rl" -#line 154 "hb-ot-shape-complex-use-machine.rl" +#line 176 "hb-ot-shape-complex-use-machine.rl" #define found_syllable(syllable_type) \ - HB_STMT_START { \ - if (0) fprintf (stderr, "syllable %d..%d %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \ - for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \ - info[i].syllable() = (syllable_serial << 4) | use_##syllable_type; \ - syllable_serial++; \ - if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ - } HB_STMT_END +HB_STMT_START { \ + if (0) fprintf (stderr, "syllable %d..%d %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \ + for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \ + info[i].syllable() = (syllable_serial << 4) | syllable_type; \ + syllable_serial++; \ + if (unlikely (syllable_serial == 16)) syllable_serial = 1; \ + } HB_STMT_END + + +template <typename Iter> +struct machine_index_t : +hb_iter_with_fallback_t<machine_index_t<Iter>, +typename Iter::item_t> +{ + machine_index_t (const Iter& it) : it (it) {} + machine_index_t (const machine_index_t& o) : it (o.it) {} + + static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator; + static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator; + + typename Iter::item_t __item__ () const { return *it; } + typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; } + unsigned __len__ () const { return it.len (); } + void __next__ () { ++it; } + void __forward__ (unsigned n) { it += n; } + void __prev__ () { --it; } + void __rewind__ (unsigned n) { it -= n; } + void operator = (unsigned n) + { unsigned index = (*it).first; if (index < n) it += n - index; else if (index > n) it -= index - n; } + void operator = (const machine_index_t& o) { *this = (*o.it).first; } + bool operator == (const machine_index_t& o) const { return (*it).first == (*o.it).first; } + bool operator != (const machine_index_t& o) const { return !(*this == o); } + + private: + Iter it; +}; +struct +{ + template <typename Iter, + hb_requires (hb_is_iterable (Iter))> + machine_index_t<hb_iter_type<Iter>> + operator () (Iter&& it) const + { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); } +} +HB_FUNCOBJ (machine_index); + + static bool not_standard_default_ignorable (const hb_glyph_info_t &i) -{ return !(i.use_category() == USE_O && _hb_glyph_info_is_default_ignorable (&i)); } +{ return !(i.use_category() == USE(O) && _hb_glyph_info_is_default_ignorable (&i)); } -static void +static inline void find_syllables_use (hb_buffer_t *buffer) { - hb_glyph_info_t *info = buffer->info; - auto p = - + hb_iter (info, buffer->len) - | hb_enumerate - | hb_filter ([] (const hb_glyph_info_t &i) { return not_standard_default_ignorable (i); }, - hb_second) - | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p) - { - if (p.second.use_category() == USE_ZWNJ) - for (unsigned i = p.first + 1; i < buffer->len; ++i) - if (not_standard_default_ignorable (info[i])) - return !_hb_glyph_info_is_unicode_mark (&info[i]); - return true; - }) - | hb_enumerate - | machine_index - ; - auto pe = p + p.len (); - auto eof = +pe; - auto ts = +p; - auto te = +p; - unsigned int act HB_UNUSED; - int cs; - -#line 355 "hb-ot-shape-complex-use-machine.hh" + hb_glyph_info_t *info = buffer->info; + auto p = + + hb_iter (info, buffer->len) + | hb_enumerate + | hb_filter ([] (const hb_glyph_info_t &i) { return not_standard_default_ignorable (i); }, + hb_second) + | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p) + { + if (p.second.use_category() == USE(ZWNJ)) + for (unsigned i = p.first + 1; i < buffer->len; ++i) + if (not_standard_default_ignorable (info[i])) + return !_hb_glyph_info_is_unicode_mark (&info[i]); + return true; + }) + | hb_enumerate + | machine_index + ; + auto pe = p + p.len (); + auto eof = +pe; + auto ts = +p; + auto te = +p; + unsigned int act HB_UNUSED; + int cs; + +#line 443 "hb-ot-shape-complex-use-machine.hh" { - cs = use_syllable_machine_start; - ts = 0; - te = 0; - act = 0; + cs = (int)use_syllable_machine_start; + ts = 0; + te = 0; } - -#line 198 "hb-ot-shape-complex-use-machine.rl" - - - unsigned int syllable_serial = 1; - -#line 368 "hb-ot-shape-complex-use-machine.hh" + +#line 260 "hb-ot-shape-complex-use-machine.rl" + + + unsigned int syllable_serial = 1; + +#line 455 "hb-ot-shape-complex-use-machine.hh" { - int _slen; - int _trans; - const unsigned char *_keys; - const char *_inds; - if ( p == pe ) - goto _test_eof; -_resume: - switch ( _use_syllable_machine_from_state_actions[cs] ) { - case 4: + unsigned int _trans = 0; + const unsigned char * _keys; + const signed char * _inds; + int _ic; + _resume: {} + if ( p == pe && p != eof ) + goto _out; + switch ( _use_syllable_machine_from_state_actions[cs] ) { + case 4: { + { #line 1 "NONE" - {ts = p;} - break; -#line 382 "hb-ot-shape-complex-use-machine.hh" - } - - _keys = _use_syllable_machine_trans_keys + (cs<<1); - _inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs]; - - _slen = _use_syllable_machine_key_spans[cs]; - _trans = _inds[ _slen > 0 && _keys[0] <=( (*p).second.second.use_category()) && - ( (*p).second.second.use_category()) <= _keys[1] ? - ( (*p).second.second.use_category()) - _keys[0] : _slen ]; - -_eof_trans: - cs = _use_syllable_machine_trans_targs[_trans]; - - if ( _use_syllable_machine_trans_actions[_trans] == 0 ) - goto _again; - - switch ( _use_syllable_machine_trans_actions[_trans] ) { - case 2: + {ts = p;}} + +#line 470 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + } + + if ( p == eof ) { + if ( _use_syllable_machine_eof_trans[cs] > 0 ) { + _trans = (unsigned int)_use_syllable_machine_eof_trans[cs] - 1; + } + } + else { + _keys = ( _use_syllable_machine_trans_keys + ((cs<<1))); + _inds = ( _use_syllable_machine_indicies + (_use_syllable_machine_index_offsets[cs])); + + if ( ((*p).second.second.use_category()) <= 52 ) { + _ic = (int)_use_syllable_machine_char_class[(int)((*p).second.second.use_category()) - 0]; + if ( _ic <= (int)(*( _keys+1)) && _ic >= (int)(*( _keys)) ) + _trans = (unsigned int)(*( _inds + (int)( _ic - (int)(*( _keys)) ) )); + else + _trans = (unsigned int)_use_syllable_machine_index_defaults[cs]; + } + else { + _trans = (unsigned int)_use_syllable_machine_index_defaults[cs]; + } + + } + cs = (int)_use_syllable_machine_cond_targs[_trans]; + + if ( _use_syllable_machine_cond_actions[_trans] != 0 ) { + + switch ( _use_syllable_machine_cond_actions[_trans] ) { + case 2: { + { #line 1 "NONE" - {te = p+1;} - break; - case 5: -#line 141 "hb-ot-shape-complex-use-machine.rl" - {te = p+1;{ found_syllable (independent_cluster); }} - break; - case 9: -#line 144 "hb-ot-shape-complex-use-machine.rl" - {te = p+1;{ found_syllable (standard_cluster); }} - break; - case 7: -#line 149 "hb-ot-shape-complex-use-machine.rl" - {te = p+1;{ found_syllable (broken_cluster); }} - break; - case 6: -#line 150 "hb-ot-shape-complex-use-machine.rl" - {te = p+1;{ found_syllable (non_cluster); }} - break; - case 10: -#line 142 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (virama_terminated_cluster); }} - break; - case 11: -#line 143 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (sakot_terminated_cluster); }} - break; - case 8: -#line 144 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (standard_cluster); }} - break; - case 13: -#line 145 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (number_joiner_terminated_cluster); }} - break; - case 12: -#line 146 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (numeral_cluster); }} - break; - case 14: -#line 147 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (symbol_cluster); }} - break; - case 17: -#line 148 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (hieroglyph_cluster); }} - break; - case 15: -#line 149 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (broken_cluster); }} - break; - case 16: -#line 150 "hb-ot-shape-complex-use-machine.rl" - {te = p;p--;{ found_syllable (non_cluster); }} - break; - case 1: -#line 149 "hb-ot-shape-complex-use-machine.rl" - {{p = ((te))-1;}{ found_syllable (broken_cluster); }} - break; -#line 460 "hb-ot-shape-complex-use-machine.hh" - } - -_again: - switch ( _use_syllable_machine_to_state_actions[cs] ) { - case 3: + {te = p+1;}} + +#line 508 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 5: { + { +#line 163 "hb-ot-shape-complex-use-machine.rl" + {te = p+1;{ +#line 163 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_independent_cluster); } + }} + +#line 521 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 9: { + { +#line 166 "hb-ot-shape-complex-use-machine.rl" + {te = p+1;{ +#line 166 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_standard_cluster); } + }} + +#line 534 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 7: { + { +#line 171 "hb-ot-shape-complex-use-machine.rl" + {te = p+1;{ +#line 171 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_broken_cluster); } + }} + +#line 547 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 6: { + { +#line 172 "hb-ot-shape-complex-use-machine.rl" + {te = p+1;{ +#line 172 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_non_cluster); } + }} + +#line 560 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 10: { + { +#line 164 "hb-ot-shape-complex-use-machine.rl" + {te = p;p = p - 1;{ +#line 164 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_virama_terminated_cluster); } + }} + +#line 573 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 11: { + { +#line 165 "hb-ot-shape-complex-use-machine.rl" + {te = p;p = p - 1;{ +#line 165 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_sakot_terminated_cluster); } + }} + +#line 586 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 8: { + { +#line 166 "hb-ot-shape-complex-use-machine.rl" + {te = p;p = p - 1;{ +#line 166 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_standard_cluster); } + }} + +#line 599 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 13: { + { +#line 167 "hb-ot-shape-complex-use-machine.rl" + {te = p;p = p - 1;{ +#line 167 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_number_joiner_terminated_cluster); } + }} + +#line 612 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 12: { + { +#line 168 "hb-ot-shape-complex-use-machine.rl" + {te = p;p = p - 1;{ +#line 168 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_numeral_cluster); } + }} + +#line 625 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 14: { + { +#line 169 "hb-ot-shape-complex-use-machine.rl" + {te = p;p = p - 1;{ +#line 169 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_symbol_cluster); } + }} + +#line 638 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 17: { + { +#line 170 "hb-ot-shape-complex-use-machine.rl" + {te = p;p = p - 1;{ +#line 170 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_hieroglyph_cluster); } + }} + +#line 651 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 15: { + { +#line 171 "hb-ot-shape-complex-use-machine.rl" + {te = p;p = p - 1;{ +#line 171 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_broken_cluster); } + }} + +#line 664 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 16: { + { +#line 172 "hb-ot-shape-complex-use-machine.rl" + {te = p;p = p - 1;{ +#line 172 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_non_cluster); } + }} + +#line 677 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + case 1: { + { +#line 171 "hb-ot-shape-complex-use-machine.rl" + {p = ((te))-1; + { +#line 171 "hb-ot-shape-complex-use-machine.rl" + found_syllable (use_broken_cluster); } + }} + +#line 691 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + } + + } + + if ( p == eof ) { + if ( cs >= 2 ) + goto _out; + } + else { + switch ( _use_syllable_machine_to_state_actions[cs] ) { + case 3: { + { #line 1 "NONE" - {ts = 0;} - break; -#line 469 "hb-ot-shape-complex-use-machine.hh" + {ts = 0;}} + +#line 711 "hb-ot-shape-complex-use-machine.hh" + + + break; + } + } + + p += 1; + goto _resume; + } + _out: {} } - - if ( ++p != pe ) - goto _resume; - _test_eof: {} - if ( p == eof ) - { - if ( _use_syllable_machine_eof_trans[cs] > 0 ) { - _trans = _use_syllable_machine_eof_trans[cs] - 1; - goto _eof_trans; - } - } - - } - -#line 203 "hb-ot-shape-complex-use-machine.rl" - + +#line 265 "hb-ot-shape-complex-use-machine.rl" + } #undef found_syllable diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh index df3652b18a..a35894ce81 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh @@ -31,56 +31,57 @@ * UnicodeData.txt does not have a header. */ -#include "hb.hh" +#ifndef HB_OT_SHAPE_COMPLEX_USE_TABLE_HH +#define HB_OT_SHAPE_COMPLEX_USE_TABLE_HH -#ifndef HB_NO_OT_SHAPE +#include "hb.hh" -#include "hb-ot-shape-complex-use.hh" +#include "hb-ot-shape-complex-use-machine.hh" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-macros" -#define B USE_B /* BASE */ -#define CS USE_CS /* CONS_WITH_STACKER */ -#define G USE_G /* HIEROGLYPH */ -#define GB USE_GB /* BASE_OTHER */ -#define H USE_H /* HALANT */ -#define HN USE_HN /* HALANT_NUM */ -#define HVM USE_HVM /* HALANT_OR_VOWEL_MODIFIER */ -#define J USE_J /* HIEROGLYPH_JOINER */ -#define N USE_N /* BASE_NUM */ -#define O USE_O /* OTHER */ -#define R USE_R /* REPHA */ -#define S USE_S /* SYM */ -#define SB USE_SB /* HIEROGLYPH_SEGMENT_BEGIN */ -#define SE USE_SE /* HIEROGLYPH_SEGMENT_END */ -#define SUB USE_SUB /* CONS_SUB */ -#define Sk USE_Sk /* SAKOT */ -#define ZWNJ USE_ZWNJ /* ZWNJ */ -#define CMAbv USE_CMAbv -#define CMBlw USE_CMBlw -#define FAbv USE_FAbv -#define FBlw USE_FBlw -#define FPst USE_FPst -#define FMAbv USE_FMAbv -#define FMBlw USE_FMBlw -#define FMPst USE_FMPst -#define MAbv USE_MAbv -#define MBlw USE_MBlw -#define MPst USE_MPst -#define MPre USE_MPre -#define SMAbv USE_SMAbv -#define SMBlw USE_SMBlw -#define VAbv USE_VAbv -#define VBlw USE_VBlw -#define VPst USE_VPst -#define VPre USE_VPre -#define VMAbv USE_VMAbv -#define VMBlw USE_VMBlw -#define VMPst USE_VMPst -#define VMPre USE_VMPre +#define B USE(B) /* BASE */ +#define CS USE(CS) /* CONS_WITH_STACKER */ +#define G USE(G) /* HIEROGLYPH */ +#define GB USE(GB) /* BASE_OTHER */ +#define H USE(H) /* HALANT */ +#define HN USE(HN) /* HALANT_NUM */ +#define HVM USE(HVM) /* HALANT_OR_VOWEL_MODIFIER */ +#define J USE(J) /* HIEROGLYPH_JOINER */ +#define N USE(N) /* BASE_NUM */ +#define O USE(O) /* OTHER */ +#define R USE(R) /* REPHA */ +#define S USE(S) /* SYM */ +#define SB USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */ +#define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */ +#define SUB USE(SUB) /* CONS_SUB */ +#define Sk USE(Sk) /* SAKOT */ +#define ZWNJ USE(ZWNJ) /* ZWNJ */ +#define CMAbv USE(CMAbv) +#define CMBlw USE(CMBlw) +#define FAbv USE(FAbv) +#define FBlw USE(FBlw) +#define FPst USE(FPst) +#define FMAbv USE(FMAbv) +#define FMBlw USE(FMBlw) +#define FMPst USE(FMPst) +#define MAbv USE(MAbv) +#define MBlw USE(MBlw) +#define MPst USE(MPst) +#define MPre USE(MPre) +#define SMAbv USE(SMAbv) +#define SMBlw USE(SMBlw) +#define VAbv USE(VAbv) +#define VBlw USE(VBlw) +#define VPst USE(VPst) +#define VPre USE(VPre) +#define VMAbv USE(VMAbv) +#define VMBlw USE(VMBlw) +#define VMPst USE(VMPst) +#define VMPre USE(VMPre) #pragma GCC diagnostic pop -static const USE_TABLE_ELEMENT_TYPE use_table[] = { +static const uint8_t use_table[] = { #define use_offset_0x0028u 0 @@ -767,7 +768,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11710 */ B, B, B, B, B, B, B, B, B, B, B, O, O, MBlw, MPre, MAbv, - /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VMAbv, O, O, O, O, + /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O, /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, #define use_offset_0x11800u 5848 @@ -1066,7 +1067,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { }; /* Table items: 8824; occupancy: 79% */ -USE_TABLE_ELEMENT_TYPE +static inline uint8_t hb_use_get_category (hb_codepoint_t u) { switch (u >> 12) @@ -1154,7 +1155,7 @@ hb_use_get_category (hb_codepoint_t u) default: break; } - return USE_O; + return USE(O); } #undef B @@ -1198,5 +1199,5 @@ hb_use_get_category (hb_codepoint_t u) #undef VMPre -#endif +#endif /* HB_OT_SHAPE_COMPLEX_USE_TABLE_HH */ /* == End of generated table == */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc index 8ac569d8bf..0d0b7e771e 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc @@ -30,14 +30,12 @@ #ifndef HB_NO_OT_SHAPE -#include "hb-ot-shape-complex-use.hh" +#include "hb-ot-shape-complex-use-machine.hh" +#include "hb-ot-shape-complex-use-table.hh" #include "hb-ot-shape-complex-arabic.hh" #include "hb-ot-shape-complex-arabic-joining-list.hh" #include "hb-ot-shape-complex-vowel-constraints.hh" -/* buffer var allocations */ -#define use_category() complex_var_u8_1() - /* * Universal Shaping Engine. @@ -69,11 +67,11 @@ use_topographical_features[] = }; /* Same order as use_topographical_features. */ enum joining_form_t { - USE_ISOL, - USE_INIT, - USE_MEDI, - USE_FINA, - _USE_NONE + JOINING_FORM_ISOL, + JOINING_FORM_INIT, + JOINING_FORM_MEDI, + JOINING_FORM_FINA, + _JOINING_FORM_NONE }; static const hb_tag_t use_other_features[] = @@ -186,22 +184,6 @@ data_destroy_use (void *data) free (data); } -enum use_syllable_type_t { - use_independent_cluster, - use_virama_terminated_cluster, - use_sakot_terminated_cluster, - use_standard_cluster, - use_number_joiner_terminated_cluster, - use_numeral_cluster, - use_symbol_cluster, - use_hieroglyph_cluster, - use_broken_cluster, - use_non_cluster, -}; - -#include "hb-ot-shape-complex-use-machine.hh" - - static void setup_masks_use (const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, @@ -239,7 +221,7 @@ setup_rphf_mask (const hb_ot_shape_plan_t *plan, foreach_syllable (buffer, start, end) { - unsigned int limit = info[start].use_category() == USE_R ? 1 : hb_min (3u, end - start); + unsigned int limit = info[start].use_category() == USE(R) ? 1 : hb_min (3u, end - start); for (unsigned int i = start; i < start + limit; i++) info[i].mask |= mask; } @@ -253,7 +235,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, if (use_plan->arabic_plan) return; - static_assert ((USE_INIT < 4 && USE_ISOL < 4 && USE_MEDI < 4 && USE_FINA < 4), ""); + static_assert ((JOINING_FORM_INIT < 4 && JOINING_FORM_ISOL < 4 && JOINING_FORM_MEDI < 4 && JOINING_FORM_FINA < 4), ""); hb_mask_t masks[4], all_masks = 0; for (unsigned int i = 0; i < 4; i++) { @@ -267,7 +249,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, hb_mask_t other_masks = ~all_masks; unsigned int last_start = 0; - joining_form_t last_form = _USE_NONE; + joining_form_t last_form = _JOINING_FORM_NONE; hb_glyph_info_t *info = buffer->info; foreach_syllable (buffer, start, end) { @@ -279,7 +261,7 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, case use_hieroglyph_cluster: case use_non_cluster: /* These don't join. Nothing to do. */ - last_form = _USE_NONE; + last_form = _JOINING_FORM_NONE; break; case use_virama_terminated_cluster: @@ -289,18 +271,18 @@ setup_topographical_masks (const hb_ot_shape_plan_t *plan, case use_numeral_cluster: case use_broken_cluster: - bool join = last_form == USE_FINA || last_form == USE_ISOL; + bool join = last_form == JOINING_FORM_FINA || last_form == JOINING_FORM_ISOL; if (join) { /* Fixup previous syllable's form. */ - last_form = last_form == USE_FINA ? USE_MEDI : USE_INIT; + last_form = last_form == JOINING_FORM_FINA ? JOINING_FORM_MEDI : JOINING_FORM_INIT; for (unsigned int i = last_start; i < start; i++) info[i].mask = (info[i].mask & other_masks) | masks[last_form]; } /* Form for this syllable. */ - last_form = join ? USE_FINA : USE_ISOL; + last_form = join ? JOINING_FORM_FINA : JOINING_FORM_ISOL; for (unsigned int i = start; i < end; i++) info[i].mask = (info[i].mask & other_masks) | masks[last_form]; @@ -336,11 +318,11 @@ record_rphf_use (const hb_ot_shape_plan_t *plan, foreach_syllable (buffer, start, end) { - /* Mark a substituted repha as USE_R. */ + /* Mark a substituted repha as USE(R). */ for (unsigned int i = start; i < end && (info[i].mask & mask); i++) if (_hb_glyph_info_substituted (&info[i])) { - info[i].use_category() = USE_R; + info[i].use_category() = USE(R); break; } } @@ -359,7 +341,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED, for (unsigned int i = start; i < end; i++) if (_hb_glyph_info_substituted (&info[i])) { - info[i].use_category() = USE_VPre; + info[i].use_category() = USE(VPre); break; } } @@ -368,7 +350,7 @@ record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED, static inline bool is_halant_use (const hb_glyph_info_t &info) { - return (info.use_category() == USE_H || info.use_category() == USE_HVM) && + return (info.use_category() == USE(H) || info.use_category() == USE(HVM)) && !_hb_glyph_info_ligated (&info); } @@ -387,24 +369,24 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end) hb_glyph_info_t *info = buffer->info; -#define POST_BASE_FLAGS64 (FLAG64 (USE_FAbv) | \ - FLAG64 (USE_FBlw) | \ - FLAG64 (USE_FPst) | \ - FLAG64 (USE_MAbv) | \ - FLAG64 (USE_MBlw) | \ - FLAG64 (USE_MPst) | \ - FLAG64 (USE_MPre) | \ - FLAG64 (USE_VAbv) | \ - FLAG64 (USE_VBlw) | \ - FLAG64 (USE_VPst) | \ - FLAG64 (USE_VPre) | \ - FLAG64 (USE_VMAbv) | \ - FLAG64 (USE_VMBlw) | \ - FLAG64 (USE_VMPst) | \ - FLAG64 (USE_VMPre)) +#define POST_BASE_FLAGS64 (FLAG64 (USE(FAbv)) | \ + FLAG64 (USE(FBlw)) | \ + FLAG64 (USE(FPst)) | \ + FLAG64 (USE(MAbv)) | \ + FLAG64 (USE(MBlw)) | \ + FLAG64 (USE(MPst)) | \ + FLAG64 (USE(MPre)) | \ + FLAG64 (USE(VAbv)) | \ + FLAG64 (USE(VBlw)) | \ + FLAG64 (USE(VPst)) | \ + FLAG64 (USE(VPre)) | \ + FLAG64 (USE(VMAbv)) | \ + FLAG64 (USE(VMBlw)) | \ + FLAG64 (USE(VMPst)) | \ + FLAG64 (USE(VMPre))) /* Move things forward. */ - if (info[start].use_category() == USE_R && end - start > 1) + if (info[start].use_category() == USE(R) && end - start > 1) { /* Got a repha. Reorder it towards the end, but before the first post-base * glyph. */ @@ -441,7 +423,7 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end) * shift things in between forward. */ j = i + 1; } - else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) && + else if (((flag) & (FLAG (USE(VPre)) | FLAG (USE(VMPre)))) && /* Only move the first component of a MultipleSubst. */ 0 == _hb_glyph_info_get_lig_comp (&info[i]) && j < i) @@ -454,76 +436,22 @@ reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end) } } -static inline void -insert_dotted_circles_use (const hb_ot_shape_plan_t *plan HB_UNUSED, - hb_font_t *font, - hb_buffer_t *buffer) -{ - if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)) - return; - - /* Note: This loop is extra overhead, but should not be measurable. - * TODO Use a buffer scratch flag to remove the loop. */ - bool has_broken_syllables = false; - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - for (unsigned int i = 0; i < count; i++) - if ((info[i].syllable() & 0x0F) == use_broken_cluster) - { - has_broken_syllables = true; - break; - } - if (likely (!has_broken_syllables)) - return; - - hb_glyph_info_t dottedcircle = {0}; - if (!font->get_nominal_glyph (0x25CCu, &dottedcircle.codepoint)) - return; - dottedcircle.use_category() = hb_use_get_category (0x25CC); - - buffer->clear_output (); - - buffer->idx = 0; - unsigned int last_syllable = 0; - while (buffer->idx < buffer->len && buffer->successful) - { - unsigned int syllable = buffer->cur().syllable(); - use_syllable_type_t syllable_type = (use_syllable_type_t) (syllable & 0x0F); - if (unlikely (last_syllable != syllable && syllable_type == use_broken_cluster)) - { - last_syllable = syllable; - - hb_glyph_info_t ginfo = dottedcircle; - ginfo.cluster = buffer->cur().cluster; - ginfo.mask = buffer->cur().mask; - ginfo.syllable() = buffer->cur().syllable(); - - /* Insert dottedcircle after possible Repha. */ - while (buffer->idx < buffer->len && buffer->successful && - last_syllable == buffer->cur().syllable() && - buffer->cur().use_category() == USE_R) - buffer->next_glyph (); - - buffer->output_info (ginfo); - } - else - buffer->next_glyph (); - } - buffer->swap_buffers (); -} - static void reorder_use (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - if (buffer->message (font, "start reordering USE")) { - insert_dotted_circles_use (plan, font, buffer); + if (buffer->message (font, "start reordering USE")) + { + hb_syllabic_insert_dotted_circles (font, buffer, + use_broken_cluster, + USE(B), + USE(R)); - foreach_syllable (buffer, start, end) - reorder_syllable_use (buffer, start, end); + foreach_syllable (buffer, start, end) + reorder_syllable_use (buffer, start, end); - (void) buffer->message (font, "end reordering USE"); + (void) buffer->message (font, "end reordering USE"); } HB_BUFFER_DEALLOCATE_VAR (buffer, use_category); diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.hh deleted file mode 100644 index 788fb6b6ac..0000000000 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.hh +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright © 2015 Mozilla Foundation. - * Copyright © 2015 Google, Inc. - * - * This is part of HarfBuzz, a text shaping library. - * - * Permission is hereby granted, without written agreement and without - * license or royalty fees, to use, copy, modify, and distribute this - * software and its documentation for any purpose, provided that the - * above copyright notice and the following two paragraphs appear in - * all copies of this software. - * - * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR - * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN - * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * Mozilla Author(s): Jonathan Kew - * Google Author(s): Behdad Esfahbod - */ - -#ifndef HB_OT_SHAPE_COMPLEX_USE_HH -#define HB_OT_SHAPE_COMPLEX_USE_HH - -#include "hb.hh" - - -#include "hb-ot-shape-complex.hh" - - -#define USE_TABLE_ELEMENT_TYPE uint8_t - -/* Cateories used in the Universal Shaping Engine spec: - * https://docs.microsoft.com/en-us/typography/script-development/use - */ -/* Note: This enum is duplicated in the -machine.rl source file. - * Not sure how to avoid duplication. */ -enum use_category_t { - USE_O = 0, /* OTHER */ - - USE_B = 1, /* BASE */ - USE_N = 4, /* BASE_NUM */ - USE_GB = 5, /* BASE_OTHER */ - USE_SUB = 11, /* CONS_SUB */ - USE_H = 12, /* HALANT */ - - USE_HN = 13, /* HALANT_NUM */ - USE_ZWNJ = 14, /* Zero width non-joiner */ - USE_R = 18, /* REPHA */ - USE_S = 19, /* SYM */ - USE_CS = 43, /* CONS_WITH_STACKER */ - - /* https://github.com/harfbuzz/harfbuzz/issues/1102 */ - USE_HVM = 44, /* HALANT_OR_VOWEL_MODIFIER */ - - USE_Sk = 48, /* SAKOT */ - USE_G = 49, /* HIEROGLYPH */ - USE_J = 50, /* HIEROGLYPH_JOINER */ - USE_SB = 51, /* HIEROGLYPH_SEGMENT_BEGIN */ - USE_SE = 52, /* HIEROGLYPH_SEGMENT_END */ - - USE_FAbv = 24, /* CONS_FINAL_ABOVE */ - USE_FBlw = 25, /* CONS_FINAL_BELOW */ - USE_FPst = 26, /* CONS_FINAL_POST */ - USE_MAbv = 27, /* CONS_MED_ABOVE */ - USE_MBlw = 28, /* CONS_MED_BELOW */ - USE_MPst = 29, /* CONS_MED_POST */ - USE_MPre = 30, /* CONS_MED_PRE */ - USE_CMAbv = 31, /* CONS_MOD_ABOVE */ - USE_CMBlw = 32, /* CONS_MOD_BELOW */ - USE_VAbv = 33, /* VOWEL_ABOVE / VOWEL_ABOVE_BELOW / VOWEL_ABOVE_BELOW_POST / VOWEL_ABOVE_POST */ - USE_VBlw = 34, /* VOWEL_BELOW / VOWEL_BELOW_POST */ - USE_VPst = 35, /* VOWEL_POST UIPC = Right */ - USE_VPre = 22, /* VOWEL_PRE / VOWEL_PRE_ABOVE / VOWEL_PRE_ABOVE_POST / VOWEL_PRE_POST */ - USE_VMAbv = 37, /* VOWEL_MOD_ABOVE */ - USE_VMBlw = 38, /* VOWEL_MOD_BELOW */ - USE_VMPst = 39, /* VOWEL_MOD_POST */ - USE_VMPre = 23, /* VOWEL_MOD_PRE */ - USE_SMAbv = 41, /* SYM_MOD_ABOVE */ - USE_SMBlw = 42, /* SYM_MOD_BELOW */ - USE_FMAbv = 45, /* CONS_FINAL_MOD UIPC = Top */ - USE_FMBlw = 46, /* CONS_FINAL_MOD UIPC = Bottom */ - USE_FMPst = 47, /* CONS_FINAL_MOD UIPC = Not_Applicable */ -}; - -HB_INTERNAL USE_TABLE_ELEMENT_TYPE -hb_use_get_category (hb_codepoint_t u); - -#endif /* HB_OT_SHAPE_COMPLEX_USE_HH */ diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc index 1af546e4fa..1037626998 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc @@ -23,15 +23,15 @@ static void _output_dotted_circle (hb_buffer_t *buffer) { - hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu); - _hb_glyph_info_reset_continuation (&dottedcircle); + (void) buffer->output_glyph (0x25CCu); + _hb_glyph_info_reset_continuation (&buffer->prev()); } static void _output_with_dotted_circle (hb_buffer_t *buffer) { _output_dotted_circle (buffer); - buffer->next_glyph (); + (void) buffer->next_glyph (); } void @@ -51,7 +51,6 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, * * https://github.com/harfbuzz/harfbuzz/issues/1019 */ - bool processed = false; buffer->clear_output (); unsigned int count = buffer->len; switch ((unsigned) buffer->props.script) @@ -97,15 +96,14 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, buffer->idx + 2 < count && 0x0907u == buffer->cur (2).codepoint) { - buffer->next_glyph (); + (void) buffer->next_glyph (); matched = true; } break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_BENGALI: @@ -124,10 +122,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, matched = 0x09E2u == buffer->cur (1).codepoint; break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_GURMUKHI: @@ -161,10 +158,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, } break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_GUJARATI: @@ -186,10 +182,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, matched = 0x0ABEu == buffer->cur (1).codepoint; break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_ORIYA: @@ -205,10 +200,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, matched = 0x0B57u == buffer->cur (1).codepoint; break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_TAMIL: @@ -220,10 +214,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, { matched = true; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_TELUGU: @@ -244,10 +237,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, matched = 0x0C55u == buffer->cur (1).codepoint; break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_KANNADA: @@ -263,10 +255,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, matched = 0x0CCCu == buffer->cur (1).codepoint; break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_MALAYALAM: @@ -290,10 +281,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, } break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_SINHALA: @@ -326,10 +316,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, } break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_BRAHMI: @@ -348,10 +337,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, matched = 0x11042u == buffer->cur (1).codepoint; break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_KHUDAWADI: @@ -370,10 +358,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, } break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_TIRHUTA: @@ -397,10 +384,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, } break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_MODI: @@ -418,10 +404,9 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, } break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; case HB_SCRIPT_TAKRI: @@ -442,21 +427,15 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED, matched = 0x116B2u == buffer->cur (1).codepoint; break; } - buffer->next_glyph (); + (void) buffer->next_glyph (); if (matched) _output_with_dotted_circle (buffer); } - processed = true; break; default: break; } - if (processed) - { - if (buffer->idx < count) - buffer->next_glyph (); - buffer->swap_buffers (); - } + buffer->swap_buffers (); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh index a1a7a6a47b..19e24b9f30 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh +++ b/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh @@ -35,8 +35,8 @@ /* buffer var allocations, used by complex shapers */ -#define complex_var_u8_0() var2.u8[2] -#define complex_var_u8_1() var2.u8[3] +#define complex_var_u8_category() var2.u8[2] +#define complex_var_u8_auxiliary() var2.u8[3] #define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32 @@ -186,27 +186,8 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_ARABIC: /* Unicode-3.0 additions */ - case HB_SCRIPT_MONGOLIAN: case HB_SCRIPT_SYRIAC: - /* Unicode-5.0 additions */ - case HB_SCRIPT_NKO: - case HB_SCRIPT_PHAGS_PA: - - /* Unicode-6.0 additions */ - case HB_SCRIPT_MANDAIC: - - /* Unicode-7.0 additions */ - case HB_SCRIPT_MANICHAEAN: - case HB_SCRIPT_PSALTER_PAHLAVI: - - /* Unicode-9.0 additions */ - case HB_SCRIPT_ADLAM: - - /* Unicode-11.0 additions */ - case HB_SCRIPT_HANIFI_ROHINGYA: - case HB_SCRIPT_SOGDIAN: - /* For Arabic script, use the Arabic shaper even if no OT script tag was found. * This is because we do fallback shaping for Arabic script (and not others). * But note that Arabic shaping is applicable only to horizontal layout; for @@ -284,8 +265,9 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) return &_hb_ot_complex_shaper_myanmar; - /* https://github.com/harfbuzz/harfbuzz/issues/1162 */ +#define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g')) case HB_SCRIPT_MYANMAR_ZAWGYI: + /* https://github.com/harfbuzz/harfbuzz/issues/1162 */ return &_hb_ot_complex_shaper_myanmar_zawgyi; @@ -294,7 +276,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_TIBETAN: /* Unicode-3.0 additions */ - //case HB_SCRIPT_MONGOLIAN: + case HB_SCRIPT_MONGOLIAN: //case HB_SCRIPT_SINHALA: /* Unicode-3.2 additions */ @@ -315,8 +297,8 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) /* Unicode-5.0 additions */ case HB_SCRIPT_BALINESE: - //case HB_SCRIPT_NKO: - //case HB_SCRIPT_PHAGS_PA: + case HB_SCRIPT_NKO: + case HB_SCRIPT_PHAGS_PA: /* Unicode-5.1 additions */ case HB_SCRIPT_CHAM: @@ -337,7 +319,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) /* Unicode-6.0 additions */ case HB_SCRIPT_BATAK: case HB_SCRIPT_BRAHMI: - //case HB_SCRIPT_MANDAIC: + case HB_SCRIPT_MANDAIC: /* Unicode-6.1 additions */ case HB_SCRIPT_CHAKMA: @@ -351,10 +333,10 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_KHOJKI: case HB_SCRIPT_KHUDAWADI: case HB_SCRIPT_MAHAJANI: - //case HB_SCRIPT_MANICHAEAN: + case HB_SCRIPT_MANICHAEAN: case HB_SCRIPT_MODI: case HB_SCRIPT_PAHAWH_HMONG: - //case HB_SCRIPT_PSALTER_PAHLAVI: + case HB_SCRIPT_PSALTER_PAHLAVI: case HB_SCRIPT_SIDDHAM: case HB_SCRIPT_TIRHUTA: @@ -363,7 +345,7 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) case HB_SCRIPT_MULTANI: /* Unicode-9.0 additions */ - //case HB_SCRIPT_ADLAM: + case HB_SCRIPT_ADLAM: case HB_SCRIPT_BHAIKSUKI: case HB_SCRIPT_MARCHEN: case HB_SCRIPT_NEWA: @@ -376,11 +358,11 @@ hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner) /* Unicode-11.0 additions */ case HB_SCRIPT_DOGRA: case HB_SCRIPT_GUNJALA_GONDI: - //case HB_SCRIPT_HANIFI_ROHINGYA: + case HB_SCRIPT_HANIFI_ROHINGYA: case HB_SCRIPT_MAKASAR: case HB_SCRIPT_MEDEFAIDRIN: case HB_SCRIPT_OLD_SOGDIAN: - //case HB_SCRIPT_SOGDIAN: + case HB_SCRIPT_SOGDIAN: /* Unicode-12.0 additions */ case HB_SCRIPT_ELYMAIC: diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc index 3eabae1b45..778b5b8bd8 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc @@ -101,8 +101,9 @@ set_glyph (hb_glyph_info_t &info, hb_font_t *font) static inline void output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph) { + /* This is very confusing indeed. */ buffer->cur().glyph_index() = glyph; - buffer->output_glyph (unichar); /* This is very confusing indeed. */ + (void) buffer->output_glyph (unichar); _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer); } @@ -110,7 +111,7 @@ static inline void next_char (hb_buffer_t *buffer, hb_codepoint_t glyph) { buffer->cur().glyph_index() = glyph; - buffer->next_glyph (); + (void) buffer->next_glyph (); } static inline void @@ -229,30 +230,35 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c, if (font->get_variation_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index())) { hb_codepoint_t unicode = buffer->cur().codepoint; - buffer->replace_glyphs (2, 1, &unicode); + (void) buffer->replace_glyphs (2, 1, &unicode); } else { /* Just pass on the two characters separately, let GSUB do its magic. */ set_glyph (buffer->cur(), font); - buffer->next_glyph (); + (void) buffer->next_glyph (); set_glyph (buffer->cur(), font); - buffer->next_glyph (); + (void) buffer->next_glyph (); } /* Skip any further variation selectors. */ - while (buffer->idx < end && unlikely (buffer->unicode->is_variation_selector (buffer->cur().codepoint))) + while (buffer->idx < end && + buffer->successful && + unlikely (buffer->unicode->is_variation_selector (buffer->cur().codepoint))) { set_glyph (buffer->cur(), font); - buffer->next_glyph (); + (void) buffer->next_glyph (); } - } else { + } + else + { set_glyph (buffer->cur(), font); - buffer->next_glyph (); + (void) buffer->next_glyph (); } } - if (likely (buffer->idx < end)) { + if (likely (buffer->idx < end)) + { set_glyph (buffer->cur(), font); - buffer->next_glyph (); + (void) buffer->next_glyph (); } } @@ -348,7 +354,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, sizeof (buffer->info[0]), &buffer->cur().glyph_index(), sizeof (buffer->info[0])); - buffer->next_glyphs (done); + if (unlikely (!buffer->next_glyphs (done))) break; } while (buffer->idx < end && buffer->successful) decompose_current_character (&c, might_short_circuit); @@ -419,6 +425,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, /* Third round, recompose */ if (!all_simple && + buffer->successful && (mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS || mode == HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT)) { @@ -428,8 +435,8 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, buffer->clear_output (); count = buffer->len; unsigned int starter = 0; - buffer->next_glyph (); - while (buffer->idx < count && buffer->successful) + (void) buffer->next_glyph (); + while (buffer->idx < count /* No need for: && buffer->successful */) { hb_codepoint_t composed, glyph; if (/* We don't try to compose a non-mark character with it's preceding starter. @@ -451,9 +458,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, font->get_nominal_glyph (composed, &glyph)) { /* Composes. */ - buffer->next_glyph (); /* Copy to out-buffer. */ - if (unlikely (!buffer->successful)) - return; + if (unlikely (!buffer->next_glyph ())) break; /* Copy to out-buffer. */ buffer->merge_out_clusters (starter, buffer->out_len); buffer->out_len--; /* Remove the second composable. */ /* Modify starter and carry on. */ @@ -466,7 +471,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan, } /* Blocked, or doesn't compose. */ - buffer->next_glyph (); + if (unlikely (!buffer->next_glyph ())) break; if (info_cc (buffer->prev()) == 0) starter = buffer->out_len - 1; diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc index 7d90558458..86ab0b4268 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape.cc +++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc @@ -534,9 +534,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) hb_glyph_info_t info = dottedcircle; info.cluster = buffer->cur().cluster; info.mask = buffer->cur().mask; - buffer->output_info (info); - while (buffer->idx < buffer->len && buffer->successful) - buffer->next_glyph (); + (void) buffer->output_info (info); buffer->swap_buffers (); } diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.h b/thirdparty/harfbuzz/src/hb-ot-shape.h index 7b1bcc0637..afdff72833 100644 --- a/thirdparty/harfbuzz/src/hb-ot-shape.h +++ b/thirdparty/harfbuzz/src/hb-ot-shape.h @@ -24,7 +24,7 @@ * Red Hat Author(s): Behdad Esfahbod */ -#ifndef HB_OT_H_IN +#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-ot.h> instead." #endif diff --git a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh index f1c391cf0e..87830b5462 100644 --- a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh @@ -6,8 +6,8 @@ * * on files with these headers: * - * <meta name="updated_at" content="2020-11-17 08:21 AM" /> - * File-Date: 2020-09-29 + * <meta name="updated_at" content="2021-02-12 04:08 PM" /> + * File-Date: 2021-03-05 */ #ifndef HB_OT_TAG_TABLE_HH @@ -169,6 +169,7 @@ static const LangTag ot_languages[] = { {"bko", HB_TAG('B','M','L',' ')}, /* Kwa' -> Bamileke */ {"bla", HB_TAG('B','K','F',' ')}, /* Siksika -> Blackfoot */ {"ble", HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe -> Balante */ + {"blg", HB_TAG('I','B','A',' ')}, /* Balau (retired code) -> Iban */ {"bli", HB_TAG_NONE }, /* Bolia != Baluchi */ {"blk", HB_TAG('B','L','K',' ')}, /* Pa’o Karen */ {"blk", HB_TAG('K','R','N',' ')}, /* Pa'o Karen -> Karen */ @@ -358,6 +359,7 @@ static const LangTag ot_languages[] = { {"czo", HB_TAG('Z','H','S',' ')}, /* Min Zhong Chinese -> Chinese, Simplified */ {"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin -> Chin */ {"da", HB_TAG('D','A','N',' ')}, /* Danish */ +/*{"dag", HB_TAG('D','A','G',' ')},*/ /* Dagbani */ {"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin -> Chin */ {"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) (retired code) */ /*{"dar", HB_TAG('D','A','R',' ')},*/ /* Dargwa */ @@ -834,6 +836,7 @@ static const LangTag ot_languages[] = { {"lri", HB_TAG('L','U','H',' ')}, /* Marachi -> Luyia */ {"lrm", HB_TAG('L','U','H',' ')}, /* Marama -> Luyia */ {"lrt", HB_TAG('C','P','P',' ')}, /* Larantuka Malay -> Creoles */ + {"lsb", HB_TAG_NONE }, /* Burundian Sign Language != Lower Sorbian */ {"lsm", HB_TAG('L','U','H',' ')}, /* Saamia -> Luyia */ {"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */ {"ltg", HB_TAG('L','V','I',' ')}, /* Latgalian -> Latvian */ @@ -990,7 +993,7 @@ static const LangTag ot_languages[] = { /*{"nga", HB_TAG('N','G','A',' ')},*/ /* Ngbaka */ {"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */ {"ngm", HB_TAG('C','P','P',' ')}, /* Ngatik Men's Creole -> Creoles */ - {"ngo", HB_TAG('S','X','T',' ')}, /* Ngoni -> Sutu */ + {"ngo", HB_TAG('S','X','T',' ')}, /* Ngoni (retired code) -> Sutu */ {"ngr", HB_TAG_NONE }, /* Engdewu != Nagari */ {"ngu", HB_TAG('N','A','H',' ')}, /* Guerrero Nahuatl -> Nahuatl */ {"nhc", HB_TAG('N','A','H',' ')}, /* Tabasco Nahuatl -> Nahuatl */ @@ -1520,6 +1523,8 @@ static const LangTag ot_languages[] = { {"xmm", HB_TAG('C','P','P',' ')}, /* Manado Malay -> Creoles */ {"xmv", HB_TAG('M','L','G',' ')}, /* Antankarana Malagasy -> Malagasy */ {"xmw", HB_TAG('M','L','G',' ')}, /* Tsimihety Malagasy -> Malagasy */ + {"xnj", HB_TAG('S','X','T',' ')}, /* Ngoni (Tanzania) -> Sutu */ + {"xnq", HB_TAG('S','X','T',' ')}, /* Ngoni (Mozambique) -> Sutu */ {"xnr", HB_TAG('D','G','R',' ')}, /* Kangri -> Dogri (macrolanguage) */ /*{"xog", HB_TAG('X','O','G',' ')},*/ /* Soga */ {"xpe", HB_TAG('X','P','E',' ')}, /* Liberia Kpelle -> Kpelle (Liberia) */ @@ -2808,6 +2813,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) return hb_language_from_string ("hnd", -1); /* Southern Hindko */ case HB_TAG('H','Y','E',' '): /* Armenian */ return hb_language_from_string ("hyw", -1); /* Western Armenian */ + case HB_TAG('I','B','A',' '): /* Iban */ + return hb_language_from_string ("iba", -1); /* Iban */ case HB_TAG('I','J','O',' '): /* Ijo */ return hb_language_from_string ("ijo", -1); /* Ijo [family] */ case HB_TAG('I','N','U',' '): /* Inuktitut */ @@ -2892,6 +2899,8 @@ hb_ot_ambiguous_tag_to_language (hb_tag_t tag) return hb_language_from_string ("sq", -1); /* Albanian [macrolanguage] */ case HB_TAG('S','R','B',' '): /* Serbian */ return hb_language_from_string ("sr", -1); /* Serbian */ + case HB_TAG('S','X','T',' '): /* Sutu */ + return hb_language_from_string ("xnj", -1); /* Ngoni (Tanzania) */ case HB_TAG('S','Y','R',' '): /* Syriac */ return hb_language_from_string ("syr", -1); /* Syriac [macrolanguage] */ case HB_TAG('S','Y','R','E'): /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */ diff --git a/thirdparty/harfbuzz/src/hb-ot-tag.cc b/thirdparty/harfbuzz/src/hb-ot-tag.cc index 19bd3639d3..fc145a41f7 100644 --- a/thirdparty/harfbuzz/src/hb-ot-tag.cc +++ b/thirdparty/harfbuzz/src/hb-ot-tag.cc @@ -164,6 +164,15 @@ hb_ot_all_tags_from_script (hb_script_t script, *count = i; } +/** + * hb_ot_tag_to_script: + * @tag: a script tag + * + * Converts a script tag to an #hb_script_t. + * + * Return value: The #hb_script_t corresponding to @tag. + * + **/ hb_script_t hb_ot_tag_to_script (hb_tag_t tag) { @@ -351,13 +360,13 @@ parse_private_use_subtag (const char *private_use_subtag, * hb_ot_tags_from_script_and_language: * @script: an #hb_script_t to convert. * @language: an #hb_language_t to convert. - * @script_count: (allow-none): maximum number of script tags to retrieve (IN) + * @script_count: (inout) (optional): maximum number of script tags to retrieve (IN) * and actual number of script tags retrieved (OUT) - * @script_tags: (out) (allow-none): array of size at least @script_count to store the + * @script_tags: (out) (optional): array of size at least @script_count to store the * script tag results - * @language_count: (allow-none): maximum number of language tags to retrieve + * @language_count: (inout) (optional): maximum number of language tags to retrieve * (IN) and actual number of language tags retrieved (OUT) - * @language_tags: (out) (allow-none): array of size at least @language_count to store + * @language_tags: (out) (optional): array of size at least @language_count to store * the language tag results * * Converts an #hb_script_t and an #hb_language_t to script and language tags. @@ -424,10 +433,12 @@ hb_ot_tags_from_script_and_language (hb_script_t script, /** * hb_ot_tag_to_language: + * @tag: an language tag * + * Converts a language tag to an #hb_language_t. * - * - * Return value: (transfer none): + * Return value: (transfer none) (nullable): + * The #hb_language_t corresponding to @tag. * * Since: 0.9.2 **/ @@ -478,9 +489,9 @@ hb_ot_tag_to_language (hb_tag_t tag) * hb_ot_tags_to_script_and_language: * @script_tag: a script tag * @language_tag: a language tag - * @script: (allow-none): the #hb_script_t corresponding to @script_tag (OUT). - * @language: (allow-none): the #hb_language_t corresponding to @script_tag and - * @language_tag (OUT). + * @script: (out) (optional): the #hb_script_t corresponding to @script_tag. + * @language: (out) (optional): the #hb_language_t corresponding to @script_tag and + * @language_tag. * * Converts a script tag and a language tag to an #hb_script_t and an * #hb_language_t. diff --git a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh index 4d4e6dcae4..7e4eaaad95 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh +++ b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh @@ -652,8 +652,8 @@ no_more_gaps: /* apply specified / inferred deltas to points */ for (unsigned int i = 0; i < points.length; i++) { - points[i].x += roundf (deltas[i].x); - points[i].y += roundf (deltas[i].y); + points[i].x += deltas[i].x; + points[i].y += deltas[i].y; } } while (iterator.move_to_next ()); diff --git a/thirdparty/harfbuzz/src/hb-ot-var.cc b/thirdparty/harfbuzz/src/hb-ot-var.cc index 1fe57383c0..6b42b45cd9 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var.cc +++ b/thirdparty/harfbuzz/src/hb-ot-var.cc @@ -56,7 +56,7 @@ * * Tests whether a face includes any OpenType variation data in the `fvar` table. * - * Return value: true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 1.4.2 **/ @@ -87,7 +87,7 @@ hb_ot_var_get_axis_count (hb_face_t *face) * hb_ot_var_get_axes: * @face: #hb_face_t to work upon * @start_offset: offset of the first lookup to retrieve - * @axes_count: (inout) (allow-none): Input = the maximum number of variation axes to return; + * @axes_count: (inout) (optional): Input = the maximum number of variation axes to return; * Output = the actual number of variation axes returned (may be zero) * @axes_array: (out caller-allocates) (array length=axes_count): The array of variation axes found * @@ -133,7 +133,7 @@ hb_ot_var_find_axis (hb_face_t *face, * hb_ot_var_get_axis_infos: * @face: #hb_face_t to work upon * @start_offset: offset of the first lookup to retrieve - * @axes_count: (inout) (allow-none): Input = the maximum number of variation axes to return; + * @axes_count: (inout) (optional): Input = the maximum number of variation axes to return; * Output = the actual number of variation axes returned (may be zero) * @axes_array: (out caller-allocates) (array length=axes_count): The array of variation axes found * @@ -162,7 +162,7 @@ hb_ot_var_get_axis_infos (hb_face_t *face, * Fetches the variation-axis information corresponding to the specified axis tag * in the specified face. * - * Return value: true if data found, false otherwise + * Return value: %true if data found, %false otherwise * * Since: 2.2.0 **/ @@ -237,7 +237,7 @@ hb_ot_var_named_instance_get_postscript_name_id (hb_face_t *face, * hb_ot_var_named_instance_get_design_coords: * @face: The #hb_face_t to work on * @instance_index: The index of the named instance to query - * @coords_length: (inout) (allow-none): Input = the maximum number of coordinates to return; + * @coords_length: (inout) (optional): Input = the maximum number of coordinates to return; * Output = the actual number of coordinates returned (may be zero) * @coords: (out) (array length=coords_length): The array of coordinates found for the query * diff --git a/thirdparty/harfbuzz/src/hb-ot-var.h b/thirdparty/harfbuzz/src/hb-ot-var.h index ef2ca0a716..ce201d3b4f 100644 --- a/thirdparty/harfbuzz/src/hb-ot-var.h +++ b/thirdparty/harfbuzz/src/hb-ot-var.h @@ -24,7 +24,7 @@ * Red Hat Author(s): Behdad Esfahbod */ -#ifndef HB_OT_H_IN +#if !defined(HB_OT_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb-ot.h> instead." #endif @@ -36,34 +36,38 @@ HB_BEGIN_DECLS /** - * hb_tag_t: - * @HB_OT_TAG_VAR_AXIS_ITALIC: Registered tag for the roman/italic axis + * HB_OT_TAG_VAR_AXIS_ITALIC: + * + * Registered tag for the roman/italic axis. */ #define HB_OT_TAG_VAR_AXIS_ITALIC HB_TAG('i','t','a','l') /** - * hb_tag_t: - * @HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE: Registered tag for the optical-size axis + * HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE: * + * Registered tag for the optical-size axis. * <note>Note: The optical-size axis supersedes the OpenType `size` feature.</note> */ #define HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE HB_TAG('o','p','s','z') /** - * hb_tag_t: - * @HB_OT_TAG_VAR_AXIS_SLANT: Registered tag for the slant axis + * HB_OT_TAG_VAR_AXIS_SLANT: + * + * Registered tag for the slant axis */ #define HB_OT_TAG_VAR_AXIS_SLANT HB_TAG('s','l','n','t') /** - * hb_tag_t: - * @HB_OT_TAG_VAR_AXIS_WIDTH: Registered tag for the width axis + * HB_OT_TAG_VAR_AXIS_WIDTH: + * + * Registered tag for the width axis. */ #define HB_OT_TAG_VAR_AXIS_WIDTH HB_TAG('w','d','t','h') /** - * hb_tag_t: - * @HB_OT_TAG_VAR_AXIS_WEIGHT: Registered tag for the weight axis + * HB_OT_TAG_VAR_AXIS_WEIGHT: + * + * Registered tag for the weight axis. */ #define HB_OT_TAG_VAR_AXIS_WEIGHT HB_TAG('w','g','h','t') @@ -88,11 +92,14 @@ hb_ot_var_get_axis_count (hb_face_t *face); * hb_ot_var_axis_flags_t: * @HB_OT_VAR_AXIS_FLAG_HIDDEN: The axis should not be exposed directly in user interfaces. * + * Flags for #hb_ot_var_axis_info_t. + * * Since: 2.2.0 */ typedef enum { /*< flags >*/ HB_OT_VAR_AXIS_FLAG_HIDDEN = 0x00000001u, + /*< private >*/ _HB_OT_VAR_AXIS_FLAG_MAX_VALUE= HB_TAG_MAX_SIGNED /*< skip >*/ } hb_ot_var_axis_flags_t; diff --git a/thirdparty/harfbuzz/src/hb-sanitize.hh b/thirdparty/harfbuzz/src/hb-sanitize.hh index 024b4d1c99..1675e8448a 100644 --- a/thirdparty/harfbuzz/src/hb-sanitize.hh +++ b/thirdparty/harfbuzz/src/hb-sanitize.hh @@ -73,7 +73,7 @@ * === The sanitize() contract === * * The sanitize() method of each object type shall return true if it's safe to - * call other methods of the object, and false otherwise. + * call other methods of the object, and %false otherwise. * * Note that what sanitize() checks for might align with what the specification * describes as valid table data, but does not have to be. In particular, we @@ -113,8 +113,8 @@ #ifndef HB_SANITIZE_MAX_OPS_MAX #define HB_SANITIZE_MAX_OPS_MAX 0x3FFFFFFF #endif -#ifndef HB_SANITIZE_MAX_SUTABLES -#define HB_SANITIZE_MAX_SUTABLES 0x4000 +#ifndef HB_SANITIZE_MAX_SUBTABLES +#define HB_SANITIZE_MAX_SUBTABLES 0x4000 #endif struct hb_sanitize_context_t : @@ -139,7 +139,7 @@ struct hb_sanitize_context_t : bool visit_subtables (unsigned count) { max_subtables += count; - return max_subtables < HB_SANITIZE_MAX_SUTABLES; + return max_subtables < HB_SANITIZE_MAX_SUBTABLES; } private: diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh index 4566153a59..fe29bdf96e 100644 --- a/thirdparty/harfbuzz/src/hb-serialize.hh +++ b/thirdparty/harfbuzz/src/hb-serialize.hh @@ -256,10 +256,11 @@ struct hb_serialize_context_t packed.push (obj); - if (unlikely (packed.in_error ())) { - // obj wasn't successfully added to packed, so clean it up otherwise it's - // links will be leaked. - propagate_error (packed); + if (unlikely (!propagate_error (packed))) + { + /* Obj wasn't successfully added to packed, so clean it up otherwise its + * links will be leaked. When we use constructor/destructors properly, we + * can remove these. */ obj->fini (); return 0; } @@ -523,7 +524,7 @@ struct hb_serialize_context_t template <typename T> void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset) { - auto &off = * ((BEInt<T, sizeof (T)> *) (parent->head + link.position)); + auto &off = * ((BEInt<T> *) (parent->head + link.position)); assert (0 == off); check_assign (off, offset); } diff --git a/thirdparty/harfbuzz/src/hb-set.cc b/thirdparty/harfbuzz/src/hb-set.cc index 3b4059ad32..86bf70034c 100644 --- a/thirdparty/harfbuzz/src/hb-set.cc +++ b/thirdparty/harfbuzz/src/hb-set.cc @@ -117,7 +117,7 @@ hb_set_destroy (hb_set_t *set) * @set: A set * @key: The user-data key to set * @data: A pointer to the user data to set - * @destroy: (optional): A callback to call when @data is not needed anymore + * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * * Attaches a user-data key/data pair to the specified set. @@ -162,7 +162,7 @@ hb_set_get_user_data (hb_set_t *set, * * Tests whether memory allocation for a set was successful. * - * Return value: %true if allocation succeeded, false otherwise + * Return value: %true if allocation succeeded, %false otherwise * * Since: 0.9.2 **/ @@ -183,6 +183,9 @@ hb_set_allocation_successful (const hb_set_t *set) void hb_set_clear (hb_set_t *set) { + if (unlikely (hb_object_is_immutable (set))) + return; + set->clear (); } @@ -209,7 +212,7 @@ hb_set_is_empty (const hb_set_t *set) * * Tests whether @codepoint belongs to @set. * - * Return value: %true if @codepoint is in @set, false otherwise + * Return value: %true if @codepoint is in @set, %false otherwise * * Since: 0.9.2 **/ @@ -298,7 +301,7 @@ hb_set_del_range (hb_set_t *set, * Tests whether @set and @other are equal (contain the same * elements). * - * Return value: %TRUE if the two sets are equal, %FALSE otherwise. + * Return value: %true if the two sets are equal, %false otherwise. * * Since: 0.9.7 **/ @@ -316,7 +319,7 @@ hb_set_is_equal (const hb_set_t *set, * * Tests whether @set is a subset of @larger_set. * - * Return value: %TRUE if the @set is a subset of (or equal to) @larger_set, %FALSE otherwise. + * Return value: %true if the @set is a subset of (or equal to) @larger_set, %false otherwise. * * Since: 1.8.1 **/ @@ -447,7 +450,7 @@ hb_set_get_population (const hb_set_t *set) * * Finds the smallest element in the set. * - * Return value: minimum of @set, or %HB_SET_VALUE_INVALID if @set is empty. + * Return value: minimum of @set, or #HB_SET_VALUE_INVALID if @set is empty. * * Since: 0.9.7 **/ @@ -463,7 +466,7 @@ hb_set_get_min (const hb_set_t *set) * * Finds the largest element in the set. * - * Return value: maximum of @set, or %HB_SET_VALUE_INVALID if @set is empty. + * Return value: maximum of @set, or #HB_SET_VALUE_INVALID if @set is empty. * * Since: 0.9.7 **/ @@ -481,9 +484,9 @@ hb_set_get_max (const hb_set_t *set) * * Fetches the next element in @set that is greater than current value of @codepoint. * - * Set @codepoint to %HB_SET_VALUE_INVALID to get started. + * Set @codepoint to #HB_SET_VALUE_INVALID to get started. * - * Return value: %true if there was a next value, false otherwise + * Return value: %true if there was a next value, %false otherwise * * Since: 0.9.2 **/ @@ -502,9 +505,9 @@ hb_set_next (const hb_set_t *set, * * Fetches the previous element in @set that is lower than current value of @codepoint. * - * Set @codepoint to %HB_SET_VALUE_INVALID to get started. + * Set @codepoint to #HB_SET_VALUE_INVALID to get started. * - * Return value: %true if there was a previous value, false otherwise + * Return value: %true if there was a previous value, %false otherwise * * Since: 1.8.0 **/ @@ -525,9 +528,9 @@ hb_set_previous (const hb_set_t *set, * Fetches the next consecutive range of elements in @set that * are greater than current value of @last. * - * Set @last to %HB_SET_VALUE_INVALID to get started. + * Set @last to #HB_SET_VALUE_INVALID to get started. * - * Return value: %true if there was a next range, false otherwise + * Return value: %true if there was a next range, %false otherwise * * Since: 0.9.7 **/ @@ -549,9 +552,9 @@ hb_set_next_range (const hb_set_t *set, * Fetches the previous consecutive range of elements in @set that * are greater than current value of @last. * - * Set @first to %HB_SET_VALUE_INVALID to get started. + * Set @first to #HB_SET_VALUE_INVALID to get started. * - * Return value: %true if there was a previous range, false otherwise + * Return value: %true if there was a previous range, %false otherwise * * Since: 1.8.0 **/ diff --git a/thirdparty/harfbuzz/src/hb-set.h b/thirdparty/harfbuzz/src/hb-set.h index cafc36dbad..0ad27f4bbd 100644 --- a/thirdparty/harfbuzz/src/hb-set.h +++ b/thirdparty/harfbuzz/src/hb-set.h @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif @@ -36,7 +36,11 @@ HB_BEGIN_DECLS -/* +/** + * HB_SET_VALUE_INVALID: + * + * Unset #hb_set_t value. + * * Since: 0.9.21 */ #define HB_SET_VALUE_INVALID ((hb_codepoint_t) -1) diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh index b6e2086a2e..ae8b5eb10f 100644 --- a/thirdparty/harfbuzz/src/hb-set.hh +++ b/thirdparty/harfbuzz/src/hb-set.hh @@ -244,7 +244,7 @@ struct hb_set_t bool resize (unsigned int count) { - if (unlikely (!successful)) return false; + if (unlikely (count > pages.length && !successful)) return false; if (!pages.resize (count) || !page_map.resize (count)) { pages.resize (page_map.length); @@ -256,19 +256,14 @@ struct hb_set_t void reset () { - if (unlikely (hb_object_is_immutable (this))) - return; - clear (); successful = true; + clear (); } void clear () { - if (unlikely (hb_object_is_immutable (this))) - return; - population = 0; - page_map.resize (0); - pages.resize (0); + if (resize (0)) + population = 0; } bool is_empty () const { @@ -278,6 +273,7 @@ struct hb_set_t return false; return true; } + explicit operator bool () const { return !is_empty (); } void dirty () { population = UINT_MAX; } @@ -389,6 +385,11 @@ struct hb_set_t { if (ds <= de) { + // Pre-allocate the workspace that compact() will need so we can bail on allocation failure + // before attempting to rewrite the page map. + hb_vector_t<unsigned> compact_workspace; + if (unlikely (!allocate_compact_workspace (compact_workspace))) return; + unsigned int write_index = 0; for (unsigned int i = 0; i < page_map.length; i++) { @@ -396,11 +397,12 @@ struct hb_set_t if (m < ds || de < m) page_map[write_index++] = page_map[i]; } - compact (write_index); + compact (compact_workspace, write_index); resize (write_index); } } + public: void del_range (hb_codepoint_t a, hb_codepoint_t b) { @@ -512,20 +514,37 @@ struct hb_set_t return true; } - void compact (unsigned int length) + bool allocate_compact_workspace(hb_vector_t<unsigned>& workspace) + { + if (unlikely(!workspace.resize (pages.length))) + { + successful = false; + return false; + } + + return true; + } + + + /* + * workspace should be a pre-sized vector allocated to hold at exactly pages.length + * elements. + */ + void compact (hb_vector_t<unsigned>& workspace, + unsigned int length) { - hb_vector_t<uint32_t> old_index_to_page_map_index; - old_index_to_page_map_index.resize(pages.length); - for (uint32_t i = 0; i < old_index_to_page_map_index.length; i++) - old_index_to_page_map_index[i] = 0xFFFFFFFF; + assert(workspace.length == pages.length); + hb_vector_t<unsigned>& old_index_to_page_map_index = workspace; - for (uint32_t i = 0; i < length; i++) + hb_fill (old_index_to_page_map_index.writer(), 0xFFFFFFFF); + /* TODO(iter) Rewrite as dagger? */ + for (unsigned i = 0; i < length; i++) old_index_to_page_map_index[page_map[i].index] = i; compact_pages (old_index_to_page_map_index); } - void compact_pages (const hb_vector_t<uint32_t>& old_index_to_page_map_index) + void compact_pages (const hb_vector_t<unsigned>& old_index_to_page_map_index) { unsigned int write_index = 0; for (unsigned int i = 0; i < pages.length; i++) @@ -543,6 +562,9 @@ struct hb_set_t template <typename Op> void process (const Op& op, const hb_set_t *other) { + const bool passthru_left = op (1, 0); + const bool passthru_right = op (0, 1); + if (unlikely (!successful)) return; dirty (); @@ -554,11 +576,17 @@ struct hb_set_t unsigned int count = 0, newCount = 0; unsigned int a = 0, b = 0; unsigned int write_index = 0; + + // Pre-allocate the workspace that compact() will need so we can bail on allocation failure + // before attempting to rewrite the page map. + hb_vector_t<unsigned> compact_workspace; + if (!passthru_left && unlikely (!allocate_compact_workspace (compact_workspace))) return; + for (; a < na && b < nb; ) { if (page_map[a].major == other->page_map[b].major) { - if (!Op::passthru_left) + if (!passthru_left) { // Move page_map entries that we're keeping from the left side set // to the front of the page_map vector. This isn't necessary if @@ -575,27 +603,27 @@ struct hb_set_t } else if (page_map[a].major < other->page_map[b].major) { - if (Op::passthru_left) + if (passthru_left) count++; a++; } else { - if (Op::passthru_right) + if (passthru_right) count++; b++; } } - if (Op::passthru_left) + if (passthru_left) count += na - a; - if (Op::passthru_right) + if (passthru_right) count += nb - b; - if (!Op::passthru_left) + if (!passthru_left) { na = write_index; next_page = write_index; - compact (write_index); + compact (compact_workspace, write_index); } if (!resize (count)) @@ -619,7 +647,7 @@ struct hb_set_t else if (page_map[a - 1].major > other->page_map[b - 1].major) { a--; - if (Op::passthru_left) + if (passthru_left) { count--; page_map[count] = page_map[a]; @@ -628,7 +656,7 @@ struct hb_set_t else { b--; - if (Op::passthru_right) + if (passthru_right) { count--; page_map[count].major = other->page_map[b].major; @@ -637,14 +665,14 @@ struct hb_set_t } } } - if (Op::passthru_left) + if (passthru_left) while (a) { a--; count--; page_map[count] = page_map [a]; } - if (Op::passthru_right) + if (passthru_right) while (b) { b--; @@ -655,6 +683,9 @@ struct hb_set_t } assert (!count); if (pages.length > newCount) + // This resize() doesn't need to be checked because we can't get here + // if the set is currently in_error() and this only resizes downwards + // which will always succeed if the set is not in_error(). resize (newCount); } diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.cc b/thirdparty/harfbuzz/src/hb-shape-plan.cc index 65a5fc4512..0d9eaddaa6 100644 --- a/thirdparty/harfbuzz/src/hb-shape-plan.cc +++ b/thirdparty/harfbuzz/src/hb-shape-plan.cc @@ -329,12 +329,12 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) * @shape_plan: A shaping plan * @key: The user-data key to set * @data: A pointer to the user data - * @destroy: (optional): A callback to call when @data is not needed anymore + * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * * Attaches a user-data key/data pair to the given shaping plan. * - * Return value: + * Return value: %true if success, %false otherwise. * * Since: 0.9.7 **/ @@ -439,7 +439,7 @@ _hb_shape_plan_execute_internal (hb_shape_plan_t *shape_plan, * Executes the given shaping plan on the specified buffer, using * the given @font and @features. * - * Return value: + * Return value: %true if success, %false otherwise. * * Since: 0.9.7 **/ diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.h b/thirdparty/harfbuzz/src/hb-shape-plan.h index 336524ee2f..fc7c041899 100644 --- a/thirdparty/harfbuzz/src/hb-shape-plan.h +++ b/thirdparty/harfbuzz/src/hb-shape-plan.h @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif diff --git a/thirdparty/harfbuzz/src/hb-shape.cc b/thirdparty/harfbuzz/src/hb-shape.cc index a3debce397..c442f4403b 100644 --- a/thirdparty/harfbuzz/src/hb-shape.cc +++ b/thirdparty/harfbuzz/src/hb-shape.cc @@ -111,10 +111,10 @@ hb_shape_list_shapers () * hb_shape_full: * @font: an #hb_font_t to use for shaping * @buffer: an #hb_buffer_t to shape - * @features: (array length=num_features) (allow-none): an array of user + * @features: (array length=num_features) (nullable): an array of user * specified #hb_feature_t or %NULL * @num_features: the length of @features array - * @shaper_list: (array zero-terminated=1) (allow-none): a %NULL-terminated + * @shaper_list: (array zero-terminated=1) (nullable): a %NULL-terminated * array of shapers to use or %NULL * * See hb_shape() for details. If @shaper_list is not %NULL, the specified @@ -146,7 +146,7 @@ hb_shape_full (hb_font_t *font, * hb_shape: * @font: an #hb_font_t to use for shaping * @buffer: an #hb_buffer_t to shape - * @features: (array length=num_features) (allow-none): an array of user + * @features: (array length=num_features) (nullable): an array of user * specified #hb_feature_t or %NULL * @num_features: the length of @features array * diff --git a/thirdparty/harfbuzz/src/hb-shape.h b/thirdparty/harfbuzz/src/hb-shape.h index 39507ff744..922f8c011e 100644 --- a/thirdparty/harfbuzz/src/hb-shape.h +++ b/thirdparty/harfbuzz/src/hb-shape.h @@ -26,7 +26,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif diff --git a/thirdparty/harfbuzz/src/hb-style.cc b/thirdparty/harfbuzz/src/hb-style.cc index 86b9f7da5f..2f45d119f9 100644 --- a/thirdparty/harfbuzz/src/hb-style.cc +++ b/thirdparty/harfbuzz/src/hb-style.cc @@ -65,6 +65,7 @@ typedef enum { HB_STYLE_TAG_WIDTH = HB_TAG ('w','d','t','h'), HB_STYLE_TAG_WEIGHT = HB_TAG ('w','g','h','t'), + /*< private >*/ _HB_STYLE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/ } hb_style_tag_t; diff --git a/thirdparty/harfbuzz/src/hb-style.h b/thirdparty/harfbuzz/src/hb-style.h index 1209c79e94..f5776cee58 100644 --- a/thirdparty/harfbuzz/src/hb-style.h +++ b/thirdparty/harfbuzz/src/hb-style.h @@ -22,7 +22,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc index 24beada3e8..d055783a4d 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.cc +++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc @@ -88,10 +88,17 @@ _gsub_closure_glyphs_lookups_features (hb_face_t *face, &lookup_indices); _remap_indexes (&lookup_indices, gsub_lookups); - //closure features + // Collect and prune features hb_set_t feature_indices; - gsub->closure_features (gsub_lookups, &feature_indices); + hb_ot_layout_collect_features (face, + HB_OT_TAG_GSUB, + nullptr, + nullptr, + nullptr, + &feature_indices); + gsub->prune_features (gsub_lookups, &feature_indices); _remap_indexes (&feature_indices, gsub_features); + gsub.destroy (); } @@ -114,9 +121,15 @@ _gpos_closure_lookups_features (hb_face_t *face, &lookup_indices); _remap_indexes (&lookup_indices, gpos_lookups); - //closure features + // Collect and prune features hb_set_t feature_indices; - gpos->closure_features (gpos_lookups, &feature_indices); + hb_ot_layout_collect_features (face, + HB_OT_TAG_GPOS, + nullptr, + nullptr, + nullptr, + &feature_indices); + gpos->prune_features (gpos_lookups, &feature_indices); _remap_indexes (&feature_indices, gpos_features); gpos.destroy (); } @@ -243,7 +256,11 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, #ifndef HB_NO_VAR if (close_over_gdef) - _collect_layout_variation_indices (plan->source, plan->_glyphset, plan->gpos_lookups, plan->layout_variation_indices, plan->layout_variation_idx_map); + _collect_layout_variation_indices (plan->source, + plan->_glyphset_gsub, + plan->gpos_lookups, + plan->layout_variation_indices, + plan->layout_variation_idx_map); #endif #ifndef HB_NO_SUBSET_CFF diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh index e9f603dd1d..cc9cb7a1a2 100644 --- a/thirdparty/harfbuzz/src/hb-subset-plan.hh +++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh @@ -172,12 +172,15 @@ struct hb_subset_plan_t add_table (hb_tag_t tag, hb_blob_t *contents) { - hb_blob_t *source_blob = source->reference_table (tag); - DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes", - HB_UNTAG(tag), - hb_blob_get_length (contents), - hb_blob_get_length (source_blob)); - hb_blob_destroy (source_blob); + if (HB_DEBUG_SUBSET) + { + hb_blob_t *source_blob = source->reference_table (tag); + DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes", + HB_UNTAG(tag), + hb_blob_get_length (contents), + hb_blob_get_length (source_blob)); + hb_blob_destroy (source_blob); + } return hb_face_builder_add_table (dest, tag, contents); } }; diff --git a/thirdparty/harfbuzz/src/hb-unicode.cc b/thirdparty/harfbuzz/src/hb-unicode.cc index d7f6a6e130..7470bb1b6e 100644 --- a/thirdparty/harfbuzz/src/hb-unicode.cc +++ b/thirdparty/harfbuzz/src/hb-unicode.cc @@ -276,7 +276,7 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs) * @ufuncs: The Unicode-functions structure * @key: The user-data key * @data: A pointer to the user data - * @destroy: (optional): A callback to call when @data is not needed anymore + * @destroy: (nullable): A callback to call when @data is not needed anymore * @replace: Whether to replace an existing data with the same key * * Attaches a user-data key/data pair to the specified Unicode-functions structure. @@ -340,7 +340,7 @@ hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs) * Tests whether the specified Unicode-functions structure * is immutable. * - * Return value: %true if @ufuncs is immutable, false otherwise + * Return value: %true if @ufuncs is immutable, %false otherwise * * Since: 0.9.2 **/ @@ -421,7 +421,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE * Calls the composition function of the specified * Unicode-functions structure @ufuncs. * - * Return value: %true if @a and @b composed, false otherwise + * Return value: %true if @a and @b composed, %false otherwise * * Since: 0.9.2 **/ @@ -446,7 +446,7 @@ hb_unicode_compose (hb_unicode_funcs_t *ufuncs, * Calls the decomposition function of the specified * Unicode-functions structure @ufuncs. * - * Return value: %true if @ab was decomposed, false otherwise + * Return value: %true if @ab was decomposed, %false otherwise * * Since: 0.9.2 **/ @@ -469,7 +469,7 @@ hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, * Fetches the compatibility decomposition of a Unicode * code point. Deprecated. * - * Return value: + * Return value: length of @decomposed. * * Since: 0.9.2 * Deprecated: 2.0.0 diff --git a/thirdparty/harfbuzz/src/hb-unicode.h b/thirdparty/harfbuzz/src/hb-unicode.h index 7ea0848c0f..c04ee15a09 100644 --- a/thirdparty/harfbuzz/src/hb-unicode.h +++ b/thirdparty/harfbuzz/src/hb-unicode.h @@ -28,7 +28,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif @@ -41,7 +41,9 @@ HB_BEGIN_DECLS /** - * HB_UNICODE_MAX + * HB_UNICODE_MAX: + * + * Maximum valid Unicode code point. * * Since: 1.9.0 **/ @@ -427,7 +429,7 @@ typedef hb_script_t (*hb_unicode_script_func_t) (hb_unicode_funcs_t *ufuncs, * The method must return an #hb_bool_t indicating the success * of the composition. * - * Return value: True is @a,@b composed, false otherwise + * Return value: %true is @a,@b composed, %false otherwise * **/ typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs, @@ -451,7 +453,7 @@ typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs, * output parameters (if successful). The method must return an * #hb_bool_t indicating the success of the composition. * - * Return value: True if @ab decomposed, false otherwise + * Return value: %true if @ab decomposed, %false otherwise * **/ typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs, @@ -467,7 +469,7 @@ typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs, * @ufuncs: A Unicode-functions structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_unicode_combining_class_func_t. * @@ -483,7 +485,7 @@ hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs, * @ufuncs: A Unicode-functions structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_unicode_general_category_func_t. * @@ -499,7 +501,7 @@ hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs, * @ufuncs: A Unicode-functions structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_unicode_mirroring_func_t. * @@ -515,7 +517,7 @@ hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs, * @ufuncs: A Unicode-functions structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_unicode_script_func_t. * @@ -531,7 +533,7 @@ hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs, * @ufuncs: A Unicode-functions structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_unicode_compose_func_t. * @@ -547,7 +549,7 @@ hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t *ufuncs, * @ufuncs: A Unicode-functions structure * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign * @user_data: Data to pass to @func - * @destroy: (optional): The function to call when @user_data is not needed anymore + * @destroy: (nullable): The function to call when @user_data is not needed anymore * * Sets the implementation function for #hb_unicode_decompose_func_t. * @@ -624,40 +626,12 @@ HB_EXTERN hb_script_t hb_unicode_script (hb_unicode_funcs_t *ufuncs, hb_codepoint_t unicode); -/** - * hb_unicode_compose: - * @ufuncs: The Unicode-functions structure - * @a: The first code point to compose - * @b: The second code point to compose - * @ab: (out): The composed code point - * - * Composes the code point sequence @a,@b by canonical equivalence into - * code point @ab. - * - * Return value: True is @a,@b composed, false otherwise - * - * Since: 0.9.2 - **/ HB_EXTERN hb_bool_t hb_unicode_compose (hb_unicode_funcs_t *ufuncs, hb_codepoint_t a, hb_codepoint_t b, hb_codepoint_t *ab); -/** - * hb_unicode_decompose: - * @ufuncs: The Unicode-functions structure - * @ab: The code point to decompose - * @a: (out): The first decomposed code point - * @b: (out): The second decomposed code point - * - * Decomposes code point @ab by canonical equivalence, into code points - * @a and @b. - * - * Return value: True if @ab decomposed, false otherwise - * - * Since: 0.9.2 - **/ HB_EXTERN hb_bool_t hb_unicode_decompose (hb_unicode_funcs_t *ufuncs, hb_codepoint_t ab, diff --git a/thirdparty/harfbuzz/src/hb-vector.hh b/thirdparty/harfbuzz/src/hb-vector.hh index 079b94a6b4..13517a9c29 100644 --- a/thirdparty/harfbuzz/src/hb-vector.hh +++ b/thirdparty/harfbuzz/src/hb-vector.hh @@ -80,7 +80,12 @@ struct hb_vector_t fini (); } - void reset () { resize (0); } + void reset () + { + if (unlikely (in_error ())) + allocated = length; // Big hack! + resize (0); + } hb_vector_t& operator = (const hb_vector_t &o) { @@ -181,7 +186,7 @@ struct hb_vector_t /* Allocate for size but don't adjust length. */ bool alloc (unsigned int size) { - if (unlikely (allocated < 0)) + if (unlikely (in_error ())) return false; if (likely (size <= (unsigned) allocated)) @@ -195,7 +200,7 @@ struct hb_vector_t Type *new_array = nullptr; bool overflows = - (int) new_allocated < 0 || + (int) in_error () || (new_allocated < (unsigned) allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type)); if (likely (!overflows)) diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h index da377b9df6..6db58c3f7c 100644 --- a/thirdparty/harfbuzz/src/hb-version.h +++ b/thirdparty/harfbuzz/src/hb-version.h @@ -24,7 +24,7 @@ * Google Author(s): Behdad Esfahbod */ -#ifndef HB_H_IN +#if !defined(HB_H_IN) && !defined(HB_NO_SINGLE_HEADER_ERROR) #error "Include <hb.h> instead." #endif @@ -36,12 +36,41 @@ HB_BEGIN_DECLS +/** + * HB_VERSION_MAJOR: + * + * The major component of the library version available at compile-time. + */ #define HB_VERSION_MAJOR 2 -#define HB_VERSION_MINOR 7 -#define HB_VERSION_MICRO 4 +/** + * HB_VERSION_MINOR: + * + * The minor component of the library version available at compile-time. + */ +#define HB_VERSION_MINOR 8 +/** + * HB_VERSION_MICRO: + * + * The micro component of the library version available at compile-time. + */ +#define HB_VERSION_MICRO 0 -#define HB_VERSION_STRING "2.7.4" +/** + * HB_VERSION_STRING: + * + * A string literal containing the library version available at compile-time. + */ +#define HB_VERSION_STRING "2.8.0" +/** + * HB_VERSION_ATLEAST: + * @major: the major component of the version number + * @minor: the minor component of the version number + * @micro: the micro component of the version number + * + * Tests the library version at compile-time against a minimum value, + * as three integer components. + */ #define HB_VERSION_ATLEAST(major,minor,micro) \ ((major)*10000+(minor)*100+(micro) <= \ HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO) diff --git a/thirdparty/harfbuzz/src/hb.hh b/thirdparty/harfbuzz/src/hb.hh index 274a0e98db..18516581c7 100644 --- a/thirdparty/harfbuzz/src/hb.hh +++ b/thirdparty/harfbuzz/src/hb.hh @@ -62,7 +62,6 @@ /* Error. Should never happen. */ #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR -#pragma GCC diagnostic error "-Wc++11-narrowing" #pragma GCC diagnostic error "-Wcast-align" #pragma GCC diagnostic error "-Wcast-function-type" #pragma GCC diagnostic error "-Wdelete-non-virtual-dtor" @@ -75,6 +74,7 @@ #pragma GCC diagnostic error "-Wmissing-braces" #pragma GCC diagnostic error "-Wmissing-declarations" #pragma GCC diagnostic error "-Wmissing-prototypes" +#pragma GCC diagnostic error "-Wnarrowing" #pragma GCC diagnostic error "-Wnested-externs" #pragma GCC diagnostic error "-Wold-style-definition" #pragma GCC diagnostic error "-Wpointer-arith" @@ -126,6 +126,7 @@ #pragma GCC diagnostic ignored "-Wformat-zero-length" #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #pragma GCC diagnostic ignored "-Wpacked" // Erratic impl in clang +#pragma GCC diagnostic ignored "-Wrange-loop-analysis" // https://github.com/harfbuzz/harfbuzz/issues/2834 #pragma GCC diagnostic ignored "-Wstrict-aliasing" #pragma GCC diagnostic ignored "-Wtype-limits" #pragma GCC diagnostic ignored "-Wc++11-compat" // only gcc raises it @@ -175,15 +176,15 @@ #include "hb-aat.h" #define HB_AAT_H_IN -#include <limits.h> -#include <math.h> -#include <float.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <assert.h> -#include <stdio.h> -#include <stdarg.h> +#include <cassert> +#include <cfloat> +#include <climits> +#include <cmath> +#include <cstdarg> +#include <cstddef> +#include <cstdio> +#include <cstdlib> +#include <cstring> #if (defined(_MSC_VER) && _MSC_VER >= 1500) || defined(__MINGW32__) #ifdef __MINGW32_VERSION @@ -244,12 +245,8 @@ extern "C" void hb_free_impl(void *ptr); #endif #if defined(__GNUC__) && (__GNUC__ >= 3) -#define HB_PURE_FUNC __attribute__((pure)) -#define HB_CONST_FUNC __attribute__((const)) #define HB_PRINTF_FUNC(format_idx, arg_idx) __attribute__((__format__ (__printf__, format_idx, arg_idx))) #else -#define HB_PURE_FUNC -#define HB_CONST_FUNC #define HB_PRINTF_FUNC(format_idx, arg_idx) #endif #if defined(__GNUC__) && (__GNUC__ >= 4) || (__clang__) @@ -394,7 +391,7 @@ extern "C" void hb_free_impl(void *ptr); #endif #ifndef HB_NO_ERRNO -# include <errno.h> +# include <cerrno> #else static int HB_UNUSED _hb_errno = 0; # undef errno @@ -440,181 +437,12 @@ static int HB_UNUSED _hb_errno = 0; #define HB_STMT_START do #define HB_STMT_END while (0) -/* Static-assert as expression. */ -template <unsigned int cond> class hb_assert_constant_t; -template <> class hb_assert_constant_t<1> {}; -#define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>)) - /* Lets assert int types. Saves trouble down the road. */ -static_assert ((sizeof (int8_t) == 1), ""); -static_assert ((sizeof (uint8_t) == 1), ""); -static_assert ((sizeof (int16_t) == 2), ""); -static_assert ((sizeof (uint16_t) == 2), ""); -static_assert ((sizeof (int32_t) == 4), ""); -static_assert ((sizeof (uint32_t) == 4), ""); -static_assert ((sizeof (int64_t) == 8), ""); -static_assert ((sizeof (uint64_t) == 8), ""); static_assert ((sizeof (hb_codepoint_t) == 4), ""); static_assert ((sizeof (hb_position_t) == 4), ""); static_assert ((sizeof (hb_mask_t) == 4), ""); static_assert ((sizeof (hb_var_int_t) == 4), ""); -#define HB_DELETE_COPY_ASSIGN(TypeName) \ - TypeName(const TypeName&) = delete; \ - void operator=(const TypeName&) = delete -#define HB_DELETE_CREATE_COPY_ASSIGN(TypeName) \ - TypeName() = delete; \ - TypeName(const TypeName&) = delete; \ - void operator=(const TypeName&) = delete - - -/* Flags */ - -/* Enable bitwise ops on enums marked as flags_t */ -/* To my surprise, looks like the function resolver is happy to silently cast - * one enum to another... So this doesn't provide the type-checking that I - * originally had in mind... :(. - * - * For MSVC warnings, see: https://github.com/harfbuzz/harfbuzz/pull/163 - */ -#ifdef _MSC_VER -# pragma warning(disable:4200) -# pragma warning(disable:4800) -#endif -#define HB_MARK_AS_FLAG_T(T) \ - extern "C++" { \ - static inline T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \ - static inline T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \ - static inline T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \ - static inline T operator ~ (T r) { return T (~(unsigned int) r); } \ - static inline T& operator |= (T &l, T r) { l = l | r; return l; } \ - static inline T& operator &= (T& l, T r) { l = l & r; return l; } \ - static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \ - } \ - static_assert (true, "") - -/* Useful for set-operations on small enums. - * For example, for testing "x ∈ {x1, x2, x3}" use: - * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3))) - */ -#define FLAG(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 32) + (((uint32_t) 1U) << (unsigned)(x))) -#define FLAG_UNSAFE(x) ((unsigned)(x) < 32 ? (((uint32_t) 1U) << (unsigned)(x)) : 0) -#define FLAG_RANGE(x,y) (ASSERT_STATIC_EXPR_ZERO ((x) < (y)) + FLAG(y+1) - FLAG(x)) -#define FLAG64(x) (ASSERT_STATIC_EXPR_ZERO ((unsigned)(x) < 64) + (((uint64_t) 1ULL) << (unsigned)(x))) -#define FLAG64_UNSAFE(x) ((unsigned)(x) < 64 ? (((uint64_t) 1ULL) << (unsigned)(x)) : 0) - - -/* Size signifying variable-sized array */ -#ifndef HB_VAR_ARRAY -#define HB_VAR_ARRAY 1 -#endif - -static inline float -_hb_roundf (float x) { return floorf (x + .5f); } -#define roundf(x) _hb_roundf(x) - -/* Endian swap, used in Windows related backends */ -static inline uint16_t hb_uint16_swap (const uint16_t v) -{ return (v >> 8) | (v << 8); } -static inline uint32_t hb_uint32_swap (const uint32_t v) -{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); } - -/* - * Big-endian integers. Here because fundamental. - */ - -template <typename Type, int Bytes> struct BEInt; - -template <typename Type> -struct BEInt<Type, 1> -{ - public: - BEInt<Type, 1>& operator = (Type V) - { - v = V; - return *this; - } - operator Type () const { return v; } - private: uint8_t v; -}; -template <typename Type> -struct BEInt<Type, 2> -{ - public: - BEInt<Type, 2>& operator = (Type V) - { - v[0] = (V >> 8) & 0xFF; - v[1] = (V ) & 0xFF; - return *this; - } - operator Type () const - { -#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \ - defined(__BYTE_ORDER) && \ - (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN) - /* Spoon-feed the compiler a big-endian integer with alignment 1. - * https://github.com/harfbuzz/harfbuzz/pull/1398 */ - struct __attribute__((packed)) packed_uint16_t { uint16_t v; }; -#if __BYTE_ORDER == __LITTLE_ENDIAN - return __builtin_bswap16 (((packed_uint16_t *) this)->v); -#else /* __BYTE_ORDER == __BIG_ENDIAN */ - return ((packed_uint16_t *) this)->v; -#endif -#endif - return (v[0] << 8) - + (v[1] ); - } - private: uint8_t v[2]; -}; -template <typename Type> -struct BEInt<Type, 3> -{ - public: - BEInt<Type, 3>& operator = (Type V) - { - v[0] = (V >> 16) & 0xFF; - v[1] = (V >> 8) & 0xFF; - v[2] = (V ) & 0xFF; - return *this; - } - operator Type () const - { - return (v[0] << 16) - + (v[1] << 8) - + (v[2] ); - } - private: uint8_t v[3]; -}; -template <typename Type> -struct BEInt<Type, 4> -{ - public: - BEInt<Type, 4>& operator = (Type V) - { - v[0] = (V >> 24) & 0xFF; - v[1] = (V >> 16) & 0xFF; - v[2] = (V >> 8) & 0xFF; - v[3] = (V ) & 0xFF; - return *this; - } - operator Type () const - { - return (v[0] << 24) - + (v[1] << 16) - + (v[2] << 8) - + (v[3] ); - } - private: uint8_t v[4]; -}; - - -/* - * For lack of a better place, put Zawgyi script hack here. - * https://github.com/harfbuzz/harfbuzz/issues/1162 - */ - -#define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g')) - /* Headers we include for everyone. Keep topologically sorted by dependency. * They express dependency amongst themselves, but no other file should include diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h index e17bc7e306..610f5d1f50 100644 --- a/thirdparty/mbedtls/include/mbedtls/config.h +++ b/thirdparty/mbedtls/include/mbedtls/config.h @@ -1747,6 +1747,23 @@ //#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT /** + * \def MBEDTLS_TEST_HOOKS + * + * Enable features for invasive testing such as introspection functions and + * hooks for fault injection. This enables additional unit tests. + * + * Merely enabling this feature should not change the behavior of the product. + * It only adds new code, and new branching points where the default behavior + * is the same as when this feature is disabled. + * However, this feature increases the attack surface: there is an added + * risk of vulnerabilities, and more gadgets that can make exploits easier. + * Therefore this feature must never be enabled in production. + * + * Uncomment to enable invasive tests. + */ +//#define MBEDTLS_TEST_HOOKS + +/** * \def MBEDTLS_THREADING_ALT * * Provide your own alternate threading implementation. diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h index 278fbbbb7a..6c099adf4d 100644 --- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h @@ -214,6 +214,13 @@ typedef struct mbedtls_ctr_drbg_context void *p_entropy; /*!< The context for the entropy function. */ #if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized if and only if f_entropy != NULL. + * This means that the mutex is initialized during the initial seeding + * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ mbedtls_threading_mutex_t mutex; #endif } @@ -277,6 +284,15 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); * device. */ #endif +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ /** * \param ctx The CTR_DRBG context to seed. * It must have been initialized with @@ -286,6 +302,8 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); * the same context unless you call * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() * again first. + * After a failed call to mbedtls_ctr_drbg_seed(), + * you must call mbedtls_ctr_drbg_free(). * \param f_entropy The entropy callback, taking as arguments the * \p p_entropy context, the buffer to fill, and the * length of the buffer. @@ -377,6 +395,11 @@ void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, * \brief This function reseeds the CTR_DRBG context, that is * extracts data from the entropy source. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param ctx The CTR_DRBG context. * \param additional Additional data to add to the state. Can be \c NULL. * \param len The length of the additional data. @@ -394,6 +417,11 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, /** * \brief This function updates the state of the CTR_DRBG context. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param ctx The CTR_DRBG context. * \param additional The data to update the state with. This must not be * \c NULL unless \p add_len is \c 0. @@ -417,6 +445,11 @@ int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param p_rng The CTR_DRBG context. This must be a pointer to a * #mbedtls_ctr_drbg_context structure. * \param output The buffer to fill. @@ -445,8 +478,16 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. - * - * + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** * \param p_rng The CTR_DRBG context. This must be a pointer to a * #mbedtls_ctr_drbg_context structure. * \param output The buffer to fill. diff --git a/thirdparty/mbedtls/include/mbedtls/entropy.h b/thirdparty/mbedtls/include/mbedtls/entropy.h index 1e1d3f56ec..1d6e9b821b 100644 --- a/thirdparty/mbedtls/include/mbedtls/entropy.h +++ b/thirdparty/mbedtls/include/mbedtls/entropy.h @@ -147,13 +147,15 @@ mbedtls_entropy_source_state; */ typedef struct mbedtls_entropy_context { - int accumulator_started; + int accumulator_started; /* 0 after init. + * 1 after the first update. + * -1 after free. */ #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) mbedtls_sha512_context accumulator; #else mbedtls_sha256_context accumulator; #endif - int source_count; + int source_count; /* Number of entries used in source. */ mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; #if defined(MBEDTLS_HAVEGE_C) mbedtls_havege_state havege_data; diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h index 970c033c15..5718e187a9 100644 --- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h +++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h @@ -128,6 +128,14 @@ typedef struct mbedtls_hmac_drbg_context void *p_entropy; /*!< context for the entropy function */ #if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized if and only if + * md_ctx->md_info != NULL. This means that the mutex is initialized + * during the initial seeding in mbedtls_hmac_drbg_seed() or + * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ mbedtls_threading_mutex_t mutex; #endif } mbedtls_hmac_drbg_context; @@ -177,7 +185,17 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); * \note During the initial seeding, this function calls * the entropy source to obtain a nonce * whose length is half the entropy length. - * + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** * \param ctx HMAC_DRBG context to be seeded. * \param md_info MD algorithm to use for HMAC_DRBG. * \param f_entropy The entropy callback, taking as arguments the @@ -216,7 +234,17 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, * * This function is meant for use in algorithms that need a pseudorandom * input such as deterministic ECDSA. - * + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** * \param ctx HMAC_DRBG context to be initialised. * \param md_info MD algorithm to use for HMAC_DRBG. * \param data Concatenation of the initial entropy string and @@ -279,6 +307,11 @@ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, /** * \brief This function updates the state of the HMAC_DRBG context. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param ctx The HMAC_DRBG context. * \param additional The data to update the state with. * If this is \c NULL, there is no additional data. @@ -295,6 +328,11 @@ int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, * \brief This function reseeds the HMAC_DRBG context, that is * extracts data from the entropy source. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param ctx The HMAC_DRBG context. * \param additional Additional data to add to the state. * If this is \c NULL, there is no additional data @@ -320,6 +358,11 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * * \param p_rng The HMAC_DRBG context. This must be a pointer to a * #mbedtls_hmac_drbg_context structure. * \param output The buffer to fill. @@ -349,7 +392,16 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng, * * This function automatically reseeds if the reseed counter is exceeded * or prediction resistance is enabled. - * + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** * \param p_rng The HMAC_DRBG context. This must be a pointer to a * #mbedtls_hmac_drbg_context structure. * \param output The buffer to fill. diff --git a/thirdparty/mbedtls/include/mbedtls/net_sockets.h b/thirdparty/mbedtls/include/mbedtls/net_sockets.h index 00fea7db19..c6e1a0270e 100644 --- a/thirdparty/mbedtls/include/mbedtls/net_sockets.h +++ b/thirdparty/mbedtls/include/mbedtls/net_sockets.h @@ -151,6 +151,7 @@ int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char * * \return 0 if successful, or one of: * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, * MBEDTLS_ERR_NET_BIND_FAILED, * MBEDTLS_ERR_NET_LISTEN_FAILED * @@ -170,6 +171,8 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char * can be NULL if client_ip is null * * \return 0 if successful, or + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, * MBEDTLS_ERR_NET_ACCEPT_FAILED, or * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to @@ -182,6 +185,10 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx, /** * \brief Check and wait for the context to be ready for read/write * + * \note The current implementation of this function uses + * select() and returns an error if the file descriptor + * is \c FD_SETSIZE or greater. + * * \param ctx Socket to check * \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and * MBEDTLS_NET_POLL_WRITE specifying the events @@ -263,16 +270,21 @@ int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); * 'timeout' seconds. If no error occurs, the actual amount * read is returned. * + * \note The current implementation of this function uses + * select() and returns an error if the file descriptor + * is \c FD_SETSIZE or greater. + * * \param ctx Socket * \param buf The buffer to write to * \param len Maximum length of the buffer * \param timeout Maximum number of milliseconds to wait for data * 0 means no timeout (wait forever) * - * \return the number of bytes received, - * or a non-zero error code: - * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \return The number of bytes received if successful. + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out. * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * Another negative error code (MBEDTLS_ERR_NET_xxx) + * for other failures. * * \note This function will block (until data becomes available or * timeout is reached) even if the socket is set to diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h index 188c37cf3a..b2f65334fe 100644 --- a/thirdparty/mbedtls/include/mbedtls/rsa.h +++ b/thirdparty/mbedtls/include/mbedtls/rsa.h @@ -124,7 +124,10 @@ extern "C" { */ typedef struct mbedtls_rsa_context { - int ver; /*!< Always 0.*/ + int ver; /*!< Reserved for internal purposes. + * Do not set this field in application + * code. Its meaning might change without + * notice. */ size_t len; /*!< The size of \p N in Bytes. */ mbedtls_mpi N; /*!< The public modulus. */ @@ -154,6 +157,7 @@ typedef struct mbedtls_rsa_context mask generating function used in the EME-OAEP and EMSA-PSS encodings. */ #if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized iff ver != 0. */ mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ #endif } diff --git a/thirdparty/mbedtls/include/mbedtls/threading.h b/thirdparty/mbedtls/include/mbedtls/threading.h index a8183a6ef4..45161ce467 100644 --- a/thirdparty/mbedtls/include/mbedtls/threading.h +++ b/thirdparty/mbedtls/include/mbedtls/threading.h @@ -73,6 +73,9 @@ extern "C" { typedef struct mbedtls_threading_mutex_t { pthread_mutex_t mutex; + /* is_valid is 0 after a failed init or a free, and nonzero after a + * successful init. This field is not considered part of the public + * API of Mbed TLS and may change without notice. */ char is_valid; } mbedtls_threading_mutex_t; #endif diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h index 5f0a8f114c..bd5c730c1d 100644 --- a/thirdparty/mbedtls/include/mbedtls/version.h +++ b/thirdparty/mbedtls/include/mbedtls/version.h @@ -65,16 +65,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 16 -#define MBEDTLS_VERSION_PATCH 9 +#define MBEDTLS_VERSION_PATCH 10 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x02100900 -#define MBEDTLS_VERSION_STRING "2.16.9" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.9" +#define MBEDTLS_VERSION_NUMBER 0x02100A00 +#define MBEDTLS_VERSION_STRING "2.16.10" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.10" #if defined(MBEDTLS_VERSION_C) diff --git a/thirdparty/mbedtls/library/base64.c b/thirdparty/mbedtls/library/base64.c index bfafb05353..692e11e3fa 100644 --- a/thirdparty/mbedtls/library/base64.c +++ b/thirdparty/mbedtls/library/base64.c @@ -97,6 +97,99 @@ static const unsigned char base64_dec_map[128] = #define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ /* + * Constant flow conditional assignment to unsigned char + */ +static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src, + unsigned char condition ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* Generate bitmask from condition, mask will either be 0xFF or 0 */ + unsigned char mask = ( condition | -condition ); + mask >>= 7; + mask = -mask; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask ); +} + +/* + * Constant flow conditional assignment to uint_32 + */ +static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src, + uint32_t condition ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */ + uint32_t mask = ( condition | -condition ); + mask >>= 31; + mask = -mask; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + *dest = ( src & mask ) | ( ( *dest ) & ~mask ); +} + +/* + * Constant flow check for equality + */ +static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b ) +{ + size_t difference = in_a ^ in_b; + + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + difference |= -difference; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* cope with the varying size of size_t per platform */ + difference >>= ( sizeof( difference ) * 8 - 1 ); + + return (unsigned char) ( 1 ^ difference ); +} + +/* + * Constant flow lookup into table. + */ +static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table, + const size_t table_size, const size_t table_index ) +{ + size_t i; + unsigned char result = 0; + + for( i = 0; i < table_size; ++i ) + { + mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) ); + } + + return result; +} + +/* * Encode a buffer into base64 format */ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, @@ -136,10 +229,17 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, C2 = *src++; C3 = *src++; - *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; - *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; - *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; - *p++ = base64_enc_map[C3 & 0x3F]; + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( C1 >> 2 ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( C3 & 0x3F ) ); } if( i < slen ) @@ -147,11 +247,15 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, C1 = *src++; C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; - *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; - *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( C1 >> 2 ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) ); if( ( i + 1 ) < slen ) - *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( C2 & 15 ) << 2 ) & 0x3F ) ); else *p++ = '='; *p++ = '='; @@ -172,6 +276,7 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, size_t i, n; uint32_t j, x; unsigned char *p; + unsigned char dec_map_lookup; /* First pass: check for validity and get output length */ for( i = n = j = 0; i < slen; i++ ) @@ -202,10 +307,12 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, if( src[i] == '=' && ++j > 2 ) return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) + dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] ); + + if( src[i] > 127 || dec_map_lookup == 127 ) return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - if( base64_dec_map[src[i]] < 64 && j != 0 ) + if( dec_map_lookup < 64 && j != 0 ) return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); n++; @@ -235,8 +342,10 @@ int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, if( *src == '\r' || *src == '\n' || *src == ' ' ) continue; - j -= ( base64_dec_map[*src] == 64 ); - x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F ); + dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src ); + + mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) ); + x = ( x << 6 ) | ( dec_map_lookup & 0x3F ); if( ++n == 4 ) { diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c index 2feb727d89..f133f6c13c 100644 --- a/thirdparty/mbedtls/library/bignum.c +++ b/thirdparty/mbedtls/library/bignum.c @@ -1354,6 +1354,12 @@ int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi for( n = B->n; n > 0; n-- ) if( B->p[n - 1] != 0 ) break; + if( n > A->n ) + { + /* B >= (2^ciL)^n > A */ + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } carry = mpi_sub_hlp( n, X->p, B->p ); if( carry != 0 ) diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c index e92008bbe8..90264e844a 100644 --- a/thirdparty/mbedtls/library/ctr_drbg.c +++ b/thirdparty/mbedtls/library/ctr_drbg.c @@ -83,10 +83,6 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif } /* @@ -99,14 +95,13 @@ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) return; #if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); + /* The mutex is initialized iff f_entropy is set. */ + if( ctx->f_entropy != NULL ) + mbedtls_mutex_free( &ctx->mutex ); #endif mbedtls_aes_free( &ctx->aes_ctx ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif } void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) @@ -422,6 +417,11 @@ int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + /* The mutex is initialized iff f_entropy is set. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + mbedtls_aes_init( &ctx->aes_ctx ); ctx->f_entropy = f_entropy; diff --git a/thirdparty/mbedtls/library/ecdsa.c b/thirdparty/mbedtls/library/ecdsa.c index da8df9cde2..2456238b17 100644 --- a/thirdparty/mbedtls/library/ecdsa.c +++ b/thirdparty/mbedtls/library/ecdsa.c @@ -247,6 +247,9 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) #endif /* MBEDTLS_ECP_RESTARTABLE */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \ + !defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + !defined(MBEDTLS_ECDSA_VERIFY_ALT) /* * Derive a suitable integer for group grp from a buffer of length len * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 @@ -269,6 +272,7 @@ static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, cleanup: return( ret ); } +#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */ #if !defined(MBEDTLS_ECDSA_SIGN_ALT) /* @@ -780,6 +784,8 @@ int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, (void) md_alg; #if defined(MBEDTLS_ECDSA_SIGN_ALT) + (void) rs_ctx; + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng ) ); #else @@ -888,6 +894,8 @@ int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, goto cleanup; } #if defined(MBEDTLS_ECDSA_VERIFY_ALT) + (void) rs_ctx; + if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, &ctx->Q, &r, &s ) ) != 0 ) goto cleanup; diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c index f6e24580c7..0532a295e6 100644 --- a/thirdparty/mbedtls/library/ecjpake.c +++ b/thirdparty/mbedtls/library/ecjpake.c @@ -850,6 +850,8 @@ static const unsigned char ecjpake_test_password[] = { 0x65, 0x73, 0x74 }; +#if !defined(MBEDTLS_ECJPAKE_ALT) + static const unsigned char ecjpake_test_x1[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, @@ -994,6 +996,8 @@ cleanup: return( ret ); } +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + /* For tests we don't need a secure RNG; * use the LGC from Numerical Recipes for simplicity */ static int ecjpake_lgc( void *p, unsigned char *out, size_t len ) @@ -1089,6 +1093,12 @@ int mbedtls_ecjpake_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "passed\n" ); +#if !defined(MBEDTLS_ECJPAKE_ALT) + /* 'reference handshake' tests can only be run against implementations + * for which we have 100% control over how the random ephemeral keys + * are generated. This is only the case for the internal mbed TLS + * implementation, so these tests are skipped in case the internal + * implementation is swapped out for an alternative one. */ if( verbose != 0 ) mbedtls_printf( " ECJPAKE test #2 (reference handshake): " ); @@ -1137,6 +1147,7 @@ int mbedtls_ecjpake_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "passed\n" ); +#endif /* ! MBEDTLS_ECJPAKE_ALT */ cleanup: mbedtls_ecjpake_free( &cli ); diff --git a/thirdparty/mbedtls/library/entropy.c b/thirdparty/mbedtls/library/entropy.c index 666c55654c..c5f414a010 100644 --- a/thirdparty/mbedtls/library/entropy.c +++ b/thirdparty/mbedtls/library/entropy.c @@ -146,6 +146,11 @@ void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) { + /* If the context was already free, don't call free() again. + * This is important for mutexes which don't allow double-free. */ + if( ctx->accumulator_started == -1 ) + return; + #if defined(MBEDTLS_HAVEGE_C) mbedtls_havege_free( &ctx->havege_data ); #endif @@ -162,7 +167,7 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) #endif ctx->source_count = 0; mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) ); - ctx->accumulator_started = 0; + ctx->accumulator_started = -1; } int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, diff --git a/thirdparty/mbedtls/library/hmac_drbg.c b/thirdparty/mbedtls/library/hmac_drbg.c index 10cbd462ba..b45d61616f 100644 --- a/thirdparty/mbedtls/library/hmac_drbg.c +++ b/thirdparty/mbedtls/library/hmac_drbg.c @@ -84,10 +84,6 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif } /* @@ -159,6 +155,10 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) return( ret ); +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + /* * Set initial working state. * Use the V memory location, which is currently all 0, to initialize the @@ -284,6 +284,11 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) return( ret ); + /* The mutex is initialized iff the md context is set up. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + md_size = mbedtls_md_get_size( md_info ); /* @@ -451,14 +456,13 @@ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) return; #if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); + /* The mutex is initialized iff the md context is set up. */ + if( ctx->md_ctx.md_info != NULL ) + mbedtls_mutex_free( &ctx->mutex ); #endif mbedtls_md_free( &ctx->md_ctx ); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif } #if defined(MBEDTLS_FS_IO) diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c index 1130408263..671115f15f 100644 --- a/thirdparty/mbedtls/library/net_sockets.c +++ b/thirdparty/mbedtls/library/net_sockets.c @@ -496,6 +496,13 @@ int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ) if( fd < 0 ) return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + /* A limitation of select() is that it only works with file descriptors + * that are strictly less than FD_SETSIZE. This is a limitation of the + * fd_set type. Error out early, because attempting to call FD_SET on a + * large file descriptor is a buffer overflow on typical platforms. */ + if( fd >= FD_SETSIZE ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + #if defined(__has_feature) #if __has_feature(memory_sanitizer) /* Ensure that memory sanitizers consider read_fds and write_fds as @@ -615,6 +622,13 @@ int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, if( fd < 0 ) return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + /* A limitation of select() is that it only works with file descriptors + * that are strictly less than FD_SETSIZE. This is a limitation of the + * fd_set type. Error out early, because attempting to call FD_SET on a + * large file descriptor is a buffer overflow on typical platforms. */ + if( fd >= FD_SETSIZE ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + FD_ZERO( &read_fds ); FD_SET( fd, &read_fds ); diff --git a/thirdparty/mbedtls/library/pkwrite.c b/thirdparty/mbedtls/library/pkwrite.c index 150626c147..a770dfb93e 100644 --- a/thirdparty/mbedtls/library/pkwrite.c +++ b/thirdparty/mbedtls/library/pkwrite.c @@ -455,7 +455,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 * } */ -#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE +#define RSA_PUB_DER_MAX_BYTES ( 38 + 2 * MBEDTLS_MPI_MAX_SIZE ) /* * RSA private keys: @@ -472,10 +472,10 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) * } */ -#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \ - MBEDTLS_MPI_MAX_SIZE % 2 -#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ - + 5 * MPI_MAX_SIZE_2 +#define MPI_MAX_SIZE_2 ( MBEDTLS_MPI_MAX_SIZE / 2 + \ + MBEDTLS_MPI_MAX_SIZE % 2 ) +#define RSA_PRV_DER_MAX_BYTES ( 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + + 5 * MPI_MAX_SIZE_2 ) #else /* MBEDTLS_RSA_C */ @@ -496,7 +496,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ * + 2 * ECP_MAX (coords) [1] * } */ -#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES +#define ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES ) /* * EC private keys: @@ -507,7 +507,7 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above * } */ -#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES +#define ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES ) #else /* MBEDTLS_ECP_C */ @@ -516,10 +516,10 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ #endif /* MBEDTLS_ECP_C */ -#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ - RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES -#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ - RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES +#define PUB_DER_MAX_BYTES ( RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES ) +#define PRV_DER_MAX_BYTES ( RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ + RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES ) int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) { diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c index a25c633bc6..c8c23dba8c 100644 --- a/thirdparty/mbedtls/library/rsa.c +++ b/thirdparty/mbedtls/library/rsa.c @@ -520,6 +520,9 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx, mbedtls_rsa_set_padding( ctx, padding, hash_id ); #if defined(MBEDTLS_THREADING_C) + /* Set ctx->ver to nonzero to indicate that the mutex has been + * initialized and will need to be freed. */ + ctx->ver = 1; mbedtls_mutex_init( &ctx->mutex ); #endif } @@ -567,9 +570,6 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, RSA_VALIDATE_RET( ctx != NULL ); RSA_VALIDATE_RET( f_rng != NULL ); - if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - /* * If the modulus is 1024 bit long or shorter, then the security strength of * the RSA algorithm is less than or equal to 80 bits and therefore an error @@ -582,6 +582,12 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, mbedtls_mpi_init( &G ); mbedtls_mpi_init( &L ); + if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + /* * find primes P and Q with Q < P so that: * 1. |P-Q| > 2^( nbits / 2 - 100 ) @@ -659,7 +665,9 @@ cleanup: if( ret != 0 ) { mbedtls_rsa_free( ctx ); - return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); + if( ( -ret & ~0x7f ) == 0 ) + ret = MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret; + return( ret ); } return( 0 ); @@ -1106,10 +1114,10 @@ cleanup: mbedtls_mpi_free( &C ); mbedtls_mpi_free( &I ); - if( ret != 0 ) + if( ret != 0 && ret >= -0x007f ) return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); - return( 0 ); + return( ret ); } #if defined(MBEDTLS_PKCS1_V21) @@ -2502,7 +2510,6 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) RSA_VALIDATE_RET( dst != NULL ); RSA_VALIDATE_RET( src != NULL ); - dst->ver = src->ver; dst->len = src->len; MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); @@ -2561,7 +2568,12 @@ void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) #endif /* MBEDTLS_RSA_NO_CRT */ #if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); + /* Free the mutex, but only if it hasn't been freed already. */ + if( ctx->ver != 0 ) + { + mbedtls_mutex_free( &ctx->mutex ); + ctx->ver = 0; + } #endif } diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c index f4f29cff5e..0dc5488c1a 100644 --- a/thirdparty/mbedtls/library/threading.c +++ b/thirdparty/mbedtls/library/threading.c @@ -98,6 +98,12 @@ static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) if( mutex == NULL ) return; + /* A nonzero value of is_valid indicates a successfully initialized + * mutex. This is a workaround for not being able to return an error + * code for this function. The lock/unlock functions return an error + * if is_valid is nonzero. The Mbed TLS unit test code uses this field + * to distinguish more states of the mutex; see helpers.function for + * details. */ mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; } diff --git a/thirdparty/mbedtls/library/version_features.c b/thirdparty/mbedtls/library/version_features.c index cbf38dc2c2..8c8e815e9d 100644 --- a/thirdparty/mbedtls/library/version_features.c +++ b/thirdparty/mbedtls/library/version_features.c @@ -553,6 +553,9 @@ static const char *features[] = { #if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT", #endif /* MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT */ +#if defined(MBEDTLS_TEST_HOOKS) + "MBEDTLS_TEST_HOOKS", +#endif /* MBEDTLS_TEST_HOOKS */ #if defined(MBEDTLS_THREADING_ALT) "MBEDTLS_THREADING_ALT", #endif /* MBEDTLS_THREADING_ALT */ diff --git a/thirdparty/meshoptimizer/indexcodec.cpp b/thirdparty/meshoptimizer/indexcodec.cpp index 5c35eb43ae..e4495b8586 100644 --- a/thirdparty/meshoptimizer/indexcodec.cpp +++ b/thirdparty/meshoptimizer/indexcodec.cpp @@ -108,7 +108,7 @@ static unsigned int decodeVByte(const unsigned char*& data) for (int i = 0; i < 4; ++i) { unsigned char group = *data++; - result |= (group & 127) << shift; + result |= unsigned(group & 127) << shift; shift += 7; if (group < 128) diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h index 4071f0a371..1714000384 100644 --- a/thirdparty/meshoptimizer/meshoptimizer.h +++ b/thirdparty/meshoptimizer/meshoptimizer.h @@ -262,7 +262,7 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterExp(void* buffer, size_t ver * The resulting index buffer references vertices from the original vertex buffer. * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended. * - * destination must contain enough space for the *source* index buffer (since optimization is iterative, this means index_count elements - *not* target_index_count!) + * destination must contain enough space for the target index buffer, worst case is index_count elements (*not* target_index_count)! * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer * target_error represents the error relative to mesh extents that can be tolerated, e.g. 0.01 = 1% deformation * result_error can be NULL; when it's not NULL, it will contain the resulting (relative) error after simplification @@ -272,15 +272,17 @@ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, co /** * Experimental: Mesh simplifier (sloppy) * Reduces the number of triangles in the mesh, sacrificing mesh apperance for simplification performance - * The algorithm doesn't preserve mesh topology but is always able to reach target triangle count. + * The algorithm doesn't preserve mesh topology but can stop short of the target goal based on target error. * Returns the number of indices after simplification, with destination containing new index data * The resulting index buffer references vertices from the original vertex buffer. * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended. * - * destination must contain enough space for the target index buffer + * destination must contain enough space for the target index buffer, worst case is index_count elements (*not* target_index_count)! * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer + * target_error represents the error relative to mesh extents that can be tolerated, e.g. 0.01 = 1% deformation + * result_error can be NULL; when it's not NULL, it will contain the resulting (relative) error after simplification */ -MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count); +MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error); /** * Experimental: Point cloud simplifier @@ -289,7 +291,7 @@ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(unsigned int* destinati * The resulting index buffer references vertices from the original vertex buffer. * If the original vertex data isn't required, creating a compact vertex buffer using meshopt_optimizeVertexFetch is recommended. * - * destination must contain enough space for the target index buffer + * destination must contain enough space for the target index buffer (target_vertex_count elements) * vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer */ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_vertex_count); @@ -533,7 +535,7 @@ inline int meshopt_decodeIndexSequence(T* destination, size_t index_count, const template <typename T> inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error = 0); template <typename T> -inline size_t meshopt_simplifySloppy(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count); +inline size_t meshopt_simplifySloppy(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error = 0); template <typename T> inline size_t meshopt_stripify(T* destination, const T* indices, size_t index_count, size_t vertex_count, T restart_index); template <typename T> @@ -855,12 +857,12 @@ inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_co } template <typename T> -inline size_t meshopt_simplifySloppy(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count) +inline size_t meshopt_simplifySloppy(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error) { meshopt_IndexAdapter<T> in(0, indices, index_count); - meshopt_IndexAdapter<T> out(destination, 0, target_index_count); + meshopt_IndexAdapter<T> out(destination, 0, index_count); - return meshopt_simplifySloppy(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count); + return meshopt_simplifySloppy(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count, target_error, result_error); } template <typename T> diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp index 5205b01172..942db14461 100644 --- a/thirdparty/meshoptimizer/simplifier.cpp +++ b/thirdparty/meshoptimizer/simplifier.cpp @@ -1400,7 +1400,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, return result_count; } -size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count) +size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* out_result_error) { using namespace meshopt; @@ -1412,9 +1412,6 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind // we expect to get ~2 triangles/vertex in the output size_t target_cell_count = target_index_count / 6; - if (target_cell_count == 0) - return 0; - meshopt_Allocator allocator; Vector3* vertex_positions = allocator.allocate<Vector3>(vertex_count); @@ -1431,18 +1428,25 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind const int kInterpolationPasses = 5; // invariant: # of triangles in min_grid <= target_count - int min_grid = 0; + int min_grid = int(1.f / (target_error < 1e-3f ? 1e-3f : target_error)); int max_grid = 1025; size_t min_triangles = 0; size_t max_triangles = index_count / 3; + // when we're error-limited, we compute the triangle count for the min. size; this accelerates convergence and provides the correct answer when we can't use a larger grid + if (min_grid > 1) + { + computeVertexIds(vertex_ids, vertex_positions, vertex_count, min_grid); + min_triangles = countTriangles(vertex_ids, indices, index_count); + } + // instead of starting in the middle, let's guess as to what the answer might be! triangle count usually grows as a square of grid size... int next_grid_size = int(sqrtf(float(target_cell_count)) + 0.5f); for (int pass = 0; pass < 10 + kInterpolationPasses; ++pass) { - assert(min_triangles < target_index_count / 3); - assert(max_grid - min_grid > 1); + if (min_triangles >= target_index_count / 3 || max_grid - min_grid <= 1) + break; // we clamp the prediction of the grid size to make sure that the search converges int grid_size = next_grid_size; @@ -1471,16 +1475,18 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind max_triangles = triangles; } - if (triangles == target_index_count / 3 || max_grid - min_grid <= 1) - break; - // we start by using interpolation search - it usually converges faster // however, interpolation search has a worst case of O(N) so we switch to binary search after a few iterations which converges in O(logN) next_grid_size = (pass < kInterpolationPasses) ? int(tip + 0.5f) : (min_grid + max_grid) / 2; } if (min_triangles == 0) + { + if (out_result_error) + *out_result_error = 1.f; + return 0; + } // build vertex->cell association by mapping all vertices with the same quantized position to the same cell size_t table_size = hashBuckets2(vertex_count); @@ -1503,18 +1509,26 @@ size_t meshopt_simplifySloppy(unsigned int* destination, const unsigned int* ind fillCellRemap(cell_remap, cell_errors, cell_count, vertex_cells, cell_quadrics, vertex_positions, vertex_count); + // compute error + float result_error = 0.f; + + for (size_t i = 0; i < cell_count; ++i) + result_error = result_error < cell_errors[i] ? cell_errors[i] : result_error; + // collapse triangles! // note that we need to filter out triangles that we've already output because we very frequently generate redundant triangles between cells :( size_t tritable_size = hashBuckets2(min_triangles); unsigned int* tritable = allocator.allocate<unsigned int>(tritable_size); size_t write = filterTriangles(destination, tritable, tritable_size, indices, index_count, vertex_cells, cell_remap); - assert(write <= target_index_count); #if TRACE - printf("result: %d cells, %d triangles (%d unfiltered)\n", int(cell_count), int(write / 3), int(min_triangles)); + printf("result: %d cells, %d triangles (%d unfiltered), error %e\n", int(cell_count), int(write / 3), int(min_triangles), sqrtf(result_error)); #endif + if (out_result_error) + *out_result_error = sqrtf(result_error); + return write; } diff --git a/thirdparty/miniupnpc/LICENSE b/thirdparty/miniupnpc/LICENSE index 1460310752..6ddd381baa 100644 --- a/thirdparty/miniupnpc/LICENSE +++ b/thirdparty/miniupnpc/LICENSE @@ -1,5 +1,5 @@ -MiniUPnP Project -Copyright (c) 2005-2019, Thomas BERNARD +MiniUPnPc +Copyright (c) 2005-2020, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without @@ -24,3 +24,4 @@ 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. + diff --git a/thirdparty/miniupnpc/miniupnpc/addr_is_reserved.c b/thirdparty/miniupnpc/miniupnpc/addr_is_reserved.c new file mode 100644 index 0000000000..7e586d7da2 --- /dev/null +++ b/thirdparty/miniupnpc/miniupnpc/addr_is_reserved.c @@ -0,0 +1,79 @@ +/* $Id: addr_is_reserved.c,v 1.4 2021/03/02 23:40:32 nanard Exp $ */ +/* vim: tabstop=4 shiftwidth=4 noexpandtab + * Project : miniupnp + * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ + * Author : Thomas BERNARD + * copyright (c) 2005-2021 Thomas Bernard + * This software is subjet to the conditions detailed in the + * provided LICENSE file. */ +#ifdef _WIN32 +/* Win32 Specific includes and defines */ +#include <winsock2.h> +#include <ws2tcpip.h> +#if !defined(_MSC_VER) +#include <stdint.h> +#else /* !defined(_MSC_VER) */ +typedef unsigned long uint32_t; +#endif /* !defined(_MSC_VER) */ +#else /* _WIN32 */ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#endif /* _WIN32 */ + +/* List of IP address blocks which are private / reserved and therefore not suitable for public external IP addresses */ +#define IP(a, b, c, d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) +#define MSK(m) (32-(m)) +static const struct { uint32_t address; uint32_t rmask; } reserved[] = { + { IP( 0, 0, 0, 0), MSK( 8) }, /* RFC1122 "This host on this network" */ + { IP( 10, 0, 0, 0), MSK( 8) }, /* RFC1918 Private-Use */ + { IP(100, 64, 0, 0), MSK(10) }, /* RFC6598 Shared Address Space */ + { IP(127, 0, 0, 0), MSK( 8) }, /* RFC1122 Loopback */ + { IP(169, 254, 0, 0), MSK(16) }, /* RFC3927 Link-Local */ + { IP(172, 16, 0, 0), MSK(12) }, /* RFC1918 Private-Use */ + { IP(192, 0, 0, 0), MSK(24) }, /* RFC6890 IETF Protocol Assignments */ + { IP(192, 0, 2, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-1) */ + { IP(192, 31, 196, 0), MSK(24) }, /* RFC7535 AS112-v4 */ + { IP(192, 52, 193, 0), MSK(24) }, /* RFC7450 AMT */ + { IP(192, 88, 99, 0), MSK(24) }, /* RFC7526 6to4 Relay Anycast */ + { IP(192, 168, 0, 0), MSK(16) }, /* RFC1918 Private-Use */ + { IP(192, 175, 48, 0), MSK(24) }, /* RFC7534 Direct Delegation AS112 Service */ + { IP(198, 18, 0, 0), MSK(15) }, /* RFC2544 Benchmarking */ + { IP(198, 51, 100, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-2) */ + { IP(203, 0, 113, 0), MSK(24) }, /* RFC5737 Documentation (TEST-NET-3) */ + { IP(224, 0, 0, 0), MSK( 4) }, /* RFC1112 Multicast */ + { IP(240, 0, 0, 0), MSK( 4) }, /* RFC1112 Reserved for Future Use + RFC919 Limited Broadcast */ +}; +#undef IP +#undef MSK + +/** + * @return 1 or 0 + */ +int addr_is_reserved(const char * addr_str) +{ + uint32_t addr_n, address; + size_t i; + +#if defined(_WIN32) && (!defined(_WIN32_WINNT_VISTA) || (_WIN32_WINNT < _WIN32_WINNT_VISTA)) + addr_n = inet_addr(addr_str); + if (addr_n == INADDR_NONE) + return 1; +#else + /* was : addr_n = inet_addr(addr_str); */ + if (inet_pton(AF_INET, addr_str, &addr_n) <= 0) { + /* error */ + return 1; + } +#endif + + address = ntohl(addr_n); + + for (i = 0; i < sizeof(reserved)/sizeof(reserved[0]); ++i) { + if ((address >> reserved[i].rmask) == (reserved[i].address >> reserved[i].rmask)) + return 1; + } + + return 0; +} diff --git a/thirdparty/miniupnpc/miniupnpc/addr_is_reserved.h b/thirdparty/miniupnpc/miniupnpc/addr_is_reserved.h new file mode 100644 index 0000000000..f8b5d66a09 --- /dev/null +++ b/thirdparty/miniupnpc/miniupnpc/addr_is_reserved.h @@ -0,0 +1,14 @@ +/* $Id: $ */ +/* vim: tabstop=4 shiftwidth=4 noexpandtab + * Project: miniupnp + * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ + * Author: Thomas Bernard + * Copyright (c) 2005-2020 Thomas Bernard + * This software is subjects to the conditions detailed + * in the LICENCE file provided within this distribution */ +#ifndef ADDR_IS_RESERVED_H_INCLUDED +#define ADDR_IS_RESERVED_H_INCLUDED + +int addr_is_reserved(const char * addr_str); + +#endif /* ADDR_IS_RESERVED_H_INCLUDED */ diff --git a/thirdparty/miniupnpc/miniupnpc/connecthostport.c b/thirdparty/miniupnpc/miniupnpc/connecthostport.c index f3982e1a77..79f832b8db 100644 --- a/thirdparty/miniupnpc/miniupnpc/connecthostport.c +++ b/thirdparty/miniupnpc/miniupnpc/connecthostport.c @@ -1,8 +1,8 @@ -/* $Id: connecthostport.c,v 1.22 2019/10/13 17:22:08 nanard Exp $ */ +/* $Id: connecthostport.c,v 1.24 2020/11/09 19:26:53 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2010-2019 Thomas Bernard + * Copyright (c) 2010-2020 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -19,7 +19,7 @@ #include <ws2tcpip.h> #include <io.h> #define MAXHOSTNAMELEN 64 -#define snprintf _snprintf +#include "win32_snprintf.h" #define herror #define socklen_t int #else /* #ifdef _WIN32 */ diff --git a/thirdparty/miniupnpc/miniupnpc/listdevices.c b/thirdparty/miniupnpc/miniupnpc/listdevices.c deleted file mode 100644 index bd9ba57efc..0000000000 --- a/thirdparty/miniupnpc/miniupnpc/listdevices.c +++ /dev/null @@ -1,197 +0,0 @@ -/* $Id: listdevices.c,v 1.6 2015/07/23 20:40:08 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2013-2015 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#ifdef _WIN32 -#include <winsock2.h> -#endif /* _WIN32 */ -#include "miniupnpc.h" - -struct upnp_dev_list { - struct upnp_dev_list * next; - char * descURL; - struct UPNPDev * * array; - size_t count; - size_t allocated_count; -}; - -#define ADD_DEVICE_COUNT_STEP 16 - -void add_device(struct upnp_dev_list * * list_head, struct UPNPDev * dev) -{ - struct upnp_dev_list * elt; - size_t i; - - if(dev == NULL) - return; - for(elt = *list_head; elt != NULL; elt = elt->next) { - if(strcmp(elt->descURL, dev->descURL) == 0) { - for(i = 0; i < elt->count; i++) { - if (strcmp(elt->array[i]->st, dev->st) == 0 && strcmp(elt->array[i]->usn, dev->usn) == 0) { - return; /* already found */ - } - } - if(elt->count >= elt->allocated_count) { - struct UPNPDev * * tmp; - elt->allocated_count += ADD_DEVICE_COUNT_STEP; - tmp = realloc(elt->array, elt->allocated_count * sizeof(struct UPNPDev *)); - if(tmp == NULL) { - fprintf(stderr, "Failed to realloc(%p, %lu)\n", elt->array, (unsigned long)(elt->allocated_count * sizeof(struct UPNPDev *))); - return; - } - elt->array = tmp; - } - elt->array[elt->count++] = dev; - return; - } - } - elt = malloc(sizeof(struct upnp_dev_list)); - if(elt == NULL) { - fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)sizeof(struct upnp_dev_list)); - return; - } - elt->next = *list_head; - elt->descURL = strdup(dev->descURL); - if(elt->descURL == NULL) { - fprintf(stderr, "Failed to strdup(%s)\n", dev->descURL); - free(elt); - return; - } - elt->allocated_count = ADD_DEVICE_COUNT_STEP; - elt->array = malloc(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *)); - if(elt->array == NULL) { - fprintf(stderr, "Failed to malloc(%lu)\n", (unsigned long)(ADD_DEVICE_COUNT_STEP * sizeof(struct UPNPDev *))); - free(elt->descURL); - free(elt); - return; - } - elt->array[0] = dev; - elt->count = 1; - *list_head = elt; -} - -void free_device(struct upnp_dev_list * elt) -{ - free(elt->descURL); - free(elt->array); - free(elt); -} - -int main(int argc, char * * argv) -{ - const char * searched_device = NULL; - const char * * searched_devices = NULL; - const char * multicastif = 0; - const char * minissdpdpath = 0; - int ipv6 = 0; - unsigned char ttl = 2; - int error = 0; - struct UPNPDev * devlist = 0; - struct UPNPDev * dev; - struct upnp_dev_list * sorted_list = NULL; - struct upnp_dev_list * dev_array; - int i; - -#ifdef _WIN32 - WSADATA wsaData; - int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); - if(nResult != NO_ERROR) - { - fprintf(stderr, "WSAStartup() failed.\n"); - return -1; - } -#endif - - for(i = 1; i < argc; i++) { - if(strcmp(argv[i], "-6") == 0) - ipv6 = 1; - else if(strcmp(argv[i], "-d") == 0) { - if(++i >= argc) { - fprintf(stderr, "%s option needs one argument\n", "-d"); - return 1; - } - searched_device = argv[i]; - } else if(strcmp(argv[i], "-t") == 0) { - if(++i >= argc) { - fprintf(stderr, "%s option needs one argument\n", "-t"); - return 1; - } - ttl = (unsigned char)atoi(argv[i]); - } else if(strcmp(argv[i], "-l") == 0) { - if(++i >= argc) { - fprintf(stderr, "-l option needs at least one argument\n"); - return 1; - } - searched_devices = (const char * *)(argv + i); - break; - } else if(strcmp(argv[i], "-m") == 0) { - if(++i >= argc) { - fprintf(stderr, "-m option needs one argument\n"); - return 1; - } - multicastif = argv[i]; - } else { - printf("usage : %s [options] [-l <device1> <device2> ...]\n", argv[0]); - printf("options :\n"); - printf(" -6 : use IPv6\n"); - printf(" -m address/ifname : network interface to use for multicast\n"); - printf(" -d <device string> : search only for this type of device\n"); - printf(" -l <device1> <device2> ... : search only for theses types of device\n"); - printf(" -t ttl : set multicast TTL. Default value is 2.\n"); - printf(" -h : this help\n"); - return 1; - } - } - - if(searched_device) { - printf("searching UPnP device type %s\n", searched_device); - devlist = upnpDiscoverDevice(searched_device, - 2000, multicastif, minissdpdpath, - 0/*localport*/, ipv6, ttl, &error); - } else if(searched_devices) { - printf("searching UPnP device types :\n"); - for(i = 0; searched_devices[i]; i++) - printf("\t%s\n", searched_devices[i]); - devlist = upnpDiscoverDevices(searched_devices, - 2000, multicastif, minissdpdpath, - 0/*localport*/, ipv6, ttl, &error, 1); - } else { - printf("searching all UPnP devices\n"); - devlist = upnpDiscoverAll(2000, multicastif, minissdpdpath, - 0/*localport*/, ipv6, ttl, &error); - } - if(devlist) { - for(dev = devlist, i = 1; dev != NULL; dev = dev->pNext, i++) { - printf("%3d: %-48s\n", i, dev->st); - printf(" %s\n", dev->descURL); - printf(" %s\n", dev->usn); - add_device(&sorted_list, dev); - } - putchar('\n'); - for (dev_array = sorted_list; dev_array != NULL ; dev_array = dev_array->next) { - printf("%s :\n", dev_array->descURL); - for(i = 0; (unsigned)i < dev_array->count; i++) { - printf("%2d: %s\n", i+1, dev_array->array[i]->st); - printf(" %s\n", dev_array->array[i]->usn); - } - putchar('\n'); - } - freeUPNPDevlist(devlist); - while(sorted_list != NULL) { - dev_array = sorted_list; - sorted_list = sorted_list->next; - free_device(dev_array); - } - } else { - printf("no device found.\n"); - } - - return 0; -} - diff --git a/thirdparty/miniupnpc/miniupnpc/minisoap.c b/thirdparty/miniupnpc/miniupnpc/minisoap.c index f92b36ce89..78606672d5 100644 --- a/thirdparty/miniupnpc/miniupnpc/minisoap.c +++ b/thirdparty/miniupnpc/miniupnpc/minisoap.c @@ -1,8 +1,8 @@ -/* $Id: minisoap.c,v 1.25 2017/04/21 10:03:24 nanard Exp $ */ +/* $Id: minisoap.c,v 1.30 2020/11/09 19:27:42 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard + * Copyright (c) 2005-2020 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. * @@ -13,7 +13,7 @@ #ifdef _WIN32 #include <io.h> #include <winsock2.h> -#define snprintf _snprintf +#include "win32_snprintf.h" #else #include <unistd.h> #include <sys/types.h> diff --git a/thirdparty/miniupnpc/miniupnpc/minissdpc.c b/thirdparty/miniupnpc/miniupnpc/minissdpc.c index 36244dedec..5d3a0fd049 100644 --- a/thirdparty/miniupnpc/miniupnpc/minissdpc.c +++ b/thirdparty/miniupnpc/miniupnpc/minissdpc.c @@ -1,15 +1,15 @@ -/* $Id: minissdpc.c,v 1.40 2019/04/23 12:12:55 nanard Exp $ */ +/* $Id: minissdpc.c,v 1.47 2021/03/02 23:38:30 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp - * Web : http://miniupnp.free.fr/ + * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas BERNARD - * copyright (c) 2005-2019 Thomas Bernard + * copyright (c) 2005-2021 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ -/*#include <syslog.h>*/ #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <time.h> #include <sys/types.h> #if defined (__NetBSD__) #include <net/if.h> @@ -20,7 +20,7 @@ #include <ws2tcpip.h> #include <io.h> #include <iphlpapi.h> -#define snprintf _snprintf +#include "win32_snprintf.h" #if !defined(_MSC_VER) #include <stdint.h> #else /* !defined(_MSC_VER) */ @@ -33,6 +33,12 @@ typedef unsigned short uint16_t; #define strncasecmp memicmp #endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ #endif /* #ifndef strncasecmp */ +#if defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_PARTITION) +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP +#define in6addr_any in6addr_any_init +static const IN6_ADDR in6addr_any_init = {0}; +#endif +#endif #endif /* _WIN32 */ #if defined(__amigaos__) || defined(__amigaos4__) #include <sys/socket.h> @@ -66,7 +72,7 @@ struct sockaddr_un { #define HAS_IP_MREQN #endif -#if !defined(HAS_IP_MREQN) && !defined(_WIN32) +#ifndef _WIN32 #include <sys/ioctl.h> #if defined(__sun) || defined(__HAIKU__) #include <sys/sockio.h> @@ -445,6 +451,36 @@ parseMSEARCHReply(const char * reply, int size, } } +#if defined(CLOCK_MONOTONIC_FAST) +#define UPNP_CLOCKID CLOCK_MONOTONIC_FAST +#elif defined(CLOCK_MONOTONIC) +#define UPNP_CLOCKID CLOCK_MONOTONIC +#endif + +static int upnp_gettimeofday(struct timeval * tv) +{ +#if defined(_WIN32) +#if defined(_WIN32_WINNT_VISTA) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA) + ULONGLONG ts = GetTickCount64(); +#else + DWORD ts = GetTickCount(); +#endif + tv->tv_sec = (long)(ts / 1000); + tv->tv_usec = (ts % 1000) * 1000; + return 0; /* success */ +#elif defined(CLOCK_MONOTONIC_FAST) || defined(CLOCK_MONOTONIC) + struct timespec ts; + int ret_code = clock_gettime(UPNP_CLOCKID, &ts); + if (ret_code == 0) + { + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + } + return ret_code; +#else + return gettimeofday(tv, NULL); +#endif +} /* port upnp discover : SSDP protocol */ #define SSDP_PORT 1900 #define XSTR(s) STR(s) @@ -540,12 +576,17 @@ ssdpDiscoverDevices(const char * const deviceTypes[], * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ if(!ipv6) { DWORD ifbestidx; +#if _WIN32_WINNT >= 0x0600 // _WIN32_WINNT_VISTA + // While we don't need IPv6 support, the IPv4 only funciton is not available in UWP apps. SOCKADDR_IN destAddr; memset(&destAddr, 0, sizeof(destAddr)); destAddr.sin_family = AF_INET; destAddr.sin_addr.s_addr = inet_addr("223.255.255.255"); destAddr.sin_port = 0; if (GetBestInterfaceEx((struct sockaddr *)&destAddr, &ifbestidx) == NO_ERROR) { +#else + if (GetBestInterface(inet_addr("223.255.255.255"), &ifbestidx) == NO_ERROR) { +#endif DWORD dwRetVal = NO_ERROR; PIP_ADAPTER_ADDRESSES pAddresses = NULL; ULONG outBufLen = 15360; @@ -672,6 +713,13 @@ ssdpDiscoverDevices(const char * const deviceTypes[], * MS Windows Vista and MS Windows Server 2008. * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */ unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */ + if(ifindex == 0) + { + if(error) + *error = MINISSDPC_INVALID_INPUT; + fprintf(stderr, "Invalid multicast interface name %s\n", multicastif); + goto error; + } if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0) { PRINT_SOCKET_ERROR("setsockopt IPV6_MULTICAST_IF"); @@ -683,7 +731,18 @@ ssdpDiscoverDevices(const char * const deviceTypes[], #endif } else { struct in_addr mc_if; - mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ +#if defined(_WIN32) +#if defined(_WIN32_WINNT_VISTA) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA) + InetPtonA(AF_INET, multicastif, &mc_if); +#else + mc_if.s_addr = inet_addr(multicastif); /* old Windows SDK do not support InetPtoA() */ +#endif +#else + /* was : mc_if.s_addr = inet_addr(multicastif); */ /* ex: 192.168.x.x */ + if (inet_pton(AF_INET, multicastif, &mc_if.s_addr) <= 0) { + mc_if.s_addr = INADDR_NONE; + } +#endif if(mc_if.s_addr != INADDR_NONE) { ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; @@ -692,16 +751,11 @@ ssdpDiscoverDevices(const char * const deviceTypes[], PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); } } else { -#ifdef HAS_IP_MREQN /* was not an ip address, try with an interface name */ +#ifndef _WIN32 +#ifdef HAS_IP_MREQN struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */ - memset(&reqn, 0, sizeof(struct ip_mreqn)); - reqn.imr_ifindex = if_nametoindex(multicastif); - if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0) - { - PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); - } -#elif !defined(_WIN32) +#endif struct ifreq ifr; int ifrlen = sizeof(ifr); strncpy(ifr.ifr_name, multicastif, IFNAMSIZ); @@ -709,12 +763,30 @@ ssdpDiscoverDevices(const char * const deviceTypes[], if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0) { PRINT_SOCKET_ERROR("ioctl(...SIOCGIFADDR...)"); + goto error; } mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; +#ifdef HAS_IP_MREQN + memset(&reqn, 0, sizeof(struct ip_mreqn)); + reqn.imr_address.s_addr = mc_if.s_addr; + reqn.imr_ifindex = if_nametoindex(multicastif); + if(reqn.imr_ifindex == 0) + { + if(error) + *error = MINISSDPC_INVALID_INPUT; + fprintf(stderr, "Invalid multicast ip address / interface name %s\n", multicastif); + goto error; + } + if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0) + { + PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); + } +#else if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF"); } +#endif #else /* _WIN32 */ #ifdef DEBUG printf("Setting of multicast interface not supported with interface name.\n"); @@ -838,73 +910,84 @@ ssdpDiscoverDevices(const char * const deviceTypes[], /* Waiting for SSDP REPLY packet to M-SEARCH * if searchalltypes is set, enter the loop only * when the last deviceType is reached */ - if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) do { - n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id); - if (n < 0) { - /* error */ - if(error) - *error = MINISSDPC_SOCKET_ERROR; - goto error; - } else if (n == 0) { - /* no data or Time Out */ -#ifdef DEBUG - printf("NODATA or TIMEOUT\n"); -#endif /* DEBUG */ - if (devlist && !searchalltypes) { - /* found some devices, stop now*/ + if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) { + struct timeval start = {0, 0}, current = {0, 0}; + upnp_gettimeofday(&start); + do { + n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id); + if (n < 0) { + /* error */ if(error) - *error = MINISSDPC_SUCCESS; + *error = MINISSDPC_SOCKET_ERROR; goto error; - } - } else { - const char * descURL=NULL; - int urlsize=0; - const char * st=NULL; - int stsize=0; - const char * usn=NULL; - int usnsize=0; - parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize); - if(st&&descURL) { + } else if (n == 0) { + /* no data or Time Out */ #ifdef DEBUG - printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n", - stsize, st, usnsize, (usn?usn:""), urlsize, descURL); + printf("NODATA or TIMEOUT\n"); #endif /* DEBUG */ - for(tmp=devlist; tmp; tmp = tmp->pNext) { - if(strncmp(tmp->descURL, descURL, urlsize) == 0 && - tmp->descURL[urlsize] == '\0' && - strncmp(tmp->st, st, stsize) == 0 && - tmp->st[stsize] == '\0' && - (usnsize == 0 || strncmp(tmp->usn, usn, usnsize) == 0) && - tmp->usn[usnsize] == '\0') - break; - } - /* at the exit of the loop above, tmp is null if - * no duplicate device was found */ - if(tmp) - continue; - tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize); - if(!tmp) { - /* memory allocation error */ + if (devlist && !searchalltypes) { + /* found some devices, stop now*/ if(error) - *error = MINISSDPC_MEMORY_ERROR; + *error = MINISSDPC_SUCCESS; goto error; } - tmp->pNext = devlist; - tmp->descURL = tmp->buffer; - tmp->st = tmp->buffer + 1 + urlsize; - tmp->usn = tmp->st + 1 + stsize; - memcpy(tmp->buffer, descURL, urlsize); - tmp->buffer[urlsize] = '\0'; - memcpy(tmp->st, st, stsize); - tmp->buffer[urlsize+1+stsize] = '\0'; - if(usn != NULL) - memcpy(tmp->usn, usn, usnsize); - tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0'; - tmp->scope_id = scope_id; - devlist = tmp; + } else { + const char * descURL=NULL; + int urlsize=0; + const char * st=NULL; + int stsize=0; + const char * usn=NULL; + int usnsize=0; + parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize); + if(st&&descURL) { +#ifdef DEBUG + printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n", + stsize, st, usnsize, (usn?usn:""), urlsize, descURL); +#endif /* DEBUG */ + for(tmp=devlist; tmp; tmp = tmp->pNext) { + if(strncmp(tmp->descURL, descURL, urlsize) == 0 && + tmp->descURL[urlsize] == '\0' && + strncmp(tmp->st, st, stsize) == 0 && + tmp->st[stsize] == '\0' && + (usnsize == 0 || strncmp(tmp->usn, usn, usnsize) == 0) && + tmp->usn[usnsize] == '\0') + break; + } + /* at the exit of the loop above, tmp is null if + * no duplicate device was found */ + if(tmp) + continue; + tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize+3); + if(!tmp) { + /* memory allocation error */ + if(error) + *error = MINISSDPC_MEMORY_ERROR; + goto error; + } + tmp->pNext = devlist; + tmp->descURL = tmp->buffer; + tmp->st = tmp->buffer + 1 + urlsize; + tmp->usn = tmp->st + 1 + stsize; + memcpy(tmp->buffer, descURL, urlsize); + tmp->buffer[urlsize] = '\0'; + memcpy(tmp->st, st, stsize); + tmp->buffer[urlsize+1+stsize] = '\0'; + if(usn != NULL) + memcpy(tmp->usn, usn, usnsize); + tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0'; + tmp->scope_id = scope_id; + devlist = tmp; + } + if (upnp_gettimeofday(¤t) >= 0) { + /* exit the loop if delay is reached */ + long interval = (current.tv_sec - start.tv_sec) * 1000; + interval += (current.tv_usec - start.tv_usec) / 1000; + if (interval > (long)delay) + break; + } } - } - } while(n > 0); + } while(n > 0); + } if(ipv6) { /* switch linklocal flag */ if(linklocal) { @@ -919,4 +1002,3 @@ error: closesocket(sudp); return devlist; } - diff --git a/thirdparty/miniupnpc/miniupnpc/miniupnpc.c b/thirdparty/miniupnpc/miniupnpc/miniupnpc.c index 95ab6cf56b..696af93237 100644 --- a/thirdparty/miniupnpc/miniupnpc/miniupnpc.c +++ b/thirdparty/miniupnpc/miniupnpc/miniupnpc.c @@ -1,9 +1,9 @@ -/* $Id: miniupnpc.c,v 1.154 2019/04/23 12:12:13 nanard Exp $ */ +/* $Id: miniupnpc.c,v 1.159 2021/03/02 23:36:32 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project : miniupnp - * Web : http://miniupnp.free.fr/ + * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas BERNARD - * copyright (c) 2005-2019 Thomas Bernard + * copyright (c) 2005-2021 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #include <stdlib.h> @@ -15,7 +15,7 @@ #include <ws2tcpip.h> #include <io.h> #include <iphlpapi.h> -#define snprintf _snprintf +#include "win32_snprintf.h" #define strdup _strdup #ifndef strncasecmp #if defined(_MSC_VER) && (_MSC_VER >= 1400) @@ -61,6 +61,7 @@ #include "minixml.h" #include "upnpcommands.h" #include "connecthostport.h" +#include "addr_is_reserved.h" /* compare the beginning of a string with a constant string */ #define COMPARE(str, cstr) (0==strncmp(str, cstr, sizeof(cstr) - 1)) @@ -73,24 +74,6 @@ #define SERVICEPREFIX "u" #define SERVICEPREFIX2 'u' -/* check if an ip address is a private (LAN) address - * see https://tools.ietf.org/html/rfc1918 */ -static int is_rfc1918addr(const char * addr) -{ - /* 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) */ - if(COMPARE(addr, "192.168.")) - return 1; - /* 10.0.0.0 - 10.255.255.255 (10/8 prefix) */ - if(COMPARE(addr, "10.")) - return 1; - /* 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) */ - if(COMPARE(addr, "172.")) { - if((atoi(addr + 4) | 0x0f) == 0x1f) - return 1; - } - return 0; -} - /* root description parsing */ MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data) { @@ -337,6 +320,8 @@ upnpDiscoverDevices(const char * const deviceTypes[], return devlist; } } +#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ + (void)minissdpdsock; /* unused */ #endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ /* direct discovery if minissdpd responses are not sufficient */ @@ -643,8 +628,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, /* checks that status is connected AND there is a external IP address assigned */ if(is_connected && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { - if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0') - && (0 != strcmp(extIpAddr, "0.0.0.0"))) + if(!addr_is_reserved(extIpAddr)) goto free_and_return; } FreeUPNPUrls(urls); @@ -665,8 +649,7 @@ UPNP_GetValidIGD(struct UPNPDev * devlist, #endif if(is_connected && (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) { - if(!is_rfc1918addr(extIpAddr) && (extIpAddr[0] != '\0') - && (0 != strcmp(extIpAddr, "0.0.0.0"))) + if(!addr_is_reserved(extIpAddr)) goto free_and_return; } FreeUPNPUrls(urls); diff --git a/thirdparty/miniupnpc/miniupnpc/miniupnpc.h b/thirdparty/miniupnpc/miniupnpc/miniupnpc.h index 8ddc282bd1..3aef8ea443 100644 --- a/thirdparty/miniupnpc/miniupnpc/miniupnpc.h +++ b/thirdparty/miniupnpc/miniupnpc/miniupnpc.h @@ -1,9 +1,9 @@ -/* $Id: miniupnpc.h,v 1.53 2018/05/07 11:05:16 nanard Exp $ */ +/* $Id: miniupnpc.h,v 1.58 2021/03/02 23:49:52 nanard Exp $ */ /* vim: tabstop=4 shiftwidth=4 noexpandtab * Project: miniupnp * http://miniupnp.free.fr/ * Author: Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard + * Copyright (c) 2005-2021 Thomas Bernard * This software is subjects to the conditions detailed * in the LICENCE file provided within this distribution */ #ifndef MINIUPNPC_H_INCLUDED @@ -20,7 +20,7 @@ #define UPNPDISCOVER_MEMORY_ERROR (-102) /* versions : */ -#define MINIUPNPC_VERSION "2.1" +#define MINIUPNPC_VERSION "2.2.2" #define MINIUPNPC_API_VERSION 17 /* Source port: diff --git a/thirdparty/miniupnpc/miniupnpc/miniupnpc_socketdef.h b/thirdparty/miniupnpc/miniupnpc/miniupnpc_socketdef.h index d4f79a7bd6..5986e58c76 100644 --- a/thirdparty/miniupnpc/miniupnpc/miniupnpc_socketdef.h +++ b/thirdparty/miniupnpc/miniupnpc/miniupnpc_socketdef.h @@ -7,7 +7,7 @@ #ifndef MINIUPNPC_SOCKETDEF_H_INCLUDED #define MINIUPNPC_SOCKETDEF_H_INCLUDED -#ifdef _MSC_VER +#ifdef _WIN32 #define ISINVALID(s) (INVALID_SOCKET==(s)) diff --git a/thirdparty/miniupnpc/miniupnpc/miniupnpcmodule.c b/thirdparty/miniupnpc/miniupnpc/miniupnpcmodule.c deleted file mode 100644 index d9341ab5bf..0000000000 --- a/thirdparty/miniupnpc/miniupnpc/miniupnpcmodule.c +++ /dev/null @@ -1,721 +0,0 @@ -/* $Id: miniupnpcmodule.c,v 1.34 2019/05/20 19:07:16 nanard Exp $*/ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp - * Author : Thomas BERNARD - * website : https://miniupnp.tuxfamily.org/ - * copyright (c) 2007-2019 Thomas Bernard - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#include <Python.h> -#define MINIUPNP_STATICLIB -#include "structmember.h" -#include "miniupnpc.h" -#include "upnpcommands.h" -#include "upnperrors.h" - -#ifdef _WIN32 -#include <winsock2.h> -#endif - -/* for compatibility with Python < 2.4 */ -#ifndef Py_RETURN_NONE -#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None -#endif - -#ifndef Py_RETURN_TRUE -#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True -#endif - -#ifndef Py_RETURN_FALSE -#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False -#endif - -/* for compatibility with Python < 3.0 */ -#ifndef PyVarObject_HEAD_INIT -#define PyVarObject_HEAD_INIT(type, size) \ - PyObject_HEAD_INIT(type) size, -#endif - -#ifndef Py_TYPE -#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) -#endif - -typedef struct { - PyObject_HEAD - /* Type-specific fields go here. */ - struct UPNPDev * devlist; - struct UPNPUrls urls; - struct IGDdatas data; - unsigned int discoverdelay; /* value passed to upnpDiscover() */ - unsigned int localport; /* value passed to upnpDiscover() */ - char lanaddr[40]; /* our ip address on the LAN */ - char * multicastif; - char * minissdpdsocket; -} UPnPObject; - -static PyMemberDef UPnP_members[] = { - {"lanaddr", T_STRING_INPLACE, offsetof(UPnPObject, lanaddr), - READONLY, "ip address on the LAN" - }, - {"discoverdelay", T_UINT, offsetof(UPnPObject, discoverdelay), - 0/*READWRITE*/, "value in ms used to wait for SSDP responses" - }, - {"localport", T_UINT, offsetof(UPnPObject, localport), - 0/*READWRITE*/, - "If localport is set to UPNP_LOCAL_PORT_SAME(1) " - "SSDP packets will be sent from the source port " - "1900 (same as destination port), if set to " - "UPNP_LOCAL_PORT_ANY(0) system assign a source " - "port, any other value will be attempted as the " - "source port" - }, - /* T_STRING is allways readonly :( */ - {"multicastif", T_STRING, offsetof(UPnPObject, multicastif), - 0, "IP of the network interface to be used for multicast operations" - }, - {"minissdpdsocket", T_STRING, offsetof(UPnPObject, minissdpdsocket), - 0, "path of the MiniSSDPd unix socket" - }, - {NULL} -}; - - -static int UPnP_init(UPnPObject *self, PyObject *args, PyObject *kwds) -{ - char* multicastif = NULL; - char* minissdpdsocket = NULL; - static char *kwlist[] = { - "multicastif", "minissdpdsocket", "discoverdelay", - "localport", NULL - }; - - if(!PyArg_ParseTupleAndKeywords(args, kwds, "|zzII", kwlist, - &multicastif, - &minissdpdsocket, - &self->discoverdelay, - &self->localport)) - return -1; - - if(self->localport>1 && - (self->localport>65534||self->localport<1024)) { - PyErr_SetString(PyExc_Exception, "Invalid localport value"); - return -1; - } - if(multicastif) - self->multicastif = strdup(multicastif); - if(minissdpdsocket) - self->minissdpdsocket = strdup(minissdpdsocket); - - return 0; -} - -static void -UPnPObject_dealloc(UPnPObject *self) -{ - freeUPNPDevlist(self->devlist); - FreeUPNPUrls(&self->urls); - free(self->multicastif); - free(self->minissdpdsocket); - Py_TYPE(self)->tp_free((PyObject*)self); -} - -static PyObject * -UPnP_discover(UPnPObject *self) -{ - struct UPNPDev * dev; - int i; - PyObject *res = NULL; - if(self->devlist) - { - freeUPNPDevlist(self->devlist); - self->devlist = 0; - } - Py_BEGIN_ALLOW_THREADS - self->devlist = upnpDiscover((int)self->discoverdelay/*timeout in ms*/, - self->multicastif, - self->minissdpdsocket, - (int)self->localport, - 0/*ip v6*/, - 2/* TTL */, - 0/*error */); - Py_END_ALLOW_THREADS - /* Py_RETURN_NONE ??? */ - for(dev = self->devlist, i = 0; dev; dev = dev->pNext) - i++; - res = Py_BuildValue("i", i); - return res; -} - -static PyObject * -UPnP_selectigd(UPnPObject *self) -{ - int r; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetValidIGD(self->devlist, &self->urls, &self->data, - self->lanaddr, sizeof(self->lanaddr)); -Py_END_ALLOW_THREADS - if(r) - { - return Py_BuildValue("s", self->urls.controlURL); - } - else - { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, "No UPnP device discovered"); - return NULL; - } -} - -static PyObject * -UPnP_totalbytesent(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalBytesSent(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("I", i); -#else - return Py_BuildValue("i", (int)i); -#endif -} - -static PyObject * -UPnP_totalbytereceived(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalBytesReceived(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("I", i); -#else - return Py_BuildValue("i", (int)i); -#endif -} - -static PyObject * -UPnP_totalpacketsent(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalPacketsSent(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("I", i); -#else - return Py_BuildValue("i", (int)i); -#endif -} - -static PyObject * -UPnP_totalpacketreceived(UPnPObject *self) -{ - UNSIGNED_INTEGER i; -Py_BEGIN_ALLOW_THREADS - i = UPNP_GetTotalPacketsReceived(self->urls.controlURL_CIF, - self->data.CIF.servicetype); -Py_END_ALLOW_THREADS -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("I", i); -#else - return Py_BuildValue("i", (int)i); -#endif -} - -static PyObject * -UPnP_statusinfo(UPnPObject *self) -{ - char status[64]; - char lastconnerror[64]; - unsigned int uptime = 0; - int r; - status[0] = '\0'; - lastconnerror[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetStatusInfo(self->urls.controlURL, self->data.first.servicetype, - status, &uptime, lastconnerror); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("(s,I,s)", status, uptime, lastconnerror); -#else - return Py_BuildValue("(s,i,s)", status, (int)uptime, lastconnerror); -#endif - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -static PyObject * -UPnP_connectiontype(UPnPObject *self) -{ - char connectionType[64]; - int r; - connectionType[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetConnectionTypeInfo(self->urls.controlURL, - self->data.first.servicetype, - connectionType); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - return Py_BuildValue("s", connectionType); - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -static PyObject * -UPnP_externalipaddress(UPnPObject *self) -{ - char externalIPAddress[40]; - int r; - externalIPAddress[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetExternalIPAddress(self->urls.controlURL, - self->data.first.servicetype, - externalIPAddress); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - return Py_BuildValue("s", externalIPAddress); - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -/* AddPortMapping(externalPort, protocol, internalHost, internalPort, desc, - * remoteHost, leaseDuration) - * protocol is 'UDP' or 'TCP' */ -static PyObject * -UPnP_addportmapping(UPnPObject *self, PyObject *args) -{ - char extPort[6]; - unsigned short ePort; - char inPort[6]; - unsigned short iPort; - const char * proto; - const char * host; - const char * desc; - const char * remoteHost; - unsigned int intLeaseDuration = 0; - char strLeaseDuration[12]; - int r; -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - if (!PyArg_ParseTuple(args, "HssHzz|I", &ePort, &proto, - &host, &iPort, &desc, &remoteHost, &intLeaseDuration)) -#else - if (!PyArg_ParseTuple(args, "HssHzz|i", &ePort, &proto, - &host, &iPort, &desc, &remoteHost, (int *)&intLeaseDuration)) -#endif - return NULL; -Py_BEGIN_ALLOW_THREADS - sprintf(extPort, "%hu", ePort); - sprintf(inPort, "%hu", iPort); - sprintf(strLeaseDuration, "%u", intLeaseDuration); - r = UPNP_AddPortMapping(self->urls.controlURL, self->data.first.servicetype, - extPort, inPort, host, desc, proto, - remoteHost, strLeaseDuration); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) - { - Py_RETURN_TRUE; - } - else - { - // TODO: RAISE an Exception. See upnpcommands.h for errors codes. - // upnperrors.c - //Py_RETURN_FALSE; - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -/* AddAnyPortMapping(externalPort, protocol, internalHost, internalPort, desc, - * remoteHost) - * protocol is 'UDP' or 'TCP' */ -static PyObject * -UPnP_addanyportmapping(UPnPObject *self, PyObject *args) -{ - char extPort[6]; - unsigned short ePort; - char inPort[6]; - unsigned short iPort; - char reservedPort[6]; - const char * proto; - const char * host; - const char * desc; - const char * remoteHost; - const char * leaseDuration = "0"; - int r; - if (!PyArg_ParseTuple(args, "HssHzz", &ePort, &proto, &host, &iPort, &desc, &remoteHost)) - return NULL; -Py_BEGIN_ALLOW_THREADS - sprintf(extPort, "%hu", ePort); - sprintf(inPort, "%hu", iPort); - r = UPNP_AddAnyPortMapping(self->urls.controlURL, self->data.first.servicetype, - extPort, inPort, host, desc, proto, - remoteHost, leaseDuration, reservedPort); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - return Py_BuildValue("i", atoi(reservedPort)); - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - - -/* DeletePortMapping(extPort, proto, removeHost='') - * proto = 'UDP', 'TCP' */ -static PyObject * -UPnP_deleteportmapping(UPnPObject *self, PyObject *args) -{ - char extPort[6]; - unsigned short ePort; - const char * proto; - const char * remoteHost = ""; - int r; - if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost)) - return NULL; -Py_BEGIN_ALLOW_THREADS - sprintf(extPort, "%hu", ePort); - r = UPNP_DeletePortMapping(self->urls.controlURL, self->data.first.servicetype, - extPort, proto, remoteHost); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - Py_RETURN_TRUE; - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -/* DeletePortMappingRange(extPort, proto, removeHost='') - * proto = 'UDP', 'TCP' */ -static PyObject * -UPnP_deleteportmappingrange(UPnPObject *self, PyObject *args) -{ - char extPortStart[6]; - unsigned short ePortStart; - char extPortEnd[6]; - unsigned short ePortEnd; - const char * proto; - unsigned char manage; - char manageStr[6]; - int r; - if(!PyArg_ParseTuple(args, "HHsb", &ePortStart, &ePortEnd, &proto, &manage)) - return NULL; -Py_BEGIN_ALLOW_THREADS - sprintf(extPortStart, "%hu", ePortStart); - sprintf(extPortEnd, "%hu", ePortEnd); - sprintf(manageStr, "%hu", (unsigned short)manage); - r = UPNP_DeletePortMappingRange(self->urls.controlURL, self->data.first.servicetype, - extPortStart, extPortEnd, proto, manageStr); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { - Py_RETURN_TRUE; - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -static PyObject * -UPnP_getportmappingnumberofentries(UPnPObject *self) -{ - unsigned int n = 0; - int r; -Py_BEGIN_ALLOW_THREADS - r = UPNP_GetPortMappingNumberOfEntries(self->urls.controlURL, - self->data.first.servicetype, - &n); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) { -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("I", n); -#else - return Py_BuildValue("i", (int)n); -#endif - } else { - /* TODO: have our own exception type ! */ - PyErr_SetString(PyExc_Exception, strupnperror(r)); - return NULL; - } -} - -/* GetSpecificPortMapping(ePort, proto, remoteHost='') - * proto = 'UDP' or 'TCP' */ -static PyObject * -UPnP_getspecificportmapping(UPnPObject *self, PyObject *args) -{ - char extPort[6]; - unsigned short ePort; - const char * proto; - const char * remoteHost = ""; - char intClient[40]; - char intPort[6]; - unsigned short iPort; - char desc[80]; - char enabled[4]; - char leaseDuration[16]; - if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost)) - return NULL; - extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0'; - desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0'; -Py_BEGIN_ALLOW_THREADS - sprintf(extPort, "%hu", ePort); - UPNP_GetSpecificPortMappingEntry(self->urls.controlURL, - self->data.first.servicetype, - extPort, proto, remoteHost, - intClient, intPort, - desc, enabled, leaseDuration); -Py_END_ALLOW_THREADS - if(intClient[0]) - { - iPort = (unsigned short)atoi(intPort); - return Py_BuildValue("(s,H,s,O,i)", - intClient, iPort, desc, - PyBool_FromLong(atoi(enabled)), - atoi(leaseDuration)); - } - else - { - Py_RETURN_NONE; - } -} - -/* GetGenericPortMapping(index) */ -static PyObject * -UPnP_getgenericportmapping(UPnPObject *self, PyObject *args) -{ - int i, r; - char index[8]; - char intClient[40]; - char intPort[6]; - unsigned short iPort; - char extPort[6]; - unsigned short ePort; - char protocol[4]; - char desc[80]; - char enabled[6]; - char rHost[64]; - char duration[16]; /* lease duration */ - unsigned int dur; - if(!PyArg_ParseTuple(args, "i", &i)) - return NULL; -Py_BEGIN_ALLOW_THREADS - snprintf(index, sizeof(index), "%d", i); - rHost[0] = '\0'; enabled[0] = '\0'; - duration[0] = '\0'; desc[0] = '\0'; - extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0'; - r = UPNP_GetGenericPortMappingEntry(self->urls.controlURL, - self->data.first.servicetype, - index, - extPort, intClient, intPort, - protocol, desc, enabled, rHost, - duration); -Py_END_ALLOW_THREADS - if(r==UPNPCOMMAND_SUCCESS) - { - ePort = (unsigned short)atoi(extPort); - iPort = (unsigned short)atoi(intPort); - dur = (unsigned int)strtoul(duration, 0, 0); -#if (PY_MAJOR_VERSION >= 3) || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION > 3) - return Py_BuildValue("(H,s,(s,H),s,s,s,I)", - ePort, protocol, intClient, iPort, - desc, enabled, rHost, dur); -#else - return Py_BuildValue("(i,s,(s,i),s,s,s,i)", - (int)ePort, protocol, intClient, (int)iPort, - desc, enabled, rHost, (int)dur); -#endif - } - else - { - Py_RETURN_NONE; - } -} - -/* miniupnpc.UPnP object Method Table */ -static PyMethodDef UPnP_methods[] = { - {"discover", (PyCFunction)UPnP_discover, METH_NOARGS, - "discover UPnP IGD devices on the network" - }, - {"selectigd", (PyCFunction)UPnP_selectigd, METH_NOARGS, - "select a valid UPnP IGD among discovered devices" - }, - {"totalbytesent", (PyCFunction)UPnP_totalbytesent, METH_NOARGS, - "return the total number of bytes sent by UPnP IGD" - }, - {"totalbytereceived", (PyCFunction)UPnP_totalbytereceived, METH_NOARGS, - "return the total number of bytes received by UPnP IGD" - }, - {"totalpacketsent", (PyCFunction)UPnP_totalpacketsent, METH_NOARGS, - "return the total number of packets sent by UPnP IGD" - }, - {"totalpacketreceived", (PyCFunction)UPnP_totalpacketreceived, METH_NOARGS, - "return the total number of packets received by UPnP IGD" - }, - {"statusinfo", (PyCFunction)UPnP_statusinfo, METH_NOARGS, - "return status and uptime" - }, - {"connectiontype", (PyCFunction)UPnP_connectiontype, METH_NOARGS, - "return IGD WAN connection type" - }, - {"externalipaddress", (PyCFunction)UPnP_externalipaddress, METH_NOARGS, - "return external IP address" - }, - {"addportmapping", (PyCFunction)UPnP_addportmapping, METH_VARARGS, - "add a port mapping" - }, - {"addanyportmapping", (PyCFunction)UPnP_addanyportmapping, METH_VARARGS, - "add a port mapping, IGD to select alternative if necessary" - }, - {"deleteportmapping", (PyCFunction)UPnP_deleteportmapping, METH_VARARGS, - "delete a port mapping" - }, - {"deleteportmappingrange", (PyCFunction)UPnP_deleteportmappingrange, METH_VARARGS, - "delete a range of port mappings" - }, - {"getportmappingnumberofentries", (PyCFunction)UPnP_getportmappingnumberofentries, METH_NOARGS, - "-- non standard --" - }, - {"getspecificportmapping", (PyCFunction)UPnP_getspecificportmapping, METH_VARARGS, - "get details about a specific port mapping entry" - }, - {"getgenericportmapping", (PyCFunction)UPnP_getgenericportmapping, METH_VARARGS, - "get all details about the port mapping at index" - }, - {NULL} /* Sentinel */ -}; - -static PyTypeObject UPnPType = { - PyVarObject_HEAD_INIT(NULL, - 0) /*ob_size*/ - "miniupnpc.UPnP", /*tp_name*/ - sizeof(UPnPObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)UPnPObject_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT, /*tp_flags*/ - "UPnP objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - UPnP_methods, /* tp_methods */ - UPnP_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)UPnP_init, /* tp_init */ - 0, /* tp_alloc */ -#ifndef _WIN32 - PyType_GenericNew,/*UPnP_new,*/ /* tp_new */ -#else - 0, -#endif -}; - -/* module methods */ -static PyMethodDef miniupnpc_methods[] = { - {NULL} /* Sentinel */ -}; - -#if PY_MAJOR_VERSION >= 3 -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "miniupnpc", /* m_name */ - "miniupnpc module.", /* m_doc */ - -1, /* m_size */ - miniupnpc_methods, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ -}; -#endif - -#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */ -#define PyMODINIT_FUNC void -#endif - -PyMODINIT_FUNC -#if PY_MAJOR_VERSION >= 3 -PyInit_miniupnpc(void) -#else -initminiupnpc(void) -#endif -{ - PyObject* m; - -#ifdef _WIN32 - /* initialize Winsock. */ - WSADATA wsaData; - int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); - if (nResult != 0) - { - /* error code could be WSASYSNOTREADY WSASYSNOTREADY - * WSASYSNOTREADY WSASYSNOTREADY WSASYSNOTREADY */ -#if PY_MAJOR_VERSION >= 3 - return 0; -#else - return; -#endif - } - - UPnPType.tp_new = PyType_GenericNew; -#endif - if (PyType_Ready(&UPnPType) < 0) -#if PY_MAJOR_VERSION >= 3 - return 0; -#else - return; -#endif - -#if PY_MAJOR_VERSION >= 3 - m = PyModule_Create(&moduledef); -#else - m = Py_InitModule3("miniupnpc", miniupnpc_methods, - "miniupnpc module."); -#endif - - Py_INCREF(&UPnPType); - PyModule_AddObject(m, "UPnP", (PyObject *)&UPnPType); - -#if PY_MAJOR_VERSION >= 3 - return m; -#endif -} - diff --git a/thirdparty/miniupnpc/miniupnpc/miniupnpcstrings.h b/thirdparty/miniupnpc/miniupnpc/miniupnpcstrings.h index a718cc7bbf..7b3d04074a 100644 --- a/thirdparty/miniupnpc/miniupnpc/miniupnpcstrings.h +++ b/thirdparty/miniupnpc/miniupnpc/miniupnpcstrings.h @@ -4,7 +4,7 @@ #include "core/version.h" #define OS_STRING VERSION_NAME "/1.0" -#define MINIUPNPC_VERSION_STRING "2.1" +#define MINIUPNPC_VERSION_STRING "2.2.2" #if 0 /* according to "UPnP Device Architecture 1.0" */ diff --git a/thirdparty/miniupnpc/miniupnpc/miniwget.c b/thirdparty/miniupnpc/miniupnpc/miniwget.c index 5c135f4efd..d5b7970632 100644 --- a/thirdparty/miniupnpc/miniupnpc/miniwget.c +++ b/thirdparty/miniupnpc/miniupnpc/miniwget.c @@ -1,8 +1,8 @@ -/* $Id: miniwget.c,v 1.78 2018/03/13 23:22:18 nanard Exp $ */ +/* $Id: miniwget.c,v 1.82 2020/05/29 21:14:22 nanard Exp $ */ /* Project : miniupnp - * Website : http://miniupnp.free.fr/ + * Website : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas Bernard - * Copyright (c) 2005-2018 Thomas Bernard + * Copyright (c) 2005-2020 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -15,7 +15,7 @@ #include <ws2tcpip.h> #include <io.h> #define MAXHOSTNAMELEN 64 -#define snprintf _snprintf +#include "win32_snprintf.h" #define socklen_t int #ifndef strncasecmp #if defined(_MSC_VER) && (_MSC_VER >= 1400) @@ -176,11 +176,14 @@ getHTTPResponse(SOCKET s, int * size, int * status_code) /* Status line * HTTP-Version SP Status-Code SP Reason-Phrase CRLF */ int sp; - for(sp = 0; sp < i; sp++) + for(sp = 0; sp < i - 1; sp++) if(header_buf[sp] == ' ') { if(*status_code < 0) - *status_code = atoi(header_buf + sp + 1); + { + if (header_buf[sp+1] >= '1' && header_buf[sp+1] <= '9') + *status_code = atoi(header_buf + sp + 1); + } else { #ifdef DEBUG diff --git a/thirdparty/miniupnpc/miniupnpc/portlistingparse.c b/thirdparty/miniupnpc/miniupnpc/portlistingparse.c index 18d967b877..162cf8b7ec 100644 --- a/thirdparty/miniupnpc/miniupnpc/portlistingparse.c +++ b/thirdparty/miniupnpc/miniupnpc/portlistingparse.c @@ -15,7 +15,7 @@ #if defined(__HAIKU__) /* rename our private function because Haiku already defines a atoui() function */ #define atoui atoui2 -#endif +#endif /* list of the elements */ static const struct { diff --git a/thirdparty/miniupnpc/miniupnpc/receivedata.c b/thirdparty/miniupnpc/miniupnpc/receivedata.c index 7b9cc5b778..7f187f6e56 100644 --- a/thirdparty/miniupnpc/miniupnpc/receivedata.c +++ b/thirdparty/miniupnpc/miniupnpc/receivedata.c @@ -1,8 +1,8 @@ -/* $Id: receivedata.c,v 1.7 2015/11/09 21:51:41 nanard Exp $ */ +/* $Id: receivedata.c,v 1.10 2021/03/02 23:33:07 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2011-2014 Thomas Bernard + * Copyright (c) 2011-2021 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -92,7 +92,13 @@ receivedata(SOCKET socket, #endif /* DEBUG */ if(scope_id) *scope_id = src_addr6->sin6_scope_id; + } else { + if(scope_id) + *scope_id = 0; } +#else /* MINIUPNPC_GET_SRC_ADDR */ + if(scope_id) + *scope_id = 0; #endif /* MINIUPNPC_GET_SRC_ADDR */ return n; } diff --git a/thirdparty/miniupnpc/miniupnpc/upnpc.c b/thirdparty/miniupnpc/miniupnpc/upnpc.c deleted file mode 100644 index cb7f18b5f6..0000000000 --- a/thirdparty/miniupnpc/miniupnpc/upnpc.c +++ /dev/null @@ -1,864 +0,0 @@ -/* $Id: upnpc.c,v 1.119 2018/03/13 23:34:46 nanard Exp $ */ -/* Project : miniupnp - * Author : Thomas Bernard - * Copyright (c) 2005-2020 Thomas Bernard - * This software is subject to the conditions detailed in the - * LICENCE file provided in this distribution. */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#ifdef _WIN32 -#include <winsock2.h> -#define snprintf _snprintf -#else -/* for IPPROTO_TCP / IPPROTO_UDP */ -#include <netinet/in.h> -#endif -#include <ctype.h> -#include "miniwget.h" -#include "miniupnpc.h" -#include "upnpcommands.h" -#include "portlistingparse.h" -#include "upnperrors.h" -#include "miniupnpcstrings.h" - -/* protofix() checks if protocol is "UDP" or "TCP" - * returns NULL if not */ -const char * protofix(const char * proto) -{ - static const char proto_tcp[4] = { 'T', 'C', 'P', 0}; - static const char proto_udp[4] = { 'U', 'D', 'P', 0}; - int i, b; - for(i=0, b=1; i<4; i++) - b = b && ( (proto[i] == proto_tcp[i]) - || (proto[i] == (proto_tcp[i] | 32)) ); - if(b) - return proto_tcp; - for(i=0, b=1; i<4; i++) - b = b && ( (proto[i] == proto_udp[i]) - || (proto[i] == (proto_udp[i] | 32)) ); - if(b) - return proto_udp; - return 0; -} - -/* is_int() checks if parameter is an integer or not - * 1 for integer - * 0 for not an integer */ -int is_int(char const* s) -{ - if(s == NULL) - return 0; - while(*s) { - /* #define isdigit(c) ((c) >= '0' && (c) <= '9') */ - if(!isdigit(*s)) - return 0; - s++; - } - return 1; -} - -static void DisplayInfos(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - char externalIPAddress[40]; - char connectionType[64]; - char status[64]; - char lastconnerr[64]; - unsigned int uptime = 0; - unsigned int brUp, brDown; - time_t timenow, timestarted; - int r; - if(UPNP_GetConnectionTypeInfo(urls->controlURL, - data->first.servicetype, - connectionType) != UPNPCOMMAND_SUCCESS) - printf("GetConnectionTypeInfo failed.\n"); - else - printf("Connection Type : %s\n", connectionType); - if(UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype, - status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS) - printf("GetStatusInfo failed.\n"); - else - printf("Status : %s, uptime=%us, LastConnectionError : %s\n", - status, uptime, lastconnerr); - if(uptime > 0) { - timenow = time(NULL); - timestarted = timenow - uptime; - printf(" Time started : %s", ctime(×tarted)); - } - if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype, - &brDown, &brUp) != UPNPCOMMAND_SUCCESS) { - printf("GetLinkLayerMaxBitRates failed.\n"); - } else { - printf("MaxBitRateDown : %u bps", brDown); - if(brDown >= 1000000) { - printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10); - } else if(brDown >= 1000) { - printf(" (%u Kbps)", brDown / 1000); - } - printf(" MaxBitRateUp %u bps", brUp); - if(brUp >= 1000000) { - printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10); - } else if(brUp >= 1000) { - printf(" (%u Kbps)", brUp / 1000); - } - printf("\n"); - } - r = UPNP_GetExternalIPAddress(urls->controlURL, - data->first.servicetype, - externalIPAddress); - if(r != UPNPCOMMAND_SUCCESS) { - printf("GetExternalIPAddress failed. (errorcode=%d)\n", r); - } else { - printf("ExternalIPAddress = %s\n", externalIPAddress); - } -} - -static void GetConnectionStatus(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - unsigned int bytessent, bytesreceived, packetsreceived, packetssent; - DisplayInfos(urls, data); - bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype); - bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype); - packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype); - packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype); - printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); - printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); -} - -static void ListRedirections(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - int r; - int i = 0; - char index[6]; - char intClient[40]; - char intPort[6]; - char extPort[6]; - char protocol[4]; - char desc[80]; - char enabled[6]; - char rHost[64]; - char duration[16]; - /*unsigned int num=0; - UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num); - printf("PortMappingNumberOfEntries : %u\n", num);*/ - printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n"); - do { - snprintf(index, 6, "%d", i); - rHost[0] = '\0'; enabled[0] = '\0'; - duration[0] = '\0'; desc[0] = '\0'; - extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0'; - r = UPNP_GetGenericPortMappingEntry(urls->controlURL, - data->first.servicetype, - index, - extPort, intClient, intPort, - protocol, desc, enabled, - rHost, duration); - if(r==0) - /* - printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n" - " desc='%s' rHost='%s'\n", - i, protocol, extPort, intClient, intPort, - enabled, duration, - desc, rHost); - */ - printf("%2d %s %5s->%s:%-5s '%s' '%s' %s\n", - i, protocol, extPort, intClient, intPort, - desc, rHost, duration); - else - printf("GetGenericPortMappingEntry() returned %d (%s)\n", - r, strupnperror(r)); - i++; - } while(r==0); -} - -static void NewListRedirections(struct UPNPUrls * urls, - struct IGDdatas * data) -{ - int r; - int i = 0; - struct PortMappingParserData pdata; - struct PortMapping * pm; - - memset(&pdata, 0, sizeof(struct PortMappingParserData)); - r = UPNP_GetListOfPortMappings(urls->controlURL, - data->first.servicetype, - "0", - "65535", - "TCP", - "1000", - &pdata); - if(r == UPNPCOMMAND_SUCCESS) - { - printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n"); - for(pm = pdata.l_head; pm != NULL; pm = pm->l_next) - { - printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", - i, pm->protocol, pm->externalPort, pm->internalClient, - pm->internalPort, - pm->description, pm->remoteHost, - (unsigned)pm->leaseTime); - i++; - } - FreePortListing(&pdata); - } - else - { - printf("GetListOfPortMappings() returned %d (%s)\n", - r, strupnperror(r)); - } - r = UPNP_GetListOfPortMappings(urls->controlURL, - data->first.servicetype, - "0", - "65535", - "UDP", - "1000", - &pdata); - if(r == UPNPCOMMAND_SUCCESS) - { - for(pm = pdata.l_head; pm != NULL; pm = pm->l_next) - { - printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n", - i, pm->protocol, pm->externalPort, pm->internalClient, - pm->internalPort, - pm->description, pm->remoteHost, - (unsigned)pm->leaseTime); - i++; - } - FreePortListing(&pdata); - } - else - { - printf("GetListOfPortMappings() returned %d (%s)\n", - r, strupnperror(r)); - } -} - -/* Test function - * 1 - get connection type - * 2 - get extenal ip address - * 3 - Add port mapping - * 4 - get this port mapping from the IGD */ -static int SetRedirectAndTest(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * iaddr, - const char * iport, - const char * eport, - const char * proto, - const char * leaseDuration, - const char * remoteHost, - const char * description, - int addAny) -{ - char externalIPAddress[40]; - char intClient[40]; - char intPort[6]; - char reservedPort[6]; - char duration[16]; - int r; - - if(!iaddr || !iport || !eport || !proto) - { - fprintf(stderr, "Wrong arguments\n"); - return -1; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "invalid protocol\n"); - return -1; - } - - r = UPNP_GetExternalIPAddress(urls->controlURL, - data->first.servicetype, - externalIPAddress); - if(r!=UPNPCOMMAND_SUCCESS) - printf("GetExternalIPAddress failed.\n"); - else - printf("ExternalIPAddress = %s\n", externalIPAddress); - - if (addAny) { - r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype, - eport, iport, iaddr, description, - proto, remoteHost, leaseDuration, reservedPort); - if(r==UPNPCOMMAND_SUCCESS) - eport = reservedPort; - else - printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n", - eport, iport, iaddr, r, strupnperror(r)); - } else { - r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype, - eport, iport, iaddr, description, - proto, remoteHost, leaseDuration); - if(r!=UPNPCOMMAND_SUCCESS) { - printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", - eport, iport, iaddr, r, strupnperror(r)); - return -2; - } - } - - r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, - data->first.servicetype, - eport, proto, remoteHost, - intClient, intPort, NULL/*desc*/, - NULL/*enabled*/, duration); - if(r!=UPNPCOMMAND_SUCCESS) { - printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n", - r, strupnperror(r)); - return -2; - } else { - printf("InternalIP:Port = %s:%s\n", intClient, intPort); - printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n", - externalIPAddress, eport, proto, intClient, intPort, duration); - } - return 0; -} - -static int -RemoveRedirect(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * eport, - const char * proto, - const char * remoteHost) -{ - int r; - if(!proto || !eport) - { - fprintf(stderr, "invalid arguments\n"); - return -1; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "protocol invalid\n"); - return -1; - } - r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost); - if(r!=UPNPCOMMAND_SUCCESS) { - printf("UPNP_DeletePortMapping() failed with code : %d\n", r); - return -2; - }else { - printf("UPNP_DeletePortMapping() returned : %d\n", r); - } - return 0; -} - -static int -RemoveRedirectRange(struct UPNPUrls * urls, - struct IGDdatas * data, - const char * ePortStart, char const * ePortEnd, - const char * proto, const char * manage) -{ - int r; - - if (!manage) - manage = "0"; - - if(!proto || !ePortStart || !ePortEnd) - { - fprintf(stderr, "invalid arguments\n"); - return -1; - } - proto = protofix(proto); - if(!proto) - { - fprintf(stderr, "protocol invalid\n"); - return -1; - } - r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage); - if(r!=UPNPCOMMAND_SUCCESS) { - printf("UPNP_DeletePortMappingRange() failed with code : %d\n", r); - return -2; - }else { - printf("UPNP_DeletePortMappingRange() returned : %d\n", r); - } - return 0; -} - -/* IGD:2, functions for service WANIPv6FirewallControl:1 */ -static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data) -{ - unsigned int bytessent, bytesreceived, packetsreceived, packetssent; - int firewallEnabled = 0, inboundPinholeAllowed = 0; - - UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed); - printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed); - printf("GetFirewallStatus:\n Firewall Enabled: %s\n Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No"); - - bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype); - bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype); - packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype); - packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype); - printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived); - printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived); -} - -/* Test function - * 1 - Add pinhole - * 2 - Check if pinhole is working from the IGD side */ -static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data, - const char * remoteaddr, const char * eport, - const char * intaddr, const char * iport, - const char * proto, const char * lease_time) -{ - char uniqueID[8]; - /*int isWorking = 0;*/ - int r; - char proto_tmp[8]; - - if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time) - { - fprintf(stderr, "Wrong arguments\n"); - return; - } - if(atoi(proto) == 0) - { - const char * protocol; - protocol = protofix(proto); - if(protocol && (strcmp("TCP", protocol) == 0)) - { - snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_TCP); - proto = proto_tmp; - } - else if(protocol && (strcmp("UDP", protocol) == 0)) - { - snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_UDP); - proto = proto_tmp; - } - else - { - fprintf(stderr, "invalid protocol\n"); - return; - } - } - r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID); - if(r!=UPNPCOMMAND_SUCCESS) - printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", - remoteaddr, eport, intaddr, iport, r, strupnperror(r)); - else - { - printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n", - remoteaddr, eport, intaddr, iport, uniqueID); - /*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking); - if(r!=UPNPCOMMAND_SUCCESS) - printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); - printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/ - } -} - -/* Test function - * 1 - Check if pinhole is working from the IGD side - * 2 - Update pinhole */ -static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data, - const char * uniqueID, const char * lease_time) -{ - int isWorking = 0; - int r; - - if(!uniqueID || !lease_time) - { - fprintf(stderr, "Wrong arguments\n"); - return; - } - r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); - printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); - if(r!=UPNPCOMMAND_SUCCESS) - printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); - if(isWorking || r==709) - { - r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time); - printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time); - if(r!=UPNPCOMMAND_SUCCESS) - printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r)); - } -} - -/* Test function - * Get pinhole timeout - */ -static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data, - const char * remoteaddr, const char * eport, - const char * intaddr, const char * iport, - const char * proto) -{ - int timeout = 0; - int r; - - if(!intaddr || !remoteaddr || !iport || !eport || !proto) - { - fprintf(stderr, "Wrong arguments\n"); - return; - } - - r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout); - if(r!=UPNPCOMMAND_SUCCESS) - printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n", - intaddr, iport, remoteaddr, eport, r, strupnperror(r)); - else - printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout); -} - -static void -GetPinholePackets(struct UPNPUrls * urls, - struct IGDdatas * data, const char * uniqueID) -{ - int r, pinholePackets = 0; - if(!uniqueID) - { - fprintf(stderr, "invalid arguments\n"); - return; - } - r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets); - if(r!=UPNPCOMMAND_SUCCESS) - printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r)); - else - printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets); -} - -static void -CheckPinhole(struct UPNPUrls * urls, - struct IGDdatas * data, const char * uniqueID) -{ - int r, isWorking = 0; - if(!uniqueID) - { - fprintf(stderr, "invalid arguments\n"); - return; - } - r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking); - if(r!=UPNPCOMMAND_SUCCESS) - printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r)); - else - printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No"); -} - -static void -RemovePinhole(struct UPNPUrls * urls, - struct IGDdatas * data, const char * uniqueID) -{ - int r; - if(!uniqueID) - { - fprintf(stderr, "invalid arguments\n"); - return; - } - r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID); - printf("UPNP_DeletePinhole() returned : %d\n", r); -} - - -/* sample upnp client program */ -int main(int argc, char ** argv) -{ - char command = 0; - char ** commandargv = 0; - int commandargc = 0; - struct UPNPDev * devlist = 0; - char lanaddr[64] = "unset"; /* my ip address on the LAN */ - int i; - const char * rootdescurl = 0; - const char * multicastif = 0; - const char * minissdpdpath = 0; - int localport = UPNP_LOCAL_PORT_ANY; - int retcode = 0; - int error = 0; - int ipv6 = 0; - unsigned char ttl = 2; /* defaulting to 2 */ - const char * description = 0; - -#ifdef _WIN32 - WSADATA wsaData; - int nResult = WSAStartup(MAKEWORD(2,2), &wsaData); - if(nResult != NO_ERROR) - { - fprintf(stderr, "WSAStartup() failed.\n"); - return -1; - } -#endif - printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING); - printf(" (c) 2005-2020 Thomas Bernard.\n"); - printf("Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/\n" - "for more information.\n"); - /* command line processing */ - for(i=1; i<argc; i++) - { - if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h")) - { - command = 0; - break; - } - if(argv[i][0] == '-') - { - if(argv[i][1] == 'u') - rootdescurl = argv[++i]; - else if(argv[i][1] == 'm') - { - multicastif = argv[++i]; - minissdpdpath = ""; /* Disable usage of minissdpd */ - } - else if(argv[i][1] == 'z') - { - char junk; - if(sscanf(argv[++i], "%d%c", &localport, &junk)!=1 || - localport<0 || localport>65535 || - (localport >1 && localport < 1024)) - { - fprintf(stderr, "Invalid localport '%s'\n", argv[i]); - localport = UPNP_LOCAL_PORT_ANY; - break; - } - } - else if(argv[i][1] == 'p') - minissdpdpath = argv[++i]; - else if(argv[i][1] == '6') - ipv6 = 1; - else if(argv[i][1] == 'e') - description = argv[++i]; - else if(argv[i][1] == 't') - ttl = (unsigned char)atoi(argv[++i]); - else - { - command = argv[i][1]; - i++; - commandargv = argv + i; - commandargc = argc - i; - break; - } - } - else - { - fprintf(stderr, "option '%s' invalid\n", argv[i]); - } - } - - if(!command - || (command == 'a' && commandargc<4) - || (command == 'd' && argc<2) - || (command == 'r' && argc<2) - || (command == 'A' && commandargc<6) - || (command == 'U' && commandargc<2) - || (command == 'D' && commandargc<1)) - { - fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration] [remote host]\n\t\tAdd port redirection\n", argv[0]); - fprintf(stderr, " \t%s [options] -d external_port protocol [remote host]\n\t\tDelete port redirection\n", argv[0]); - fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]); - fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]); - fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -n ip port external_port protocol [duration] [remote host]\n\t\tAdd (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]); - fprintf(stderr, " \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -G remote_ip remote_port internal_ip internal_port protocol\n\t\tGet Outbound Pinhole Timeout (for IGD:2 only)\n", argv[0]); - fprintf(stderr, " \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]); - fprintf(stderr, "\nprotocol is UDP or TCP\n"); - fprintf(stderr, "Options:\n"); - fprintf(stderr, " -e description : set description for port mapping.\n"); - fprintf(stderr, " -6 : use ip v6 instead of ip v4.\n"); - fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n"); - fprintf(stderr, " -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n"); - fprintf(stderr, " -z localport : SSDP packets local (source) port (1024-65535).\n"); - fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n"); - fprintf(stderr, " -t ttl : set multicast TTL. Default value is 2.\n"); - return 1; - } - - if( rootdescurl - || (devlist = upnpDiscover(2000, multicastif, minissdpdpath, - localport, ipv6, ttl, &error))) - { - struct UPNPDev * device; - struct UPNPUrls urls; - struct IGDdatas data; - if(devlist) - { - printf("List of UPNP devices found on the network :\n"); - for(device = devlist; device; device = device->pNext) - { - printf(" desc: %s\n st: %s\n\n", - device->descURL, device->st); - } - } - else if(!rootdescurl) - { - printf("upnpDiscover() error code=%d\n", error); - } - i = 1; - if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr))) - || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)))) - { - switch(i) { - case 1: - printf("Found valid IGD : %s\n", urls.controlURL); - break; - case 2: - printf("Found a (not connected?) IGD : %s\n", urls.controlURL); - printf("Trying to continue anyway\n"); - break; - case 3: - printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL); - printf("Trying to continue anyway\n"); - break; - default: - printf("Found device (igd ?) : %s\n", urls.controlURL); - printf("Trying to continue anyway\n"); - } - printf("Local LAN ip address : %s\n", lanaddr); - #if 0 - printf("getting \"%s\"\n", urls.ipcondescURL); - descXML = miniwget(urls.ipcondescURL, &descXMLsize); - if(descXML) - { - /*fwrite(descXML, 1, descXMLsize, stdout);*/ - free(descXML); descXML = NULL; - } - #endif - - switch(command) - { - case 'l': - DisplayInfos(&urls, &data); - ListRedirections(&urls, &data); - break; - case 'L': - NewListRedirections(&urls, &data); - break; - case 'a': - if (SetRedirectAndTest(&urls, &data, - commandargv[0], commandargv[1], - commandargv[2], commandargv[3], - (commandargc > 4)&is_int(commandargv[4])?commandargv[4]:"0", - (commandargc > 4)&!is_int(commandargv[4])?commandargv[4]:(commandargc > 5)?commandargv[5]:NULL, - description, 0) < 0) - retcode = 2; - break; - case 'd': - if (RemoveRedirect(&urls, &data, commandargv[0], commandargv[1], - commandargc > 2 ? commandargv[2] : NULL) < 0) - retcode = 2; - break; - case 'n': /* aNy */ - if (SetRedirectAndTest(&urls, &data, - commandargv[0], commandargv[1], - commandargv[2], commandargv[3], - (commandargc > 4)&is_int(commandargv[4])?commandargv[4]:"0", - (commandargc > 4)&!is_int(commandargv[4])?commandargv[4]:(commandargc > 5)?commandargv[5]:NULL, - description, 1) < 0) - retcode = 2; - break; - case 'N': - if (commandargc < 3) - fprintf(stderr, "too few arguments\n"); - - if (RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2], - commandargc > 3 ? commandargv[3] : NULL) < 0) - retcode = 2; - break; - case 's': - GetConnectionStatus(&urls, &data); - break; - case 'r': - i = 0; - while(i<commandargc) - { - if(!is_int(commandargv[i])) { - /* 1st parameter not an integer : error */ - fprintf(stderr, "command -r : %s is not an port number\n", commandargv[i]); - retcode = 1; - break; - } else if(is_int(commandargv[i+1])){ - /* 2nd parameter is an integer : <port> <external_port> <protocol> */ - if (SetRedirectAndTest(&urls, &data, - lanaddr, commandargv[i], - commandargv[i+1], commandargv[i+2], "0", NULL, - description, 0) < 0) - retcode = 2; - i+=3; /* 3 parameters parsed */ - } else { - /* 2nd parameter not an integer : <port> <protocol> */ - if (SetRedirectAndTest(&urls, &data, - lanaddr, commandargv[i], - commandargv[i], commandargv[i+1], "0", NULL, - description, 0) < 0) - retcode = 2; - i+=2; /* 2 parameters parsed */ - } - } - break; - case 'A': - SetPinholeAndTest(&urls, &data, - commandargv[0], commandargv[1], - commandargv[2], commandargv[3], - commandargv[4], commandargv[5]); - break; - case 'U': - GetPinholeAndUpdate(&urls, &data, - commandargv[0], commandargv[1]); - break; - case 'C': - for(i=0; i<commandargc; i++) - { - CheckPinhole(&urls, &data, commandargv[i]); - } - break; - case 'K': - for(i=0; i<commandargc; i++) - { - GetPinholePackets(&urls, &data, commandargv[i]); - } - break; - case 'D': - for(i=0; i<commandargc; i++) - { - RemovePinhole(&urls, &data, commandargv[i]); - } - break; - case 'S': - GetFirewallStatus(&urls, &data); - break; - case 'G': - GetPinholeOutboundTimeout(&urls, &data, - commandargv[0], commandargv[1], - commandargv[2], commandargv[3], - commandargv[4]); - break; - case 'P': - printf("Presentation URL found:\n"); - printf(" %s\n", data.presentationurl); - break; - default: - fprintf(stderr, "Unknown switch -%c\n", command); - retcode = 1; - } - - FreeUPNPUrls(&urls); - } - else - { - fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n"); - retcode = 1; - } - freeUPNPDevlist(devlist); devlist = 0; - } - else - { - fprintf(stderr, "No IGD UPnP Device found on the network !\n"); - retcode = 1; - } -#ifdef _WIN32 - nResult = WSACleanup(); - if(nResult != NO_ERROR) { - fprintf(stderr, "WSACleanup() failed.\n"); - } -#endif /* _WIN32 */ - return retcode; -} - diff --git a/thirdparty/miniupnpc/miniupnpc/upnpdev.h b/thirdparty/miniupnpc/miniupnpc/upnpdev.h index f4ae174426..9b2cb431ba 100644 --- a/thirdparty/miniupnpc/miniupnpc/upnpdev.h +++ b/thirdparty/miniupnpc/miniupnpc/upnpdev.h @@ -1,8 +1,8 @@ -/* $Id: upnpdev.h,v 1.1 2015/08/28 12:14:19 nanard Exp $ */ +/* $Id: upnpdev.h,v 1.3 2020/05/29 15:57:42 nanard Exp $ */ /* Project : miniupnp - * Web : http://miniupnp.free.fr/ + * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ * Author : Thomas BERNARD - * copyright (c) 2005-2018 Thomas Bernard + * copyright (c) 2005-2020 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #ifndef UPNPDEV_H_INCLUDED @@ -20,7 +20,15 @@ struct UPNPDev { char * st; char * usn; unsigned int scope_id; - char buffer[3]; +#if defined(__STDC_VERSION) && __STDC_VERSION__ >= 199901L + /* C99 flexible array member */ + char buffer[]; +#elif defined(__GNUC__) + char buffer[0]; +#else + /* Fallback to a hack */ + char buffer[1]; +#endif }; /* freeUPNPDevlist() diff --git a/thirdparty/miniupnpc/miniupnpc/upnperrors.c b/thirdparty/miniupnpc/miniupnpc/upnperrors.c deleted file mode 100644 index 4496e8622c..0000000000 --- a/thirdparty/miniupnpc/miniupnpc/upnperrors.c +++ /dev/null @@ -1,112 +0,0 @@ -/* $Id: upnperrors.c,v 1.10 2019/08/24 08:49:53 nanard Exp $ */ -/* vim: tabstop=4 shiftwidth=4 noexpandtab - * Project : miniupnp - * Author : Thomas BERNARD - * copyright (c) 2007-2019 Thomas Bernard - * All Right reserved. - * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#include <string.h> -#include "upnperrors.h" -#include "upnpcommands.h" -#include "miniupnpc.h" - -const char * strupnperror(int err) -{ - const char * s = NULL; - switch(err) { - case UPNPCOMMAND_SUCCESS: - s = "Success"; - break; - case UPNPCOMMAND_UNKNOWN_ERROR: - s = "Miniupnpc Unknown Error"; - break; - case UPNPCOMMAND_INVALID_ARGS: - s = "Miniupnpc Invalid Arguments"; - break; - case UPNPCOMMAND_INVALID_RESPONSE: - s = "Miniupnpc Invalid response"; - break; - case UPNPCOMMAND_HTTP_ERROR: - s = "Miniupnpc HTTP error"; - break; - case UPNPDISCOVER_SOCKET_ERROR: - s = "Miniupnpc Socket error"; - break; - case UPNPDISCOVER_MEMORY_ERROR: - case UPNPCOMMAND_MEM_ALLOC_ERROR: - s = "Miniupnpc Memory allocation error"; - break; - case 401: - s = "Invalid Action"; - break; - case 402: - s = "Invalid Args"; - break; - case 501: - s = "Action Failed"; - break; - case 606: - s = "Action not authorized"; - break; - case 701: - s = "PinholeSpaceExhausted"; - break; - case 702: - s = "FirewallDisabled"; - break; - case 703: - s = "InboundPinholeNotAllowed"; - break; - case 704: - s = "NoSuchEntry"; - break; - case 705: - s = "ProtocolNotSupported"; - break; - case 706: - s = "InternalPortWildcardingNotAllowed"; - break; - case 707: - s = "ProtocolWildcardingNotAllowed"; - break; - case 708: - s = "InvalidLayer2Address"; - break; - case 709: - s = "NoPacketSent"; - break; - case 713: - s = "SpecifiedArrayIndexInvalid"; - break; - case 714: - s = "NoSuchEntryInArray"; - break; - case 715: - s = "WildCardNotPermittedInSrcIP"; - break; - case 716: - s = "WildCardNotPermittedInExtPort"; - break; - case 718: - s = "ConflictInMappingEntry"; - break; - case 724: - s = "SamePortValuesRequired"; - break; - case 725: - s = "OnlyPermanentLeasesSupported"; - break; - case 726: - s = "RemoteHostOnlySupportsWildcard"; - break; - case 727: - s = "ExternalPortOnlySupportsWildcard"; - break; - default: - s = "UnknownError"; - break; - } - return s; -} diff --git a/thirdparty/miniupnpc/miniupnpc/upnperrors.h b/thirdparty/miniupnpc/miniupnpc/upnperrors.h deleted file mode 100644 index 8499d9a1c9..0000000000 --- a/thirdparty/miniupnpc/miniupnpc/upnperrors.h +++ /dev/null @@ -1,26 +0,0 @@ -/* $Id: upnperrors.h,v 1.2 2008/07/02 23:31:15 nanard Exp $ */ -/* (c) 2007-2015 Thomas Bernard - * All rights reserved. - * MiniUPnP Project. - * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * This software is subjet to the conditions detailed in the - * provided LICENCE file. */ -#ifndef UPNPERRORS_H_INCLUDED -#define UPNPERRORS_H_INCLUDED - -#include "miniupnpc_declspec.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* strupnperror() - * Return a string description of the UPnP error code - * or NULL for undefinded errors */ -MINIUPNP_LIBSPEC const char * strupnperror(int err); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/thirdparty/miniupnpc/miniupnpc/win32_snprintf.h b/thirdparty/miniupnpc/miniupnpc/win32_snprintf.h new file mode 100644 index 0000000000..1fc284ecff --- /dev/null +++ b/thirdparty/miniupnpc/miniupnpc/win32_snprintf.h @@ -0,0 +1,71 @@ +/* vim: tabstop=4 shiftwidth=4 noexpandtab + * MiniUPnP project + * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/ + * (c) 2020 Pali Rohár + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ + +#ifndef WIN32_SNPRINTF_H +#define WIN32_SNPRINTF_H + +#ifdef _WIN32 + +#include <stdio.h> + +/* snprintf is supported by: + * - Visual Studio 2015 or new + * - mingw32 with iso c ext + * - mingw-w64 with ansi stdio + * - mingw-w64 6.0.0 or new with ucrt + * - mingw-w64 8.0.0 or new with iso c ext + */ +#if ( \ + (defined(_MSC_VER) && _MSC_VER < 1900) /* Visual Studio older than 2015 */ || \ + (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) && defined(__NO_ISOCEXT)) /* mingw32 without iso c ext */ || \ + (defined(__MINGW64_VERSION_MAJOR) && /* mingw-w64 not ... */ !( \ + (defined (__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO != 0)) /* ... with ansi stdio */ || \ + (__MINGW64_VERSION_MAJOR >= 6 && defined(_UCRT)) /* ... at least 6.0.0 with ucrt */ || \ + (__MINGW64_VERSION_MAJOR >= 8 && !defined(__NO_ISOCEXT)) /* ... at least 8.0.0 with iso c ext */ || \ + 0) || \ +0) + +/* _scprintf is supported by: + * - Visual Studio 2002 or new + * - msvcr70.dll or new + * - msvcrt.dll on Windows XP or new + */ +#if ( \ + (defined(_MSC_VER) && _MSC_VER < 1300) /* Visual Studio older than 2002 */ || \ + (defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x700) /* msvcrt older than 7.0 */ || \ +0) +#define CHECK_SCPRINTF 0 +#define IF_SCPRINTF(expr) 0 +#define ELSE_SCPRINTF(expr) expr +#else +#define CHECK_SCPRINTF 1 +#define IF_SCPRINTF(expr) expr +#define ELSE_SCPRINTF(expr) 0 +#endif + +/* Emulation of snprintf for win32 */ +#define snprintf(buf, size, fmt, ...) ( \ + (((size) != 0 && (buf) != NULL) ? ( /* _snprintf does not work with NULL buffer */ \ + _snprintf((buf), (size), (fmt), __VA_ARGS__), /* _snprintf returns -1 on overflow, so ignore its value */ \ + (((char *)buf)[(size_t)(size)-1] = 0), /* _snprintf does not fill nul byte on overflow */ \ + 0) : 0), \ + (CHECK_SCPRINTF ? IF_SCPRINTF( \ + _scprintf((fmt), __VA_ARGS__) /* calculate return value for snprintf via _scprintf */ \ + ) : ELSE_SCPRINTF( \ + ((size) != 0 && (buf) != NULL) ? \ + strlen((buf)) /* return just length of buffer */ \ + : \ + 1 /* no buffer, impossible to calculate, return just non-zero number */ \ + ) \ + ) \ +) + +#endif + +#endif /* _WIN32 */ + +#endif /* WIN32_SNPRINTF_H */ diff --git a/thirdparty/miniupnpc/windows_fix.diff b/thirdparty/miniupnpc/windows_fix.diff deleted file mode 100644 index 460b596888..0000000000 --- a/thirdparty/miniupnpc/windows_fix.diff +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/thirdparty/miniupnpc/miniupnpc/minissdpc.c b/thirdparty/miniupnpc/miniupnpc/minissdpc.c -index 29f8110155..ea9af02e1f 100644 ---- a/thirdparty/miniupnpc/miniupnpc/minissdpc.c -+++ b/thirdparty/miniupnpc/miniupnpc/minissdpc.c -@@ -683,11 +683,7 @@ ssdpDiscoverDevices(const char * const deviceTypes[], - #endif - } else { - struct in_addr mc_if; --#if defined(_WIN32) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA) -- InetPtonA(AF_INET, multicastif, &mc_if); --#else - mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ --#endif - if(mc_if.s_addr != INADDR_NONE) - { - ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; diff --git a/thirdparty/misc/patches/polypartition-godot-types.patch b/thirdparty/misc/patches/polypartition-godot-types.patch new file mode 100644 index 0000000000..59fdb2707c --- /dev/null +++ b/thirdparty/misc/patches/polypartition-godot-types.patch @@ -0,0 +1,819 @@ +diff --git a/thirdparty/misc/polypartition.cpp b/thirdparty/misc/polypartition.cpp +index 3a8a6efa8319..4f1b6dcb21d8 100644 +--- a/thirdparty/misc/polypartition.cpp ++++ b/thirdparty/misc/polypartition.cpp +@@ -23,10 +23,7 @@ + + #include "polypartition.h" + +-#include <math.h> +-#include <string.h> + #include <algorithm> +-#include <vector> + + TPPLPoly::TPPLPoly() { + hole = false; +@@ -186,7 +183,7 @@ int TPPLPartition::Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TP + // Removes holes from inpolys by merging them with non-holes. + int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) { + TPPLPolyList polys; +- TPPLPolyList::iterator holeiter, polyiter, iter, iter2; ++ TPPLPolyList::Element *holeiter, *polyiter, *iter, *iter2; + long i, i2, holepointindex, polypointindex; + TPPLPoint holepoint, polypoint, bestpolypoint; + TPPLPoint linep1, linep2; +@@ -198,15 +195,15 @@ int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) { + + // Check for the trivial case of no holes. + hasholes = false; +- for (iter = inpolys->begin(); iter != inpolys->end(); iter++) { +- if (iter->IsHole()) { ++ for (iter = inpolys->front(); iter; iter = iter->next()) { ++ if (iter->get().IsHole()) { + hasholes = true; + break; + } + } + if (!hasholes) { +- for (iter = inpolys->begin(); iter != inpolys->end(); iter++) { +- outpolys->push_back(*iter); ++ for (iter = inpolys->front(); iter; iter = iter->next()) { ++ outpolys->push_back(iter->get()); + } + return 1; + } +@@ -216,8 +213,8 @@ int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) { + while (1) { + // Find the hole point with the largest x. + hasholes = false; +- for (iter = polys.begin(); iter != polys.end(); iter++) { +- if (!iter->IsHole()) { ++ for (iter = polys.front(); iter; iter = iter->next()) { ++ if (!iter->get().IsHole()) { + continue; + } + +@@ -227,8 +224,8 @@ int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) { + holepointindex = 0; + } + +- for (i = 0; i < iter->GetNumPoints(); i++) { +- if (iter->GetPoint(i).x > holeiter->GetPoint(holepointindex).x) { ++ for (i = 0; i < iter->get().GetNumPoints(); i++) { ++ if (iter->get().GetPoint(i).x > holeiter->get().GetPoint(holepointindex).x) { + holeiter = iter; + holepointindex = i; + } +@@ -237,24 +234,24 @@ int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) { + if (!hasholes) { + break; + } +- holepoint = holeiter->GetPoint(holepointindex); ++ holepoint = holeiter->get().GetPoint(holepointindex); + + pointfound = false; +- for (iter = polys.begin(); iter != polys.end(); iter++) { +- if (iter->IsHole()) { ++ for (iter = polys.front(); iter; iter = iter->next()) { ++ if (iter->get().IsHole()) { + continue; + } +- for (i = 0; i < iter->GetNumPoints(); i++) { +- if (iter->GetPoint(i).x <= holepoint.x) { ++ for (i = 0; i < iter->get().GetNumPoints(); i++) { ++ if (iter->get().GetPoint(i).x <= holepoint.x) { + continue; + } +- if (!InCone(iter->GetPoint((i + iter->GetNumPoints() - 1) % (iter->GetNumPoints())), +- iter->GetPoint(i), +- iter->GetPoint((i + 1) % (iter->GetNumPoints())), ++ if (!InCone(iter->get().GetPoint((i + iter->get().GetNumPoints() - 1) % (iter->get().GetNumPoints())), ++ iter->get().GetPoint(i), ++ iter->get().GetPoint((i + 1) % (iter->get().GetNumPoints())), + holepoint)) { + continue; + } +- polypoint = iter->GetPoint(i); ++ polypoint = iter->get().GetPoint(i); + if (pointfound) { + v1 = Normalize(polypoint - holepoint); + v2 = Normalize(bestpolypoint - holepoint); +@@ -263,13 +260,13 @@ int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) { + } + } + pointvisible = true; +- for (iter2 = polys.begin(); iter2 != polys.end(); iter2++) { +- if (iter2->IsHole()) { ++ for (iter2 = polys.front(); iter2; iter2->next()) { ++ if (iter2->get().IsHole()) { + continue; + } +- for (i2 = 0; i2 < iter2->GetNumPoints(); i2++) { +- linep1 = iter2->GetPoint(i2); +- linep2 = iter2->GetPoint((i2 + 1) % (iter2->GetNumPoints())); ++ for (i2 = 0; i2 < iter2->get().GetNumPoints(); i2++) { ++ linep1 = iter2->get().GetPoint(i2); ++ linep2 = iter2->get().GetPoint((i2 + 1) % (iter2->get().GetNumPoints())); + if (Intersects(holepoint, polypoint, linep1, linep2)) { + pointvisible = false; + break; +@@ -292,18 +289,18 @@ int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) { + return 0; + } + +- newpoly.Init(holeiter->GetNumPoints() + polyiter->GetNumPoints() + 2); ++ newpoly.Init(holeiter->get().GetNumPoints() + polyiter->get().GetNumPoints() + 2); + i2 = 0; + for (i = 0; i <= polypointindex; i++) { +- newpoly[i2] = polyiter->GetPoint(i); ++ newpoly[i2] = polyiter->get().GetPoint(i); + i2++; + } +- for (i = 0; i <= holeiter->GetNumPoints(); i++) { +- newpoly[i2] = holeiter->GetPoint((i + holepointindex) % holeiter->GetNumPoints()); ++ for (i = 0; i <= holeiter->get().GetNumPoints(); i++) { ++ newpoly[i2] = holeiter->get().GetPoint((i + holepointindex) % holeiter->get().GetNumPoints()); + i2++; + } +- for (i = polypointindex; i < polyiter->GetNumPoints(); i++) { +- newpoly[i2] = polyiter->GetPoint(i); ++ for (i = polypointindex; i < polyiter->get().GetNumPoints(); i++) { ++ newpoly[i2] = polyiter->get().GetPoint(i); + i2++; + } + +@@ -312,8 +309,8 @@ int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) { + polys.push_back(newpoly); + } + +- for (iter = polys.begin(); iter != polys.end(); iter++) { +- outpolys->push_back(*iter); ++ for (iter = polys.front(); iter; iter = iter->next()) { ++ outpolys->push_back(iter->get()); + } + + return 1; +@@ -524,13 +521,13 @@ int TPPLPartition::Triangulate_EC(TPPLPoly *poly, TPPLPolyList *triangles) { + + int TPPLPartition::Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles) { + TPPLPolyList outpolys; +- TPPLPolyList::iterator iter; ++ TPPLPolyList::Element *iter; + + if (!RemoveHoles(inpolys, &outpolys)) { + return 0; + } +- for (iter = outpolys.begin(); iter != outpolys.end(); iter++) { +- if (!Triangulate_EC(&(*iter), triangles)) { ++ for (iter = outpolys.front(); iter; iter = iter->next()) { ++ if (!Triangulate_EC(&(iter->get()), triangles)) { + return 0; + } + } +@@ -543,7 +540,7 @@ int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts) { + } + + TPPLPolyList triangles; +- TPPLPolyList::iterator iter1, iter2; ++ TPPLPolyList::Element *iter1, *iter2; + TPPLPoly *poly1 = NULL, *poly2 = NULL; + TPPLPoly newpoly; + TPPLPoint d1, d2, p1, p2, p3; +@@ -578,19 +575,19 @@ int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts) { + return 0; + } + +- for (iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) { +- poly1 = &(*iter1); ++ for (iter1 = triangles.front(); iter1; iter1 = iter1->next()) { ++ poly1 = &(iter1->get()); + for (i11 = 0; i11 < poly1->GetNumPoints(); i11++) { + d1 = poly1->GetPoint(i11); + i12 = (i11 + 1) % (poly1->GetNumPoints()); + d2 = poly1->GetPoint(i12); + + isdiagonal = false; +- for (iter2 = iter1; iter2 != triangles.end(); iter2++) { ++ for (iter2 = iter1; iter2; iter2 = iter2->next()) { + if (iter1 == iter2) { + continue; + } +- poly2 = &(*iter2); ++ poly2 = &(iter2->get()); + + for (i21 = 0; i21 < poly2->GetNumPoints(); i21++) { + if ((d2.x != poly2->GetPoint(i21).x) || (d2.y != poly2->GetPoint(i21).y)) { +@@ -660,16 +657,16 @@ int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts) { + } + + triangles.erase(iter2); +- *iter1 = newpoly; +- poly1 = &(*iter1); ++ iter1->get() = newpoly; ++ poly1 = &(iter1->get()); + i11 = -1; + + continue; + } + } + +- for (iter1 = triangles.begin(); iter1 != triangles.end(); iter1++) { +- parts->push_back(*iter1); ++ for (iter1 = triangles.front(); iter1; iter1 = iter1->next()) { ++ parts->push_back(iter1->get()); + } + + return 1; +@@ -677,13 +674,13 @@ int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts) { + + int TPPLPartition::ConvexPartition_HM(TPPLPolyList *inpolys, TPPLPolyList *parts) { + TPPLPolyList outpolys; +- TPPLPolyList::iterator iter; ++ TPPLPolyList::Element *iter; + + if (!RemoveHoles(inpolys, &outpolys)) { + return 0; + } +- for (iter = outpolys.begin(); iter != outpolys.end(); iter++) { +- if (!ConvexPartition_HM(&(*iter), parts)) { ++ for (iter = outpolys.front(); iter; iter = iter->next()) { ++ if (!ConvexPartition_HM(&(iter->get()), parts)) { + return 0; + } + } +@@ -824,8 +821,8 @@ int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, TPPLPolyList *triangles) { + newdiagonal.index1 = 0; + newdiagonal.index2 = n - 1; + diagonals.push_back(newdiagonal); +- while (!diagonals.empty()) { +- diagonal = *(diagonals.begin()); ++ while (!diagonals.is_empty()) { ++ diagonal = diagonals.front()->get(); + diagonals.pop_front(); + bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex; + if (bestvertex == -1) { +@@ -873,10 +870,10 @@ void TPPLPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 + pairs->push_front(newdiagonal); + dpstates[a][b].weight = w; + } else { +- if ((!pairs->empty()) && (i <= pairs->begin()->index1)) { ++ if ((!pairs->is_empty()) && (i <= pairs->front()->get().index1)) { + return; + } +- while ((!pairs->empty()) && (pairs->begin()->index2 >= j)) { ++ while ((!pairs->is_empty()) && (pairs->front()->get().index2 >= j)) { + pairs->pop_front(); + } + pairs->push_front(newdiagonal); +@@ -885,7 +882,7 @@ void TPPLPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 + + void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { + DiagonalList *pairs = NULL; +- DiagonalList::iterator iter, lastiter; ++ DiagonalList::Element *iter, *lastiter; + long top; + long w; + +@@ -902,23 +899,23 @@ void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPS + } + if (j - i > 1) { + pairs = &(dpstates[i][j].pairs); +- iter = pairs->end(); +- lastiter = pairs->end(); +- while (iter != pairs->begin()) { ++ iter = pairs->back(); ++ lastiter = pairs->back(); ++ while (iter != pairs->front()) { + iter--; +- if (!IsReflex(vertices[iter->index2].p, vertices[j].p, vertices[k].p)) { ++ if (!IsReflex(vertices[iter->get().index2].p, vertices[j].p, vertices[k].p)) { + lastiter = iter; + } else { + break; + } + } +- if (lastiter == pairs->end()) { ++ if (lastiter == pairs->back()) { + w++; + } else { +- if (IsReflex(vertices[k].p, vertices[i].p, vertices[lastiter->index1].p)) { ++ if (IsReflex(vertices[k].p, vertices[i].p, vertices[lastiter->get().index1].p)) { + w++; + } else { +- top = lastiter->index1; ++ top = lastiter->get().index1; + } + } + } +@@ -927,7 +924,7 @@ void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPS + + void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { + DiagonalList *pairs = NULL; +- DiagonalList::iterator iter, lastiter; ++ DiagonalList::Element *iter, *lastiter; + long top; + long w; + +@@ -946,21 +943,21 @@ void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPS + if (k - j > 1) { + pairs = &(dpstates[j][k].pairs); + +- iter = pairs->begin(); +- if ((!pairs->empty()) && (!IsReflex(vertices[i].p, vertices[j].p, vertices[iter->index1].p))) { ++ iter = pairs->front(); ++ if ((!pairs->is_empty()) && (!IsReflex(vertices[i].p, vertices[j].p, vertices[iter->get().index1].p))) { + lastiter = iter; +- while (iter != pairs->end()) { +- if (!IsReflex(vertices[i].p, vertices[j].p, vertices[iter->index1].p)) { ++ while (iter) { ++ if (!IsReflex(vertices[i].p, vertices[j].p, vertices[iter->get().index1].p)) { + lastiter = iter; +- iter++; ++ iter = iter->next(); + } else { + break; + } + } +- if (IsReflex(vertices[lastiter->index2].p, vertices[k].p, vertices[i].p)) { ++ if (IsReflex(vertices[lastiter->get().index2].p, vertices[k].p, vertices[i].p)) { + w++; + } else { +- top = lastiter->index2; ++ top = lastiter->get().index2; + } + } else { + w++; +@@ -981,11 +978,11 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts) { + DiagonalList diagonals, diagonals2; + Diagonal diagonal, newdiagonal; + DiagonalList *pairs = NULL, *pairs2 = NULL; +- DiagonalList::iterator iter, iter2; ++ DiagonalList::Element *iter, *iter2; + int ret; + TPPLPoly newpoly; +- std::vector<long> indices; +- std::vector<long>::iterator iiter; ++ List<long> indices; ++ List<long>::Element *iiter; + bool ijreal, jkreal; + + n = poly->GetNumPoints(); +@@ -1110,35 +1107,35 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts) { + newdiagonal.index1 = 0; + newdiagonal.index2 = n - 1; + diagonals.push_front(newdiagonal); +- while (!diagonals.empty()) { +- diagonal = *(diagonals.begin()); ++ while (!diagonals.is_empty()) { ++ diagonal = diagonals.front()->get(); + diagonals.pop_front(); + if ((diagonal.index2 - diagonal.index1) <= 1) { + continue; + } + pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs); +- if (pairs->empty()) { ++ if (pairs->is_empty()) { + ret = 0; + break; + } + if (!vertices[diagonal.index1].isConvex) { +- iter = pairs->end(); ++ iter = pairs->back(); + iter--; +- j = iter->index2; ++ j = iter->get().index2; + newdiagonal.index1 = j; + newdiagonal.index2 = diagonal.index2; + diagonals.push_front(newdiagonal); + if ((j - diagonal.index1) > 1) { +- if (iter->index1 != iter->index2) { ++ if (iter->get().index1 != iter->get().index2) { + pairs2 = &(dpstates[diagonal.index1][j].pairs); + while (1) { +- if (pairs2->empty()) { ++ if (pairs2->is_empty()) { + ret = 0; + break; + } +- iter2 = pairs2->end(); ++ iter2 = pairs2->back(); + iter2--; +- if (iter->index1 != iter2->index1) { ++ if (iter->get().index1 != iter2->get().index1) { + pairs2->pop_back(); + } else { + break; +@@ -1153,21 +1150,21 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts) { + diagonals.push_front(newdiagonal); + } + } else { +- iter = pairs->begin(); +- j = iter->index1; ++ iter = pairs->front(); ++ j = iter->get().index1; + newdiagonal.index1 = diagonal.index1; + newdiagonal.index2 = j; + diagonals.push_front(newdiagonal); + if ((diagonal.index2 - j) > 1) { +- if (iter->index1 != iter->index2) { ++ if (iter->get().index1 != iter->get().index2) { + pairs2 = &(dpstates[j][diagonal.index2].pairs); + while (1) { +- if (pairs2->empty()) { ++ if (pairs2->is_empty()) { + ret = 0; + break; + } +- iter2 = pairs2->begin(); +- if (iter->index2 != iter2->index2) { ++ iter2 = pairs2->front(); ++ if (iter->get().index2 != iter2->get().index2) { + pairs2->pop_front(); + } else { + break; +@@ -1197,8 +1194,8 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts) { + newdiagonal.index1 = 0; + newdiagonal.index2 = n - 1; + diagonals.push_front(newdiagonal); +- while (!diagonals.empty()) { +- diagonal = *(diagonals.begin()); ++ while (!diagonals.is_empty()) { ++ diagonal = diagonals.front()->get(); + diagonals.pop_front(); + if ((diagonal.index2 - diagonal.index1) <= 1) { + continue; +@@ -1210,8 +1207,8 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts) { + indices.push_back(diagonal.index2); + diagonals2.push_front(diagonal); + +- while (!diagonals2.empty()) { +- diagonal = *(diagonals2.begin()); ++ while (!diagonals2.is_empty()) { ++ diagonal = diagonals2.front()->get(); + diagonals2.pop_front(); + if ((diagonal.index2 - diagonal.index1) <= 1) { + continue; +@@ -1220,16 +1217,16 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts) { + jkreal = true; + pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs); + if (!vertices[diagonal.index1].isConvex) { +- iter = pairs->end(); ++ iter = pairs->back(); + iter--; +- j = iter->index2; +- if (iter->index1 != iter->index2) { ++ j = iter->get().index2; ++ if (iter->get().index1 != iter->get().index2) { + ijreal = false; + } + } else { +- iter = pairs->begin(); +- j = iter->index1; +- if (iter->index1 != iter->index2) { ++ iter = pairs->front(); ++ j = iter->get().index1; ++ if (iter->get().index1 != iter->get().index2) { + jkreal = false; + } + } +@@ -1253,11 +1250,12 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts) { + indices.push_back(j); + } + +- std::sort(indices.begin(), indices.end()); ++ //std::sort(indices.begin(), indices.end()); ++ indices.sort(); + newpoly.Init((long)indices.size()); + k = 0; +- for (iiter = indices.begin(); iiter != indices.end(); iiter++) { +- newpoly[k] = vertices[*iiter].p; ++ for (iiter = indices.front(); iiter != indices.back(); iiter = iiter->next()) { ++ newpoly[k] = vertices[iiter->get()].p; + k++; + } + parts->push_back(newpoly); +@@ -1281,7 +1279,7 @@ int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts) { + // "Computational Geometry: Algorithms and Applications" + // by Mark de Berg, Otfried Cheong, Marc van Kreveld, and Mark Overmars. + int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monotonePolys) { +- TPPLPolyList::iterator iter; ++ TPPLPolyList::Element *iter; + MonotoneVertex *vertices = NULL; + long i, numvertices, vindex, vindex2, newnumvertices, maxnumvertices; + long polystartindex, polyendindex; +@@ -1291,11 +1289,8 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto + bool error = false; + + numvertices = 0; +- for (iter = inpolys->begin(); iter != inpolys->end(); iter++) { +- if (!iter->Valid()) { +- return 0; +- } +- numvertices += iter->GetNumPoints(); ++ for (iter = inpolys->front(); iter; iter++) { ++ numvertices += iter->get().GetNumPoints(); + } + + maxnumvertices = numvertices * 3; +@@ -1303,8 +1298,8 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto + newnumvertices = numvertices; + + polystartindex = 0; +- for (iter = inpolys->begin(); iter != inpolys->end(); iter++) { +- poly = &(*iter); ++ for (iter = inpolys->front(); iter; iter++) { ++ poly = &(iter->get()); + polyendindex = polystartindex + poly->GetNumPoints() - 1; + for (i = 0; i < poly->GetNumPoints(); i++) { + vertices[i + polystartindex].p = poly->GetPoint(i); +@@ -1360,14 +1355,14 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto + // Note that while set doesn't actually have to be implemented as + // a tree, complexity requirements for operations are the same as + // for the balanced binary search tree. +- std::set<ScanLineEdge> edgeTree; ++ Set<ScanLineEdge> edgeTree; + // Store iterators to the edge tree elements. + // This makes deleting existing edges much faster. +- std::set<ScanLineEdge>::iterator *edgeTreeIterators, edgeIter; +- edgeTreeIterators = new std::set<ScanLineEdge>::iterator[maxnumvertices]; +- std::pair<std::set<ScanLineEdge>::iterator, bool> edgeTreeRet; ++ Set<ScanLineEdge>::Element **edgeTreeIterators, *edgeIter; ++ edgeTreeIterators = new Set<ScanLineEdge>::Element *[maxnumvertices]; ++ //Pair<Set<ScanLineEdge>::iterator, bool> edgeTreeRet; + for (i = 0; i < numvertices; i++) { +- edgeTreeIterators[i] = edgeTree.end(); ++ edgeTreeIterators[i] = nullptr; + } + + // For each vertex. +@@ -1387,13 +1382,14 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto + newedge.p1 = v->p; + newedge.p2 = vertices[v->next].p; + newedge.index = vindex; +- edgeTreeRet = edgeTree.insert(newedge); +- edgeTreeIterators[vindex] = edgeTreeRet.first; ++ //edgeTreeRet = edgeTree.insert(newedge); ++ //edgeTreeIterators[vindex] = edgeTreeRet.first; ++ edgeTreeIterators[vindex] = edgeTree.insert(newedge); + helpers[vindex] = vindex; + break; + + case TPPL_VERTEXTYPE_END: +- if (edgeTreeIterators[v->previous] == edgeTree.end()) { ++ if (edgeTreeIterators[v->previous] == edgeTree.back()) { + error = true; + break; + } +@@ -1412,29 +1408,30 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto + newedge.p1 = v->p; + newedge.p2 = v->p; + edgeIter = edgeTree.lower_bound(newedge); +- if (edgeIter == edgeTree.begin()) { ++ if (edgeIter == edgeTree.front()) { + error = true; + break; + } + edgeIter--; + // Insert the diagonal connecting vi to helper(e_j) in D. +- AddDiagonal(vertices, &newnumvertices, vindex, helpers[edgeIter->index], ++ AddDiagonal(vertices, &newnumvertices, vindex, helpers[edgeIter->get().index], + vertextypes, edgeTreeIterators, &edgeTree, helpers); + vindex2 = newnumvertices - 2; + v2 = &(vertices[vindex2]); + // helper(e_j) in v_i. +- helpers[edgeIter->index] = vindex; ++ helpers[edgeIter->get().index] = vindex; + // Insert e_i in T and set helper(e_i) to v_i. + newedge.p1 = v2->p; + newedge.p2 = vertices[v2->next].p; + newedge.index = vindex2; +- edgeTreeRet = edgeTree.insert(newedge); +- edgeTreeIterators[vindex2] = edgeTreeRet.first; ++ //edgeTreeRet = edgeTree.insert(newedge); ++ //edgeTreeIterators[vindex2] = edgeTreeRet.first; ++ edgeTreeIterators[vindex2] = edgeTree.insert(newedge); + helpers[vindex2] = vindex2; + break; + + case TPPL_VERTEXTYPE_MERGE: +- if (edgeTreeIterators[v->previous] == edgeTree.end()) { ++ if (edgeTreeIterators[v->previous] == edgeTree.back()) { + error = true; + break; + } +@@ -1452,25 +1449,25 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto + newedge.p1 = v->p; + newedge.p2 = v->p; + edgeIter = edgeTree.lower_bound(newedge); +- if (edgeIter == edgeTree.begin()) { ++ if (edgeIter == edgeTree.front()) { + error = true; + break; + } + edgeIter--; + // If helper(e_j) is a merge vertex. +- if (vertextypes[helpers[edgeIter->index]] == TPPL_VERTEXTYPE_MERGE) { ++ if (vertextypes[helpers[edgeIter->get().index]] == TPPL_VERTEXTYPE_MERGE) { + // Insert the diagonal connecting v_i to helper(e_j) in D. +- AddDiagonal(vertices, &newnumvertices, vindex2, helpers[edgeIter->index], ++ AddDiagonal(vertices, &newnumvertices, vindex2, helpers[edgeIter->get().index], + vertextypes, edgeTreeIterators, &edgeTree, helpers); + } + // helper(e_j) <- v_i +- helpers[edgeIter->index] = vindex2; ++ helpers[edgeIter->get().index] = vindex2; + break; + + case TPPL_VERTEXTYPE_REGULAR: + // If the interior of P lies to the right of v_i. + if (Below(v->p, vertices[v->previous].p)) { +- if (edgeTreeIterators[v->previous] == edgeTree.end()) { ++ if (edgeTreeIterators[v->previous] == edgeTree.back()) { + error = true; + break; + } +@@ -1488,27 +1485,28 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto + newedge.p1 = v2->p; + newedge.p2 = vertices[v2->next].p; + newedge.index = vindex2; +- edgeTreeRet = edgeTree.insert(newedge); +- edgeTreeIterators[vindex2] = edgeTreeRet.first; ++ //edgeTreeRet = edgeTree.insert(newedge); ++ //edgeTreeIterators[vindex2] = edgeTreeRet.first; ++ edgeTreeIterators[vindex2] = edgeTree.insert(newedge); + helpers[vindex2] = vindex; + } else { + // Search in T to find the edge e_j directly left of v_i. + newedge.p1 = v->p; + newedge.p2 = v->p; + edgeIter = edgeTree.lower_bound(newedge); +- if (edgeIter == edgeTree.begin()) { ++ if (edgeIter == edgeTree.front()) { + error = true; + break; + } +- edgeIter--; ++ edgeIter = edgeIter->prev(); + // If helper(e_j) is a merge vertex. +- if (vertextypes[helpers[edgeIter->index]] == TPPL_VERTEXTYPE_MERGE) { ++ if (vertextypes[helpers[edgeIter->get().index]] == TPPL_VERTEXTYPE_MERGE) { + // Insert the diagonal connecting v_i to helper(e_j) in D. +- AddDiagonal(vertices, &newnumvertices, vindex, helpers[edgeIter->index], ++ AddDiagonal(vertices, &newnumvertices, vindex, helpers[edgeIter->get().index], + vertextypes, edgeTreeIterators, &edgeTree, helpers); + } + // helper(e_j) <- v_i. +- helpers[edgeIter->index] = vindex; ++ helpers[edgeIter->get().index] = vindex; + } + break; + } +@@ -1569,8 +1567,8 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto + + // Adds a diagonal to the doubly-connected list of vertices. + void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2, +- TPPLVertexType *vertextypes, std::set<ScanLineEdge>::iterator *edgeTreeIterators, +- std::set<ScanLineEdge> *edgeTree, long *helpers) { ++ TPPLVertexType *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators, ++ Set<ScanLineEdge> *edgeTree, long *helpers) { + long newindex1, newindex2; + + newindex1 = *numvertices; +@@ -1597,14 +1595,14 @@ void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, lon + vertextypes[newindex1] = vertextypes[index1]; + edgeTreeIterators[newindex1] = edgeTreeIterators[index1]; + helpers[newindex1] = helpers[index1]; +- if (edgeTreeIterators[newindex1] != edgeTree->end()) { +- edgeTreeIterators[newindex1]->index = newindex1; ++ if (edgeTreeIterators[newindex1] != edgeTree->back()) { ++ edgeTreeIterators[newindex1]->get().index = newindex1; + } + vertextypes[newindex2] = vertextypes[index2]; + edgeTreeIterators[newindex2] = edgeTreeIterators[index2]; + helpers[newindex2] = helpers[index2]; +- if (edgeTreeIterators[newindex2] != edgeTree->end()) { +- edgeTreeIterators[newindex2]->index = newindex2; ++ if (edgeTreeIterators[newindex2] != edgeTree->back()) { ++ edgeTreeIterators[newindex2]->get().index = newindex2; + } + } + +@@ -1830,13 +1828,13 @@ int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles + + int TPPLPartition::Triangulate_MONO(TPPLPolyList *inpolys, TPPLPolyList *triangles) { + TPPLPolyList monotone; +- TPPLPolyList::iterator iter; ++ TPPLPolyList::Element *iter; + + if (!MonotonePartition(inpolys, &monotone)) { + return 0; + } +- for (iter = monotone.begin(); iter != monotone.end(); iter++) { +- if (!TriangulateMonotone(&(*iter), triangles)) { ++ for (iter = monotone.front(); iter; iter = iter->next()) { ++ if (!TriangulateMonotone(&(iter->get()), triangles)) { + return 0; + } + } +diff --git a/thirdparty/misc/polypartition.h b/thirdparty/misc/polypartition.h +index f163f5d2173f..b2d905a3ef76 100644 +--- a/thirdparty/misc/polypartition.h ++++ b/thirdparty/misc/polypartition.h +@@ -24,8 +24,9 @@ + #ifndef POLYPARTITION_H + #define POLYPARTITION_H + +-#include <list> +-#include <set> ++#include "core/math/vector2.h" ++#include "core/templates/list.h" ++#include "core/templates/set.h" + + typedef double tppl_float; + +@@ -44,49 +45,7 @@ enum TPPLVertexType { + }; + + // 2D point structure. +-struct TPPLPoint { +- tppl_float x; +- tppl_float y; +- // User-specified vertex identifier. Note that this isn't used internally +- // by the library, but will be faithfully copied around. +- int id; +- +- TPPLPoint operator+(const TPPLPoint &p) const { +- TPPLPoint r; +- r.x = x + p.x; +- r.y = y + p.y; +- return r; +- } +- +- TPPLPoint operator-(const TPPLPoint &p) const { +- TPPLPoint r; +- r.x = x - p.x; +- r.y = y - p.y; +- return r; +- } +- +- TPPLPoint operator*(const tppl_float f) const { +- TPPLPoint r; +- r.x = x * f; +- r.y = y * f; +- return r; +- } +- +- TPPLPoint operator/(const tppl_float f) const { +- TPPLPoint r; +- r.x = x / f; +- r.y = y / f; +- return r; +- } +- +- bool operator==(const TPPLPoint &p) const { +- return ((x == p.x) && (y == p.y)); +- } +- +- bool operator!=(const TPPLPoint &p) const { +- return !((x == p.x) && (y == p.y)); +- } +-}; ++typedef Vector2 TPPLPoint; + + // Polygon implemented as an array of points with a "hole" flag. + class TPPLPoly { +@@ -168,9 +127,9 @@ class TPPLPoly { + }; + + #ifdef TPPL_ALLOCATOR +-typedef std::list<TPPLPoly, TPPL_ALLOCATOR(TPPLPoly)> TPPLPolyList; ++typedef List<TPPLPoly, TPPL_ALLOCATOR(TPPLPoly)> TPPLPolyList; + #else +-typedef std::list<TPPLPoly> TPPLPolyList; ++typedef List<TPPLPoly> TPPLPolyList; + #endif + + class TPPLPartition { +@@ -209,9 +168,9 @@ public: + }; + + #ifdef TPPL_ALLOCATOR +- typedef std::list<Diagonal, TPPL_ALLOCATOR(Diagonal)> DiagonalList; ++ typedef List<Diagonal, TPPL_ALLOCATOR(Diagonal)> DiagonalList; + #else +- typedef std::list<Diagonal> DiagonalList; ++ typedef List<Diagonal> DiagonalList; + #endif + + // Dynamic programming state for minimum-weight triangulation. +@@ -265,8 +224,8 @@ public: + // Helper functions for MonotonePartition. + bool Below(TPPLPoint &p1, TPPLPoint &p2); + void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2, +- TPPLVertexType *vertextypes, std::set<ScanLineEdge>::iterator *edgeTreeIterators, +- std::set<ScanLineEdge> *edgeTree, long *helpers); ++ TPPLVertexType *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators, ++ Set<ScanLineEdge> *edgeTree, long *helpers); + + // Triangulates a monotone polygon, used in Triangulate_MONO. + int TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles); diff --git a/thirdparty/misc/polypartition.cpp b/thirdparty/misc/polypartition.cpp new file mode 100644 index 0000000000..4f1b6dcb21 --- /dev/null +++ b/thirdparty/misc/polypartition.cpp @@ -0,0 +1,1849 @@ +/*************************************************************************/ +/* Copyright (c) 2011-2021 Ivan Fratric and contributors. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "polypartition.h" + +#include <algorithm> + +TPPLPoly::TPPLPoly() { + hole = false; + numpoints = 0; + points = NULL; +} + +TPPLPoly::~TPPLPoly() { + if (points) { + delete[] points; + } +} + +void TPPLPoly::Clear() { + if (points) { + delete[] points; + } + hole = false; + numpoints = 0; + points = NULL; +} + +void TPPLPoly::Init(long numpoints) { + Clear(); + this->numpoints = numpoints; + points = new TPPLPoint[numpoints]; +} + +void TPPLPoly::Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3) { + Init(3); + points[0] = p1; + points[1] = p2; + points[2] = p3; +} + +TPPLPoly::TPPLPoly(const TPPLPoly &src) : + TPPLPoly() { + hole = src.hole; + numpoints = src.numpoints; + + if (numpoints > 0) { + points = new TPPLPoint[numpoints]; + memcpy(points, src.points, numpoints * sizeof(TPPLPoint)); + } +} + +TPPLPoly &TPPLPoly::operator=(const TPPLPoly &src) { + Clear(); + hole = src.hole; + numpoints = src.numpoints; + + if (numpoints > 0) { + points = new TPPLPoint[numpoints]; + memcpy(points, src.points, numpoints * sizeof(TPPLPoint)); + } + + return *this; +} + +TPPLOrientation TPPLPoly::GetOrientation() const { + long i1, i2; + tppl_float area = 0; + for (i1 = 0; i1 < numpoints; i1++) { + i2 = i1 + 1; + if (i2 == numpoints) { + i2 = 0; + } + area += points[i1].x * points[i2].y - points[i1].y * points[i2].x; + } + if (area > 0) { + return TPPL_ORIENTATION_CCW; + } + if (area < 0) { + return TPPL_ORIENTATION_CW; + } + return TPPL_ORIENTATION_NONE; +} + +void TPPLPoly::SetOrientation(TPPLOrientation orientation) { + TPPLOrientation polyorientation = GetOrientation(); + if (polyorientation != TPPL_ORIENTATION_NONE && polyorientation != orientation) { + Invert(); + } +} + +void TPPLPoly::Invert() { + std::reverse(points, points + numpoints); +} + +TPPLPartition::PartitionVertex::PartitionVertex() : + previous(NULL), next(NULL) { +} + +TPPLPoint TPPLPartition::Normalize(const TPPLPoint &p) { + TPPLPoint r; + tppl_float n = sqrt(p.x * p.x + p.y * p.y); + if (n != 0) { + r = p / n; + } else { + r.x = 0; + r.y = 0; + } + return r; +} + +tppl_float TPPLPartition::Distance(const TPPLPoint &p1, const TPPLPoint &p2) { + tppl_float dx, dy; + dx = p2.x - p1.x; + dy = p2.y - p1.y; + return (sqrt(dx * dx + dy * dy)); +} + +// Checks if two lines intersect. +int TPPLPartition::Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22) { + if ((p11.x == p21.x) && (p11.y == p21.y)) { + return 0; + } + if ((p11.x == p22.x) && (p11.y == p22.y)) { + return 0; + } + if ((p12.x == p21.x) && (p12.y == p21.y)) { + return 0; + } + if ((p12.x == p22.x) && (p12.y == p22.y)) { + return 0; + } + + TPPLPoint v1ort, v2ort, v; + tppl_float dot11, dot12, dot21, dot22; + + v1ort.x = p12.y - p11.y; + v1ort.y = p11.x - p12.x; + + v2ort.x = p22.y - p21.y; + v2ort.y = p21.x - p22.x; + + v = p21 - p11; + dot21 = v.x * v1ort.x + v.y * v1ort.y; + v = p22 - p11; + dot22 = v.x * v1ort.x + v.y * v1ort.y; + + v = p11 - p21; + dot11 = v.x * v2ort.x + v.y * v2ort.y; + v = p12 - p21; + dot12 = v.x * v2ort.x + v.y * v2ort.y; + + if (dot11 * dot12 > 0) { + return 0; + } + if (dot21 * dot22 > 0) { + return 0; + } + + return 1; +} + +// Removes holes from inpolys by merging them with non-holes. +int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) { + TPPLPolyList polys; + TPPLPolyList::Element *holeiter, *polyiter, *iter, *iter2; + long i, i2, holepointindex, polypointindex; + TPPLPoint holepoint, polypoint, bestpolypoint; + TPPLPoint linep1, linep2; + TPPLPoint v1, v2; + TPPLPoly newpoly; + bool hasholes; + bool pointvisible; + bool pointfound; + + // Check for the trivial case of no holes. + hasholes = false; + for (iter = inpolys->front(); iter; iter = iter->next()) { + if (iter->get().IsHole()) { + hasholes = true; + break; + } + } + if (!hasholes) { + for (iter = inpolys->front(); iter; iter = iter->next()) { + outpolys->push_back(iter->get()); + } + return 1; + } + + polys = *inpolys; + + while (1) { + // Find the hole point with the largest x. + hasholes = false; + for (iter = polys.front(); iter; iter = iter->next()) { + if (!iter->get().IsHole()) { + continue; + } + + if (!hasholes) { + hasholes = true; + holeiter = iter; + holepointindex = 0; + } + + for (i = 0; i < iter->get().GetNumPoints(); i++) { + if (iter->get().GetPoint(i).x > holeiter->get().GetPoint(holepointindex).x) { + holeiter = iter; + holepointindex = i; + } + } + } + if (!hasholes) { + break; + } + holepoint = holeiter->get().GetPoint(holepointindex); + + pointfound = false; + for (iter = polys.front(); iter; iter = iter->next()) { + if (iter->get().IsHole()) { + continue; + } + for (i = 0; i < iter->get().GetNumPoints(); i++) { + if (iter->get().GetPoint(i).x <= holepoint.x) { + continue; + } + if (!InCone(iter->get().GetPoint((i + iter->get().GetNumPoints() - 1) % (iter->get().GetNumPoints())), + iter->get().GetPoint(i), + iter->get().GetPoint((i + 1) % (iter->get().GetNumPoints())), + holepoint)) { + continue; + } + polypoint = iter->get().GetPoint(i); + if (pointfound) { + v1 = Normalize(polypoint - holepoint); + v2 = Normalize(bestpolypoint - holepoint); + if (v2.x > v1.x) { + continue; + } + } + pointvisible = true; + for (iter2 = polys.front(); iter2; iter2->next()) { + if (iter2->get().IsHole()) { + continue; + } + for (i2 = 0; i2 < iter2->get().GetNumPoints(); i2++) { + linep1 = iter2->get().GetPoint(i2); + linep2 = iter2->get().GetPoint((i2 + 1) % (iter2->get().GetNumPoints())); + if (Intersects(holepoint, polypoint, linep1, linep2)) { + pointvisible = false; + break; + } + } + if (!pointvisible) { + break; + } + } + if (pointvisible) { + pointfound = true; + bestpolypoint = polypoint; + polyiter = iter; + polypointindex = i; + } + } + } + + if (!pointfound) { + return 0; + } + + newpoly.Init(holeiter->get().GetNumPoints() + polyiter->get().GetNumPoints() + 2); + i2 = 0; + for (i = 0; i <= polypointindex; i++) { + newpoly[i2] = polyiter->get().GetPoint(i); + i2++; + } + for (i = 0; i <= holeiter->get().GetNumPoints(); i++) { + newpoly[i2] = holeiter->get().GetPoint((i + holepointindex) % holeiter->get().GetNumPoints()); + i2++; + } + for (i = polypointindex; i < polyiter->get().GetNumPoints(); i++) { + newpoly[i2] = polyiter->get().GetPoint(i); + i2++; + } + + polys.erase(holeiter); + polys.erase(polyiter); + polys.push_back(newpoly); + } + + for (iter = polys.front(); iter; iter = iter->next()) { + outpolys->push_back(iter->get()); + } + + return 1; +} + +bool TPPLPartition::IsConvex(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3) { + tppl_float tmp; + tmp = (p3.y - p1.y) * (p2.x - p1.x) - (p3.x - p1.x) * (p2.y - p1.y); + if (tmp > 0) { + return 1; + } else { + return 0; + } +} + +bool TPPLPartition::IsReflex(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3) { + tppl_float tmp; + tmp = (p3.y - p1.y) * (p2.x - p1.x) - (p3.x - p1.x) * (p2.y - p1.y); + if (tmp < 0) { + return 1; + } else { + return 0; + } +} + +bool TPPLPartition::IsInside(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p) { + if (IsConvex(p1, p, p2)) { + return false; + } + if (IsConvex(p2, p, p3)) { + return false; + } + if (IsConvex(p3, p, p1)) { + return false; + } + return true; +} + +bool TPPLPartition::InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p) { + bool convex; + + convex = IsConvex(p1, p2, p3); + + if (convex) { + if (!IsConvex(p1, p2, p)) { + return false; + } + if (!IsConvex(p2, p3, p)) { + return false; + } + return true; + } else { + if (IsConvex(p1, p2, p)) { + return true; + } + if (IsConvex(p2, p3, p)) { + return true; + } + return false; + } +} + +bool TPPLPartition::InCone(PartitionVertex *v, TPPLPoint &p) { + TPPLPoint p1, p2, p3; + + p1 = v->previous->p; + p2 = v->p; + p3 = v->next->p; + + return InCone(p1, p2, p3, p); +} + +void TPPLPartition::UpdateVertexReflexity(PartitionVertex *v) { + PartitionVertex *v1 = NULL, *v3 = NULL; + v1 = v->previous; + v3 = v->next; + v->isConvex = !IsReflex(v1->p, v->p, v3->p); +} + +void TPPLPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices) { + long i; + PartitionVertex *v1 = NULL, *v3 = NULL; + TPPLPoint vec1, vec3; + + v1 = v->previous; + v3 = v->next; + + v->isConvex = IsConvex(v1->p, v->p, v3->p); + + vec1 = Normalize(v1->p - v->p); + vec3 = Normalize(v3->p - v->p); + v->angle = vec1.x * vec3.x + vec1.y * vec3.y; + + if (v->isConvex) { + v->isEar = true; + for (i = 0; i < numvertices; i++) { + if ((vertices[i].p.x == v->p.x) && (vertices[i].p.y == v->p.y)) { + continue; + } + if ((vertices[i].p.x == v1->p.x) && (vertices[i].p.y == v1->p.y)) { + continue; + } + if ((vertices[i].p.x == v3->p.x) && (vertices[i].p.y == v3->p.y)) { + continue; + } + if (IsInside(v1->p, v->p, v3->p, vertices[i].p)) { + v->isEar = false; + break; + } + } + } else { + v->isEar = false; + } +} + +// Triangulation by ear removal. +int TPPLPartition::Triangulate_EC(TPPLPoly *poly, TPPLPolyList *triangles) { + if (!poly->Valid()) { + return 0; + } + + long numvertices; + PartitionVertex *vertices = NULL; + PartitionVertex *ear = NULL; + TPPLPoly triangle; + long i, j; + bool earfound; + + if (poly->GetNumPoints() < 3) { + return 0; + } + if (poly->GetNumPoints() == 3) { + triangles->push_back(*poly); + return 1; + } + + numvertices = poly->GetNumPoints(); + + vertices = new PartitionVertex[numvertices]; + for (i = 0; i < numvertices; i++) { + vertices[i].isActive = true; + vertices[i].p = poly->GetPoint(i); + if (i == (numvertices - 1)) { + vertices[i].next = &(vertices[0]); + } else { + vertices[i].next = &(vertices[i + 1]); + } + if (i == 0) { + vertices[i].previous = &(vertices[numvertices - 1]); + } else { + vertices[i].previous = &(vertices[i - 1]); + } + } + for (i = 0; i < numvertices; i++) { + UpdateVertex(&vertices[i], vertices, numvertices); + } + + for (i = 0; i < numvertices - 3; i++) { + earfound = false; + // Find the most extruded ear. + for (j = 0; j < numvertices; j++) { + if (!vertices[j].isActive) { + continue; + } + if (!vertices[j].isEar) { + continue; + } + if (!earfound) { + earfound = true; + ear = &(vertices[j]); + } else { + if (vertices[j].angle > ear->angle) { + ear = &(vertices[j]); + } + } + } + if (!earfound) { + delete[] vertices; + return 0; + } + + triangle.Triangle(ear->previous->p, ear->p, ear->next->p); + triangles->push_back(triangle); + + ear->isActive = false; + ear->previous->next = ear->next; + ear->next->previous = ear->previous; + + if (i == numvertices - 4) { + break; + } + + UpdateVertex(ear->previous, vertices, numvertices); + UpdateVertex(ear->next, vertices, numvertices); + } + for (i = 0; i < numvertices; i++) { + if (vertices[i].isActive) { + triangle.Triangle(vertices[i].previous->p, vertices[i].p, vertices[i].next->p); + triangles->push_back(triangle); + break; + } + } + + delete[] vertices; + + return 1; +} + +int TPPLPartition::Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles) { + TPPLPolyList outpolys; + TPPLPolyList::Element *iter; + + if (!RemoveHoles(inpolys, &outpolys)) { + return 0; + } + for (iter = outpolys.front(); iter; iter = iter->next()) { + if (!Triangulate_EC(&(iter->get()), triangles)) { + return 0; + } + } + return 1; +} + +int TPPLPartition::ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts) { + if (!poly->Valid()) { + return 0; + } + + TPPLPolyList triangles; + TPPLPolyList::Element *iter1, *iter2; + TPPLPoly *poly1 = NULL, *poly2 = NULL; + TPPLPoly newpoly; + TPPLPoint d1, d2, p1, p2, p3; + long i11, i12, i21, i22, i13, i23, j, k; + bool isdiagonal; + long numreflex; + + // Check if the poly is already convex. + numreflex = 0; + for (i11 = 0; i11 < poly->GetNumPoints(); i11++) { + if (i11 == 0) { + i12 = poly->GetNumPoints() - 1; + } else { + i12 = i11 - 1; + } + if (i11 == (poly->GetNumPoints() - 1)) { + i13 = 0; + } else { + i13 = i11 + 1; + } + if (IsReflex(poly->GetPoint(i12), poly->GetPoint(i11), poly->GetPoint(i13))) { + numreflex = 1; + break; + } + } + if (numreflex == 0) { + parts->push_back(*poly); + return 1; + } + + if (!Triangulate_EC(poly, &triangles)) { + return 0; + } + + for (iter1 = triangles.front(); iter1; iter1 = iter1->next()) { + poly1 = &(iter1->get()); + for (i11 = 0; i11 < poly1->GetNumPoints(); i11++) { + d1 = poly1->GetPoint(i11); + i12 = (i11 + 1) % (poly1->GetNumPoints()); + d2 = poly1->GetPoint(i12); + + isdiagonal = false; + for (iter2 = iter1; iter2; iter2 = iter2->next()) { + if (iter1 == iter2) { + continue; + } + poly2 = &(iter2->get()); + + for (i21 = 0; i21 < poly2->GetNumPoints(); i21++) { + if ((d2.x != poly2->GetPoint(i21).x) || (d2.y != poly2->GetPoint(i21).y)) { + continue; + } + i22 = (i21 + 1) % (poly2->GetNumPoints()); + if ((d1.x != poly2->GetPoint(i22).x) || (d1.y != poly2->GetPoint(i22).y)) { + continue; + } + isdiagonal = true; + break; + } + if (isdiagonal) { + break; + } + } + + if (!isdiagonal) { + continue; + } + + p2 = poly1->GetPoint(i11); + if (i11 == 0) { + i13 = poly1->GetNumPoints() - 1; + } else { + i13 = i11 - 1; + } + p1 = poly1->GetPoint(i13); + if (i22 == (poly2->GetNumPoints() - 1)) { + i23 = 0; + } else { + i23 = i22 + 1; + } + p3 = poly2->GetPoint(i23); + + if (!IsConvex(p1, p2, p3)) { + continue; + } + + p2 = poly1->GetPoint(i12); + if (i12 == (poly1->GetNumPoints() - 1)) { + i13 = 0; + } else { + i13 = i12 + 1; + } + p3 = poly1->GetPoint(i13); + if (i21 == 0) { + i23 = poly2->GetNumPoints() - 1; + } else { + i23 = i21 - 1; + } + p1 = poly2->GetPoint(i23); + + if (!IsConvex(p1, p2, p3)) { + continue; + } + + newpoly.Init(poly1->GetNumPoints() + poly2->GetNumPoints() - 2); + k = 0; + for (j = i12; j != i11; j = (j + 1) % (poly1->GetNumPoints())) { + newpoly[k] = poly1->GetPoint(j); + k++; + } + for (j = i22; j != i21; j = (j + 1) % (poly2->GetNumPoints())) { + newpoly[k] = poly2->GetPoint(j); + k++; + } + + triangles.erase(iter2); + iter1->get() = newpoly; + poly1 = &(iter1->get()); + i11 = -1; + + continue; + } + } + + for (iter1 = triangles.front(); iter1; iter1 = iter1->next()) { + parts->push_back(iter1->get()); + } + + return 1; +} + +int TPPLPartition::ConvexPartition_HM(TPPLPolyList *inpolys, TPPLPolyList *parts) { + TPPLPolyList outpolys; + TPPLPolyList::Element *iter; + + if (!RemoveHoles(inpolys, &outpolys)) { + return 0; + } + for (iter = outpolys.front(); iter; iter = iter->next()) { + if (!ConvexPartition_HM(&(iter->get()), parts)) { + return 0; + } + } + return 1; +} + +// Minimum-weight polygon triangulation by dynamic programming. +// Time complexity: O(n^3) +// Space complexity: O(n^2) +int TPPLPartition::Triangulate_OPT(TPPLPoly *poly, TPPLPolyList *triangles) { + if (!poly->Valid()) { + return 0; + } + + long i, j, k, gap, n; + DPState **dpstates = NULL; + TPPLPoint p1, p2, p3, p4; + long bestvertex; + tppl_float weight, minweight, d1, d2; + Diagonal diagonal, newdiagonal; + DiagonalList diagonals; + TPPLPoly triangle; + int ret = 1; + + n = poly->GetNumPoints(); + dpstates = new DPState *[n]; + for (i = 1; i < n; i++) { + dpstates[i] = new DPState[i]; + } + + // Initialize states and visibility. + for (i = 0; i < (n - 1); i++) { + p1 = poly->GetPoint(i); + for (j = i + 1; j < n; j++) { + dpstates[j][i].visible = true; + dpstates[j][i].weight = 0; + dpstates[j][i].bestvertex = -1; + if (j != (i + 1)) { + p2 = poly->GetPoint(j); + + // Visibility check. + if (i == 0) { + p3 = poly->GetPoint(n - 1); + } else { + p3 = poly->GetPoint(i - 1); + } + if (i == (n - 1)) { + p4 = poly->GetPoint(0); + } else { + p4 = poly->GetPoint(i + 1); + } + if (!InCone(p3, p1, p4, p2)) { + dpstates[j][i].visible = false; + continue; + } + + if (j == 0) { + p3 = poly->GetPoint(n - 1); + } else { + p3 = poly->GetPoint(j - 1); + } + if (j == (n - 1)) { + p4 = poly->GetPoint(0); + } else { + p4 = poly->GetPoint(j + 1); + } + if (!InCone(p3, p2, p4, p1)) { + dpstates[j][i].visible = false; + continue; + } + + for (k = 0; k < n; k++) { + p3 = poly->GetPoint(k); + if (k == (n - 1)) { + p4 = poly->GetPoint(0); + } else { + p4 = poly->GetPoint(k + 1); + } + if (Intersects(p1, p2, p3, p4)) { + dpstates[j][i].visible = false; + break; + } + } + } + } + } + dpstates[n - 1][0].visible = true; + dpstates[n - 1][0].weight = 0; + dpstates[n - 1][0].bestvertex = -1; + + for (gap = 2; gap < n; gap++) { + for (i = 0; i < (n - gap); i++) { + j = i + gap; + if (!dpstates[j][i].visible) { + continue; + } + bestvertex = -1; + for (k = (i + 1); k < j; k++) { + if (!dpstates[k][i].visible) { + continue; + } + if (!dpstates[j][k].visible) { + continue; + } + + if (k <= (i + 1)) { + d1 = 0; + } else { + d1 = Distance(poly->GetPoint(i), poly->GetPoint(k)); + } + if (j <= (k + 1)) { + d2 = 0; + } else { + d2 = Distance(poly->GetPoint(k), poly->GetPoint(j)); + } + + weight = dpstates[k][i].weight + dpstates[j][k].weight + d1 + d2; + + if ((bestvertex == -1) || (weight < minweight)) { + bestvertex = k; + minweight = weight; + } + } + if (bestvertex == -1) { + for (i = 1; i < n; i++) { + delete[] dpstates[i]; + } + delete[] dpstates; + + return 0; + } + + dpstates[j][i].bestvertex = bestvertex; + dpstates[j][i].weight = minweight; + } + } + + newdiagonal.index1 = 0; + newdiagonal.index2 = n - 1; + diagonals.push_back(newdiagonal); + while (!diagonals.is_empty()) { + diagonal = diagonals.front()->get(); + diagonals.pop_front(); + bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex; + if (bestvertex == -1) { + ret = 0; + break; + } + triangle.Triangle(poly->GetPoint(diagonal.index1), poly->GetPoint(bestvertex), poly->GetPoint(diagonal.index2)); + triangles->push_back(triangle); + if (bestvertex > (diagonal.index1 + 1)) { + newdiagonal.index1 = diagonal.index1; + newdiagonal.index2 = bestvertex; + diagonals.push_back(newdiagonal); + } + if (diagonal.index2 > (bestvertex + 1)) { + newdiagonal.index1 = bestvertex; + newdiagonal.index2 = diagonal.index2; + diagonals.push_back(newdiagonal); + } + } + + for (i = 1; i < n; i++) { + delete[] dpstates[i]; + } + delete[] dpstates; + + return ret; +} + +void TPPLPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates) { + Diagonal newdiagonal; + DiagonalList *pairs = NULL; + long w2; + + w2 = dpstates[a][b].weight; + if (w > w2) { + return; + } + + pairs = &(dpstates[a][b].pairs); + newdiagonal.index1 = i; + newdiagonal.index2 = j; + + if (w < w2) { + pairs->clear(); + pairs->push_front(newdiagonal); + dpstates[a][b].weight = w; + } else { + if ((!pairs->is_empty()) && (i <= pairs->front()->get().index1)) { + return; + } + while ((!pairs->is_empty()) && (pairs->front()->get().index2 >= j)) { + pairs->pop_front(); + } + pairs->push_front(newdiagonal); + } +} + +void TPPLPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { + DiagonalList *pairs = NULL; + DiagonalList::Element *iter, *lastiter; + long top; + long w; + + if (!dpstates[i][j].visible) { + return; + } + top = j; + w = dpstates[i][j].weight; + if (k - j > 1) { + if (!dpstates[j][k].visible) { + return; + } + w += dpstates[j][k].weight + 1; + } + if (j - i > 1) { + pairs = &(dpstates[i][j].pairs); + iter = pairs->back(); + lastiter = pairs->back(); + while (iter != pairs->front()) { + iter--; + if (!IsReflex(vertices[iter->get().index2].p, vertices[j].p, vertices[k].p)) { + lastiter = iter; + } else { + break; + } + } + if (lastiter == pairs->back()) { + w++; + } else { + if (IsReflex(vertices[k].p, vertices[i].p, vertices[lastiter->get().index1].p)) { + w++; + } else { + top = lastiter->get().index1; + } + } + } + UpdateState(i, k, w, top, j, dpstates); +} + +void TPPLPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { + DiagonalList *pairs = NULL; + DiagonalList::Element *iter, *lastiter; + long top; + long w; + + if (!dpstates[j][k].visible) { + return; + } + top = j; + w = dpstates[j][k].weight; + + if (j - i > 1) { + if (!dpstates[i][j].visible) { + return; + } + w += dpstates[i][j].weight + 1; + } + if (k - j > 1) { + pairs = &(dpstates[j][k].pairs); + + iter = pairs->front(); + if ((!pairs->is_empty()) && (!IsReflex(vertices[i].p, vertices[j].p, vertices[iter->get().index1].p))) { + lastiter = iter; + while (iter) { + if (!IsReflex(vertices[i].p, vertices[j].p, vertices[iter->get().index1].p)) { + lastiter = iter; + iter = iter->next(); + } else { + break; + } + } + if (IsReflex(vertices[lastiter->get().index2].p, vertices[k].p, vertices[i].p)) { + w++; + } else { + top = lastiter->get().index2; + } + } else { + w++; + } + } + UpdateState(i, k, w, j, top, dpstates); +} + +int TPPLPartition::ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts) { + if (!poly->Valid()) { + return 0; + } + + TPPLPoint p1, p2, p3, p4; + PartitionVertex *vertices = NULL; + DPState2 **dpstates = NULL; + long i, j, k, n, gap; + DiagonalList diagonals, diagonals2; + Diagonal diagonal, newdiagonal; + DiagonalList *pairs = NULL, *pairs2 = NULL; + DiagonalList::Element *iter, *iter2; + int ret; + TPPLPoly newpoly; + List<long> indices; + List<long>::Element *iiter; + bool ijreal, jkreal; + + n = poly->GetNumPoints(); + vertices = new PartitionVertex[n]; + + dpstates = new DPState2 *[n]; + for (i = 0; i < n; i++) { + dpstates[i] = new DPState2[n]; + } + + // Initialize vertex information. + for (i = 0; i < n; i++) { + vertices[i].p = poly->GetPoint(i); + vertices[i].isActive = true; + if (i == 0) { + vertices[i].previous = &(vertices[n - 1]); + } else { + vertices[i].previous = &(vertices[i - 1]); + } + if (i == (poly->GetNumPoints() - 1)) { + vertices[i].next = &(vertices[0]); + } else { + vertices[i].next = &(vertices[i + 1]); + } + } + for (i = 1; i < n; i++) { + UpdateVertexReflexity(&(vertices[i])); + } + + // Initialize states and visibility. + for (i = 0; i < (n - 1); i++) { + p1 = poly->GetPoint(i); + for (j = i + 1; j < n; j++) { + dpstates[i][j].visible = true; + if (j == i + 1) { + dpstates[i][j].weight = 0; + } else { + dpstates[i][j].weight = 2147483647; + } + if (j != (i + 1)) { + p2 = poly->GetPoint(j); + + // Visibility check. + if (!InCone(&vertices[i], p2)) { + dpstates[i][j].visible = false; + continue; + } + if (!InCone(&vertices[j], p1)) { + dpstates[i][j].visible = false; + continue; + } + + for (k = 0; k < n; k++) { + p3 = poly->GetPoint(k); + if (k == (n - 1)) { + p4 = poly->GetPoint(0); + } else { + p4 = poly->GetPoint(k + 1); + } + if (Intersects(p1, p2, p3, p4)) { + dpstates[i][j].visible = false; + break; + } + } + } + } + } + for (i = 0; i < (n - 2); i++) { + j = i + 2; + if (dpstates[i][j].visible) { + dpstates[i][j].weight = 0; + newdiagonal.index1 = i + 1; + newdiagonal.index2 = i + 1; + dpstates[i][j].pairs.push_back(newdiagonal); + } + } + + dpstates[0][n - 1].visible = true; + vertices[0].isConvex = false; // By convention. + + for (gap = 3; gap < n; gap++) { + for (i = 0; i < n - gap; i++) { + if (vertices[i].isConvex) { + continue; + } + k = i + gap; + if (dpstates[i][k].visible) { + if (!vertices[k].isConvex) { + for (j = i + 1; j < k; j++) { + TypeA(i, j, k, vertices, dpstates); + } + } else { + for (j = i + 1; j < (k - 1); j++) { + if (vertices[j].isConvex) { + continue; + } + TypeA(i, j, k, vertices, dpstates); + } + TypeA(i, k - 1, k, vertices, dpstates); + } + } + } + for (k = gap; k < n; k++) { + if (vertices[k].isConvex) { + continue; + } + i = k - gap; + if ((vertices[i].isConvex) && (dpstates[i][k].visible)) { + TypeB(i, i + 1, k, vertices, dpstates); + for (j = i + 2; j < k; j++) { + if (vertices[j].isConvex) { + continue; + } + TypeB(i, j, k, vertices, dpstates); + } + } + } + } + + // Recover solution. + ret = 1; + newdiagonal.index1 = 0; + newdiagonal.index2 = n - 1; + diagonals.push_front(newdiagonal); + while (!diagonals.is_empty()) { + diagonal = diagonals.front()->get(); + diagonals.pop_front(); + if ((diagonal.index2 - diagonal.index1) <= 1) { + continue; + } + pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs); + if (pairs->is_empty()) { + ret = 0; + break; + } + if (!vertices[diagonal.index1].isConvex) { + iter = pairs->back(); + iter--; + j = iter->get().index2; + newdiagonal.index1 = j; + newdiagonal.index2 = diagonal.index2; + diagonals.push_front(newdiagonal); + if ((j - diagonal.index1) > 1) { + if (iter->get().index1 != iter->get().index2) { + pairs2 = &(dpstates[diagonal.index1][j].pairs); + while (1) { + if (pairs2->is_empty()) { + ret = 0; + break; + } + iter2 = pairs2->back(); + iter2--; + if (iter->get().index1 != iter2->get().index1) { + pairs2->pop_back(); + } else { + break; + } + } + if (ret == 0) { + break; + } + } + newdiagonal.index1 = diagonal.index1; + newdiagonal.index2 = j; + diagonals.push_front(newdiagonal); + } + } else { + iter = pairs->front(); + j = iter->get().index1; + newdiagonal.index1 = diagonal.index1; + newdiagonal.index2 = j; + diagonals.push_front(newdiagonal); + if ((diagonal.index2 - j) > 1) { + if (iter->get().index1 != iter->get().index2) { + pairs2 = &(dpstates[j][diagonal.index2].pairs); + while (1) { + if (pairs2->is_empty()) { + ret = 0; + break; + } + iter2 = pairs2->front(); + if (iter->get().index2 != iter2->get().index2) { + pairs2->pop_front(); + } else { + break; + } + } + if (ret == 0) { + break; + } + } + newdiagonal.index1 = j; + newdiagonal.index2 = diagonal.index2; + diagonals.push_front(newdiagonal); + } + } + } + + if (ret == 0) { + for (i = 0; i < n; i++) { + delete[] dpstates[i]; + } + delete[] dpstates; + delete[] vertices; + + return ret; + } + + newdiagonal.index1 = 0; + newdiagonal.index2 = n - 1; + diagonals.push_front(newdiagonal); + while (!diagonals.is_empty()) { + diagonal = diagonals.front()->get(); + diagonals.pop_front(); + if ((diagonal.index2 - diagonal.index1) <= 1) { + continue; + } + + indices.clear(); + diagonals2.clear(); + indices.push_back(diagonal.index1); + indices.push_back(diagonal.index2); + diagonals2.push_front(diagonal); + + while (!diagonals2.is_empty()) { + diagonal = diagonals2.front()->get(); + diagonals2.pop_front(); + if ((diagonal.index2 - diagonal.index1) <= 1) { + continue; + } + ijreal = true; + jkreal = true; + pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs); + if (!vertices[diagonal.index1].isConvex) { + iter = pairs->back(); + iter--; + j = iter->get().index2; + if (iter->get().index1 != iter->get().index2) { + ijreal = false; + } + } else { + iter = pairs->front(); + j = iter->get().index1; + if (iter->get().index1 != iter->get().index2) { + jkreal = false; + } + } + + newdiagonal.index1 = diagonal.index1; + newdiagonal.index2 = j; + if (ijreal) { + diagonals.push_back(newdiagonal); + } else { + diagonals2.push_back(newdiagonal); + } + + newdiagonal.index1 = j; + newdiagonal.index2 = diagonal.index2; + if (jkreal) { + diagonals.push_back(newdiagonal); + } else { + diagonals2.push_back(newdiagonal); + } + + indices.push_back(j); + } + + //std::sort(indices.begin(), indices.end()); + indices.sort(); + newpoly.Init((long)indices.size()); + k = 0; + for (iiter = indices.front(); iiter != indices.back(); iiter = iiter->next()) { + newpoly[k] = vertices[iiter->get()].p; + k++; + } + parts->push_back(newpoly); + } + + for (i = 0; i < n; i++) { + delete[] dpstates[i]; + } + delete[] dpstates; + delete[] vertices; + + return ret; +} + +// Creates a monotone partition of a list of polygons that +// can contain holes. Triangulates a set of polygons by +// first partitioning them into monotone polygons. +// Time complexity: O(n*log(n)), n is the number of vertices. +// Space complexity: O(n) +// The algorithm used here is outlined in the book +// "Computational Geometry: Algorithms and Applications" +// by Mark de Berg, Otfried Cheong, Marc van Kreveld, and Mark Overmars. +int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monotonePolys) { + TPPLPolyList::Element *iter; + MonotoneVertex *vertices = NULL; + long i, numvertices, vindex, vindex2, newnumvertices, maxnumvertices; + long polystartindex, polyendindex; + TPPLPoly *poly = NULL; + MonotoneVertex *v = NULL, *v2 = NULL, *vprev = NULL, *vnext = NULL; + ScanLineEdge newedge; + bool error = false; + + numvertices = 0; + for (iter = inpolys->front(); iter; iter++) { + numvertices += iter->get().GetNumPoints(); + } + + maxnumvertices = numvertices * 3; + vertices = new MonotoneVertex[maxnumvertices]; + newnumvertices = numvertices; + + polystartindex = 0; + for (iter = inpolys->front(); iter; iter++) { + poly = &(iter->get()); + polyendindex = polystartindex + poly->GetNumPoints() - 1; + for (i = 0; i < poly->GetNumPoints(); i++) { + vertices[i + polystartindex].p = poly->GetPoint(i); + if (i == 0) { + vertices[i + polystartindex].previous = polyendindex; + } else { + vertices[i + polystartindex].previous = i + polystartindex - 1; + } + if (i == (poly->GetNumPoints() - 1)) { + vertices[i + polystartindex].next = polystartindex; + } else { + vertices[i + polystartindex].next = i + polystartindex + 1; + } + } + polystartindex = polyendindex + 1; + } + + // Construct the priority queue. + long *priority = new long[numvertices]; + for (i = 0; i < numvertices; i++) { + priority[i] = i; + } + std::sort(priority, &(priority[numvertices]), VertexSorter(vertices)); + + // Determine vertex types. + TPPLVertexType *vertextypes = new TPPLVertexType[maxnumvertices]; + for (i = 0; i < numvertices; i++) { + v = &(vertices[i]); + vprev = &(vertices[v->previous]); + vnext = &(vertices[v->next]); + + if (Below(vprev->p, v->p) && Below(vnext->p, v->p)) { + if (IsConvex(vnext->p, vprev->p, v->p)) { + vertextypes[i] = TPPL_VERTEXTYPE_START; + } else { + vertextypes[i] = TPPL_VERTEXTYPE_SPLIT; + } + } else if (Below(v->p, vprev->p) && Below(v->p, vnext->p)) { + if (IsConvex(vnext->p, vprev->p, v->p)) { + vertextypes[i] = TPPL_VERTEXTYPE_END; + } else { + vertextypes[i] = TPPL_VERTEXTYPE_MERGE; + } + } else { + vertextypes[i] = TPPL_VERTEXTYPE_REGULAR; + } + } + + // Helpers. + long *helpers = new long[maxnumvertices]; + + // Binary search tree that holds edges intersecting the scanline. + // Note that while set doesn't actually have to be implemented as + // a tree, complexity requirements for operations are the same as + // for the balanced binary search tree. + Set<ScanLineEdge> edgeTree; + // Store iterators to the edge tree elements. + // This makes deleting existing edges much faster. + Set<ScanLineEdge>::Element **edgeTreeIterators, *edgeIter; + edgeTreeIterators = new Set<ScanLineEdge>::Element *[maxnumvertices]; + //Pair<Set<ScanLineEdge>::iterator, bool> edgeTreeRet; + for (i = 0; i < numvertices; i++) { + edgeTreeIterators[i] = nullptr; + } + + // For each vertex. + for (i = 0; i < numvertices; i++) { + vindex = priority[i]; + v = &(vertices[vindex]); + vindex2 = vindex; + v2 = v; + + // Depending on the vertex type, do the appropriate action. + // Comments in the following sections are copied from + // "Computational Geometry: Algorithms and Applications". + // Notation: e_i = e subscript i, v_i = v subscript i, etc. + switch (vertextypes[vindex]) { + case TPPL_VERTEXTYPE_START: + // Insert e_i in T and set helper(e_i) to v_i. + newedge.p1 = v->p; + newedge.p2 = vertices[v->next].p; + newedge.index = vindex; + //edgeTreeRet = edgeTree.insert(newedge); + //edgeTreeIterators[vindex] = edgeTreeRet.first; + edgeTreeIterators[vindex] = edgeTree.insert(newedge); + helpers[vindex] = vindex; + break; + + case TPPL_VERTEXTYPE_END: + if (edgeTreeIterators[v->previous] == edgeTree.back()) { + error = true; + break; + } + // If helper(e_i - 1) is a merge vertex + if (vertextypes[helpers[v->previous]] == TPPL_VERTEXTYPE_MERGE) { + // Insert the diagonal connecting vi to helper(e_i - 1) in D. + AddDiagonal(vertices, &newnumvertices, vindex, helpers[v->previous], + vertextypes, edgeTreeIterators, &edgeTree, helpers); + } + // Delete e_i - 1 from T + edgeTree.erase(edgeTreeIterators[v->previous]); + break; + + case TPPL_VERTEXTYPE_SPLIT: + // Search in T to find the edge e_j directly left of v_i. + newedge.p1 = v->p; + newedge.p2 = v->p; + edgeIter = edgeTree.lower_bound(newedge); + if (edgeIter == edgeTree.front()) { + error = true; + break; + } + edgeIter--; + // Insert the diagonal connecting vi to helper(e_j) in D. + AddDiagonal(vertices, &newnumvertices, vindex, helpers[edgeIter->get().index], + vertextypes, edgeTreeIterators, &edgeTree, helpers); + vindex2 = newnumvertices - 2; + v2 = &(vertices[vindex2]); + // helper(e_j) in v_i. + helpers[edgeIter->get().index] = vindex; + // Insert e_i in T and set helper(e_i) to v_i. + newedge.p1 = v2->p; + newedge.p2 = vertices[v2->next].p; + newedge.index = vindex2; + //edgeTreeRet = edgeTree.insert(newedge); + //edgeTreeIterators[vindex2] = edgeTreeRet.first; + edgeTreeIterators[vindex2] = edgeTree.insert(newedge); + helpers[vindex2] = vindex2; + break; + + case TPPL_VERTEXTYPE_MERGE: + if (edgeTreeIterators[v->previous] == edgeTree.back()) { + error = true; + break; + } + // if helper(e_i - 1) is a merge vertex + if (vertextypes[helpers[v->previous]] == TPPL_VERTEXTYPE_MERGE) { + // Insert the diagonal connecting vi to helper(e_i - 1) in D. + AddDiagonal(vertices, &newnumvertices, vindex, helpers[v->previous], + vertextypes, edgeTreeIterators, &edgeTree, helpers); + vindex2 = newnumvertices - 2; + v2 = &(vertices[vindex2]); + } + // Delete e_i - 1 from T. + edgeTree.erase(edgeTreeIterators[v->previous]); + // Search in T to find the edge e_j directly left of v_i. + newedge.p1 = v->p; + newedge.p2 = v->p; + edgeIter = edgeTree.lower_bound(newedge); + if (edgeIter == edgeTree.front()) { + error = true; + break; + } + edgeIter--; + // If helper(e_j) is a merge vertex. + if (vertextypes[helpers[edgeIter->get().index]] == TPPL_VERTEXTYPE_MERGE) { + // Insert the diagonal connecting v_i to helper(e_j) in D. + AddDiagonal(vertices, &newnumvertices, vindex2, helpers[edgeIter->get().index], + vertextypes, edgeTreeIterators, &edgeTree, helpers); + } + // helper(e_j) <- v_i + helpers[edgeIter->get().index] = vindex2; + break; + + case TPPL_VERTEXTYPE_REGULAR: + // If the interior of P lies to the right of v_i. + if (Below(v->p, vertices[v->previous].p)) { + if (edgeTreeIterators[v->previous] == edgeTree.back()) { + error = true; + break; + } + // If helper(e_i - 1) is a merge vertex. + if (vertextypes[helpers[v->previous]] == TPPL_VERTEXTYPE_MERGE) { + // Insert the diagonal connecting v_i to helper(e_i - 1) in D. + AddDiagonal(vertices, &newnumvertices, vindex, helpers[v->previous], + vertextypes, edgeTreeIterators, &edgeTree, helpers); + vindex2 = newnumvertices - 2; + v2 = &(vertices[vindex2]); + } + // Delete e_i - 1 from T. + edgeTree.erase(edgeTreeIterators[v->previous]); + // Insert e_i in T and set helper(e_i) to v_i. + newedge.p1 = v2->p; + newedge.p2 = vertices[v2->next].p; + newedge.index = vindex2; + //edgeTreeRet = edgeTree.insert(newedge); + //edgeTreeIterators[vindex2] = edgeTreeRet.first; + edgeTreeIterators[vindex2] = edgeTree.insert(newedge); + helpers[vindex2] = vindex; + } else { + // Search in T to find the edge e_j directly left of v_i. + newedge.p1 = v->p; + newedge.p2 = v->p; + edgeIter = edgeTree.lower_bound(newedge); + if (edgeIter == edgeTree.front()) { + error = true; + break; + } + edgeIter = edgeIter->prev(); + // If helper(e_j) is a merge vertex. + if (vertextypes[helpers[edgeIter->get().index]] == TPPL_VERTEXTYPE_MERGE) { + // Insert the diagonal connecting v_i to helper(e_j) in D. + AddDiagonal(vertices, &newnumvertices, vindex, helpers[edgeIter->get().index], + vertextypes, edgeTreeIterators, &edgeTree, helpers); + } + // helper(e_j) <- v_i. + helpers[edgeIter->get().index] = vindex; + } + break; + } + + if (error) + break; + } + + char *used = new char[newnumvertices]; + memset(used, 0, newnumvertices * sizeof(char)); + + if (!error) { + // Return result. + long size; + TPPLPoly mpoly; + for (i = 0; i < newnumvertices; i++) { + if (used[i]) { + continue; + } + v = &(vertices[i]); + vnext = &(vertices[v->next]); + size = 1; + while (vnext != v) { + vnext = &(vertices[vnext->next]); + size++; + } + mpoly.Init(size); + v = &(vertices[i]); + mpoly[0] = v->p; + vnext = &(vertices[v->next]); + size = 1; + used[i] = 1; + used[v->next] = 1; + while (vnext != v) { + mpoly[size] = vnext->p; + used[vnext->next] = 1; + vnext = &(vertices[vnext->next]); + size++; + } + monotonePolys->push_back(mpoly); + } + } + + // Cleanup. + delete[] vertices; + delete[] priority; + delete[] vertextypes; + delete[] edgeTreeIterators; + delete[] helpers; + delete[] used; + + if (error) { + return 0; + } else { + return 1; + } +} + +// Adds a diagonal to the doubly-connected list of vertices. +void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2, + TPPLVertexType *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators, + Set<ScanLineEdge> *edgeTree, long *helpers) { + long newindex1, newindex2; + + newindex1 = *numvertices; + (*numvertices)++; + newindex2 = *numvertices; + (*numvertices)++; + + vertices[newindex1].p = vertices[index1].p; + vertices[newindex2].p = vertices[index2].p; + + vertices[newindex2].next = vertices[index2].next; + vertices[newindex1].next = vertices[index1].next; + + vertices[vertices[index2].next].previous = newindex2; + vertices[vertices[index1].next].previous = newindex1; + + vertices[index1].next = newindex2; + vertices[newindex2].previous = index1; + + vertices[index2].next = newindex1; + vertices[newindex1].previous = index2; + + // Update all relevant structures. + vertextypes[newindex1] = vertextypes[index1]; + edgeTreeIterators[newindex1] = edgeTreeIterators[index1]; + helpers[newindex1] = helpers[index1]; + if (edgeTreeIterators[newindex1] != edgeTree->back()) { + edgeTreeIterators[newindex1]->get().index = newindex1; + } + vertextypes[newindex2] = vertextypes[index2]; + edgeTreeIterators[newindex2] = edgeTreeIterators[index2]; + helpers[newindex2] = helpers[index2]; + if (edgeTreeIterators[newindex2] != edgeTree->back()) { + edgeTreeIterators[newindex2]->get().index = newindex2; + } +} + +bool TPPLPartition::Below(TPPLPoint &p1, TPPLPoint &p2) { + if (p1.y < p2.y) { + return true; + } else if (p1.y == p2.y) { + if (p1.x < p2.x) { + return true; + } + } + return false; +} + +// Sorts in the falling order of y values, if y is equal, x is used instead. +bool TPPLPartition::VertexSorter::operator()(long index1, long index2) { + if (vertices[index1].p.y > vertices[index2].p.y) { + return true; + } else if (vertices[index1].p.y == vertices[index2].p.y) { + if (vertices[index1].p.x > vertices[index2].p.x) { + return true; + } + } + return false; +} + +bool TPPLPartition::ScanLineEdge::IsConvex(const TPPLPoint &p1, const TPPLPoint &p2, const TPPLPoint &p3) const { + tppl_float tmp; + tmp = (p3.y - p1.y) * (p2.x - p1.x) - (p3.x - p1.x) * (p2.y - p1.y); + if (tmp > 0) { + return 1; + } + + return 0; +} + +bool TPPLPartition::ScanLineEdge::operator<(const ScanLineEdge &other) const { + if (other.p1.y == other.p2.y) { + if (p1.y == p2.y) { + return (p1.y < other.p1.y); + } + return IsConvex(p1, p2, other.p1); + } else if (p1.y == p2.y) { + return !IsConvex(other.p1, other.p2, p1); + } else if (p1.y < other.p1.y) { + return !IsConvex(other.p1, other.p2, p1); + } else { + return IsConvex(p1, p2, other.p1); + } +} + +// Triangulates monotone polygon. +// Time complexity: O(n) +// Space complexity: O(n) +int TPPLPartition::TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles) { + if (!inPoly->Valid()) { + return 0; + } + + long i, i2, j, topindex, bottomindex, leftindex, rightindex, vindex; + TPPLPoint *points = NULL; + long numpoints; + TPPLPoly triangle; + + numpoints = inPoly->GetNumPoints(); + points = inPoly->GetPoints(); + + // Trivial case. + if (numpoints == 3) { + triangles->push_back(*inPoly); + return 1; + } + + topindex = 0; + bottomindex = 0; + for (i = 1; i < numpoints; i++) { + if (Below(points[i], points[bottomindex])) { + bottomindex = i; + } + if (Below(points[topindex], points[i])) { + topindex = i; + } + } + + // Check if the poly is really monotone. + i = topindex; + while (i != bottomindex) { + i2 = i + 1; + if (i2 >= numpoints) { + i2 = 0; + } + if (!Below(points[i2], points[i])) { + return 0; + } + i = i2; + } + i = bottomindex; + while (i != topindex) { + i2 = i + 1; + if (i2 >= numpoints) { + i2 = 0; + } + if (!Below(points[i], points[i2])) { + return 0; + } + i = i2; + } + + char *vertextypes = new char[numpoints]; + long *priority = new long[numpoints]; + + // Merge left and right vertex chains. + priority[0] = topindex; + vertextypes[topindex] = 0; + leftindex = topindex + 1; + if (leftindex >= numpoints) { + leftindex = 0; + } + rightindex = topindex - 1; + if (rightindex < 0) { + rightindex = numpoints - 1; + } + for (i = 1; i < (numpoints - 1); i++) { + if (leftindex == bottomindex) { + priority[i] = rightindex; + rightindex--; + if (rightindex < 0) { + rightindex = numpoints - 1; + } + vertextypes[priority[i]] = -1; + } else if (rightindex == bottomindex) { + priority[i] = leftindex; + leftindex++; + if (leftindex >= numpoints) { + leftindex = 0; + } + vertextypes[priority[i]] = 1; + } else { + if (Below(points[leftindex], points[rightindex])) { + priority[i] = rightindex; + rightindex--; + if (rightindex < 0) { + rightindex = numpoints - 1; + } + vertextypes[priority[i]] = -1; + } else { + priority[i] = leftindex; + leftindex++; + if (leftindex >= numpoints) { + leftindex = 0; + } + vertextypes[priority[i]] = 1; + } + } + } + priority[i] = bottomindex; + vertextypes[bottomindex] = 0; + + long *stack = new long[numpoints]; + long stackptr = 0; + + stack[0] = priority[0]; + stack[1] = priority[1]; + stackptr = 2; + + // For each vertex from top to bottom trim as many triangles as possible. + for (i = 2; i < (numpoints - 1); i++) { + vindex = priority[i]; + if (vertextypes[vindex] != vertextypes[stack[stackptr - 1]]) { + for (j = 0; j < (stackptr - 1); j++) { + if (vertextypes[vindex] == 1) { + triangle.Triangle(points[stack[j + 1]], points[stack[j]], points[vindex]); + } else { + triangle.Triangle(points[stack[j]], points[stack[j + 1]], points[vindex]); + } + triangles->push_back(triangle); + } + stack[0] = priority[i - 1]; + stack[1] = priority[i]; + stackptr = 2; + } else { + stackptr--; + while (stackptr > 0) { + if (vertextypes[vindex] == 1) { + if (IsConvex(points[vindex], points[stack[stackptr - 1]], points[stack[stackptr]])) { + triangle.Triangle(points[vindex], points[stack[stackptr - 1]], points[stack[stackptr]]); + triangles->push_back(triangle); + stackptr--; + } else { + break; + } + } else { + if (IsConvex(points[vindex], points[stack[stackptr]], points[stack[stackptr - 1]])) { + triangle.Triangle(points[vindex], points[stack[stackptr]], points[stack[stackptr - 1]]); + triangles->push_back(triangle); + stackptr--; + } else { + break; + } + } + } + stackptr++; + stack[stackptr] = vindex; + stackptr++; + } + } + vindex = priority[i]; + for (j = 0; j < (stackptr - 1); j++) { + if (vertextypes[stack[j + 1]] == 1) { + triangle.Triangle(points[stack[j]], points[stack[j + 1]], points[vindex]); + } else { + triangle.Triangle(points[stack[j + 1]], points[stack[j]], points[vindex]); + } + triangles->push_back(triangle); + } + + delete[] priority; + delete[] vertextypes; + delete[] stack; + + return 1; +} + +int TPPLPartition::Triangulate_MONO(TPPLPolyList *inpolys, TPPLPolyList *triangles) { + TPPLPolyList monotone; + TPPLPolyList::Element *iter; + + if (!MonotonePartition(inpolys, &monotone)) { + return 0; + } + for (iter = monotone.front(); iter; iter = iter->next()) { + if (!TriangulateMonotone(&(iter->get()), triangles)) { + return 0; + } + } + return 1; +} + +int TPPLPartition::Triangulate_MONO(TPPLPoly *poly, TPPLPolyList *triangles) { + TPPLPolyList polys; + polys.push_back(*poly); + + return Triangulate_MONO(&polys, triangles); +} diff --git a/thirdparty/misc/polypartition.h b/thirdparty/misc/polypartition.h new file mode 100644 index 0000000000..b2d905a3ef --- /dev/null +++ b/thirdparty/misc/polypartition.h @@ -0,0 +1,378 @@ +/*************************************************************************/ +/* Copyright (c) 2011-2021 Ivan Fratric and contributors. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef POLYPARTITION_H +#define POLYPARTITION_H + +#include "core/math/vector2.h" +#include "core/templates/list.h" +#include "core/templates/set.h" + +typedef double tppl_float; + +enum TPPLOrientation { + TPPL_ORIENTATION_CW = -1, + TPPL_ORIENTATION_NONE = 0, + TPPL_ORIENTATION_CCW = 1, +}; + +enum TPPLVertexType { + TPPL_VERTEXTYPE_REGULAR = 0, + TPPL_VERTEXTYPE_START = 1, + TPPL_VERTEXTYPE_END = 2, + TPPL_VERTEXTYPE_SPLIT = 3, + TPPL_VERTEXTYPE_MERGE = 4, +}; + +// 2D point structure. +typedef Vector2 TPPLPoint; + +// Polygon implemented as an array of points with a "hole" flag. +class TPPLPoly { + protected: + TPPLPoint *points; + long numpoints; + bool hole; + + public: + // Constructors and destructors. + TPPLPoly(); + ~TPPLPoly(); + + TPPLPoly(const TPPLPoly &src); + TPPLPoly &operator=(const TPPLPoly &src); + + // Getters and setters. + long GetNumPoints() const { + return numpoints; + } + + bool IsHole() const { + return hole; + } + + void SetHole(bool hole) { + this->hole = hole; + } + + TPPLPoint &GetPoint(long i) { + return points[i]; + } + + const TPPLPoint &GetPoint(long i) const { + return points[i]; + } + + TPPLPoint *GetPoints() { + return points; + } + + TPPLPoint &operator[](int i) { + return points[i]; + } + + const TPPLPoint &operator[](int i) const { + return points[i]; + } + + // Clears the polygon points. + void Clear(); + + // Inits the polygon with numpoints vertices. + void Init(long numpoints); + + // Creates a triangle with points p1, p2, and p3. + void Triangle(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3); + + // Inverts the orfer of vertices. + void Invert(); + + // Returns the orientation of the polygon. + // Possible values: + // TPPL_ORIENTATION_CCW: Polygon vertices are in counter-clockwise order. + // TPPL_ORIENTATION_CW: Polygon vertices are in clockwise order. + // TPPL_ORIENTATION_NONE: The polygon has no (measurable) area. + TPPLOrientation GetOrientation() const; + + // Sets the polygon orientation. + // Possible values: + // TPPL_ORIENTATION_CCW: Sets vertices in counter-clockwise order. + // TPPL_ORIENTATION_CW: Sets vertices in clockwise order. + // TPPL_ORIENTATION_NONE: Reverses the orientation of the vertices if there + // is one, otherwise does nothing (if orientation is already NONE). + void SetOrientation(TPPLOrientation orientation); + + // Checks whether a polygon is valid or not. + inline bool Valid() const { return this->numpoints >= 3; } +}; + +#ifdef TPPL_ALLOCATOR +typedef List<TPPLPoly, TPPL_ALLOCATOR(TPPLPoly)> TPPLPolyList; +#else +typedef List<TPPLPoly> TPPLPolyList; +#endif + +class TPPLPartition { + protected: + struct PartitionVertex { + bool isActive; + bool isConvex; + bool isEar; + + TPPLPoint p; + tppl_float angle; + PartitionVertex *previous; + PartitionVertex *next; + + PartitionVertex(); + }; + + struct MonotoneVertex { + TPPLPoint p; + long previous; + long next; + }; + + class VertexSorter { + MonotoneVertex *vertices; + +public: + VertexSorter(MonotoneVertex *v) : + vertices(v) {} + bool operator()(long index1, long index2); + }; + + struct Diagonal { + long index1; + long index2; + }; + +#ifdef TPPL_ALLOCATOR + typedef List<Diagonal, TPPL_ALLOCATOR(Diagonal)> DiagonalList; +#else + typedef List<Diagonal> DiagonalList; +#endif + + // Dynamic programming state for minimum-weight triangulation. + struct DPState { + bool visible; + tppl_float weight; + long bestvertex; + }; + + // Dynamic programming state for convex partitioning. + struct DPState2 { + bool visible; + long weight; + DiagonalList pairs; + }; + + // Edge that intersects the scanline. + struct ScanLineEdge { + mutable long index; + TPPLPoint p1; + TPPLPoint p2; + + // Determines if the edge is to the left of another edge. + bool operator<(const ScanLineEdge &other) const; + + bool IsConvex(const TPPLPoint &p1, const TPPLPoint &p2, const TPPLPoint &p3) const; + }; + + // Standard helper functions. + bool IsConvex(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3); + bool IsReflex(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3); + bool IsInside(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p); + + bool InCone(TPPLPoint &p1, TPPLPoint &p2, TPPLPoint &p3, TPPLPoint &p); + bool InCone(PartitionVertex *v, TPPLPoint &p); + + int Intersects(TPPLPoint &p11, TPPLPoint &p12, TPPLPoint &p21, TPPLPoint &p22); + + TPPLPoint Normalize(const TPPLPoint &p); + tppl_float Distance(const TPPLPoint &p1, const TPPLPoint &p2); + + // Helper functions for Triangulate_EC. + void UpdateVertexReflexity(PartitionVertex *v); + void UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices); + + // Helper functions for ConvexPartition_OPT. + void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates); + void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates); + void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates); + + // Helper functions for MonotonePartition. + bool Below(TPPLPoint &p1, TPPLPoint &p2); + void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2, + TPPLVertexType *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators, + Set<ScanLineEdge> *edgeTree, long *helpers); + + // Triangulates a monotone polygon, used in Triangulate_MONO. + int TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles); + + public: + // Simple heuristic procedure for removing holes from a list of polygons. + // It works by creating a diagonal from the right-most hole vertex + // to some other visible vertex. + // Time complexity: O(h*(n^2)), h is the # of holes, n is the # of vertices. + // Space complexity: O(n) + // params: + // inpolys: + // A list of polygons that can contain holes. + // Vertices of all non-hole polys have to be in counter-clockwise order. + // Vertices of all hole polys have to be in clockwise order. + // outpolys: + // A list of polygons without holes. + // Returns 1 on success, 0 on failure. + int RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys); + + // Triangulates a polygon by ear clipping. + // Time complexity: O(n^2), n is the number of vertices. + // Space complexity: O(n) + // params: + // poly: + // An input polygon to be triangulated. + // Vertices have to be in counter-clockwise order. + // triangles: + // A list of triangles (result). + // Returns 1 on success, 0 on failure. + int Triangulate_EC(TPPLPoly *poly, TPPLPolyList *triangles); + + // Triangulates a list of polygons that may contain holes by ear clipping + // algorithm. It first calls RemoveHoles to get rid of the holes, and then + // calls Triangulate_EC for each resulting polygon. + // Time complexity: O(h*(n^2)), h is the # of holes, n is the # of vertices. + // Space complexity: O(n) + // params: + // inpolys: + // A list of polygons to be triangulated (can contain holes). + // Vertices of all non-hole polys have to be in counter-clockwise order. + // Vertices of all hole polys have to be in clockwise order. + // triangles: + // A list of triangles (result). + // Returns 1 on success, 0 on failure. + int Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles); + + // Creates an optimal polygon triangulation in terms of minimal edge length. + // Time complexity: O(n^3), n is the number of vertices + // Space complexity: O(n^2) + // params: + // poly: + // An input polygon to be triangulated. + // Vertices have to be in counter-clockwise order. + // triangles: + // A list of triangles (result). + // Returns 1 on success, 0 on failure. + int Triangulate_OPT(TPPLPoly *poly, TPPLPolyList *triangles); + + // Triangulates a polygon by first partitioning it into monotone polygons. + // Time complexity: O(n*log(n)), n is the number of vertices. + // Space complexity: O(n) + // params: + // poly: + // An input polygon to be triangulated. + // Vertices have to be in counter-clockwise order. + // triangles: + // A list of triangles (result). + // Returns 1 on success, 0 on failure. + int Triangulate_MONO(TPPLPoly *poly, TPPLPolyList *triangles); + + // Triangulates a list of polygons by first + // partitioning them into monotone polygons. + // Time complexity: O(n*log(n)), n is the number of vertices. + // Space complexity: O(n) + // params: + // inpolys: + // A list of polygons to be triangulated (can contain holes). + // Vertices of all non-hole polys have to be in counter-clockwise order. + // Vertices of all hole polys have to be in clockwise order. + // triangles: + // A list of triangles (result). + // Returns 1 on success, 0 on failure. + int Triangulate_MONO(TPPLPolyList *inpolys, TPPLPolyList *triangles); + + // Creates a monotone partition of a list of polygons that + // can contain holes. Triangulates a set of polygons by + // first partitioning them into monotone polygons. + // Time complexity: O(n*log(n)), n is the number of vertices. + // Space complexity: O(n) + // params: + // inpolys: + // A list of polygons to be triangulated (can contain holes). + // Vertices of all non-hole polys have to be in counter-clockwise order. + // Vertices of all hole polys have to be in clockwise order. + // monotonePolys: + // A list of monotone polygons (result). + // Returns 1 on success, 0 on failure. + int MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monotonePolys); + + // Partitions a polygon into convex polygons by using the + // Hertel-Mehlhorn algorithm. The algorithm gives at most four times + // the number of parts as the optimal algorithm, however, in practice + // it works much better than that and often gives optimal partition. + // It uses triangulation obtained by ear clipping as intermediate result. + // Time complexity O(n^2), n is the number of vertices. + // Space complexity: O(n) + // params: + // poly: + // An input polygon to be partitioned. + // Vertices have to be in counter-clockwise order. + // parts: + // Resulting list of convex polygons. + // Returns 1 on success, 0 on failure. + int ConvexPartition_HM(TPPLPoly *poly, TPPLPolyList *parts); + + // Partitions a list of polygons into convex parts by using the + // Hertel-Mehlhorn algorithm. The algorithm gives at most four times + // the number of parts as the optimal algorithm, however, in practice + // it works much better than that and often gives optimal partition. + // It uses triangulation obtained by ear clipping as intermediate result. + // Time complexity O(n^2), n is the number of vertices. + // Space complexity: O(n) + // params: + // inpolys: + // An input list of polygons to be partitioned. Vertices of + // all non-hole polys have to be in counter-clockwise order. + // Vertices of all hole polys have to be in clockwise order. + // parts: + // Resulting list of convex polygons. + // Returns 1 on success, 0 on failure. + int ConvexPartition_HM(TPPLPolyList *inpolys, TPPLPolyList *parts); + + // Optimal convex partitioning (in terms of number of resulting + // convex polygons) using the Keil-Snoeyink algorithm. + // For reference, see M. Keil, J. Snoeyink, "On the time bound for + // convex decomposition of simple polygons", 1998. + // Time complexity O(n^3), n is the number of vertices. + // Space complexity: O(n^3) + // params: + // poly: + // An input polygon to be partitioned. + // Vertices have to be in counter-clockwise order. + // parts: + // Resulting list of convex polygons. + // Returns 1 on success, 0 on failure. + int ConvexPartition_OPT(TPPLPoly *poly, TPPLPolyList *parts); +}; + +#endif diff --git a/thirdparty/misc/r128.h b/thirdparty/misc/r128.h index 1f7aab78fb..a345cc47ba 100644 --- a/thirdparty/misc/r128.h +++ b/thirdparty/misc/r128.h @@ -1,5 +1,5 @@ /* -r128.h: 128-bit (64.64) signed fixed-point arithmetic. Version 1.4.3 +r128.h: 128-bit (64.64) signed fixed-point arithmetic. Version 1.4.4 COMPILATION ----------- @@ -76,8 +76,8 @@ OTHER DEALINGS IN THE SOFTWARE. # include <stdint.h> # define R128_S32 int32_t # define R128_U32 uint32_t -# define R128_S64 int64_t -# define R128_U64 uint64_t +# define R128_S64 long long +# define R128_U64 unsigned long long # define R128_LIT_S64(x) x##ll # define R128_LIT_U64(x) x##ull #endif @@ -701,7 +701,7 @@ static R128_U32 r128__udiv64(R128_U32 nlo, R128_U32 nhi, R128_U32 d, R128_U32 *r return (R128_U32)(n64 / d); # endif } -#elif !defined(_M_X64) || defined(R128_STDC_ONLY) +#elif defined(R128_STDC_ONLY) || !R128_INTEL #define r128__umul64(a, b) ((a) * (R128_U64)(b)) static R128_U32 r128__udiv64(R128_U32 nlo, R128_U32 nhi, R128_U32 d, R128_U32 *rem) { @@ -799,7 +799,7 @@ static void r128__umul128(R128 *dst, R128_U64 a, R128_U64 b) // MSVC x64 provides neither inline assembly nor (pre-2019) a div intrinsic, so we do fake // "inline assembly" to avoid long division or outline assembly. #pragma code_seg(".text") -__declspec(allocate(".text")) static const unsigned char r128__udiv128Code[] = { +__declspec(allocate(".text") align(16)) static const unsigned char r128__udiv128Code[] = { 0x48, 0x8B, 0xC1, //mov rax, rcx 0x49, 0xF7, 0xF0, //div rax, r8 0x49, 0x89, 0x11, //mov qword ptr [r9], rdx diff --git a/thirdparty/misc/triangulator.cpp b/thirdparty/misc/triangulator.cpp deleted file mode 100644 index d6b63c6638..0000000000 --- a/thirdparty/misc/triangulator.cpp +++ /dev/null @@ -1,1550 +0,0 @@ -//Copyright (C) 2011 by Ivan Fratric -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in -//all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -//THE SOFTWARE. - - -#include <stdio.h> -#include <string.h> -#include <math.h> - -#include "triangulator.h" - - -#define TRIANGULATOR_VERTEXTYPE_REGULAR 0 -#define TRIANGULATOR_VERTEXTYPE_START 1 -#define TRIANGULATOR_VERTEXTYPE_END 2 -#define TRIANGULATOR_VERTEXTYPE_SPLIT 3 -#define TRIANGULATOR_VERTEXTYPE_MERGE 4 - -TriangulatorPoly::TriangulatorPoly() { - hole = false; - numpoints = 0; - points = NULL; -} - -TriangulatorPoly::~TriangulatorPoly() { - if(points) delete [] points; -} - -void TriangulatorPoly::Clear() { - if(points) delete [] points; - hole = false; - numpoints = 0; - points = NULL; -} - -void TriangulatorPoly::Init(long numpoints) { - Clear(); - this->numpoints = numpoints; - points = new Vector2[numpoints]; -} - -void TriangulatorPoly::Triangle(Vector2 &p1, Vector2 &p2, Vector2 &p3) { - Init(3); - points[0] = p1; - points[1] = p2; - points[2] = p3; -} - -TriangulatorPoly::TriangulatorPoly(const TriangulatorPoly &src) { - hole = src.hole; - numpoints = src.numpoints; - points = new Vector2[numpoints]; - memcpy(points, src.points, numpoints*sizeof(Vector2)); -} - -TriangulatorPoly& TriangulatorPoly::operator=(const TriangulatorPoly &src) { - Clear(); - hole = src.hole; - numpoints = src.numpoints; - points = new Vector2[numpoints]; - memcpy(points, src.points, numpoints*sizeof(Vector2)); - return *this; -} - -int TriangulatorPoly::GetOrientation() { - long i1,i2; - real_t area = 0; - for(i1=0; i1<numpoints; i1++) { - i2 = i1+1; - if(i2 == numpoints) i2 = 0; - area += points[i1].x * points[i2].y - points[i1].y * points[i2].x; - } - if(area>0) return TRIANGULATOR_CCW; - if(area<0) return TRIANGULATOR_CW; - return 0; -} - -void TriangulatorPoly::SetOrientation(int orientation) { - int polyorientation = GetOrientation(); - if(polyorientation&&(polyorientation!=orientation)) { - Invert(); - } -} - -void TriangulatorPoly::Invert() { - long i; - Vector2 *invpoints; - - invpoints = new Vector2[numpoints]; - for(i=0;i<numpoints;i++) { - invpoints[i] = points[numpoints-i-1]; - } - - delete [] points; - points = invpoints; -} - -Vector2 TriangulatorPartition::Normalize(const Vector2 &p) { - Vector2 r; - real_t n = sqrt(p.x*p.x + p.y*p.y); - if(n!=0) { - r = p/n; - } else { - r.x = 0; - r.y = 0; - } - return r; -} - -real_t TriangulatorPartition::Distance(const Vector2 &p1, const Vector2 &p2) { - real_t dx,dy; - dx = p2.x - p1.x; - dy = p2.y - p1.y; - return(sqrt(dx*dx + dy*dy)); -} - -//checks if two lines intersect -int TriangulatorPartition::Intersects(Vector2 &p11, Vector2 &p12, Vector2 &p21, Vector2 &p22) { - if((p11.x == p21.x)&&(p11.y == p21.y)) return 0; - if((p11.x == p22.x)&&(p11.y == p22.y)) return 0; - if((p12.x == p21.x)&&(p12.y == p21.y)) return 0; - if((p12.x == p22.x)&&(p12.y == p22.y)) return 0; - - Vector2 v1ort,v2ort,v; - real_t dot11,dot12,dot21,dot22; - - v1ort.x = p12.y-p11.y; - v1ort.y = p11.x-p12.x; - - v2ort.x = p22.y-p21.y; - v2ort.y = p21.x-p22.x; - - v = p21-p11; - dot21 = v.x*v1ort.x + v.y*v1ort.y; - v = p22-p11; - dot22 = v.x*v1ort.x + v.y*v1ort.y; - - v = p11-p21; - dot11 = v.x*v2ort.x + v.y*v2ort.y; - v = p12-p21; - dot12 = v.x*v2ort.x + v.y*v2ort.y; - - if(dot11*dot12>0) return 0; - if(dot21*dot22>0) return 0; - - return 1; -} - -//removes holes from inpolys by merging them with non-holes -int TriangulatorPartition::RemoveHoles(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *outpolys) { - List<TriangulatorPoly> polys; - List<TriangulatorPoly>::Element *holeiter,*polyiter,*iter,*iter2; - long i,i2,holepointindex,polypointindex; - Vector2 holepoint,polypoint,bestpolypoint; - Vector2 linep1,linep2; - Vector2 v1,v2; - TriangulatorPoly newpoly; - bool hasholes; - bool pointvisible; - bool pointfound; - - //check for trivial case (no holes) - hasholes = false; - for(iter = inpolys->front(); iter; iter=iter->next()) { - if(iter->get().IsHole()) { - hasholes = true; - break; - } - } - if(!hasholes) { - for(iter = inpolys->front(); iter; iter=iter->next()) { - outpolys->push_back(iter->get()); - } - return 1; - } - - polys = *inpolys; - - while(1) { - //find the hole point with the largest x - hasholes = false; - for(iter = polys.front(); iter; iter=iter->next()) { - if(!iter->get().IsHole()) continue; - - if(!hasholes) { - hasholes = true; - holeiter = iter; - holepointindex = 0; - } - - for(i=0; i < iter->get().GetNumPoints(); i++) { - if(iter->get().GetPoint(i).x > holeiter->get().GetPoint(holepointindex).x) { - holeiter = iter; - holepointindex = i; - } - } - } - if(!hasholes) break; - holepoint = holeiter->get().GetPoint(holepointindex); - - pointfound = false; - for(iter = polys.front(); iter; iter=iter->next()) { - if(iter->get().IsHole()) continue; - for(i=0; i < iter->get().GetNumPoints(); i++) { - if(iter->get().GetPoint(i).x <= holepoint.x) continue; - if(!InCone(iter->get().GetPoint((i+iter->get().GetNumPoints()-1)%(iter->get().GetNumPoints())), - iter->get().GetPoint(i), - iter->get().GetPoint((i+1)%(iter->get().GetNumPoints())), - holepoint)) - continue; - polypoint = iter->get().GetPoint(i); - if(pointfound) { - v1 = Normalize(polypoint-holepoint); - v2 = Normalize(bestpolypoint-holepoint); - if(v2.x > v1.x) continue; - } - pointvisible = true; - for(iter2 = polys.front(); iter2; iter2=iter2->next()) { - if(iter2->get().IsHole()) continue; - for(i2=0; i2 < iter2->get().GetNumPoints(); i2++) { - linep1 = iter2->get().GetPoint(i2); - linep2 = iter2->get().GetPoint((i2+1)%(iter2->get().GetNumPoints())); - if(Intersects(holepoint,polypoint,linep1,linep2)) { - pointvisible = false; - break; - } - } - if(!pointvisible) break; - } - if(pointvisible) { - pointfound = true; - bestpolypoint = polypoint; - polyiter = iter; - polypointindex = i; - } - } - } - - if(!pointfound) return 0; - - newpoly.Init(holeiter->get().GetNumPoints() + polyiter->get().GetNumPoints() + 2); - i2 = 0; - for(i=0;i<=polypointindex;i++) { - newpoly[i2] = polyiter->get().GetPoint(i); - i2++; - } - for(i=0;i<=holeiter->get().GetNumPoints();i++) { - newpoly[i2] = holeiter->get().GetPoint((i+holepointindex)%holeiter->get().GetNumPoints()); - i2++; - } - for(i=polypointindex;i<polyiter->get().GetNumPoints();i++) { - newpoly[i2] = polyiter->get().GetPoint(i); - i2++; - } - - polys.erase(holeiter); - polys.erase(polyiter); - polys.push_back(newpoly); - } - - for(iter = polys.front(); iter; iter=iter->next()) { - outpolys->push_back(iter->get()); - } - - return 1; -} - -bool TriangulatorPartition::IsConvex(Vector2& p1, Vector2& p2, Vector2& p3) { - real_t tmp; - tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y); - if(tmp>0) return 1; - else return 0; -} - -bool TriangulatorPartition::IsReflex(Vector2& p1, Vector2& p2, Vector2& p3) { - real_t tmp; - tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y); - if(tmp<0) return 1; - else return 0; -} - -bool TriangulatorPartition::IsInside(Vector2& p1, Vector2& p2, Vector2& p3, Vector2 &p) { - if(IsConvex(p1,p,p2)) return false; - if(IsConvex(p2,p,p3)) return false; - if(IsConvex(p3,p,p1)) return false; - return true; -} - -bool TriangulatorPartition::InCone(Vector2 &p1, Vector2 &p2, Vector2 &p3, Vector2 &p) { - bool convex; - - convex = IsConvex(p1,p2,p3); - - if(convex) { - if(!IsConvex(p1,p2,p)) return false; - if(!IsConvex(p2,p3,p)) return false; - return true; - } else { - if(IsConvex(p1,p2,p)) return true; - if(IsConvex(p2,p3,p)) return true; - return false; - } -} - -bool TriangulatorPartition::InCone(PartitionVertex *v, Vector2 &p) { - Vector2 p1,p2,p3; - - p1 = v->previous->p; - p2 = v->p; - p3 = v->next->p; - - return InCone(p1,p2,p3,p); -} - -void TriangulatorPartition::UpdateVertexReflexity(PartitionVertex *v) { - PartitionVertex *v1,*v3; - v1 = v->previous; - v3 = v->next; - v->isConvex = !IsReflex(v1->p,v->p,v3->p); -} - -void TriangulatorPartition::UpdateVertex(PartitionVertex *v, PartitionVertex *vertices, long numvertices) { - long i; - PartitionVertex *v1,*v3; - Vector2 vec1,vec3; - - v1 = v->previous; - v3 = v->next; - - v->isConvex = IsConvex(v1->p,v->p,v3->p); - - vec1 = Normalize(v1->p - v->p); - vec3 = Normalize(v3->p - v->p); - v->angle = vec1.x*vec3.x + vec1.y*vec3.y; - - if(v->isConvex) { - v->isEar = true; - for(i=0;i<numvertices;i++) { - if((vertices[i].p.x==v->p.x)&&(vertices[i].p.y==v->p.y)) continue; - if((vertices[i].p.x==v1->p.x)&&(vertices[i].p.y==v1->p.y)) continue; - if((vertices[i].p.x==v3->p.x)&&(vertices[i].p.y==v3->p.y)) continue; - if(IsInside(v1->p,v->p,v3->p,vertices[i].p)) { - v->isEar = false; - break; - } - } - } else { - v->isEar = false; - } -} - -//triangulation by ear removal -int TriangulatorPartition::Triangulate_EC(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) { - long numvertices; - PartitionVertex *vertices; - PartitionVertex *ear; - TriangulatorPoly triangle; - long i,j; - bool earfound; - - if(poly->GetNumPoints() < 3) return 0; - if(poly->GetNumPoints() == 3) { - triangles->push_back(*poly); - return 1; - } - - numvertices = poly->GetNumPoints(); - - vertices = new PartitionVertex[numvertices]; - for(i=0;i<numvertices;i++) { - vertices[i].isActive = true; - vertices[i].p = poly->GetPoint(i); - if(i==(numvertices-1)) vertices[i].next=&(vertices[0]); - else vertices[i].next=&(vertices[i+1]); - if(i==0) vertices[i].previous = &(vertices[numvertices-1]); - else vertices[i].previous = &(vertices[i-1]); - } - for(i=0;i<numvertices;i++) { - UpdateVertex(&vertices[i],vertices,numvertices); - } - - for(i=0;i<numvertices-3;i++) { - earfound = false; - //find the most extruded ear - for(j=0;j<numvertices;j++) { - if(!vertices[j].isActive) continue; - if(!vertices[j].isEar) continue; - if(!earfound) { - earfound = true; - ear = &(vertices[j]); - } else { - if(vertices[j].angle > ear->angle) { - ear = &(vertices[j]); - } - } - } - if(!earfound) { - delete [] vertices; - return 0; - } - - triangle.Triangle(ear->previous->p,ear->p,ear->next->p); - triangles->push_back(triangle); - - ear->isActive = false; - ear->previous->next = ear->next; - ear->next->previous = ear->previous; - - if(i==numvertices-4) break; - - UpdateVertex(ear->previous,vertices,numvertices); - UpdateVertex(ear->next,vertices,numvertices); - } - for(i=0;i<numvertices;i++) { - if(vertices[i].isActive) { - triangle.Triangle(vertices[i].previous->p,vertices[i].p,vertices[i].next->p); - triangles->push_back(triangle); - break; - } - } - - delete [] vertices; - - return 1; -} - -int TriangulatorPartition::Triangulate_EC(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles) { - List<TriangulatorPoly> outpolys; - List<TriangulatorPoly>::Element*iter; - - if(!RemoveHoles(inpolys,&outpolys)) return 0; - for(iter=outpolys.front();iter;iter=iter->next()) { - if(!Triangulate_EC(&(iter->get()),triangles)) return 0; - } - return 1; -} - -int TriangulatorPartition::ConvexPartition_HM(TriangulatorPoly *poly, List<TriangulatorPoly> *parts) { - List<TriangulatorPoly> triangles; - List<TriangulatorPoly>::Element *iter1,*iter2; - TriangulatorPoly *poly1,*poly2; - TriangulatorPoly newpoly; - Vector2 d1,d2,p1,p2,p3; - long i11,i12,i21,i22,i13,i23,j,k; - bool isdiagonal; - long numreflex; - - //check if the poly is already convex - numreflex = 0; - for(i11=0;i11<poly->GetNumPoints();i11++) { - if(i11==0) i12 = poly->GetNumPoints()-1; - else i12=i11-1; - if(i11==(poly->GetNumPoints()-1)) i13=0; - else i13=i11+1; - if(IsReflex(poly->GetPoint(i12),poly->GetPoint(i11),poly->GetPoint(i13))) { - numreflex = 1; - break; - } - } - if(numreflex == 0) { - parts->push_back(*poly); - return 1; - } - - if(!Triangulate_EC(poly,&triangles)) return 0; - - for(iter1 = triangles.front(); iter1 ; iter1=iter1->next()) { - poly1 = &(iter1->get()); - for(i11=0;i11<poly1->GetNumPoints();i11++) { - d1 = poly1->GetPoint(i11); - i12 = (i11+1)%(poly1->GetNumPoints()); - d2 = poly1->GetPoint(i12); - - isdiagonal = false; - for(iter2 = iter1; iter2 ; iter2=iter2->next()) { - if(iter1 == iter2) continue; - poly2 = &(iter2->get()); - - for(i21=0;i21<poly2->GetNumPoints();i21++) { - if((d2.x != poly2->GetPoint(i21).x)||(d2.y != poly2->GetPoint(i21).y)) continue; - i22 = (i21+1)%(poly2->GetNumPoints()); - if((d1.x != poly2->GetPoint(i22).x)||(d1.y != poly2->GetPoint(i22).y)) continue; - isdiagonal = true; - break; - } - if(isdiagonal) break; - } - - if(!isdiagonal) continue; - - p2 = poly1->GetPoint(i11); - if(i11 == 0) i13 = poly1->GetNumPoints()-1; - else i13 = i11-1; - p1 = poly1->GetPoint(i13); - if(i22 == (poly2->GetNumPoints()-1)) i23 = 0; - else i23 = i22+1; - p3 = poly2->GetPoint(i23); - - if(!IsConvex(p1,p2,p3)) continue; - - p2 = poly1->GetPoint(i12); - if(i12 == (poly1->GetNumPoints()-1)) i13 = 0; - else i13 = i12+1; - p3 = poly1->GetPoint(i13); - if(i21 == 0) i23 = poly2->GetNumPoints()-1; - else i23 = i21-1; - p1 = poly2->GetPoint(i23); - - if(!IsConvex(p1,p2,p3)) continue; - - newpoly.Init(poly1->GetNumPoints()+poly2->GetNumPoints()-2); - k = 0; - for(j=i12;j!=i11;j=(j+1)%(poly1->GetNumPoints())) { - newpoly[k] = poly1->GetPoint(j); - k++; - } - for(j=i22;j!=i21;j=(j+1)%(poly2->GetNumPoints())) { - newpoly[k] = poly2->GetPoint(j); - k++; - } - - triangles.erase(iter2); - iter1->get() = newpoly; - poly1 = &(iter1->get()); - i11 = -1; - - continue; - } - } - - for(iter1 = triangles.front(); iter1 ; iter1=iter1->next()) { - parts->push_back(iter1->get()); - } - - return 1; -} - -int TriangulatorPartition::ConvexPartition_HM(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *parts) { - List<TriangulatorPoly> outpolys; - List<TriangulatorPoly>::Element* iter; - - if(!RemoveHoles(inpolys,&outpolys)) return 0; - for(iter=outpolys.front();iter;iter=iter->next()) { - if(!ConvexPartition_HM(&(iter->get()),parts)) return 0; - } - return 1; -} - -//minimum-weight polygon triangulation by dynamic programming -//O(n^3) time complexity -//O(n^2) space complexity -int TriangulatorPartition::Triangulate_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) { - long i,j,k,gap,n; - DPState **dpstates; - Vector2 p1,p2,p3,p4; - long bestvertex; - real_t weight,minweight,d1,d2; - Diagonal diagonal,newdiagonal; - List<Diagonal> diagonals; - TriangulatorPoly triangle; - int ret = 1; - - n = poly->GetNumPoints(); - dpstates = new DPState *[n]; - for(i=1;i<n;i++) { - dpstates[i] = new DPState[i]; - } - - //init states and visibility - for(i=0;i<(n-1);i++) { - p1 = poly->GetPoint(i); - for(j=i+1;j<n;j++) { - dpstates[j][i].visible = true; - dpstates[j][i].weight = 0; - dpstates[j][i].bestvertex = -1; - if(j!=(i+1)) { - p2 = poly->GetPoint(j); - - //visibility check - if(i==0) p3 = poly->GetPoint(n-1); - else p3 = poly->GetPoint(i-1); - if(i==(n-1)) p4 = poly->GetPoint(0); - else p4 = poly->GetPoint(i+1); - if(!InCone(p3,p1,p4,p2)) { - dpstates[j][i].visible = false; - continue; - } - - if(j==0) p3 = poly->GetPoint(n-1); - else p3 = poly->GetPoint(j-1); - if(j==(n-1)) p4 = poly->GetPoint(0); - else p4 = poly->GetPoint(j+1); - if(!InCone(p3,p2,p4,p1)) { - dpstates[j][i].visible = false; - continue; - } - - for(k=0;k<n;k++) { - p3 = poly->GetPoint(k); - if(k==(n-1)) p4 = poly->GetPoint(0); - else p4 = poly->GetPoint(k+1); - if(Intersects(p1,p2,p3,p4)) { - dpstates[j][i].visible = false; - break; - } - } - } - } - } - dpstates[n-1][0].visible = true; - dpstates[n-1][0].weight = 0; - dpstates[n-1][0].bestvertex = -1; - - for(gap = 2; gap<n; gap++) { - for(i=0; i<(n-gap); i++) { - j = i+gap; - if(!dpstates[j][i].visible) continue; - bestvertex = -1; - for(k=(i+1);k<j;k++) { - if(!dpstates[k][i].visible) continue; - if(!dpstates[j][k].visible) continue; - - if(k<=(i+1)) d1=0; - else d1 = Distance(poly->GetPoint(i),poly->GetPoint(k)); - if(j<=(k+1)) d2=0; - else d2 = Distance(poly->GetPoint(k),poly->GetPoint(j)); - - weight = dpstates[k][i].weight + dpstates[j][k].weight + d1 + d2; - - if((bestvertex == -1)||(weight<minweight)) { - bestvertex = k; - minweight = weight; - } - } - if(bestvertex == -1) { - for(i=1;i<n;i++) { - delete [] dpstates[i]; - } - delete [] dpstates; - - return 0; - } - - dpstates[j][i].bestvertex = bestvertex; - dpstates[j][i].weight = minweight; - } - } - - newdiagonal.index1 = 0; - newdiagonal.index2 = n-1; - diagonals.push_back(newdiagonal); - while(!diagonals.is_empty()) { - diagonal = (diagonals.front()->get()); - diagonals.pop_front(); - bestvertex = dpstates[diagonal.index2][diagonal.index1].bestvertex; - if(bestvertex == -1) { - ret = 0; - break; - } - triangle.Triangle(poly->GetPoint(diagonal.index1),poly->GetPoint(bestvertex),poly->GetPoint(diagonal.index2)); - triangles->push_back(triangle); - if(bestvertex > (diagonal.index1+1)) { - newdiagonal.index1 = diagonal.index1; - newdiagonal.index2 = bestvertex; - diagonals.push_back(newdiagonal); - } - if(diagonal.index2 > (bestvertex+1)) { - newdiagonal.index1 = bestvertex; - newdiagonal.index2 = diagonal.index2; - diagonals.push_back(newdiagonal); - } - } - - for(i=1;i<n;i++) { - delete [] dpstates[i]; - } - delete [] dpstates; - - return ret; -} - -void TriangulatorPartition::UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates) { - Diagonal newdiagonal; - List<Diagonal> *pairs; - long w2; - - w2 = dpstates[a][b].weight; - if(w>w2) return; - - pairs = &(dpstates[a][b].pairs); - newdiagonal.index1 = i; - newdiagonal.index2 = j; - - if(w<w2) { - pairs->clear(); - pairs->push_front(newdiagonal); - dpstates[a][b].weight = w; - } else { - if((!pairs->is_empty())&&(i <= pairs->front()->get().index1)) return; - while((!pairs->is_empty())&&(pairs->front()->get().index2 >= j)) pairs->pop_front(); - pairs->push_front(newdiagonal); - } -} - -void TriangulatorPartition::TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { - List<Diagonal> *pairs; - List<Diagonal>::Element *iter,*lastiter; - long top; - long w; - - if(!dpstates[i][j].visible) return; - top = j; - w = dpstates[i][j].weight; - if(k-j > 1) { - if (!dpstates[j][k].visible) return; - w += dpstates[j][k].weight + 1; - } - if(j-i > 1) { - pairs = &(dpstates[i][j].pairs); - iter = NULL; - lastiter = NULL; - while(iter!=pairs->front()) { - if (!iter) - iter=pairs->back(); - else - iter=iter->prev(); - - if(!IsReflex(vertices[iter->get().index2].p,vertices[j].p,vertices[k].p)) lastiter = iter; - else break; - } - if(lastiter == NULL) w++; - else { - if(IsReflex(vertices[k].p,vertices[i].p,vertices[lastiter->get().index1].p)) w++; - else top = lastiter->get().index1; - } - } - UpdateState(i,k,w,top,j,dpstates); -} - -void TriangulatorPartition::TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates) { - List<Diagonal> *pairs; - List<Diagonal>::Element* iter,*lastiter; - long top; - long w; - - if(!dpstates[j][k].visible) return; - top = j; - w = dpstates[j][k].weight; - - if (j-i > 1) { - if (!dpstates[i][j].visible) return; - w += dpstates[i][j].weight + 1; - } - if (k-j > 1) { - pairs = &(dpstates[j][k].pairs); - - iter = pairs->front(); - if((!pairs->is_empty())&&(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->get().index1].p))) { - lastiter = iter; - while(iter!=NULL) { - if(!IsReflex(vertices[i].p,vertices[j].p,vertices[iter->get().index1].p)) { - lastiter = iter; - iter=iter->next(); - } - else break; - } - if(IsReflex(vertices[lastiter->get().index2].p,vertices[k].p,vertices[i].p)) w++; - else top = lastiter->get().index2; - } else w++; - } - UpdateState(i,k,w,j,top,dpstates); -} - -int TriangulatorPartition::ConvexPartition_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *parts) { - Vector2 p1,p2,p3,p4; - PartitionVertex *vertices; - DPState2 **dpstates; - long i,j,k,n,gap; - List<Diagonal> diagonals,diagonals2; - Diagonal diagonal,newdiagonal; - List<Diagonal> *pairs,*pairs2; - List<Diagonal>::Element* iter,*iter2; - int ret; - TriangulatorPoly newpoly; - List<long> indices; - List<long>::Element* iiter; - bool ijreal,jkreal; - - n = poly->GetNumPoints(); - vertices = new PartitionVertex[n]; - - dpstates = new DPState2 *[n]; - for(i=0;i<n;i++) { - dpstates[i] = new DPState2[n]; - } - - //init vertex information - for(i=0;i<n;i++) { - vertices[i].p = poly->GetPoint(i); - vertices[i].isActive = true; - if(i==0) vertices[i].previous = &(vertices[n-1]); - else vertices[i].previous = &(vertices[i-1]); - if(i==(poly->GetNumPoints()-1)) vertices[i].next = &(vertices[0]); - else vertices[i].next = &(vertices[i+1]); - } - for(i=1;i<n;i++) { - UpdateVertexReflexity(&(vertices[i])); - } - - //init states and visibility - for(i=0;i<(n-1);i++) { - p1 = poly->GetPoint(i); - for(j=i+1;j<n;j++) { - dpstates[i][j].visible = true; - if(j==i+1) { - dpstates[i][j].weight = 0; - } else { - dpstates[i][j].weight = 2147483647; - } - if(j!=(i+1)) { - p2 = poly->GetPoint(j); - - //visibility check - if(!InCone(&vertices[i],p2)) { - dpstates[i][j].visible = false; - continue; - } - if(!InCone(&vertices[j],p1)) { - dpstates[i][j].visible = false; - continue; - } - - for(k=0;k<n;k++) { - p3 = poly->GetPoint(k); - if(k==(n-1)) p4 = poly->GetPoint(0); - else p4 = poly->GetPoint(k+1); - if(Intersects(p1,p2,p3,p4)) { - dpstates[i][j].visible = false; - break; - } - } - } - } - } - for(i=0;i<(n-2);i++) { - j = i+2; - if(dpstates[i][j].visible) { - dpstates[i][j].weight = 0; - newdiagonal.index1 = i+1; - newdiagonal.index2 = i+1; - dpstates[i][j].pairs.push_back(newdiagonal); - } - } - - dpstates[0][n-1].visible = true; - vertices[0].isConvex = false; //by convention - - for(gap=3; gap<n; gap++) { - for(i=0;i<n-gap;i++) { - if(vertices[i].isConvex) continue; - k = i+gap; - if(dpstates[i][k].visible) { - if(!vertices[k].isConvex) { - for(j=i+1;j<k;j++) TypeA(i,j,k,vertices,dpstates); - } else { - for(j=i+1;j<(k-1);j++) { - if(vertices[j].isConvex) continue; - TypeA(i,j,k,vertices,dpstates); - } - TypeA(i,k-1,k,vertices,dpstates); - } - } - } - for(k=gap;k<n;k++) { - if(vertices[k].isConvex) continue; - i = k-gap; - if((vertices[i].isConvex)&&(dpstates[i][k].visible)) { - TypeB(i,i+1,k,vertices,dpstates); - for(j=i+2;j<k;j++) { - if(vertices[j].isConvex) continue; - TypeB(i,j,k,vertices,dpstates); - } - } - } - } - - - //recover solution - ret = 1; - newdiagonal.index1 = 0; - newdiagonal.index2 = n-1; - diagonals.push_front(newdiagonal); - while(!diagonals.is_empty()) { - diagonal = (diagonals.front()->get()); - diagonals.pop_front(); - if((diagonal.index2 - diagonal.index1) <=1) continue; - pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs); - if(pairs->is_empty()) { - ret = 0; - break; - } - if(!vertices[diagonal.index1].isConvex) { - iter = pairs->back(); - - j = iter->get().index2; - newdiagonal.index1 = j; - newdiagonal.index2 = diagonal.index2; - diagonals.push_front(newdiagonal); - if((j - diagonal.index1)>1) { - if(iter->get().index1 != iter->get().index2) { - pairs2 = &(dpstates[diagonal.index1][j].pairs); - while(1) { - if(pairs2->is_empty()) { - ret = 0; - break; - } - iter2 = pairs2->back(); - - if(iter->get().index1 != iter2->get().index1) pairs2->pop_back(); - else break; - } - if(ret == 0) break; - } - newdiagonal.index1 = diagonal.index1; - newdiagonal.index2 = j; - diagonals.push_front(newdiagonal); - } - } else { - iter = pairs->front(); - j = iter->get().index1; - newdiagonal.index1 = diagonal.index1; - newdiagonal.index2 = j; - diagonals.push_front(newdiagonal); - if((diagonal.index2 - j) > 1) { - if(iter->get().index1 != iter->get().index2) { - pairs2 = &(dpstates[j][diagonal.index2].pairs); - while(1) { - if(pairs2->is_empty()) { - ret = 0; - break; - } - iter2 = pairs2->front(); - if(iter->get().index2 != iter2->get().index2) pairs2->pop_front(); - else break; - } - if(ret == 0) break; - } - newdiagonal.index1 = j; - newdiagonal.index2 = diagonal.index2; - diagonals.push_front(newdiagonal); - } - } - } - - if(ret == 0) { - for(i=0;i<n;i++) { - delete [] dpstates[i]; - } - delete [] dpstates; - delete [] vertices; - - return ret; - } - - newdiagonal.index1 = 0; - newdiagonal.index2 = n-1; - diagonals.push_front(newdiagonal); - while(!diagonals.is_empty()) { - diagonal = (diagonals.front())->get(); - diagonals.pop_front(); - if((diagonal.index2 - diagonal.index1) <= 1) continue; - - indices.clear(); - diagonals2.clear(); - indices.push_back(diagonal.index1); - indices.push_back(diagonal.index2); - diagonals2.push_front(diagonal); - - while(!diagonals2.is_empty()) { - diagonal = (diagonals2.front()->get()); - diagonals2.pop_front(); - if((diagonal.index2 - diagonal.index1) <= 1) continue; - ijreal = true; - jkreal = true; - pairs = &(dpstates[diagonal.index1][diagonal.index2].pairs); - if(!vertices[diagonal.index1].isConvex) { - iter = pairs->back(); - j = iter->get().index2; - if(iter->get().index1 != iter->get().index2) ijreal = false; - } else { - iter = pairs->front(); - j = iter->get().index1; - if(iter->get().index1 != iter->get().index2) jkreal = false; - } - - newdiagonal.index1 = diagonal.index1; - newdiagonal.index2 = j; - if(ijreal) { - diagonals.push_back(newdiagonal); - } else { - diagonals2.push_back(newdiagonal); - } - - newdiagonal.index1 = j; - newdiagonal.index2 = diagonal.index2; - if(jkreal) { - diagonals.push_back(newdiagonal); - } else { - diagonals2.push_back(newdiagonal); - } - - indices.push_back(j); - } - - indices.sort(); - newpoly.Init((long)indices.size()); - k=0; - for(iiter = indices.front();iiter;iiter=iiter->next()) { - newpoly[k] = vertices[iiter->get()].p; - k++; - } - parts->push_back(newpoly); - } - - for(i=0;i<n;i++) { - delete [] dpstates[i]; - } - delete [] dpstates; - delete [] vertices; - - return ret; -} - -//triangulates a set of polygons by first partitioning them into monotone polygons -//O(n*log(n)) time complexity, O(n) space complexity -//the algorithm used here is outlined in the book -//"Computational Geometry: Algorithms and Applications" -//by Mark de Berg, Otfried Cheong, Marc van Kreveld and Mark Overmars -int TriangulatorPartition::MonotonePartition(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *monotonePolys) { - List<TriangulatorPoly>::Element *iter; - MonotoneVertex *vertices; - long i,numvertices,vindex,vindex2,newnumvertices,maxnumvertices; - long polystartindex, polyendindex; - TriangulatorPoly *poly; - MonotoneVertex *v,*v2,*vprev,*vnext; - ScanLineEdge newedge; - bool error = false; - - numvertices = 0; - for(iter = inpolys->front(); iter ; iter=iter->next()) { - numvertices += iter->get().GetNumPoints(); - } - - maxnumvertices = numvertices*3; - vertices = new MonotoneVertex[maxnumvertices]; - newnumvertices = numvertices; - - polystartindex = 0; - for(iter = inpolys->front(); iter ; iter=iter->next()) { - poly = &(iter->get()); - polyendindex = polystartindex + poly->GetNumPoints()-1; - for(i=0;i<poly->GetNumPoints();i++) { - vertices[i+polystartindex].p = poly->GetPoint(i); - if(i==0) vertices[i+polystartindex].previous = polyendindex; - else vertices[i+polystartindex].previous = i+polystartindex-1; - if(i==(poly->GetNumPoints()-1)) vertices[i+polystartindex].next = polystartindex; - else vertices[i+polystartindex].next = i+polystartindex+1; - } - polystartindex = polyendindex+1; - } - - //construct the priority queue - long *priority = new long [numvertices]; - for(i=0;i<numvertices;i++) priority[i] = i; - SortArray<long,VertexSorter> sorter; - sorter.compare.vertices=vertices; - sorter.sort(priority,numvertices); - - //determine vertex types - char *vertextypes = new char[maxnumvertices]; - for(i=0;i<numvertices;i++) { - v = &(vertices[i]); - vprev = &(vertices[v->previous]); - vnext = &(vertices[v->next]); - - if(Below(vprev->p,v->p)&&Below(vnext->p,v->p)) { - if(IsConvex(vnext->p,vprev->p,v->p)) { - vertextypes[i] = TRIANGULATOR_VERTEXTYPE_START; - } else { - vertextypes[i] = TRIANGULATOR_VERTEXTYPE_SPLIT; - } - } else if(Below(v->p,vprev->p)&&Below(v->p,vnext->p)) { - if(IsConvex(vnext->p,vprev->p,v->p)) - { - vertextypes[i] = TRIANGULATOR_VERTEXTYPE_END; - } else { - vertextypes[i] = TRIANGULATOR_VERTEXTYPE_MERGE; - } - } else { - vertextypes[i] = TRIANGULATOR_VERTEXTYPE_REGULAR; - } - } - - //helpers - long *helpers = new long[maxnumvertices]; - - //binary search tree that holds edges intersecting the scanline - //note that while set doesn't actually have to be implemented as a tree - //complexity requirements for operations are the same as for the balanced binary search tree - Set<ScanLineEdge> edgeTree; - //store iterators to the edge tree elements - //this makes deleting existing edges much faster - Set<ScanLineEdge>::Element **edgeTreeIterators,*edgeIter; - edgeTreeIterators = new Set<ScanLineEdge>::Element*[maxnumvertices]; - //Pair<Set<ScanLineEdge>::Element*,bool> edgeTreeRet; - for(i = 0; i<numvertices; i++) edgeTreeIterators[i] = NULL; - - //for each vertex - for(i=0;i<numvertices;i++) { - vindex = priority[i]; - v = &(vertices[vindex]); - vindex2 = vindex; - v2 = v; - - //depending on the vertex type, do the appropriate action - //comments in the following sections are copied from "Computational Geometry: Algorithms and Applications" - switch(vertextypes[vindex]) { - case TRIANGULATOR_VERTEXTYPE_START: - //Insert ei in T and set helper(ei) to vi. - newedge.p1 = v->p; - newedge.p2 = vertices[v->next].p; - newedge.index = vindex; - edgeTreeIterators[vindex] = edgeTree.insert(newedge); - helpers[vindex] = vindex; - break; - - case TRIANGULATOR_VERTEXTYPE_END: - //if helper(ei-1) is a merge vertex - if(vertextypes[helpers[v->previous]]==TRIANGULATOR_VERTEXTYPE_MERGE) { - //Insert the diagonal connecting vi to helper(ei-1) in D. - AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous], - vertextypes, edgeTreeIterators, &edgeTree, helpers); - } - //Delete ei-1 from T - edgeTree.erase(edgeTreeIterators[v->previous]); - break; - - case TRIANGULATOR_VERTEXTYPE_SPLIT: - //Search in T to find the edge e j directly left of vi. - newedge.p1 = v->p; - newedge.p2 = v->p; - edgeIter = edgeTree.lower_bound(newedge); - if(edgeIter == edgeTree.front()) { - error = true; - break; - } - edgeIter=edgeIter->prev(); - //Insert the diagonal connecting vi to helper(ej) in D. - AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->get().index], - vertextypes, edgeTreeIterators, &edgeTree, helpers); - vindex2 = newnumvertices-2; - v2 = &(vertices[vindex2]); - //helper(e j)�vi - helpers[edgeIter->get().index] = vindex; - //Insert ei in T and set helper(ei) to vi. - newedge.p1 = v2->p; - newedge.p2 = vertices[v2->next].p; - newedge.index = vindex2; - - edgeTreeIterators[vindex2] = edgeTree.insert(newedge); - helpers[vindex2] = vindex2; - break; - - case TRIANGULATOR_VERTEXTYPE_MERGE: - //if helper(ei-1) is a merge vertex - if(vertextypes[helpers[v->previous]]==TRIANGULATOR_VERTEXTYPE_MERGE) { - //Insert the diagonal connecting vi to helper(ei-1) in D. - AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous], - vertextypes, edgeTreeIterators, &edgeTree, helpers); - vindex2 = newnumvertices-2; - v2 = &(vertices[vindex2]); - } - //Delete ei-1 from T. - edgeTree.erase(edgeTreeIterators[v->previous]); - //Search in T to find the edge e j directly left of vi. - newedge.p1 = v->p; - newedge.p2 = v->p; - edgeIter = edgeTree.lower_bound(newedge); - if(edgeIter == edgeTree.front()) { - error = true; - break; - } - edgeIter=edgeIter->prev(); - //if helper(ej) is a merge vertex - if(vertextypes[helpers[edgeIter->get().index]]==TRIANGULATOR_VERTEXTYPE_MERGE) { - //Insert the diagonal connecting vi to helper(e j) in D. - AddDiagonal(vertices,&newnumvertices,vindex2,helpers[edgeIter->get().index], - vertextypes, edgeTreeIterators, &edgeTree, helpers); - } - //helper(e j)�vi - helpers[edgeIter->get().index] = vindex2; - break; - - case TRIANGULATOR_VERTEXTYPE_REGULAR: - //if the interior of P lies to the right of vi - if(Below(v->p,vertices[v->previous].p)) { - //if helper(ei-1) is a merge vertex - if(vertextypes[helpers[v->previous]]==TRIANGULATOR_VERTEXTYPE_MERGE) { - //Insert the diagonal connecting vi to helper(ei-1) in D. - AddDiagonal(vertices,&newnumvertices,vindex,helpers[v->previous], - vertextypes, edgeTreeIterators, &edgeTree, helpers); - vindex2 = newnumvertices-2; - v2 = &(vertices[vindex2]); - } - //Delete ei-1 from T. - edgeTree.erase(edgeTreeIterators[v->previous]); - //Insert ei in T and set helper(ei) to vi. - newedge.p1 = v2->p; - newedge.p2 = vertices[v2->next].p; - newedge.index = vindex2; - edgeTreeIterators[vindex2] = edgeTree.insert(newedge); - helpers[vindex2] = vindex; - } else { - //Search in T to find the edge ej directly left of vi. - newedge.p1 = v->p; - newedge.p2 = v->p; - edgeIter = edgeTree.lower_bound(newedge); - if(edgeIter == edgeTree.front()) { - error = true; - break; - } - edgeIter=edgeIter->prev(); - //if helper(ej) is a merge vertex - if(vertextypes[helpers[edgeIter->get().index]]==TRIANGULATOR_VERTEXTYPE_MERGE) { - //Insert the diagonal connecting vi to helper(e j) in D. - AddDiagonal(vertices,&newnumvertices,vindex,helpers[edgeIter->get().index], - vertextypes, edgeTreeIterators, &edgeTree, helpers); - } - //helper(e j)�vi - helpers[edgeIter->get().index] = vindex; - } - break; - } - - if(error) break; - } - - char *used = new char[newnumvertices]; - memset(used,0,newnumvertices*sizeof(char)); - - if(!error) { - //return result - long size; - TriangulatorPoly mpoly; - for(i=0;i<newnumvertices;i++) { - if(used[i]) continue; - v = &(vertices[i]); - vnext = &(vertices[v->next]); - size = 1; - while(vnext!=v) { - vnext = &(vertices[vnext->next]); - size++; - } - mpoly.Init(size); - v = &(vertices[i]); - mpoly[0] = v->p; - vnext = &(vertices[v->next]); - size = 1; - used[i] = 1; - used[v->next] = 1; - while(vnext!=v) { - mpoly[size] = vnext->p; - used[vnext->next] = 1; - vnext = &(vertices[vnext->next]); - size++; - } - monotonePolys->push_back(mpoly); - } - } - - //cleanup - delete [] vertices; - delete [] priority; - delete [] vertextypes; - delete [] edgeTreeIterators; - delete [] helpers; - delete [] used; - - if(error) { - return 0; - } else { - return 1; - } -} - -//adds a diagonal to the doubly-connected list of vertices -void TriangulatorPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2, - char *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators, - Set<ScanLineEdge> *edgeTree, long *helpers) -{ - long newindex1,newindex2; - - newindex1 = *numvertices; - (*numvertices)++; - newindex2 = *numvertices; - (*numvertices)++; - - vertices[newindex1].p = vertices[index1].p; - vertices[newindex2].p = vertices[index2].p; - - vertices[newindex2].next = vertices[index2].next; - vertices[newindex1].next = vertices[index1].next; - - vertices[vertices[index2].next].previous = newindex2; - vertices[vertices[index1].next].previous = newindex1; - - vertices[index1].next = newindex2; - vertices[newindex2].previous = index1; - - vertices[index2].next = newindex1; - vertices[newindex1].previous = index2; - - //update all relevant structures - vertextypes[newindex1] = vertextypes[index1]; - edgeTreeIterators[newindex1] = edgeTreeIterators[index1]; - helpers[newindex1] = helpers[index1]; - if(edgeTreeIterators[newindex1] != NULL) - edgeTreeIterators[newindex1]->get().index = newindex1; - vertextypes[newindex2] = vertextypes[index2]; - edgeTreeIterators[newindex2] = edgeTreeIterators[index2]; - helpers[newindex2] = helpers[index2]; - if(edgeTreeIterators[newindex2] != NULL) - edgeTreeIterators[newindex2]->get().index = newindex2; -} - -bool TriangulatorPartition::Below(Vector2 &p1, Vector2 &p2) { - if(p1.y < p2.y) return true; - else if(p1.y == p2.y) { - if(p1.x < p2.x) return true; - } - return false; -} - - - - - -//sorts in the falling order of y values, if y is equal, x is used instead -bool TriangulatorPartition::VertexSorter::operator() (long index1, long index2) const { - if(vertices[index1].p.y > vertices[index2].p.y) return true; - else if(vertices[index1].p.y == vertices[index2].p.y) { - if(vertices[index1].p.x > vertices[index2].p.x) return true; - } - return false; -} - -bool TriangulatorPartition::ScanLineEdge::IsConvex(const Vector2& p1, const Vector2& p2, const Vector2& p3) const { - real_t tmp; - tmp = (p3.y-p1.y)*(p2.x-p1.x)-(p3.x-p1.x)*(p2.y-p1.y); - if(tmp>0) return 1; - else return 0; -} - -bool TriangulatorPartition::ScanLineEdge::operator < (const ScanLineEdge & other) const { - if(other.p1.y == other.p2.y) { - if(p1.y == p2.y) { - if(p1.y < other.p1.y) return true; - else return false; - } - if(IsConvex(p1,p2,other.p1)) return true; - else return false; - } else if(p1.y == p2.y) { - if(IsConvex(other.p1,other.p2,p1)) return false; - else return true; - } else if(p1.y < other.p1.y) { - if(IsConvex(other.p1,other.p2,p1)) return false; - else return true; - } else { - if(IsConvex(p1,p2,other.p1)) return true; - else return false; - } -} - -//triangulates monotone polygon -//O(n) time, O(n) space complexity -int TriangulatorPartition::TriangulateMonotone(TriangulatorPoly *inPoly, List<TriangulatorPoly> *triangles) { - long i,i2,j,topindex,bottomindex,leftindex,rightindex,vindex; - Vector2 *points; - long numpoints; - TriangulatorPoly triangle; - - numpoints = inPoly->GetNumPoints(); - points = inPoly->GetPoints(); - - //trivial calses - if(numpoints < 3) return 0; - if(numpoints == 3) { - triangles->push_back(*inPoly); - } - - topindex = 0; bottomindex=0; - for(i=1;i<numpoints;i++) { - if(Below(points[i],points[bottomindex])) bottomindex = i; - if(Below(points[topindex],points[i])) topindex = i; - } - - //check if the poly is really monotone - i = topindex; - while(i!=bottomindex) { - i2 = i+1; if(i2>=numpoints) i2 = 0; - if(!Below(points[i2],points[i])) return 0; - i = i2; - } - i = bottomindex; - while(i!=topindex) { - i2 = i+1; if(i2>=numpoints) i2 = 0; - if(!Below(points[i],points[i2])) return 0; - i = i2; - } - - char *vertextypes = new char[numpoints]; - long *priority = new long[numpoints]; - - //merge left and right vertex chains - priority[0] = topindex; - vertextypes[topindex] = 0; - leftindex = topindex+1; if(leftindex>=numpoints) leftindex = 0; - rightindex = topindex-1; if(rightindex<0) rightindex = numpoints-1; - for(i=1;i<(numpoints-1);i++) { - if(leftindex==bottomindex) { - priority[i] = rightindex; - rightindex--; if(rightindex<0) rightindex = numpoints-1; - vertextypes[priority[i]] = -1; - } else if(rightindex==bottomindex) { - priority[i] = leftindex; - leftindex++; if(leftindex>=numpoints) leftindex = 0; - vertextypes[priority[i]] = 1; - } else { - if(Below(points[leftindex],points[rightindex])) { - priority[i] = rightindex; - rightindex--; if(rightindex<0) rightindex = numpoints-1; - vertextypes[priority[i]] = -1; - } else { - priority[i] = leftindex; - leftindex++; if(leftindex>=numpoints) leftindex = 0; - vertextypes[priority[i]] = 1; - } - } - } - priority[i] = bottomindex; - vertextypes[bottomindex] = 0; - - long *stack = new long[numpoints]; - long stackptr = 0; - - stack[0] = priority[0]; - stack[1] = priority[1]; - stackptr = 2; - - //for each vertex from top to bottom trim as many triangles as possible - for(i=2;i<(numpoints-1);i++) { - vindex = priority[i]; - if(vertextypes[vindex]!=vertextypes[stack[stackptr-1]]) { - for(j=0;j<(stackptr-1);j++) { - if(vertextypes[vindex]==1) { - triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]); - } else { - triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]); - } - triangles->push_back(triangle); - } - stack[0] = priority[i-1]; - stack[1] = priority[i]; - stackptr = 2; - } else { - stackptr--; - while(stackptr>0) { - if(vertextypes[vindex]==1) { - if(IsConvex(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]])) { - triangle.Triangle(points[vindex],points[stack[stackptr-1]],points[stack[stackptr]]); - triangles->push_back(triangle); - stackptr--; - } else { - break; - } - } else { - if(IsConvex(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]])) { - triangle.Triangle(points[vindex],points[stack[stackptr]],points[stack[stackptr-1]]); - triangles->push_back(triangle); - stackptr--; - } else { - break; - } - } - } - stackptr++; - stack[stackptr] = vindex; - stackptr++; - } - } - vindex = priority[i]; - for(j=0;j<(stackptr-1);j++) { - if(vertextypes[stack[j+1]]==1) { - triangle.Triangle(points[stack[j]],points[stack[j+1]],points[vindex]); - } else { - triangle.Triangle(points[stack[j+1]],points[stack[j]],points[vindex]); - } - triangles->push_back(triangle); - } - - delete [] priority; - delete [] vertextypes; - delete [] stack; - - return 1; -} - -int TriangulatorPartition::Triangulate_MONO(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles) { - List<TriangulatorPoly> monotone; - List<TriangulatorPoly>::Element* iter; - - if(!MonotonePartition(inpolys,&monotone)) return 0; - for(iter = monotone.front(); iter;iter=iter->next()) { - if(!TriangulateMonotone(&(iter->get()),triangles)) return 0; - } - return 1; -} - -int TriangulatorPartition::Triangulate_MONO(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles) { - List<TriangulatorPoly> polys; - polys.push_back(*poly); - - return Triangulate_MONO(&polys, triangles); -} diff --git a/thirdparty/misc/triangulator.h b/thirdparty/misc/triangulator.h deleted file mode 100644 index 24b79e7d34..0000000000 --- a/thirdparty/misc/triangulator.h +++ /dev/null @@ -1,306 +0,0 @@ -//Copyright (C) 2011 by Ivan Fratric -// -//Permission is hereby granted, free of charge, to any person obtaining a copy -//of this software and associated documentation files (the "Software"), to deal -//in the Software without restriction, including without limitation the rights -//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -//copies of the Software, and to permit persons to whom the Software is -//furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included in -//all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -//THE SOFTWARE. - -#ifndef TRIANGULATOR_H -#define TRIANGULATOR_H - -#include "core/templates/list.h" -#include "core/math/vector2.h" -#include "core/templates/set.h" - -//2D point structure - -#define TRIANGULATOR_CCW 1 -#define TRIANGULATOR_CW -1 -//Polygon implemented as an array of points with a 'hole' flag -class TriangulatorPoly { -protected: - - - - Vector2 *points; - long numpoints; - bool hole; - -public: - - //constructors/destructors - TriangulatorPoly(); - ~TriangulatorPoly(); - - TriangulatorPoly(const TriangulatorPoly &src); - TriangulatorPoly& operator=(const TriangulatorPoly &src); - - //getters and setters - long GetNumPoints() { - return numpoints; - } - - bool IsHole() { - return hole; - } - - void SetHole(bool hole) { - this->hole = hole; - } - - Vector2 &GetPoint(long i) { - return points[i]; - } - - Vector2 *GetPoints() { - return points; - } - - Vector2& operator[] (int i) { - return points[i]; - } - - //clears the polygon points - void Clear(); - - //inits the polygon with numpoints vertices - void Init(long numpoints); - - //creates a triangle with points p1,p2,p3 - void Triangle(Vector2 &p1, Vector2 &p2, Vector2 &p3); - - //inverts the orfer of vertices - void Invert(); - - //returns the orientation of the polygon - //possible values: - // Triangulator_CCW : polygon vertices are in counter-clockwise order - // Triangulator_CW : polygon vertices are in clockwise order - // 0 : the polygon has no (measurable) area - int GetOrientation(); - - //sets the polygon orientation - //orientation can be - // Triangulator_CCW : sets vertices in counter-clockwise order - // Triangulator_CW : sets vertices in clockwise order - void SetOrientation(int orientation); -}; - -class TriangulatorPartition { -protected: - struct PartitionVertex { - bool isActive; - bool isConvex; - bool isEar; - - Vector2 p; - real_t angle; - PartitionVertex *previous; - PartitionVertex *next; - }; - - struct MonotoneVertex { - Vector2 p; - long previous; - long next; - }; - - struct VertexSorter{ - mutable MonotoneVertex *vertices; - bool operator() (long index1, long index2) const; - }; - - struct Diagonal { - long index1; - long index2; - }; - - //dynamic programming state for minimum-weight triangulation - struct DPState { - bool visible; - real_t weight; - long bestvertex; - }; - - //dynamic programming state for convex partitioning - struct DPState2 { - bool visible; - long weight; - List<Diagonal> pairs; - }; - - //edge that intersects the scanline - struct ScanLineEdge { - mutable long index; - Vector2 p1; - Vector2 p2; - - //determines if the edge is to the left of another edge - bool operator< (const ScanLineEdge & other) const; - - bool IsConvex(const Vector2& p1, const Vector2& p2, const Vector2& p3) const; - }; - - //standard helper functions - bool IsConvex(Vector2& p1, Vector2& p2, Vector2& p3); - bool IsReflex(Vector2& p1, Vector2& p2, Vector2& p3); - bool IsInside(Vector2& p1, Vector2& p2, Vector2& p3, Vector2 &p); - - bool InCone(Vector2 &p1, Vector2 &p2, Vector2 &p3, Vector2 &p); - bool InCone(PartitionVertex *v, Vector2 &p); - - int Intersects(Vector2 &p11, Vector2 &p12, Vector2 &p21, Vector2 &p22); - - Vector2 Normalize(const Vector2 &p); - real_t Distance(const Vector2 &p1, const Vector2 &p2); - - //helper functions for Triangulate_EC - void UpdateVertexReflexity(PartitionVertex *v); - void UpdateVertex(PartitionVertex *v,PartitionVertex *vertices, long numvertices); - - //helper functions for ConvexPartition_OPT - void UpdateState(long a, long b, long w, long i, long j, DPState2 **dpstates); - void TypeA(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates); - void TypeB(long i, long j, long k, PartitionVertex *vertices, DPState2 **dpstates); - - //helper functions for MonotonePartition - bool Below(Vector2 &p1, Vector2 &p2); - void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2, - char *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators, - Set<ScanLineEdge> *edgeTree, long *helpers); - - //triangulates a monotone polygon, used in Triangulate_MONO - int TriangulateMonotone(TriangulatorPoly *inPoly, List<TriangulatorPoly> *triangles); - -public: - - //simple heuristic procedure for removing holes from a list of polygons - //works by creating a diagonal from the rightmost hole vertex to some visible vertex - //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices - //space complexity: O(n) - //params: - // inpolys : a list of polygons that can contain holes - // vertices of all non-hole polys have to be in counter-clockwise order - // vertices of all hole polys have to be in clockwise order - // outpolys : a list of polygons without holes - //returns 1 on success, 0 on failure - int RemoveHoles(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *outpolys); - - //triangulates a polygon by ear clipping - //time complexity O(n^2), n is the number of vertices - //space complexity: O(n) - //params: - // poly : an input polygon to be triangulated - // vertices have to be in counter-clockwise order - // triangles : a list of triangles (result) - //returns 1 on success, 0 on failure - int Triangulate_EC(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles); - - //triangulates a list of polygons that may contain holes by ear clipping algorithm - //first calls RemoveHoles to get rid of the holes, and then Triangulate_EC for each resulting polygon - //time complexity: O(h*(n^2)), h is the number of holes, n is the number of vertices - //space complexity: O(n) - //params: - // inpolys : a list of polygons to be triangulated (can contain holes) - // vertices of all non-hole polys have to be in counter-clockwise order - // vertices of all hole polys have to be in clockwise order - // triangles : a list of triangles (result) - //returns 1 on success, 0 on failure - int Triangulate_EC(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles); - - //creates an optimal polygon triangulation in terms of minimal edge length - //time complexity: O(n^3), n is the number of vertices - //space complexity: O(n^2) - //params: - // poly : an input polygon to be triangulated - // vertices have to be in counter-clockwise order - // triangles : a list of triangles (result) - //returns 1 on success, 0 on failure - int Triangulate_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles); - - //triangulates a polygons by firstly partitioning it into monotone polygons - //time complexity: O(n*log(n)), n is the number of vertices - //space complexity: O(n) - //params: - // poly : an input polygon to be triangulated - // vertices have to be in counter-clockwise order - // triangles : a list of triangles (result) - //returns 1 on success, 0 on failure - int Triangulate_MONO(TriangulatorPoly *poly, List<TriangulatorPoly> *triangles); - - //triangulates a list of polygons by firstly partitioning them into monotone polygons - //time complexity: O(n*log(n)), n is the number of vertices - //space complexity: O(n) - //params: - // inpolys : a list of polygons to be triangulated (can contain holes) - // vertices of all non-hole polys have to be in counter-clockwise order - // vertices of all hole polys have to be in clockwise order - // triangles : a list of triangles (result) - //returns 1 on success, 0 on failure - int Triangulate_MONO(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *triangles); - - //creates a monotone partition of a list of polygons that can contain holes - //time complexity: O(n*log(n)), n is the number of vertices - //space complexity: O(n) - //params: - // inpolys : a list of polygons to be triangulated (can contain holes) - // vertices of all non-hole polys have to be in counter-clockwise order - // vertices of all hole polys have to be in clockwise order - // monotonePolys : a list of monotone polygons (result) - //returns 1 on success, 0 on failure - int MonotonePartition(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *monotonePolys); - - //partitions a polygon into convex polygons by using Hertel-Mehlhorn algorithm - //the algorithm gives at most four times the number of parts as the optimal algorithm - //however, in practice it works much better than that and often gives optimal partition - //uses triangulation obtained by ear clipping as intermediate result - //time complexity O(n^2), n is the number of vertices - //space complexity: O(n) - //params: - // poly : an input polygon to be partitioned - // vertices have to be in counter-clockwise order - // parts : resulting list of convex polygons - //returns 1 on success, 0 on failure - int ConvexPartition_HM(TriangulatorPoly *poly, List<TriangulatorPoly> *parts); - - //partitions a list of polygons into convex parts by using Hertel-Mehlhorn algorithm - //the algorithm gives at most four times the number of parts as the optimal algorithm - //however, in practice it works much better than that and often gives optimal partition - //uses triangulation obtained by ear clipping as intermediate result - //time complexity O(n^2), n is the number of vertices - //space complexity: O(n) - //params: - // inpolys : an input list of polygons to be partitioned - // vertices of all non-hole polys have to be in counter-clockwise order - // vertices of all hole polys have to be in clockwise order - // parts : resulting list of convex polygons - //returns 1 on success, 0 on failure - int ConvexPartition_HM(List<TriangulatorPoly> *inpolys, List<TriangulatorPoly> *parts); - - //optimal convex partitioning (in terms of number of resulting convex polygons) - //using the Keil-Snoeyink algorithm - //M. Keil, J. Snoeyink, "On the time bound for convex decomposition of simple polygons", 1998 - //time complexity O(n^3), n is the number of vertices - //space complexity: O(n^3) - // poly : an input polygon to be partitioned - // vertices have to be in counter-clockwise order - // parts : resulting list of convex polygons - //returns 1 on success, 0 on failure - int ConvexPartition_OPT(TriangulatorPoly *poly, List<TriangulatorPoly> *parts); -}; - - -#endif diff --git a/thirdparty/opus/celt/arm/arm2gnu.pl b/thirdparty/opus/celt/arm/arm2gnu.pl deleted file mode 100755 index 6c922ac819..0000000000 --- a/thirdparty/opus/celt/arm/arm2gnu.pl +++ /dev/null @@ -1,353 +0,0 @@ -#!/usr/bin/perl -# Copyright (C) 2002-2013 Xiph.org Foundation -# -# 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. -# -# 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. - -my $bigend; # little/big endian -my $nxstack; -my $apple = 0; -my $symprefix = ""; - -$nxstack = 0; - -eval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}' - if $running_under_some_shell; - -while ($ARGV[0] =~ /^-/) { - $_ = shift; - last if /^--$/; - if (/^-n$/) { - $nflag++; - next; - } - if (/^--apple$/) { - $apple = 1; - $symprefix = "_"; - next; - } - die "I don't recognize this switch: $_\\n"; -} -$printit++ unless $nflag; - -$\ = "\n"; # automatically add newline on print -$n=0; - -$thumb = 0; # ARM mode by default, not Thumb. -@proc_stack = (); - -printf (" .syntax unified\n"); - -LINE: -while (<>) { - - # For ADRLs we need to add a new line after the substituted one. - $addPadding = 0; - - # First, we do not dare to touch *anything* inside double quotes, do we? - # Second, if you want a dollar character in the string, - # insert two of them -- that's how ARM C and assembler treat strings. - s/^([A-Za-z_]\w*)[ \t]+DCB[ \t]*\"/$1: .ascii \"/ && do { s/\$\$/\$/g; next }; - s/\bDCB\b[ \t]*\"/.ascii \"/ && do { s/\$\$/\$/g; next }; - s/^(\S+)\s+RN\s+(\S+)/$1 .req r$2/ && do { s/\$\$/\$/g; next }; - # If there's nothing on a line but a comment, don't try to apply any further - # substitutions (this is a cheap hack to avoid mucking up the license header) - s/^([ \t]*);/$1@/ && do { s/\$\$/\$/g; next }; - # If substituted -- leave immediately ! - - s/@/,:/; - s/;/@/; - while ( /@.*'/ ) { - s/(@.*)'/$1/g; - } - s/\{FALSE\}/0/g; - s/\{TRUE\}/1/g; - s/\{(\w\w\w\w+)\}/$1/g; - s/\bINCLUDE[ \t]*([^ \t\n]+)/.include \"$1\"/; - s/\bGET[ \t]*([^ \t\n]+)/.include \"${ my $x=$1; $x =~ s|\.s|-gnu.S|; \$x }\"/; - s/\bIMPORT\b/.extern/; - s/\bEXPORT\b\s*/.global $symprefix/; - s/^(\s+)\[/$1IF/; - s/^(\s+)\|/$1ELSE/; - s/^(\s+)\]/$1ENDIF/; - s/IF *:DEF:/ .ifdef/; - s/IF *:LNOT: *:DEF:/ .ifndef/; - s/ELSE/ .else/; - s/ENDIF/ .endif/; - - if( /\bIF\b/ ) { - s/\bIF\b/ .if/; - s/=/==/; - } - if ( $n == 2) { - s/\$/\\/g; - } - if ($n == 1) { - s/\$//g; - s/label//g; - $n = 2; - } - if ( /MACRO/ ) { - s/MACRO *\n/.macro/; - $n=1; - } - if ( /\bMEND\b/ ) { - s/\bMEND\b/.endm/; - $n=0; - } - - # ".rdata" doesn't work in 'as' version 2.13.2, as it is ".rodata" there. - # - if ( /\bAREA\b/ ) { - my $align; - $align = "2"; - if ( /ALIGN=(\d+)/ ) { - $align = $1; - } - if ( /CODE/ ) { - $nxstack = 1; - } - s/^(.+)CODE(.+)READONLY(.*)/ .text/; - s/^(.+)DATA(.+)READONLY(.*)/ .section .rdata/; - s/^(.+)\|\|\.data\|\|(.+)/ .data/; - s/^(.+)\|\|\.bss\|\|(.+)/ .bss/; - s/$/; .p2align $align/; - # Enable NEON instructions but don't produce a binary that requires - # ARMv7. RVCT does not have equivalent directives, so we just do this - # for all CODE areas. - if ( /.text/ ) { - # Separating .arch, .fpu, etc., by semicolons does not work (gas - # thinks the semicolon is part of the arch name, even when there's - # whitespace separating them). Sadly this means our line numbers - # won't match the original source file (we could use the .line - # directive, which is documented to be obsolete, but then gdb will - # show the wrong line in the translated source file). - s/$/; .arch armv7-a\n .fpu neon\n .object_arch armv4t/ unless ($apple); - } - } - - s/\|\|\.constdata\$(\d+)\|\|/.L_CONST$1/; # ||.constdata$3|| - s/\|\|\.bss\$(\d+)\|\|/.L_BSS$1/; # ||.bss$2|| - s/\|\|\.data\$(\d+)\|\|/.L_DATA$1/; # ||.data$2|| - s/\|\|([a-zA-Z0-9_]+)\@([a-zA-Z0-9_]+)\|\|/@ $&/; - s/^(\s+)\%(\s)/ .space $1/; - - s/\|(.+)\.(\d+)\|/\.$1_$2/; # |L80.123| -> .L80_123 - s/\bCODE32\b/.code 32/ && do {$thumb = 0}; - s/\bCODE16\b/.code 16/ && do {$thumb = 1}; - if (/\bPROC\b/) - { - my $prefix; - my $proc; - /^([A-Za-z_\.]\w+)\b/; - $proc = $1; - $prefix = ""; - if ($proc) - { - $prefix = $prefix.sprintf("\t.type\t%s, %%function; ",$proc) unless ($apple); - # Make sure we $prefix isn't empty here (for the $apple case). - # We handle mangling the label here, make sure it doesn't match - # the label handling below (if $prefix would be empty). - $prefix = "; "; - push(@proc_stack, $proc); - s/^[A-Za-z_\.]\w+/$symprefix$&:/; - } - $prefix = $prefix."\t.thumb_func; " if ($thumb); - s/\bPROC\b/@ $&/; - $_ = $prefix.$_; - } - s/^(\s*)(S|Q|SH|U|UQ|UH)ASX\b/$1$2ADDSUBX/; - s/^(\s*)(S|Q|SH|U|UQ|UH)SAX\b/$1$2SUBADDX/; - if (/\bENDP\b/) - { - my $proc; - s/\bENDP\b/@ $&/; - $proc = pop(@proc_stack); - $_ = "\t.size $proc, .-$proc".$_ if ($proc && !$apple); - } - s/\bSUBT\b/@ $&/; - s/\bDATA\b/@ $&/; # DATA directive is deprecated -- Asm guide, p.7-25 - s/\bKEEP\b/@ $&/; - s/\bEXPORTAS\b/@ $&/; - s/\|\|(.)+\bEQU\b/@ $&/; - s/\|\|([\w\$]+)\|\|/$1/; - s/\bENTRY\b/@ $&/; - s/\bASSERT\b/@ $&/; - s/\bGBLL\b/@ $&/; - s/\bGBLA\b/@ $&/; - s/^\W+OPT\b/@ $&/; - s/:OR:/|/g; - s/:SHL:/<</g; - s/:SHR:/>>/g; - s/:AND:/&/g; - s/:LAND:/&&/g; - s/CPSR/cpsr/; - s/SPSR/spsr/; - s/ALIGN$/.balign 4/; - s/ALIGN\s+([0-9x]+)$/.balign $1/; - s/psr_cxsf/psr_all/; - s/LTORG/.ltorg/; - s/^([A-Za-z_]\w*)[ \t]+EQU/ .set $1,/; - s/^([A-Za-z_]\w*)[ \t]+SETL/ .set $1,/; - s/^([A-Za-z_]\w*)[ \t]+SETA/ .set $1,/; - s/^([A-Za-z_]\w*)[ \t]+\*/ .set $1,/; - - # {PC} + 0xdeadfeed --> . + 0xdeadfeed - s/\{PC\} \+/ \. +/; - - # Single hex constant on the line ! - # - # >>> NOTE <<< - # Double-precision floats in gcc are always mixed-endian, which means - # bytes in two words are little-endian, but words are big-endian. - # So, 0x0000deadfeed0000 would be stored as 0x0000dead at low address - # and 0xfeed0000 at high address. - # - s/\bDCFD\b[ \t]+0x([a-fA-F0-9]{8})([a-fA-F0-9]{8})/.long 0x$1, 0x$2/; - # Only decimal constants on the line, no hex ! - s/\bDCFD\b[ \t]+([0-9\.\-]+)/.double $1/; - - # Single hex constant on the line ! -# s/\bDCFS\b[ \t]+0x([a-f0-9]{8})([a-f0-9]{8})/.long 0x$1, 0x$2/; - # Only decimal constants on the line, no hex ! -# s/\bDCFS\b[ \t]+([0-9\.\-]+)/.double $1/; - s/\bDCFS[ \t]+0x/.word 0x/; - s/\bDCFS\b/.float/; - - s/^([A-Za-z_]\w*)[ \t]+DCD/$1 .word/; - s/\bDCD\b/.word/; - s/^([A-Za-z_]\w*)[ \t]+DCW/$1 .short/; - s/\bDCW\b/.short/; - s/^([A-Za-z_]\w*)[ \t]+DCB/$1 .byte/; - s/\bDCB\b/.byte/; - s/^([A-Za-z_]\w*)[ \t]+\%/.comm $1,/; - s/^[A-Za-z_\.]\w+/$&:/; - s/^(\d+)/$1:/; - s/\%(\d+)/$1b_or_f/; - s/\%[Bb](\d+)/$1b/; - s/\%[Ff](\d+)/$1f/; - s/\%[Ff][Tt](\d+)/$1f/; - s/&([\dA-Fa-f]+)/0x$1/; - if ( /\b2_[01]+\b/ ) { - s/\b2_([01]+)\b/conv$1&&&&/g; - while ( /[01][01][01][01]&&&&/ ) { - s/0000&&&&/&&&&0/g; - s/0001&&&&/&&&&1/g; - s/0010&&&&/&&&&2/g; - s/0011&&&&/&&&&3/g; - s/0100&&&&/&&&&4/g; - s/0101&&&&/&&&&5/g; - s/0110&&&&/&&&&6/g; - s/0111&&&&/&&&&7/g; - s/1000&&&&/&&&&8/g; - s/1001&&&&/&&&&9/g; - s/1010&&&&/&&&&A/g; - s/1011&&&&/&&&&B/g; - s/1100&&&&/&&&&C/g; - s/1101&&&&/&&&&D/g; - s/1110&&&&/&&&&E/g; - s/1111&&&&/&&&&F/g; - } - s/000&&&&/&&&&0/g; - s/001&&&&/&&&&1/g; - s/010&&&&/&&&&2/g; - s/011&&&&/&&&&3/g; - s/100&&&&/&&&&4/g; - s/101&&&&/&&&&5/g; - s/110&&&&/&&&&6/g; - s/111&&&&/&&&&7/g; - s/00&&&&/&&&&0/g; - s/01&&&&/&&&&1/g; - s/10&&&&/&&&&2/g; - s/11&&&&/&&&&3/g; - s/0&&&&/&&&&0/g; - s/1&&&&/&&&&1/g; - s/conv&&&&/0x/g; - } - - if ( /commandline/) - { - if( /-bigend/) - { - $bigend=1; - } - } - - if ( /\bDCDU\b/ ) - { - my $cmd=$_; - my $value; - my $prefix; - my $w1; - my $w2; - my $w3; - my $w4; - - s/\s+DCDU\b/@ $&/; - - $cmd =~ /\bDCDU\b\s+0x(\d+)/; - $value = $1; - $value =~ /(\w\w)(\w\w)(\w\w)(\w\w)/; - $w1 = $1; - $w2 = $2; - $w3 = $3; - $w4 = $4; - - if( $bigend ne "") - { - # big endian - $prefix = "\t.byte\t0x".$w1.";". - "\t.byte\t0x".$w2.";". - "\t.byte\t0x".$w3.";". - "\t.byte\t0x".$w4."; "; - } - else - { - # little endian - $prefix = "\t.byte\t0x".$w4.";". - "\t.byte\t0x".$w3.";". - "\t.byte\t0x".$w2.";". - "\t.byte\t0x".$w1."; "; - } - $_=$prefix.$_; - } - - if ( /\badrl\b/i ) - { - s/\badrl\s+(\w+)\s*,\s*(\w+)/ldr $1,=$2/i; - $addPadding = 1; - } - s/\bEND\b/@ END/; -} continue { - printf ("%s", $_) if $printit; - if ($addPadding != 0) - { - printf (" mov r0,r0\n"); - $addPadding = 0; - } -} -#If we had a code section, mark that this object doesn't need an executable -# stack. -if ($nxstack && !$apple) { - printf (" .section\t.note.GNU-stack,\"\",\%\%progbits\n"); -} diff --git a/thirdparty/pcre2/AUTHORS b/thirdparty/pcre2/AUTHORS index 8d4e15a247..f001cb770e 100644 --- a/thirdparty/pcre2/AUTHORS +++ b/thirdparty/pcre2/AUTHORS @@ -2,13 +2,13 @@ THE MAIN PCRE2 LIBRARY CODE --------------------------- Written by: Philip Hazel -Email local part: ph10 -Email domain: cam.ac.uk +Email local part: Philip.Hazel +Email domain: gmail.com University of Cambridge Computing Service, Cambridge, England. -Copyright (c) 1997-2019 University of Cambridge +Copyright (c) 1997-2020 University of Cambridge All rights reserved @@ -19,7 +19,7 @@ Written by: Zoltan Herczeg Email local part: hzmester Emain domain: freemail.hu -Copyright(c) 2010-2019 Zoltan Herczeg +Copyright(c) 2010-2020 Zoltan Herczeg All rights reserved. @@ -30,7 +30,7 @@ Written by: Zoltan Herczeg Email local part: hzmester Emain domain: freemail.hu -Copyright(c) 2009-2019 Zoltan Herczeg +Copyright(c) 2009-2020 Zoltan Herczeg All rights reserved. #### diff --git a/thirdparty/pcre2/LICENCE b/thirdparty/pcre2/LICENCE index 142b3b3f9a..155d073127 100644 --- a/thirdparty/pcre2/LICENCE +++ b/thirdparty/pcre2/LICENCE @@ -20,13 +20,13 @@ THE BASIC LIBRARY FUNCTIONS --------------------------- Written by: Philip Hazel -Email local part: ph10 -Email domain: cam.ac.uk +Email local part: Philip.Hazel +Email domain: gmail.com University of Cambridge Computing Service, Cambridge, England. -Copyright (c) 1997-2019 University of Cambridge +Copyright (c) 1997-2020 University of Cambridge All rights reserved. @@ -37,7 +37,7 @@ Written by: Zoltan Herczeg Email local part: hzmester Email domain: freemail.hu -Copyright(c) 2010-2019 Zoltan Herczeg +Copyright(c) 2010-2020 Zoltan Herczeg All rights reserved. @@ -48,7 +48,7 @@ Written by: Zoltan Herczeg Email local part: hzmester Email domain: freemail.hu -Copyright(c) 2009-2019 Zoltan Herczeg +Copyright(c) 2009-2020 Zoltan Herczeg All rights reserved. diff --git a/thirdparty/pcre2/src/config.h b/thirdparty/pcre2/src/config.h index 787bb9c999..10f4104790 100644 --- a/thirdparty/pcre2/src/config.h +++ b/thirdparty/pcre2/src/config.h @@ -52,6 +52,9 @@ sure both macros are undefined; an emulation function will then be used. */ LF does in an ASCII/Unicode environment. */ /* #undef EBCDIC_NL25 */ +/* Define this if your compiler supports __attribute__((uninitialized)) */ +/* #undef HAVE_ATTRIBUTE_UNINITIALIZED */ + /* Define to 1 if you have the `bcopy' function. */ /* #undef HAVE_BCOPY */ @@ -76,6 +79,9 @@ sure both macros are undefined; an emulation function will then be used. */ /* Define to 1 if you have the <limits.h> header file. */ /* #undef HAVE_LIMITS_H */ +/* Define to 1 if you have the `memfd_create' function. */ +/* #undef HAVE_MEMFD_CREATE */ + /* Define to 1 if you have the `memmove' function. */ /* #undef HAVE_MEMMOVE */ @@ -218,7 +224,7 @@ sure both macros are undefined; an emulation function will then be used. */ #define PACKAGE_NAME "PCRE2" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "PCRE2 10.34" +#define PACKAGE_STRING "PCRE2 10.36" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "pcre2" @@ -227,7 +233,7 @@ sure both macros are undefined; an emulation function will then be used. */ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "10.34" +#define PACKAGE_VERSION "10.36" /* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested parentheses (of any kind) in a pattern. This limits the amount of system @@ -352,7 +358,7 @@ sure both macros are undefined; an emulation function will then be used. */ #endif /* Version number of package */ -#define VERSION "10.34" +#define VERSION "10.36" /* Define to 1 if on MINIX. */ /* #undef _MINIX */ diff --git a/thirdparty/pcre2/src/pcre2.h b/thirdparty/pcre2/src/pcre2.h index cb9d61a35b..f204ec8180 100644 --- a/thirdparty/pcre2/src/pcre2.h +++ b/thirdparty/pcre2/src/pcre2.h @@ -5,7 +5,7 @@ /* This is the public header file for the PCRE library, second API, to be #included by applications that call PCRE2 functions. - Copyright (c) 2016-2019 University of Cambridge + Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE. /* The current PCRE version information. */ #define PCRE2_MAJOR 10 -#define PCRE2_MINOR 34 +#define PCRE2_MINOR 36 #define PCRE2_PRERELEASE -#define PCRE2_DATE 2019-11-21 +#define PCRE2_DATE 2020-12-04 /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE2, the appropriate @@ -181,6 +181,9 @@ pcre2_jit_match() ignores the latter since it bypasses all sanity checks). */ #define PCRE2_SUBSTITUTE_OVERFLOW_LENGTH 0x00001000u /* pcre2_substitute() only */ #define PCRE2_NO_JIT 0x00002000u /* Not for pcre2_dfa_match() */ #define PCRE2_COPY_MATCHED_SUBJECT 0x00004000u +#define PCRE2_SUBSTITUTE_LITERAL 0x00008000u /* pcre2_substitute() only */ +#define PCRE2_SUBSTITUTE_MATCHED 0x00010000u /* pcre2_substitute() only */ +#define PCRE2_SUBSTITUTE_REPLACEMENT_ONLY 0x00020000u /* pcre2_substitute() only */ /* Options for pcre2_pattern_convert(). */ @@ -445,6 +448,7 @@ released, the numbers must not be changed. */ #define PCRE2_CONFIG_HEAPLIMIT 12 #define PCRE2_CONFIG_NEVER_BACKSLASH_C 13 #define PCRE2_CONFIG_COMPILED_WIDTHS 14 +#define PCRE2_CONFIG_TABLES_LENGTH 15 /* Types for code units in patterns and subject strings. */ diff --git a/thirdparty/pcre2/src/pcre2_auto_possess.c b/thirdparty/pcre2/src/pcre2_auto_possess.c index 5b95b9b8a8..c64cf856d1 100644 --- a/thirdparty/pcre2/src/pcre2_auto_possess.c +++ b/thirdparty/pcre2/src/pcre2_auto_possess.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2019 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -292,6 +292,7 @@ possessification, and if so, fills a list with its properties. Arguments: code points to start of expression utf TRUE if in UTF mode + ucp TRUE if in UCP mode fcc points to the case-flipping table list points to output list list[0] will be filled with the opcode @@ -304,7 +305,7 @@ Returns: points to the start of the next opcode if *code is accepted */ static PCRE2_SPTR -get_chr_property_list(PCRE2_SPTR code, BOOL utf, const uint8_t *fcc, +get_chr_property_list(PCRE2_SPTR code, BOOL utf, BOOL ucp, const uint8_t *fcc, uint32_t *list) { PCRE2_UCHAR c = *code; @@ -316,7 +317,8 @@ uint32_t chr; uint32_t *clist_dest; const uint32_t *clist_src; #else -(void)utf; /* Suppress "unused parameter" compiler warning */ +(void)utf; /* Suppress "unused parameter" compiler warnings */ +(void)ucp; #endif list[0] = c; @@ -396,7 +398,7 @@ switch(c) list[2] = chr; #ifdef SUPPORT_UNICODE - if (chr < 128 || (chr < 256 && !utf)) + if (chr < 128 || (chr < 256 && !utf && !ucp)) list[3] = fcc[chr]; else list[3] = UCD_OTHERCASE(chr); @@ -503,6 +505,7 @@ which case the base cannot be possessified. Arguments: code points to the byte code utf TRUE in UTF mode + ucp TRUE in UCP mode cb compile data block base_list the data list of the base opcode base_end the end of the base opcode @@ -512,7 +515,7 @@ Returns: TRUE if the auto-possessification is possible */ static BOOL -compare_opcodes(PCRE2_SPTR code, BOOL utf, const compile_block *cb, +compare_opcodes(PCRE2_SPTR code, BOOL utf, BOOL ucp, const compile_block *cb, const uint32_t *base_list, PCRE2_SPTR base_end, int *rec_limit) { PCRE2_UCHAR c; @@ -651,7 +654,7 @@ for(;;) while (*next_code == OP_ALT) { - if (!compare_opcodes(code, utf, cb, base_list, base_end, rec_limit)) + if (!compare_opcodes(code, utf, ucp, cb, base_list, base_end, rec_limit)) return FALSE; code = next_code + 1 + LINK_SIZE; next_code += GET(next_code, 1); @@ -672,7 +675,8 @@ for(;;) /* The bracket content will be checked by the OP_BRA/OP_CBRA case above. */ next_code += 1 + LINK_SIZE; - if (!compare_opcodes(next_code, utf, cb, base_list, base_end, rec_limit)) + if (!compare_opcodes(next_code, utf, ucp, cb, base_list, base_end, + rec_limit)) return FALSE; code += PRIV(OP_lengths)[c]; @@ -688,7 +692,7 @@ for(;;) /* We now have the next appropriate opcode to compare with the base. Check for a supported opcode, and load its properties. */ - code = get_chr_property_list(code, utf, cb->fcc, list); + code = get_chr_property_list(code, utf, ucp, cb->fcc, list); if (code == NULL) return FALSE; /* Unsupported */ /* If either opcode is a small character list, set pointers for comparing @@ -1100,7 +1104,6 @@ leaving the remainder of the pattern unpossessified. Arguments: code points to start of the byte code - utf TRUE in UTF mode cb compile data block Returns: 0 for success @@ -1108,13 +1111,15 @@ Returns: 0 for success */ int -PRIV(auto_possessify)(PCRE2_UCHAR *code, BOOL utf, const compile_block *cb) +PRIV(auto_possessify)(PCRE2_UCHAR *code, const compile_block *cb) { PCRE2_UCHAR c; PCRE2_SPTR end; PCRE2_UCHAR *repeat_opcode; uint32_t list[8]; int rec_limit = 1000; /* Was 10,000 but clang+ASAN uses a lot of stack. */ +BOOL utf = (cb->external_options & PCRE2_UTF) != 0; +BOOL ucp = (cb->external_options & PCRE2_UCP) != 0; for (;;) { @@ -1126,10 +1131,11 @@ for (;;) { c -= get_repeat_base(c) - OP_STAR; end = (c <= OP_MINUPTO) ? - get_chr_property_list(code, utf, cb->fcc, list) : NULL; + get_chr_property_list(code, utf, ucp, cb->fcc, list) : NULL; list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO; - if (end != NULL && compare_opcodes(end, utf, cb, list, end, &rec_limit)) + if (end != NULL && compare_opcodes(end, utf, ucp, cb, list, end, + &rec_limit)) { switch(c) { @@ -1181,11 +1187,11 @@ for (;;) if (c >= OP_CRSTAR && c <= OP_CRMINRANGE) { /* end must not be NULL. */ - end = get_chr_property_list(code, utf, cb->fcc, list); + end = get_chr_property_list(code, utf, ucp, cb->fcc, list); list[1] = (c & 1) == 0; - if (compare_opcodes(end, utf, cb, list, end, &rec_limit)) + if (compare_opcodes(end, utf, ucp, cb, list, end, &rec_limit)) { switch (c) { diff --git a/thirdparty/pcre2/src/pcre2_chartables.c b/thirdparty/pcre2/src/pcre2_chartables.c index 0e07edb494..861914d1ac 100644 --- a/thirdparty/pcre2/src/pcre2_chartables.c +++ b/thirdparty/pcre2/src/pcre2_chartables.c @@ -2,17 +2,21 @@ * Perl-Compatible Regular Expressions * *************************************************/ -/* This file was automatically written by the dftables auxiliary +/* This file was automatically written by the pcre2_dftables auxiliary program. It contains character tables that are used when no external tables are passed to PCRE2 by the application that calls it. The tables are used only for characters whose code values are less than 256. */ -/*The dftables program (which is distributed with PCRE2) can be used to -build alternative versions of this file. This is necessary if you are +/* This set of tables was written in the C locale. */ + +/* The pcre2_ftables program (which is distributed with PCRE2) can be used +to build alternative versions of this file. This is necessary if you are running in an EBCDIC environment, or if you want to default to a different -encoding, for example ISO-8859-1. When dftables is run, it creates these -tables in the current locale. This happens automatically if PCRE2 is -configured with --enable-rebuild-chartables. */ +encoding, for example ISO-8859-1. When pcre2_dftables is run, it creates +these tables in the "C" locale by default. This happens automatically if +PCRE2 is configured with --enable-rebuild-chartables. However, you can run +pcre2_dftables manually with the -L option to build tables using the LC_ALL +locale. */ /* The following #include is present because without it gcc 4.x may remove the array definition from the final binary if PCRE2 is built into a static @@ -102,54 +106,54 @@ const uint8_t PRIV(default_tables)[] = { /* This table contains bit maps for various character classes. Each map is 32 bytes long and the bits run from the least significant end of each byte. The classes that have their own maps are: space, xdigit, digit, upper, lower, word, -graph print, punct, and cntrl. Other classes are built from combinations. */ +graph, print, punct, and cntrl. Other classes are built from combinations. */ - 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00, + 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00, /* space */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, /* xdigit */ 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, /* digit */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* upper */ 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* lower */ 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03, /* word */ 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff, /* graph */ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, /* print */ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc, + 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc, /* punct */ 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, /* cntrl */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, diff --git a/thirdparty/pcre2/src/pcre2_compile.c b/thirdparty/pcre2/src/pcre2_compile.c index f2e6b6b5bd..e811f12f02 100644 --- a/thirdparty/pcre2/src/pcre2_compile.c +++ b/thirdparty/pcre2/src/pcre2_compile.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2019 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -1202,7 +1202,7 @@ in the decoded tables. */ if ((code->flags & PCRE2_DEREF_TABLES) != 0) { - ref_count = (PCRE2_SIZE *)(code->tables + tables_length); + ref_count = (PCRE2_SIZE *)(code->tables + TABLES_LENGTH); (*ref_count)++; } @@ -1232,15 +1232,15 @@ if (newcode == NULL) return NULL; memcpy(newcode, code, code->blocksize); newcode->executable_jit = NULL; -newtables = code->memctl.malloc(tables_length + sizeof(PCRE2_SIZE), +newtables = code->memctl.malloc(TABLES_LENGTH + sizeof(PCRE2_SIZE), code->memctl.memory_data); if (newtables == NULL) { code->memctl.free((void *)newcode, code->memctl.memory_data); return NULL; } -memcpy(newtables, code->tables, tables_length); -ref_count = (PCRE2_SIZE *)(newtables + tables_length); +memcpy(newtables, code->tables, TABLES_LENGTH); +ref_count = (PCRE2_SIZE *)(newtables + TABLES_LENGTH); *ref_count = 1; newcode->tables = newtables; @@ -1270,7 +1270,7 @@ if (code != NULL) be freed when there are no more references to them. The *ref_count should always be > 0. */ - ref_count = (PCRE2_SIZE *)(code->tables + tables_length); + ref_count = (PCRE2_SIZE *)(code->tables + TABLES_LENGTH); if (*ref_count > 0) { (*ref_count)--; @@ -2344,7 +2344,7 @@ if (ptr > *nameptr + MAX_NAME_SIZE) *errorcodeptr = ERR48; goto FAILED; } -*namelenptr = ptr - *nameptr; +*namelenptr = (uint32_t)(ptr - *nameptr); /* Subpattern names must not be empty, and their terminator is checked here. (What follows a verb or alpha assertion name is checked separately.) */ @@ -3653,7 +3653,7 @@ while (ptr < ptrend) if (ptr >= ptrend) goto UNCLOSED_PARENTHESIS; /* If ( is not followed by ? it is either a capture or a special verb or an - alpha assertion. */ + alpha assertion or a positive non-atomic lookahead. */ if (*ptr != CHAR_QUESTION_MARK) { @@ -3685,10 +3685,10 @@ while (ptr < ptrend) break; /* Handle "alpha assertions" such as (*pla:...). Most of these are - synonyms for the historical symbolic assertions, but the script run ones - are new. They are distinguished by starting with a lower case letter. - Checking both ends of the alphabet makes this work in all character - codes. */ + synonyms for the historical symbolic assertions, but the script run and + non-atomic lookaround ones are new. They are distinguished by starting + with a lower case letter. Checking both ends of the alphabet makes this + work in all character codes. */ else if (CHMAX_255(c) && (cb->ctypes[c] & ctype_lcletter) != 0) { @@ -3747,9 +3747,7 @@ while (ptr < ptrend) goto POSITIVE_LOOK_AHEAD; case META_LOOKAHEAD_NA: - *parsed_pattern++ = meta; - ptr++; - goto POST_ASSERTION; + goto POSITIVE_NONATOMIC_LOOK_AHEAD; case META_LOOKAHEADNOT: goto NEGATIVE_LOOK_AHEAD; @@ -4333,6 +4331,7 @@ while (ptr < ptrend) { 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; @@ -4438,6 +4437,12 @@ while (ptr < ptrend) ptr++; goto POST_ASSERTION; + case CHAR_ASTERISK: + POSITIVE_NONATOMIC_LOOK_AHEAD: /* Come from (?* */ + *parsed_pattern++ = META_LOOKAHEAD_NA; + ptr++; + goto POST_ASSERTION; + case CHAR_EXCLAMATION_MARK: NEGATIVE_LOOK_AHEAD: /* Come from (*nla: */ *parsed_pattern++ = META_LOOKAHEADNOT; @@ -4447,20 +4452,23 @@ while (ptr < ptrend) /* ---- Lookbehind assertions ---- */ - /* (?< followed by = or ! is a lookbehind assertion. Otherwise (?< is the - start of the name of a capturing group. */ + /* (?< followed by = or ! or * is a lookbehind assertion. Otherwise (?< + is the start of the name of a capturing group. */ case CHAR_LESS_THAN_SIGN: if (ptrend - ptr <= 1 || - (ptr[1] != CHAR_EQUALS_SIGN && ptr[1] != CHAR_EXCLAMATION_MARK)) + (ptr[1] != CHAR_EQUALS_SIGN && + ptr[1] != CHAR_EXCLAMATION_MARK && + ptr[1] != CHAR_ASTERISK)) { terminator = CHAR_GREATER_THAN_SIGN; goto DEFINE_NAME; } *parsed_pattern++ = (ptr[1] == CHAR_EQUALS_SIGN)? - META_LOOKBEHIND : META_LOOKBEHINDNOT; + META_LOOKBEHIND : (ptr[1] == CHAR_EXCLAMATION_MARK)? + META_LOOKBEHINDNOT : META_LOOKBEHIND_NA; - POST_LOOKBEHIND: /* Come from (*plb: (*naplb: and (*nlb: */ + POST_LOOKBEHIND: /* Come from (*plb: (*naplb: and (*nlb: */ *has_lookbehind = TRUE; offset = (PCRE2_SIZE)(ptr - cb->start_pattern - 2); PUTOFFSET(offset, parsed_pattern); @@ -4633,8 +4641,6 @@ while (ptr < ptrend) *parsed_pattern++ = META_KET; } - - if (top_nest == (nest_save *)(cb->start_workspace)) top_nest = NULL; else top_nest--; } @@ -4899,7 +4905,7 @@ range. */ if ((options & PCRE2_CASELESS) != 0) { #ifdef SUPPORT_UNICODE - if ((options & PCRE2_UTF) != 0) + if ((options & (PCRE2_UTF|PCRE2_UCP)) != 0) { int rc; uint32_t oc, od; @@ -5314,7 +5320,8 @@ dynamically as we process the pattern. */ #ifdef SUPPORT_UNICODE BOOL utf = (options & PCRE2_UTF) != 0; -#else /* No UTF support */ +BOOL ucp = (options & PCRE2_UCP) != 0; +#else /* No Unicode support */ BOOL utf = FALSE; #endif @@ -5559,12 +5566,12 @@ for (;; pptr++) zerofirstcu = firstcu; zerofirstcuflags = firstcuflags; - /* For caseless UTF mode, check whether this character has more than - one other case. If so, generate a special OP_NOTPROP item instead of + /* For caseless UTF or UCP mode, check whether this character has more + than one other case. If so, generate a special OP_NOTPROP item instead of OP_NOTI. */ #ifdef SUPPORT_UNICODE - if (utf && (options & PCRE2_CASELESS) != 0 && + if ((utf||ucp) && (options & PCRE2_CASELESS) != 0 && (d = UCD_CASESET(c)) != 0) { *code++ = OP_NOTPROP; @@ -5597,7 +5604,7 @@ for (;; pptr++) uint32_t d; #ifdef SUPPORT_UNICODE - if (utf && c > 127) d = UCD_OTHERCASE(c); else + if ((utf || ucp) && c > 127) d = UCD_OTHERCASE(c); else #endif { #if PCRE2_CODE_UNIT_WIDTH != 8 @@ -6671,23 +6678,11 @@ for (;; pptr++) } /* For a back reference, update the back reference map and the - maximum back reference. Then, for each group, we must check to - see if it is recursive, that is, it is inside the group that it - references. A flag is set so that the group can be made atomic. - */ + maximum back reference. */ cb->backref_map |= (groupnumber < 32)? (1u << groupnumber) : 1; if (groupnumber > cb->top_backref) cb->top_backref = groupnumber; - - for (oc = cb->open_caps; oc != NULL; oc = oc->next) - { - if (oc->number == groupnumber) - { - oc->flag = TRUE; - break; - } - } } } @@ -7081,15 +7076,18 @@ for (;; pptr++) previous[GET(previous, 1)] != OP_ALT) goto END_REPEAT; - /* There is no sense in actually repeating assertions. The only - potential use of repetition is in cases when the assertion is optional. - Therefore, if the minimum is greater than zero, just ignore the repeat. - If the maximum is not zero or one, set it to 1. */ + /* Perl allows all assertions to be quantified, and when they contain + capturing parentheses and/or are optional there are potential uses for + this feature. PCRE2 used to force the maximum quantifier to 1 on the + invalid grounds that further repetition was never useful. This was + always a bit pointless, since an assertion could be wrapped with a + repeated group to achieve the effect. General repetition is now + permitted, but if the maximum is unlimited it is set to one more than + the minimum. */ if (op_previous < OP_ONCE) /* Assertion */ { - if (repeat_min > 0) goto END_REPEAT; - if (repeat_max > 1) repeat_max = 1; + if (repeat_max == REPEAT_UNLIMITED) repeat_max = repeat_min + 1; } /* The case of a zero minimum is special because of the need to stick @@ -7682,19 +7680,6 @@ for (;; pptr++) cb->backref_map |= (meta_arg < 32)? (1u << meta_arg) : 1; if (meta_arg > cb->top_backref) cb->top_backref = meta_arg; - - /* Check to see if this back reference is recursive, that it, it - is inside the group that it references. A flag is set so that the - group can be made atomic. */ - - for (oc = cb->open_caps; oc != NULL; oc = oc->next) - { - if (oc->number == meta_arg) - { - oc->flag = TRUE; - break; - } - } break; @@ -7840,11 +7825,12 @@ for (;; pptr++) NORMAL_CHAR_SET: /* Character is already in meta */ matched_char = TRUE; - /* For caseless UTF mode, check whether this character has more than one - other case. If so, generate a special OP_PROP item instead of OP_CHARI. */ + /* For caseless UTF or UCP mode, check whether this character has more than + one other case. If so, generate a special OP_PROP item instead of OP_CHARI. + */ #ifdef SUPPORT_UNICODE - if (utf && (options & PCRE2_CASELESS) != 0) + if ((utf||ucp) && (options & PCRE2_CASELESS) != 0) { uint32_t caseset = UCD_CASESET(meta); if (caseset != 0) @@ -8053,7 +8039,6 @@ if (*code == OP_CBRA) capnumber = GET2(code, 1 + LINK_SIZE); capitem.number = capnumber; capitem.next = cb->open_caps; - capitem.flag = FALSE; capitem.assert_depth = cb->assert_depth; cb->open_caps = &capitem; } @@ -8182,26 +8167,9 @@ for (;;) PUT(code, 1, (int)(code - start_bracket)); code += 1 + LINK_SIZE; - /* If it was a capturing subpattern, check to see if it contained any - recursive back references. If so, we must wrap it in atomic brackets. In - any event, remove the block from the chain. */ + /* If it was a capturing subpattern, remove the block from the chain. */ - if (capnumber > 0) - { - if (cb->open_caps->flag) - { - (void)memmove(start_bracket + 1 + LINK_SIZE, start_bracket, - CU2BYTES(code - start_bracket)); - *start_bracket = OP_ONCE; - code += 1 + LINK_SIZE; - PUT(start_bracket, 1, (int)(code - start_bracket)); - *code = OP_KET; - PUT(code, 1, (int)(code - start_bracket)); - code += 1 + LINK_SIZE; - length += 2 + 2*LINK_SIZE; - } - cb->open_caps = cb->open_caps->next; - } + if (capnumber > 0) cb->open_caps = cb->open_caps->next; /* Set values to pass back */ @@ -8836,9 +8804,10 @@ memset(slot + IMM2_SIZE + length, 0, /* This function is called to skip parts of the parsed pattern when finding the length of a lookbehind branch. It is called after (*ACCEPT) and (*FAIL) to find -the end of the branch, it is called to skip over an internal lookaround, and it -is also called to skip to the end of a class, during which it will never -encounter nested groups (but there's no need to have special code for that). +the end of the branch, it is called to skip over an internal lookaround or +(DEFINE) group, and it is also called to skip to the end of a class, during +which it will never encounter nested groups (but there's no need to have +special code for that). When called to find the end of a branch or group, pptr must point to the first meta code inside the branch, not the branch-starting code. In other cases it @@ -9316,14 +9285,21 @@ for (;; pptr++) itemlength = grouplength; break; - /* Check nested groups - advance past the initial data for each type and - then seek a fixed length with get_grouplength(). */ + /* A (DEFINE) group is never obeyed inline and so it does not contribute to + the length of this branch. Skip from the following item to the next + unpaired ket. */ + + case META_COND_DEFINE: + pptr = parsed_skip(pptr + 1, PSKIP_KET); + break; + + /* Check other nested groups - advance past the initial data for each type + and then seek a fixed length with get_grouplength(). */ case META_COND_NAME: case META_COND_NUMBER: case META_COND_RNAME: case META_COND_RNUMBER: - case META_COND_DEFINE: pptr += 2 + SIZEOFFSET; goto CHECK_GROUP; @@ -9580,6 +9556,10 @@ for (; *pptr != META_END; pptr++) break; case META_COND_DEFINE: + pptr += SIZEOFFSET; + nestlevel++; + break; + case META_COND_NAME: case META_COND_NUMBER: case META_COND_RNAME: @@ -9660,6 +9640,7 @@ pcre2_compile(PCRE2_SPTR pattern, PCRE2_SIZE patlen, uint32_t options, int *errorptr, PCRE2_SIZE *erroroffset, pcre2_compile_context *ccontext) { BOOL utf; /* Set TRUE for UTF mode */ +BOOL ucp; /* Set TRUE for UCP mode */ BOOL has_lookbehind = FALSE; /* Set TRUE if a lookbehind is found */ BOOL zero_terminated; /* Set TRUE for zero-terminated pattern */ pcre2_real_code *re = NULL; /* What we will return */ @@ -9947,8 +9928,8 @@ if (utf) /* Check UCP lockout. */ -if ((cb.external_options & (PCRE2_UCP|PCRE2_NEVER_UCP)) == - (PCRE2_UCP|PCRE2_NEVER_UCP)) +ucp = (cb.external_options & PCRE2_UCP) != 0; +if (ucp && (cb.external_options & PCRE2_NEVER_UCP) != 0) { errorcode = ERR75; goto HAD_EARLY_ERROR; @@ -10324,7 +10305,7 @@ function call. */ if (errorcode == 0 && (re->overall_options & PCRE2_NO_AUTO_POSSESS) == 0) { PCRE2_UCHAR *temp = (PCRE2_UCHAR *)codestart; - if (PRIV(auto_possessify)(temp, utf, &cb) != 0) errorcode = ERR80; + if (PRIV(auto_possessify)(temp, &cb) != 0) errorcode = ERR80; } /* Failed to compile, or error while post-processing. */ @@ -10372,21 +10353,25 @@ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0) if ((firstcuflags & REQ_CASELESS) != 0) { - if (firstcu < 128 || (!utf && firstcu < 255)) + if (firstcu < 128 || (!utf && !ucp && firstcu < 255)) { if (cb.fcc[firstcu] != firstcu) re->flags |= PCRE2_FIRSTCASELESS; } - /* The first code unit is > 128 in UTF mode, or > 255 otherwise. In - 8-bit UTF mode, codepoints in the range 128-255 are introductory code - points and cannot have another case. In 16-bit and 32-bit modes, we can - check wide characters when UTF (and therefore UCP) is supported. */ + /* The first code unit is > 128 in UTF or UCP mode, or > 255 otherwise. + In 8-bit UTF mode, codepoints in the range 128-255 are introductory code + points and cannot have another case, but if UCP is set they may do. */ -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 - else if (firstcu <= MAX_UTF_CODE_POINT && +#ifdef SUPPORT_UNICODE +#if PCRE2_CODE_UNIT_WIDTH == 8 + else if (ucp && !utf && UCD_OTHERCASE(firstcu) != firstcu) + re->flags |= PCRE2_FIRSTCASELESS; +#else + else if ((utf || ucp) && firstcu <= MAX_UTF_CODE_POINT && UCD_OTHERCASE(firstcu) != firstcu) re->flags |= PCRE2_FIRSTCASELESS; #endif +#endif /* SUPPORT_UNICODE */ } } @@ -10435,14 +10420,20 @@ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0) if ((reqcuflags & REQ_CASELESS) != 0) { - if (reqcu < 128 || (!utf && reqcu < 255)) + if (reqcu < 128 || (!utf && !ucp && reqcu < 255)) { if (cb.fcc[reqcu] != reqcu) re->flags |= PCRE2_LASTCASELESS; } -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 - else if (reqcu <= MAX_UTF_CODE_POINT && UCD_OTHERCASE(reqcu) != reqcu) - re->flags |= PCRE2_LASTCASELESS; +#ifdef SUPPORT_UNICODE +#if PCRE2_CODE_UNIT_WIDTH == 8 + else if (ucp && !utf && UCD_OTHERCASE(reqcu) != reqcu) + re->flags |= PCRE2_LASTCASELESS; +#else + else if ((utf || ucp) && reqcu <= MAX_UTF_CODE_POINT && + UCD_OTHERCASE(reqcu) != reqcu) + re->flags |= PCRE2_LASTCASELESS; #endif +#endif /* SUPPORT_UNICODE */ } } } diff --git a/thirdparty/pcre2/src/pcre2_config.c b/thirdparty/pcre2/src/pcre2_config.c index e487b10220..5ef103caf7 100644 --- a/thirdparty/pcre2/src/pcre2_config.c +++ b/thirdparty/pcre2/src/pcre2_config.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2017 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -43,7 +43,8 @@ POSSIBILITY OF SUCH DAMAGE. #endif /* Save the configured link size, which is in bytes. In 16-bit and 32-bit modes -its value gets changed by pcre2_internal.h to be in code units. */ +its value gets changed by pcre2_intmodedep.h (included by pcre2_internal.h) to +be in code units. */ static int configured_link_size = LINK_SIZE; @@ -94,6 +95,7 @@ if (where == NULL) /* Requests a length */ case PCRE2_CONFIG_NEWLINE: case PCRE2_CONFIG_PARENSLIMIT: case PCRE2_CONFIG_STACKRECURSE: /* Obsolete */ + case PCRE2_CONFIG_TABLES_LENGTH: case PCRE2_CONFIG_UNICODE: return sizeof(uint32_t); @@ -191,6 +193,10 @@ switch (what) *((uint32_t *)where) = 0; break; + case PCRE2_CONFIG_TABLES_LENGTH: + *((uint32_t *)where) = TABLES_LENGTH; + break; + case PCRE2_CONFIG_UNICODE_VERSION: { #if defined SUPPORT_UNICODE diff --git a/thirdparty/pcre2/src/pcre2_dfa_match.c b/thirdparty/pcre2/src/pcre2_dfa_match.c index 7d8ffe8a3e..625695b7cb 100644 --- a/thirdparty/pcre2/src/pcre2_dfa_match.c +++ b/thirdparty/pcre2/src/pcre2_dfa_match.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2019 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -548,6 +548,7 @@ PCRE2_SPTR start_code = mb->start_code; #ifdef SUPPORT_UNICODE BOOL utf = (mb->poptions & PCRE2_UTF) != 0; +BOOL utf_or_ucp = utf || (mb->poptions & PCRE2_UCP) != 0; #else BOOL utf = FALSE; #endif @@ -2190,7 +2191,7 @@ for (;;) if (clen == 0) break; #ifdef SUPPORT_UNICODE - if (utf) + if (utf_or_ucp) { if (c == d) { ADD_NEW(state_offset + dlen + 1, 0); } else { @@ -2204,7 +2205,7 @@ for (;;) } else #endif /* SUPPORT_UNICODE */ - /* Not UTF mode */ + /* Not UTF or UCP mode */ { if (TABLE_GET(c, lcc, c) == TABLE_GET(d, lcc, d)) { ADD_NEW(state_offset + 2, 0); } @@ -2339,7 +2340,7 @@ for (;;) { uint32_t otherd; #ifdef SUPPORT_UNICODE - if (utf && d >= 128) + if (utf_or_ucp && d >= 128) otherd = UCD_OTHERCASE(d); else #endif /* SUPPORT_UNICODE */ @@ -2374,7 +2375,7 @@ for (;;) if (caseless) { #ifdef SUPPORT_UNICODE - if (utf && d >= 128) + if (utf_or_ucp && d >= 128) otherd = UCD_OTHERCASE(d); else #endif /* SUPPORT_UNICODE */ @@ -2417,7 +2418,7 @@ for (;;) if (caseless) { #ifdef SUPPORT_UNICODE - if (utf && d >= 128) + if (utf_or_ucp && d >= 128) otherd = UCD_OTHERCASE(d); else #endif /* SUPPORT_UNICODE */ @@ -2458,7 +2459,7 @@ for (;;) if (caseless) { #ifdef SUPPORT_UNICODE - if (utf && d >= 128) + if (utf_or_ucp && d >= 128) otherd = UCD_OTHERCASE(d); else #endif /* SUPPORT_UNICODE */ @@ -2491,7 +2492,7 @@ for (;;) if (caseless) { #ifdef SUPPORT_UNICODE - if (utf && d >= 128) + if (utf_or_ucp && d >= 128) otherd = UCD_OTHERCASE(d); else #endif /* SUPPORT_UNICODE */ @@ -2531,7 +2532,7 @@ for (;;) if (caseless) { #ifdef SUPPORT_UNICODE - if (utf && d >= 128) + if (utf_or_ucp && d >= 128) otherd = UCD_OTHERCASE(d); else #endif /* SUPPORT_UNICODE */ @@ -3526,10 +3527,15 @@ if ((re->flags & PCRE2_FIRSTSET) != 0) if ((re->flags & PCRE2_FIRSTCASELESS) != 0) { first_cu2 = TABLE_GET(first_cu, mb->tables + fcc_offset, first_cu); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 - if (utf && first_cu > 127) +#ifdef SUPPORT_UNICODE +#if PCRE2_CODE_UNIT_WIDTH == 8 + if (first_cu > 127 && !utf && (re->overall_options & PCRE2_UCP) != 0) + first_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(first_cu); +#else + if (first_cu > 127 && (utf || (re->overall_options & PCRE2_UCP) != 0)) first_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(first_cu); #endif +#endif /* SUPPORT_UNICODE */ } } else @@ -3545,9 +3551,15 @@ if ((re->flags & PCRE2_LASTSET) != 0) if ((re->flags & PCRE2_LASTCASELESS) != 0) { req_cu2 = TABLE_GET(req_cu, mb->tables + fcc_offset, req_cu); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 - if (utf && req_cu > 127) req_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(req_cu); +#ifdef SUPPORT_UNICODE +#if PCRE2_CODE_UNIT_WIDTH == 8 + if (req_cu > 127 && !utf && (re->overall_options & PCRE2_UCP) != 0) + req_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(req_cu); +#else + if (req_cu > 127 && (utf || (re->overall_options & PCRE2_UCP) != 0)) + req_cu2 = (PCRE2_UCHAR)UCD_OTHERCASE(req_cu); #endif +#endif /* SUPPORT_UNICODE */ } } diff --git a/thirdparty/pcre2/src/pcre2_internal.h b/thirdparty/pcre2/src/pcre2_internal.h index fe8ffe5c80..d8fad1e93b 100644 --- a/thirdparty/pcre2/src/pcre2_internal.h +++ b/thirdparty/pcre2/src/pcre2_internal.h @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2019 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -76,6 +76,17 @@ typedef int BOOL; #include <valgrind/memcheck.h> #endif +/* -ftrivial-auto-var-init support supports initializing all local variables +to avoid some classes of bug, but this can cause an unacceptable slowdown +for large on-stack arrays in hot functions. This macro lets us annotate +such arrays. */ + +#ifdef HAVE_ATTRIBUTE_UNINITIALIZED +#define PCRE2_KEEP_UNINITIALIZED __attribute__((uninitialized)) +#else +#define PCRE2_KEEP_UNINITIALIZED +#endif + /* Older versions of MSVC lack snprintf(). This define allows for warning/error-free compilation and testing with MSVC compilers back to at least MSVC 10/2010. Except for VC6 (which is missing some fundamentals and fails). */ @@ -579,7 +590,7 @@ total length of the tables. */ #define fcc_offset 256 /* Flip case */ #define cbits_offset 512 /* Character classes */ #define ctypes_offset (cbits_offset + cbit_length) /* Character types */ -#define tables_length (ctypes_offset + 256) +#define TABLES_LENGTH (ctypes_offset + 256) /* -------------------- Character and string names ------------------------ */ @@ -1759,13 +1770,11 @@ typedef struct pcre2_memctl { /* Structure for building a chain of open capturing subpatterns during compiling, so that instructions to close them can be compiled when (*ACCEPT) is -encountered. This is also used to identify subpatterns that contain recursive -back references to themselves, so that they can be made atomic. */ +encountered. */ typedef struct open_capitem { struct open_capitem *next; /* Chain link */ uint16_t number; /* Capture number */ - uint16_t flag; /* Set TRUE if recursive back ref */ uint16_t assert_depth; /* Assertion depth when opened */ } open_capitem; @@ -1954,7 +1963,7 @@ is available. */ #define _pcre2_was_newline PCRE2_SUFFIX(_pcre2_was_newline_) #define _pcre2_xclass PCRE2_SUFFIX(_pcre2_xclass_) -extern int _pcre2_auto_possessify(PCRE2_UCHAR *, BOOL, +extern int _pcre2_auto_possessify(PCRE2_UCHAR *, const compile_block *); extern int _pcre2_check_escape(PCRE2_SPTR *, PCRE2_SPTR, uint32_t *, int *, uint32_t, uint32_t, BOOL, compile_block *); diff --git a/thirdparty/pcre2/src/pcre2_jit_compile.c b/thirdparty/pcre2/src/pcre2_jit_compile.c index f564127c2a..1977d28aa5 100644 --- a/thirdparty/pcre2/src/pcre2_jit_compile.c +++ b/thirdparty/pcre2/src/pcre2_jit_compile.c @@ -223,6 +223,12 @@ enum control_types { type_then_trap = 1 }; +enum early_fail_types { + type_skip = 0, + type_fail = 1, + type_fail_range = 2 +}; + typedef int (SLJIT_FUNC *jit_function)(jit_arguments *args); /* The following structure is the key data type for the recursive @@ -405,8 +411,8 @@ typedef struct compiler_common { /* Fast forward skipping byte code pointer. */ PCRE2_SPTR fast_forward_bc_ptr; /* Locals used by fast fail optimization. */ - sljit_s32 fast_fail_start_ptr; - sljit_s32 fast_fail_end_ptr; + sljit_s32 early_fail_start_ptr; + sljit_s32 early_fail_end_ptr; /* Flipped and lower case tables. */ const sljit_u8 *fcc; @@ -476,7 +482,7 @@ typedef struct compiler_common { #ifdef SUPPORT_UNICODE BOOL utf; BOOL invalid_utf; - BOOL use_ucp; + BOOL ucp; /* Points to saving area for iref. */ sljit_s32 iref_ptr; jump_list *getucd; @@ -607,6 +613,8 @@ the start pointers when the end of the capturing group has not yet reached. */ sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw)) #define OP2(op, dst, dstw, src1, src1w, src2, src2w) \ sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w)) +#define OP_SRC(op, src, srcw) \ + sljit_emit_op_src(compiler, (op), (src), (srcw)) #define LABEL() \ sljit_emit_label(compiler) #define JUMP(type) \ @@ -823,7 +831,7 @@ the start pointers when the end of the capturing group has not yet reached. */ static PCRE2_SPTR bracketend(PCRE2_SPTR cc) { -SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); +SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); do cc += GET(cc, 1); while (*cc == OP_ALT); SLJIT_ASSERT(*cc >= OP_KET && *cc <= OP_KETRPOS); cc += 1 + LINK_SIZE; @@ -833,7 +841,7 @@ return cc; static int no_alternatives(PCRE2_SPTR cc) { int count = 0; -SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); +SLJIT_ASSERT((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND)); do { cc += GET(cc, 1); @@ -918,6 +926,8 @@ switch(*cc) case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: + case OP_ASSERT_NA: + case OP_ASSERTBACK_NA: case OP_ONCE: case OP_SCRIPT_RUN: case OP_BRA: @@ -1050,8 +1060,7 @@ switch(*cc) return cc + 1 + 2 + cc[1]; default: - /* Unsupported opcodes: OP_ASSERT_NA and OP_ASSERTBACK_NA */ - /* SLJIT_UNREACHABLE(); */ + SLJIT_UNREACHABLE(); return NULL; } } @@ -1061,6 +1070,7 @@ static BOOL check_opcode_types(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPT int count; PCRE2_SPTR slot; PCRE2_SPTR assert_back_end = cc - 1; +PCRE2_SPTR assert_na_end = cc - 1; /* Calculate important variables (like stack size) and checks whether all opcodes are supported. */ while (cc < ccend) @@ -1087,6 +1097,14 @@ while (cc < ccend) cc += 1 + IMM2_SIZE; break; + case OP_ASSERT_NA: + case OP_ASSERTBACK_NA: + slot = bracketend(cc); + if (slot > assert_na_end) + assert_na_end = slot; + cc += 1 + LINK_SIZE; + break; + case OP_CBRAPOS: case OP_SCBRAPOS: common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] = 0; @@ -1154,6 +1172,9 @@ while (cc < ccend) case OP_COMMIT_ARG: case OP_PRUNE_ARG: + if (cc < assert_na_end) + return FALSE; + /* Fall through */ case OP_MARK: if (common->mark_ptr == 0) { @@ -1172,6 +1193,8 @@ while (cc < ccend) case OP_SKIP: if (cc < assert_back_end) common->has_skip_in_assert_back = TRUE; + if (cc < assert_na_end) + return FALSE; cc += 1; break; @@ -1180,9 +1203,19 @@ while (cc < ccend) common->has_skip_arg = TRUE; if (cc < assert_back_end) common->has_skip_in_assert_back = TRUE; + if (cc < assert_na_end) + return FALSE; cc += 1 + 2 + cc[1]; break; + case OP_PRUNE: + case OP_COMMIT: + case OP_ASSERT_ACCEPT: + if (cc < assert_na_end) + return FALSE; + cc++; + break; + default: cc = next_opcode(common, cc); if (cc == NULL) @@ -1193,183 +1226,355 @@ while (cc < ccend) return TRUE; } -static BOOL is_accelerated_repeat(PCRE2_SPTR cc) +#define EARLY_FAIL_ENHANCE_MAX (1 + 1) + +/* +start: + 0 - skip / early fail allowed + 1 - only early fail with range allowed + >1 - (start - 1) early fail is processed + +return: current number of iterators enhanced with fast fail +*/ +static int detect_early_fail(compiler_common *common, PCRE2_SPTR cc, int *private_data_start, sljit_s32 depth, int start) { -switch(*cc) - { - case OP_TYPESTAR: - case OP_TYPEMINSTAR: - case OP_TYPEPLUS: - case OP_TYPEMINPLUS: - case OP_TYPEPOSSTAR: - case OP_TYPEPOSPLUS: - return (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI); +PCRE2_SPTR next_alt; +PCRE2_SPTR end; +PCRE2_SPTR accelerated_start; +int result = 0; +int count; +BOOL fast_forward_allowed = TRUE; - case OP_STAR: - case OP_MINSTAR: - case OP_PLUS: - case OP_MINPLUS: - case OP_POSSTAR: - case OP_POSPLUS: +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(start < EARLY_FAIL_ENHANCE_MAX); - case OP_STARI: - case OP_MINSTARI: - case OP_PLUSI: - case OP_MINPLUSI: - case OP_POSSTARI: - case OP_POSPLUSI: +do + { + count = start; + next_alt = cc + GET(cc, 1); + cc += 1 + LINK_SIZE + ((*cc == OP_CBRA) ? IMM2_SIZE : 0); - case OP_NOTSTAR: - case OP_NOTMINSTAR: - case OP_NOTPLUS: - case OP_NOTMINPLUS: - case OP_NOTPOSSTAR: - case OP_NOTPOSPLUS: + while (TRUE) + { + accelerated_start = NULL; - case OP_NOTSTARI: - case OP_NOTMINSTARI: - case OP_NOTPLUSI: - case OP_NOTMINPLUSI: - case OP_NOTPOSSTARI: - case OP_NOTPOSPLUSI: - return TRUE; + switch(*cc) + { + case OP_SOD: + case OP_SOM: + case OP_SET_SOM: + case OP_NOT_WORD_BOUNDARY: + case OP_WORD_BOUNDARY: + case OP_EODN: + case OP_EOD: + case OP_CIRC: + case OP_CIRCM: + case OP_DOLL: + case OP_DOLLM: + /* Zero width assertions. */ + cc++; + continue; + + case OP_NOT_DIGIT: + case OP_DIGIT: + case OP_NOT_WHITESPACE: + case OP_WHITESPACE: + case OP_NOT_WORDCHAR: + case OP_WORDCHAR: + case OP_ANY: + case OP_ALLANY: + case OP_ANYBYTE: + case OP_NOT_HSPACE: + case OP_HSPACE: + case OP_NOT_VSPACE: + case OP_VSPACE: + fast_forward_allowed = FALSE; + cc++; + continue; - case OP_CLASS: - case OP_NCLASS: -#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 - case OP_XCLASS: - cc += (*cc == OP_XCLASS) ? GET(cc, 1) : (int)(1 + (32 / sizeof(PCRE2_UCHAR))); -#else - cc += (1 + (32 / sizeof(PCRE2_UCHAR))); + case OP_ANYNL: + case OP_EXTUNI: + fast_forward_allowed = FALSE; + if (count == 0) + count = 1; + cc++; + continue; + + case OP_NOTPROP: + case OP_PROP: + fast_forward_allowed = FALSE; + cc += 1 + 2; + continue; + + case OP_CHAR: + case OP_CHARI: + case OP_NOT: + case OP_NOTI: + fast_forward_allowed = FALSE; + cc += 2; +#ifdef SUPPORT_UNICODE + if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); #endif + continue; - switch(*cc) - { - case OP_CRSTAR: - case OP_CRMINSTAR: - case OP_CRPLUS: - case OP_CRMINPLUS: - case OP_CRPOSSTAR: - case OP_CRPOSPLUS: - return TRUE; - } - break; - } -return FALSE; -} + case OP_TYPESTAR: + case OP_TYPEMINSTAR: + case OP_TYPEPLUS: + case OP_TYPEMINPLUS: + case OP_TYPEPOSSTAR: + case OP_TYPEPOSPLUS: + /* The type or prop opcode is skipped in the next iteration. */ + cc += 1; -static SLJIT_INLINE BOOL detect_fast_forward_skip(compiler_common *common, int *private_data_start) -{ -PCRE2_SPTR cc = common->start; -PCRE2_SPTR end; + if (cc[0] != OP_ANYNL && cc[0] != OP_EXTUNI) + { + accelerated_start = cc - 1; + break; + } -/* Skip not repeated brackets. */ -while (TRUE) - { - switch(*cc) - { - case OP_SOD: - case OP_SOM: - case OP_SET_SOM: - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - case OP_EODN: - case OP_EOD: - case OP_CIRC: - case OP_CIRCM: - case OP_DOLL: - case OP_DOLLM: - /* Zero width assertions. */ - cc++; - continue; - } + if (count == 0) + count = 1; + fast_forward_allowed = FALSE; + continue; - if (*cc != OP_BRA && *cc != OP_CBRA) - break; + case OP_TYPEUPTO: + case OP_TYPEMINUPTO: + case OP_TYPEEXACT: + case OP_TYPEPOSUPTO: + cc += IMM2_SIZE; + /* Fall through */ + + case OP_TYPEQUERY: + case OP_TYPEMINQUERY: + case OP_TYPEPOSQUERY: + /* The type or prop opcode is skipped in the next iteration. */ + fast_forward_allowed = FALSE; + if (count == 0) + count = 1; + cc += 1; + continue; + + case OP_STAR: + case OP_MINSTAR: + case OP_PLUS: + case OP_MINPLUS: + case OP_POSSTAR: + case OP_POSPLUS: + + case OP_STARI: + case OP_MINSTARI: + case OP_PLUSI: + case OP_MINPLUSI: + case OP_POSSTARI: + case OP_POSPLUSI: + + case OP_NOTSTAR: + case OP_NOTMINSTAR: + case OP_NOTPLUS: + case OP_NOTMINPLUS: + case OP_NOTPOSSTAR: + case OP_NOTPOSPLUS: + + case OP_NOTSTARI: + case OP_NOTMINSTARI: + case OP_NOTPLUSI: + case OP_NOTMINPLUSI: + case OP_NOTPOSSTARI: + case OP_NOTPOSPLUSI: + accelerated_start = cc; + cc += 2; +#ifdef SUPPORT_UNICODE + if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif + break; - end = cc + GET(cc, 1); - if (*end != OP_KET || PRIVATE_DATA(end) != 0) - return FALSE; - if (*cc == OP_CBRA) - { - if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) - return FALSE; - cc += IMM2_SIZE; - } - cc += 1 + LINK_SIZE; - } + case OP_UPTO: + case OP_MINUPTO: + case OP_EXACT: + case OP_POSUPTO: + case OP_UPTOI: + case OP_MINUPTOI: + case OP_EXACTI: + case OP_POSUPTOI: + case OP_NOTUPTO: + case OP_NOTMINUPTO: + case OP_NOTEXACT: + case OP_NOTPOSUPTO: + case OP_NOTUPTOI: + case OP_NOTMINUPTOI: + case OP_NOTEXACTI: + case OP_NOTPOSUPTOI: + cc += IMM2_SIZE; + /* Fall through */ + + case OP_QUERY: + case OP_MINQUERY: + case OP_POSQUERY: + case OP_QUERYI: + case OP_MINQUERYI: + case OP_POSQUERYI: + case OP_NOTQUERY: + case OP_NOTMINQUERY: + case OP_NOTPOSQUERY: + case OP_NOTQUERYI: + case OP_NOTMINQUERYI: + case OP_NOTPOSQUERYI: + fast_forward_allowed = FALSE; + if (count == 0) + count = 1; + cc += 2; +#ifdef SUPPORT_UNICODE + if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]); +#endif + continue; -if (is_accelerated_repeat(cc)) - { - common->fast_forward_bc_ptr = cc; - common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start; - *private_data_start += sizeof(sljit_sw); - return TRUE; - } -return FALSE; -} + case OP_CLASS: + case OP_NCLASS: +#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 + case OP_XCLASS: + accelerated_start = cc; + cc += ((*cc == OP_XCLASS) ? GET(cc, 1) : (unsigned int)(1 + (32 / sizeof(PCRE2_UCHAR)))); +#else + accelerated_start = cc; + cc += (1 + (32 / sizeof(PCRE2_UCHAR))); +#endif -static SLJIT_INLINE void detect_fast_fail(compiler_common *common, PCRE2_SPTR cc, int *private_data_start, sljit_s32 depth) -{ - PCRE2_SPTR next_alt; + switch (*cc) + { + case OP_CRSTAR: + case OP_CRMINSTAR: + case OP_CRPLUS: + case OP_CRMINPLUS: + case OP_CRPOSSTAR: + case OP_CRPOSPLUS: + cc++; + break; - SLJIT_ASSERT(*cc == OP_BRA || *cc == OP_CBRA); + case OP_CRRANGE: + case OP_CRMINRANGE: + case OP_CRPOSRANGE: + cc += 2 * IMM2_SIZE; + /* Fall through */ + case OP_CRQUERY: + case OP_CRMINQUERY: + case OP_CRPOSQUERY: + cc++; + if (count == 0) + count = 1; + /* Fall through */ + default: + accelerated_start = NULL; + fast_forward_allowed = FALSE; + continue; + } + break; - if (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) - return; + case OP_ONCE: + case OP_BRA: + case OP_CBRA: + end = cc + GET(cc, 1); - next_alt = bracketend(cc) - (1 + LINK_SIZE); - if (*next_alt != OP_KET || PRIVATE_DATA(next_alt) != 0) - return; + if (*end == OP_KET && PRIVATE_DATA(end) == 0) + { + if (*cc == OP_CBRA) + { + if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) + break; + cc += IMM2_SIZE; + } - do - { - next_alt = cc + GET(cc, 1); + cc += 1 + LINK_SIZE; + continue; + } - cc += 1 + LINK_SIZE + ((*cc == OP_CBRA) ? IMM2_SIZE : 0); + fast_forward_allowed = FALSE; + if (depth >= 4) + break; - while (TRUE) - { - switch(*cc) + end = bracketend(cc) - (1 + LINK_SIZE); + if (*end != OP_KET || PRIVATE_DATA(end) != 0) + break; + + if (*cc == OP_CBRA && common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0) + break; + + count = detect_early_fail(common, cc, private_data_start, depth + 1, count); + if (count < EARLY_FAIL_ENHANCE_MAX) { - case OP_SOD: - case OP_SOM: - case OP_SET_SOM: - case OP_NOT_WORD_BOUNDARY: - case OP_WORD_BOUNDARY: - case OP_EODN: - case OP_EOD: - case OP_CIRC: - case OP_CIRCM: - case OP_DOLL: - case OP_DOLLM: - /* Zero width assertions. */ - cc++; + cc = end + (1 + LINK_SIZE); continue; } break; - } - if (depth > 0 && (*cc == OP_BRA || *cc == OP_CBRA)) - detect_fast_fail(common, cc, private_data_start, depth - 1); + case OP_KET: + SLJIT_ASSERT(PRIVATE_DATA(cc) == 0); + if (cc >= next_alt) + break; + cc += 1 + LINK_SIZE; + continue; + } - if (is_accelerated_repeat(cc)) + if (accelerated_start != NULL) { - common->private_data_ptrs[(cc + 1) - common->start] = *private_data_start; + if (count == 0) + { + count++; - if (common->fast_fail_start_ptr == 0) - common->fast_fail_start_ptr = *private_data_start; + if (fast_forward_allowed && *next_alt == OP_KET) + { + common->fast_forward_bc_ptr = accelerated_start; + common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_skip; + *private_data_start += sizeof(sljit_sw); + } + else + { + common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_fail; - *private_data_start += sizeof(sljit_sw); - common->fast_fail_end_ptr = *private_data_start; + if (common->early_fail_start_ptr == 0) + common->early_fail_start_ptr = *private_data_start; - if (*private_data_start > SLJIT_MAX_LOCAL_SIZE) - return; + *private_data_start += sizeof(sljit_sw); + common->early_fail_end_ptr = *private_data_start; + + if (*private_data_start > SLJIT_MAX_LOCAL_SIZE) + return EARLY_FAIL_ENHANCE_MAX; + } + } + else + { + common->private_data_ptrs[(accelerated_start + 1) - common->start] = ((*private_data_start) << 3) | type_fail_range; + + if (common->early_fail_start_ptr == 0) + common->early_fail_start_ptr = *private_data_start; + + *private_data_start += 2 * sizeof(sljit_sw); + common->early_fail_end_ptr = *private_data_start; + + if (*private_data_start > SLJIT_MAX_LOCAL_SIZE) + return EARLY_FAIL_ENHANCE_MAX; + } + + count++; + + if (count < EARLY_FAIL_ENHANCE_MAX) + continue; } - cc = next_alt; + break; } - while (*cc == OP_ALT); + + if (*cc != OP_ALT && *cc != OP_KET) + result = EARLY_FAIL_ENHANCE_MAX; + else if (result < count) + result = count; + + fast_forward_allowed = FALSE; + cc = next_alt; + } +while (*cc == OP_ALT); + +return result; } static int get_class_iterator_size(PCRE2_SPTR cc) @@ -1586,6 +1791,8 @@ while (cc < ccend) case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: + case OP_ASSERT_NA: + case OP_ASSERTBACK_NA: case OP_ONCE: case OP_SCRIPT_RUN: case OP_BRAPOS: @@ -1627,57 +1834,57 @@ while (cc < ccend) case OP_BRAZERO: case OP_BRAMINZERO: case OP_BRAPOSZERO: - repeat_check = FALSE; size = 1; + repeat_check = FALSE; break; CASE_ITERATOR_PRIVATE_DATA_1 - space = 1; size = -2; + space = 1; break; CASE_ITERATOR_PRIVATE_DATA_2A - space = 2; size = -2; + space = 2; break; CASE_ITERATOR_PRIVATE_DATA_2B - space = 2; size = -(2 + IMM2_SIZE); + space = 2; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_1 - space = 1; size = 1; + space = 1; break; CASE_ITERATOR_TYPE_PRIVATE_DATA_2A + size = 1; if (cc[1] != OP_ANYNL && cc[1] != OP_EXTUNI) space = 2; - size = 1; break; case OP_TYPEUPTO: + size = 1 + IMM2_SIZE; if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) space = 2; - size = 1 + IMM2_SIZE; break; case OP_TYPEMINUPTO: - space = 2; size = 1 + IMM2_SIZE; + space = 2; break; case OP_CLASS: case OP_NCLASS: - space = get_class_iterator_size(cc + size); size = 1 + 32 / sizeof(PCRE2_UCHAR); + space = get_class_iterator_size(cc + size); break; #if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8 case OP_XCLASS: - space = get_class_iterator_size(cc + size); size = GET(cc, 1); + space = get_class_iterator_size(cc + size); break; #endif @@ -2163,6 +2370,8 @@ while (cc < ccend) case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: + case OP_ASSERT_NA: + case OP_ASSERTBACK_NA: case OP_ONCE: case OP_SCRIPT_RUN: case OP_BRAPOS: @@ -2487,6 +2696,8 @@ while (cc < ccend) case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: + case OP_ASSERT_NA: + case OP_ASSERTBACK_NA: case OP_ONCE: case OP_SCRIPT_RUN: case OP_BRAPOS: @@ -2660,8 +2871,8 @@ while (cc < ccend) } if (common->control_head_ptr != 0 && !control_head_found) { - shared_srcw[0] = common->control_head_ptr; - shared_count = 1; + private_srcw[0] = common->control_head_ptr; + private_count = 1; control_head_found = TRUE; } cc += 1 + 2 + cc[1]; @@ -2671,8 +2882,8 @@ while (cc < ccend) SLJIT_ASSERT(common->control_head_ptr != 0); if (!control_head_found) { - shared_srcw[0] = common->control_head_ptr; - shared_count = 1; + private_srcw[0] = common->control_head_ptr; + private_count = 1; control_head_found = TRUE; } cc++; @@ -2756,7 +2967,7 @@ PCRE2_SPTR end = bracketend(cc); BOOL has_alternatives = cc[GET(cc, 1)] == OP_ALT; /* Assert captures then. */ -if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) +if (*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) current_offset = NULL; /* Conditional block does not. */ if (*cc == OP_COND || *cc == OP_SCOND) @@ -2768,7 +2979,7 @@ if (has_alternatives) while (cc < end) { - if ((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NOT) || (*cc >= OP_ONCE && *cc <= OP_SCOND)) + if ((*cc >= OP_ASSERT && *cc <= OP_ASSERTBACK_NA) || (*cc >= OP_ONCE && *cc <= OP_SCOND)) cc = set_then_offsets(common, cc, current_offset); else { @@ -2938,16 +3149,54 @@ else } } -static SLJIT_INLINE void reset_fast_fail(compiler_common *common) +static SLJIT_INLINE void reset_early_fail(compiler_common *common) { DEFINE_COMPILER; +sljit_u32 size = (sljit_u32)(common->early_fail_end_ptr - common->early_fail_start_ptr); +sljit_u32 uncleared_size; +sljit_s32 src = SLJIT_IMM; sljit_s32 i; +struct sljit_label *loop; + +SLJIT_ASSERT(common->early_fail_start_ptr < common->early_fail_end_ptr); + +if (size == sizeof(sljit_sw)) + { + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->early_fail_start_ptr, SLJIT_IMM, 0); + return; + } + +if (sljit_get_register_index(TMP3) >= 0 && !sljit_has_cpu_feature(SLJIT_HAS_ZERO_REGISTER)) + { + OP1(SLJIT_MOV, TMP3, 0, SLJIT_IMM, 0); + src = TMP3; + } + +if (size <= 6 * sizeof(sljit_sw)) + { + for (i = common->early_fail_start_ptr; i < common->early_fail_end_ptr; i += sizeof(sljit_sw)) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), i, src, 0); + return; + } -SLJIT_ASSERT(common->fast_fail_start_ptr < common->fast_fail_end_ptr); +GET_LOCAL_BASE(TMP1, 0, common->early_fail_start_ptr); -OP2(SLJIT_SUB, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -for (i = common->fast_fail_start_ptr; i < common->fast_fail_end_ptr; i += sizeof(sljit_sw)) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), i, TMP1, 0); +uncleared_size = ((size / sizeof(sljit_sw)) % 3) * sizeof(sljit_sw); + +OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, size - uncleared_size); + +loop = LABEL(); +OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), 0, src, 0); +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 3 * sizeof(sljit_sw)); +OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -2 * (sljit_sw)sizeof(sljit_sw), src, 0); +OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), -1 * (sljit_sw)sizeof(sljit_sw), src, 0); +CMPTO(SLJIT_LESS, TMP1, 0, TMP2, 0, loop); + +if (uncleared_size >= sizeof(sljit_sw)) + OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), 0, src, 0); + +if (uncleared_size >= 2 * sizeof(sljit_sw)) + OP1(SLJIT_MOV, SLJIT_MEM1(TMP1), sizeof(sljit_sw), src, 0); } static SLJIT_INLINE void do_reset_match(compiler_common *common, int length) @@ -3193,16 +3442,19 @@ static SLJIT_INLINE BOOL char_has_othercase(compiler_common *common, PCRE2_SPTR unsigned int c; #ifdef SUPPORT_UNICODE -if (common->utf) +if (common->utf || common->ucp) { - GETCHAR(c, cc); - if (c > 127) + if (common->utf) { - return c != UCD_OTHERCASE(c); + GETCHAR(c, cc); } -#if PCRE2_CODE_UNIT_WIDTH != 8 + else + c = *cc; + + if (c > 127) + return c != UCD_OTHERCASE(c); + return common->fcc[c] != c; -#endif } else #endif @@ -3214,10 +3466,8 @@ static SLJIT_INLINE unsigned int char_othercase(compiler_common *common, unsigne { /* Returns with the othercase. */ #ifdef SUPPORT_UNICODE -if (common->utf && c > 127) - { +if ((common->utf || common->ucp) && c > 127) return UCD_OTHERCASE(c); - } #endif return TABLE_GET(c, common->fcc, c); } @@ -3231,15 +3481,19 @@ int n; #endif #ifdef SUPPORT_UNICODE -if (common->utf) +if (common->utf || common->ucp) { - GETCHAR(c, cc); + if (common->utf) + { + GETCHAR(c, cc); + } + else + c = *cc; + if (c <= 127) oc = common->fcc[c]; else - { oc = UCD_OTHERCASE(c); - } } else { @@ -4083,7 +4337,7 @@ jump = JUMP(SLJIT_NOT_ZERO); /* Two byte sequence. */ OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3000); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(jump); OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); @@ -4096,7 +4350,7 @@ jump = JUMP(SLJIT_NOT_ZERO); /* Three byte sequence. */ OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0000); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); /* Four byte sequence. */ JUMPHERE(jump); @@ -4106,7 +4360,7 @@ OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3)); OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void do_utfreadtype8(compiler_common *common) @@ -4131,18 +4385,18 @@ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3f); OP2(SLJIT_OR, TMP2, 0, TMP2, 0, TMP1, 0); OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), common->ctypes); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(compare); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); /* We only have types for characters less than 256. */ JUMPHERE(jump); OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(utf8_table4) - 0xc0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void do_utfreadchar_invalid(compiler_common *common) @@ -4182,7 +4436,7 @@ OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); jump = JUMP(SLJIT_NOT_ZERO); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(jump); @@ -4225,7 +4479,7 @@ if (has_cmov) } else exit_invalid[4] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(jump); @@ -4254,7 +4508,7 @@ else exit_invalid[6] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(buffer_end_close); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); @@ -4271,7 +4525,7 @@ exit_invalid[8] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40); OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800); jump = JUMP(SLJIT_NOT_ZERO); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); /* Three-byte sequence. */ JUMPHERE(jump); @@ -4301,7 +4555,7 @@ for (i = 0; i < 11; i++) sljit_set_label(exit_invalid[i], exit_invalid_label); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void do_utfreadnewline_invalid(compiler_common *common) @@ -4324,7 +4578,14 @@ if (common->nltype != NLTYPE_ANY) /* All newlines are ascii, just skip intermediate octets. */ jump[0] = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); loop = LABEL(); - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + if (sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_SUPP | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)) == SLJIT_SUCCESS) + sljit_emit_mem(compiler, MOV_UCHAR | SLJIT_MEM_POST, TMP2, SLJIT_MEM1(STR_PTR), IN_UCHARS(1)); + else + { + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + } + OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc0); CMPTO(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, 0x80, loop); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); @@ -4332,7 +4593,7 @@ if (common->nltype != NLTYPE_ANY) JUMPHERE(jump[0]); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); - sljit_emit_fast_return(compiler, RETURN_ADDR, 0); + OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); return; } @@ -4363,14 +4624,14 @@ JUMPHERE(jump[0]); JUMPHERE(jump[4]); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); /* Two byte long newline: 0x85. */ JUMPHERE(jump[1]); CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, 0x85, skip_start); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x85); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); /* Three byte long newlines: 0x2028 and 0x2029. */ JUMPHERE(jump[2]); @@ -4385,7 +4646,7 @@ CMPTO(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x40, skip_start); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 0x2000); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void do_utfmoveback_invalid(compiler_common *common) @@ -4414,7 +4675,7 @@ jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x20); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); /* Three-byte sequence. */ JUMPHERE(jump); @@ -4427,7 +4688,7 @@ jump = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x10); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); /* Four-byte sequence. */ JUMPHERE(jump); @@ -4440,7 +4701,7 @@ exit_invalid[3] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x05); exit_ok_label = LABEL(); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); /* Two-byte sequence. */ JUMPHERE(buffer_start_close); @@ -4470,7 +4731,7 @@ sljit_set_label(exit_invalid[5], exit_invalid_label); sljit_set_label(exit_invalid[6], exit_invalid_label); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(3)); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(exit_invalid[4]); /* -2 + 4 = 2 */ @@ -4481,7 +4742,7 @@ for (i = 0; i < 4; i++) sljit_set_label(exit_invalid[i], exit_invalid_label); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(4)); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void do_utfpeakcharback(compiler_common *common) @@ -4518,7 +4779,7 @@ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6); OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void do_utfpeakcharback_invalid(compiler_common *common) @@ -4548,7 +4809,7 @@ two_byte_entry = LABEL(); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 6); /* If TMP1 is in 0x80-0xbf range, TMP1 is also increased by (0x2 << 6). */ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(jump[1]); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xc2 - 0x80); @@ -4586,7 +4847,7 @@ if (has_cmov) else exit_invalid[3] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0x800); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(jump[1]); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0 - 0x80); @@ -4612,7 +4873,7 @@ else exit_invalid[5] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x10000); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(jump[0]); OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, IN_UCHARS(1)); @@ -4635,7 +4896,7 @@ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xe0); CMPTO(SLJIT_LESS, TMP2, 0, SLJIT_IMM, 0x10, three_byte_entry); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(jump[0]); exit_invalid[7] = CMP(SLJIT_GREATER, TMP2, 0, STR_PTR, 0); @@ -4650,7 +4911,7 @@ for (i = 0; i < 8; i++) sljit_set_label(exit_invalid[i], exit_invalid_label); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } #endif /* PCRE2_CODE_UNIT_WIDTH == 8 */ @@ -4680,13 +4941,13 @@ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x10000); exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x400); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(exit_invalid[0]); JUMPHERE(exit_invalid[1]); JUMPHERE(exit_invalid[2]); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void do_utfreadnewline_invalid(compiler_common *common) @@ -4713,12 +4974,12 @@ OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(exit_invalid[0]); JUMPHERE(exit_invalid[1]); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void do_utfmoveback_invalid(compiler_common *common) @@ -4738,7 +4999,7 @@ exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x400); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(exit_invalid[0]); JUMPHERE(exit_invalid[1]); @@ -4746,7 +5007,7 @@ JUMPHERE(exit_invalid[2]); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void do_utfpeakcharback_invalid(compiler_common *common) @@ -4771,14 +5032,14 @@ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 10); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); JUMPHERE(jump); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(exit_invalid[0]); JUMPHERE(exit_invalid[1]); JUMPHERE(exit_invalid[2]); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, INVALID_UTF_CHAR); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } #endif /* PCRE2_CODE_UNIT_WIDTH == 16 */ @@ -4824,7 +5085,7 @@ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCD_BLOCK_SHIFT); OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2)); OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void do_getucdtype(compiler_common *common) @@ -4871,7 +5132,7 @@ 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_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } #endif /* SUPPORT_UNICODE */ @@ -5159,6 +5420,8 @@ while (TRUE) case OP_ASSERT_NOT: case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: + case OP_ASSERT_NA: + case OP_ASSERTBACK_NA: cc = bracketend(cc); continue; @@ -5458,7 +5721,12 @@ while (TRUE) #endif { chr = *cc; - othercase[0] = TABLE_GET(chr, common->fcc, chr); +#ifdef SUPPORT_UNICODE + if (common->ucp && chr > 127) + othercase[0] = UCD_OTHERCASE(chr); + else +#endif + othercase[0] = TABLE_GET(chr, common->fcc, chr); } } else @@ -5887,8 +6155,8 @@ oc = first_char; if ((common->re->flags & PCRE2_FIRSTCASELESS) != 0) { oc = TABLE_GET(first_char, common->fcc, first_char); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 - if (first_char > 127 && common->utf) +#if defined SUPPORT_UNICODE + if (first_char > 127 && (common->utf || common->ucp)) oc = UCD_OTHERCASE(first_char); #endif } @@ -5900,9 +6168,9 @@ static SLJIT_INLINE void fast_forward_newline(compiler_common *common) { DEFINE_COMPILER; struct sljit_label *loop; -struct sljit_jump *lastchar; +struct sljit_jump *lastchar = NULL; struct sljit_jump *firstchar; -struct sljit_jump *quit; +struct sljit_jump *quit = NULL; struct sljit_jump *foundcr = NULL; struct sljit_jump *notfoundnl; jump_list *newline = NULL; @@ -5915,39 +6183,71 @@ if (common->match_end_ptr != 0) if (common->nltype == NLTYPE_FIXED && common->newline > 255) { - lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - if (HAS_VIRTUAL_REGISTERS) +#ifdef JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD + if (JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD && common->mode == PCRE2_JIT_COMPLETE) { - OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + if (HAS_VIRTUAL_REGISTERS) + { + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + } + else + { + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin)); + } + firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); + + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); + OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_NOT_EQUAL); +#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 + OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT); +#endif + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0); + + fast_forward_char_pair_simd(common, 1, common->newline & 0xff, common->newline & 0xff, 0, (common->newline >> 8) & 0xff, (common->newline >> 8) & 0xff); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2)); } else +#endif /* JIT_HAS_FAST_FORWARD_CHAR_PAIR_SIMD */ { - OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str)); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin)); - } - firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); + lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + if (HAS_VIRTUAL_REGISTERS) + { + OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin)); + } + else + { + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, str)); + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin)); + } + firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); - OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); - OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); - OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER_EQUAL); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2)); + OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0); + OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER_EQUAL); #if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32 - OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT); + OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT); #endif - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); - loop = LABEL(); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); - OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); - OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); - CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); - CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); + loop = LABEL(); + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + quit = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-2)); + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(-1)); + CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff, loop); + CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, SLJIT_IMM, common->newline & 0xff, loop); + + JUMPHERE(quit); + JUMPHERE(lastchar); + } - JUMPHERE(quit); JUMPHERE(firstchar); - JUMPHERE(lastchar); if (common->match_end_ptr != 0) OP1(SLJIT_MOV, STR_END, 0, TMP3, 0); @@ -5964,22 +6264,59 @@ else /* Example: match /^/ to \r\n from offset 1. */ firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0); -move_back(common, NULL, FALSE); + +if (common->nltype == NLTYPE_ANY) + move_back(common, NULL, FALSE); +else + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); loop = LABEL(); common->ff_newline_shortcut = loop; -read_char(common, common->nlmin, common->nlmax, NULL, READ_CHAR_NEWLINE); -lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); -if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) - foundcr = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); -check_newlinechar(common, common->nltype, &newline, FALSE); -set_jumps(newline, loop); +#ifdef JIT_HAS_FAST_FORWARD_CHAR_SIMD +if (JIT_HAS_FAST_FORWARD_CHAR_SIMD && (common->nltype == NLTYPE_FIXED || common->nltype == NLTYPE_ANYCRLF)) + { + if (common->nltype == NLTYPE_ANYCRLF) + { + fast_forward_char_simd(common, CHAR_CR, CHAR_LF, 0); + if (common->mode != PCRE2_JIT_COMPLETE) + lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + + OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); + 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 + { + fast_forward_char_simd(common, common->newline, common->newline, 0); + + OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + if (common->mode != PCRE2_JIT_COMPLETE) + { + OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0); + CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0); + } + } + } +else +#endif /* JIT_HAS_FAST_FORWARD_CHAR_SIMD */ + { + read_char(common, common->nlmin, common->nlmax, NULL, READ_CHAR_NEWLINE); + lastchar = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); + if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) + foundcr = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR); + check_newlinechar(common, common->nltype, &newline, FALSE); + set_jumps(newline, loop); + } if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) { - quit = JUMP(SLJIT_JUMP); - JUMPHERE(foundcr); + if (quit == NULL) + { + quit = JUMP(SLJIT_JUMP); + JUMPHERE(foundcr); + } + notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0); OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL); @@ -5991,7 +6328,9 @@ if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF) JUMPHERE(notfoundnl); JUMPHERE(quit); } -JUMPHERE(lastchar); + +if (lastchar) + JUMPHERE(lastchar); JUMPHERE(firstchar); if (common->match_end_ptr != 0) @@ -6072,67 +6411,80 @@ if (common->match_end_ptr != 0) OP1(SLJIT_MOV, STR_END, 0, RETURN_ADDR, 0); } -static SLJIT_INLINE struct sljit_jump *search_requested_char(compiler_common *common, PCRE2_UCHAR req_char, BOOL caseless, BOOL has_firstchar) +static SLJIT_INLINE jump_list *search_requested_char(compiler_common *common, PCRE2_UCHAR req_char, BOOL caseless, BOOL has_firstchar) { DEFINE_COMPILER; struct sljit_label *loop; struct sljit_jump *toolong; -struct sljit_jump *alreadyfound; +struct sljit_jump *already_found; struct sljit_jump *found; -struct sljit_jump *foundoc = NULL; -struct sljit_jump *notfound; +struct sljit_jump *found_oc = NULL; +jump_list *not_found = NULL; sljit_u32 oc, bit; SLJIT_ASSERT(common->req_char_ptr != 0); -OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr); -OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, REQ_CU_MAX); -toolong = CMP(SLJIT_LESS, TMP1, 0, STR_END, 0); -alreadyfound = CMP(SLJIT_LESS, STR_PTR, 0, TMP2, 0); +OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(REQ_CU_MAX) * 100); +OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr); +toolong = CMP(SLJIT_LESS, TMP2, 0, STR_END, 0); +already_found = CMP(SLJIT_LESS, STR_PTR, 0, TMP1, 0); if (has_firstchar) OP2(SLJIT_ADD, TMP1, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); else OP1(SLJIT_MOV, TMP1, 0, STR_PTR, 0); -loop = LABEL(); -notfound = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0); - -OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0); oc = req_char; if (caseless) { oc = TABLE_GET(req_char, common->fcc, req_char); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 - if (req_char > 127 && common->utf) +#if defined SUPPORT_UNICODE + if (req_char > 127 && (common->utf || common->ucp)) oc = UCD_OTHERCASE(req_char); #endif } -if (req_char == oc) - found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char); + +#ifdef JIT_HAS_FAST_REQUESTED_CHAR_SIMD +if (JIT_HAS_FAST_REQUESTED_CHAR_SIMD) + { + not_found = fast_requested_char_simd(common, req_char, oc); + } else +#endif { - bit = req_char ^ oc; - if (is_powerof2(bit)) - { - OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit); - found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit); - } + loop = LABEL(); + add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0)); + + OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(TMP1), 0); + + if (req_char == oc) + found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char); else { - found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char); - foundoc = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, oc); + bit = req_char ^ oc; + if (is_powerof2(bit)) + { + OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, bit); + found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char | bit); + } + else + { + found = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, req_char); + found_oc = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, oc); + } } + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); + JUMPTO(SLJIT_JUMP, loop); + + JUMPHERE(found); + if (found_oc) + JUMPHERE(found_oc); } -OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1)); -JUMPTO(SLJIT_JUMP, loop); -JUMPHERE(found); -if (foundoc) - JUMPHERE(foundoc); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->req_char_ptr, TMP1, 0); -JUMPHERE(alreadyfound); + +JUMPHERE(already_found); JUMPHERE(toolong); -return notfound; +return not_found; } static void do_revertframes(compiler_common *common) @@ -6170,7 +6522,7 @@ JUMPTO(SLJIT_JUMP, mainloop); JUMPHERE(jump); jump = CMP(SLJIT_NOT_ZERO /* SIG_LESS */, TMP2, 0, SLJIT_IMM, 0); /* End of reverting values. */ -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); JUMPHERE(jump); OP1(SLJIT_NEG, TMP2, 0, TMP2, 0); @@ -6219,9 +6571,11 @@ if (common->invalid_utf) if (common->mode != PCRE2_JIT_COMPLETE) { + OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0); OP1(SLJIT_MOV, TMP2, 0, STR_PTR, 0); move_back(common, NULL, TRUE); check_start_used_ptr(common); + OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0); } } @@ -6240,7 +6594,7 @@ else /* Testing char type. */ #ifdef SUPPORT_UNICODE -if (common->use_ucp) +if (common->ucp) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); @@ -6286,7 +6640,7 @@ peek_char(common, READ_CHAR_MAX, SLJIT_MEM1(SLJIT_SP), LOCALS1, &invalid_utf2); valid_utf = LABEL(); -if (common->use_ucp) +if (common->ucp) { OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, 1); jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE); @@ -6326,7 +6680,7 @@ set_jumps(skipread_list, LABEL()); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP2(SLJIT_XOR | SLJIT_SET_Z, TMP2, 0, TMP2, 0, TMP3, 0); -sljit_emit_fast_return(compiler, TMP1, 0); +OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); #ifdef SUPPORT_UNICODE if (common->invalid_utf) @@ -6338,12 +6692,12 @@ if (common->invalid_utf) OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, -1); - sljit_emit_fast_return(compiler, TMP1, 0); + OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); set_jumps(invalid_utf2, LABEL()); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, TMP2, 0, TMP3, 0); - sljit_emit_fast_return(compiler, TMP1, 0); + OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); } #endif /* SUPPORT_UNICODE */ } @@ -6633,7 +6987,7 @@ if (common->utf) #endif #endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void check_hspace(compiler_common *common) @@ -6672,7 +7026,7 @@ if (common->utf) #endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void check_vspace(compiler_common *common) @@ -6700,7 +7054,7 @@ if (common->utf) #endif /* SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == [16|32] */ OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL); -sljit_emit_fast_return(compiler, RETURN_ADDR, 0); +OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0); } static void do_casefulcmp(compiler_common *common) @@ -6780,7 +7134,7 @@ if (char1_reg == STR_END) OP1(SLJIT_MOV, char2_reg, 0, RETURN_ADDR, 0); } -sljit_emit_fast_return(compiler, TMP1, 0); +OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); } static void do_caselesscmp(compiler_common *common) @@ -6878,7 +7232,7 @@ if (char2_reg == STACK_TOP) } OP1(SLJIT_MOV, char1_reg, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); -sljit_emit_fast_return(compiler, TMP1, 0); +OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); } static PCRE2_SPTR byte_sequence_compare(compiler_common *common, BOOL caseless, PCRE2_SPTR cc, @@ -7189,7 +7543,13 @@ cc = ccbegin; if ((cc[-1] & XCL_NOT) != 0) read_char(common, min, max, backtracks, READ_CHAR_UPDATE_STR_PTR); else + { +#ifdef SUPPORT_UNICODE + read_char(common, min, max, (needstype || needsscript) ? backtracks : NULL, 0); +#else /* !SUPPORT_UNICODE */ read_char(common, min, max, NULL, 0); +#endif /* SUPPORT_UNICODE */ + } if ((cc[-1] & XCL_HASPROP) == 0) { @@ -7275,16 +7635,11 @@ if (needstype || needsscript) /* Before anything else, we deal with scripts. */ if (needsscript) { -// PH hacking - OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2); - OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3); - OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); - - OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); - - OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 0); + OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3); + 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), 3); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script)); ccbegin = cc; @@ -7319,41 +7674,52 @@ if (needstype || needsscript) } cc = ccbegin; - } - if (needschar) - OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); + if (needstype) + { + /* TMP2 has already been shifted by 2 */ + if (!needschar) + { + OP2(SLJIT_ADD, TMP1, 0, TMP2, 0, TMP2, 0); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); + + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); + } + else + { + OP2(SLJIT_ADD, TMP1, 0, TMP2, 0, TMP2, 0); + OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); - if (needstype) + OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); + OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); + typereg = RETURN_ADDR; + } + } + else if (needschar) + OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); + } + else if (needstype) { + OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3); + OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2); + if (!needschar) { -// PH hacking - OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2); - OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3); - OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); - OP2(SLJIT_ADD, TMP1, 0, TMP2, 0, TMP1, 0); + OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0); - OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); - - OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 0); - -// OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM2(TMP1, TMP2), 3); + OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); } else { -// PH hacking - OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2); - - OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3); - - OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); - OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); + OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); + OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype)); typereg = RETURN_ADDR; } } + else if (needschar) + OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0); } #endif /* SUPPORT_UNICODE */ @@ -8728,16 +9094,13 @@ if (common->utf && *cc == OP_REFI) CMPTO(SLJIT_EQUAL, TMP1, 0, char1_reg, 0, loop); -// PH hacking OP1(SLJIT_MOV, TMP3, 0, TMP1, 0); add_jump(compiler, &common->getucd, JUMP(SLJIT_FAST_CALL)); - OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2); - + OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 2); OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 3); - - OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); + OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0); OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_records)); @@ -9597,7 +9960,8 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK) } else { - OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), 0); + SLJIT_ASSERT(extrasize == 3); + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(-1)); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), bra == OP_BRAZERO ? STR_PTR : SLJIT_IMM, 0); } } @@ -9929,7 +10293,7 @@ if (opcode == OP_CBRA || opcode == OP_SCBRA) BACKTRACK_AS(bracket_backtrack)->private_data_ptr = private_data_ptr; matchingpath += IMM2_SIZE; } -else if (opcode == OP_ONCE || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND) +else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_ONCE || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND) { /* Other brackets simply allocate the next entry. */ private_data_ptr = PRIVATE_DATA(ccbegin); @@ -10114,7 +10478,7 @@ else if (opcode == OP_CBRA || opcode == OP_SCBRA) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0); } } -else if (opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND) +else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND) { /* Saving the previous value. */ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); @@ -10240,6 +10604,9 @@ compile_matchingpath(common, matchingpath, cc, backtrack); if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return NULL; +if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); + if (opcode == OP_ONCE) match_once_common(common, ket, BACKTRACK_AS(bracket_backtrack)->u.framesize, private_data_ptr, has_alternatives, needs_control_head); @@ -10840,8 +11207,8 @@ backtrack_common *backtrack; PCRE2_UCHAR opcode; PCRE2_UCHAR type; sljit_u32 max = 0, exact; -BOOL fast_fail; -sljit_s32 fast_str_ptr; +sljit_s32 early_fail_ptr = PRIVATE_DATA(cc + 1); +sljit_s32 early_fail_type; BOOL charpos_enabled; PCRE2_UCHAR charpos_char; unsigned int charpos_othercasebit; @@ -10855,21 +11222,27 @@ int base = (private_data_ptr == 0) ? SLJIT_MEM1(STACK_TOP) : SLJIT_MEM1(SLJIT_SP int offset0 = (private_data_ptr == 0) ? STACK(0) : private_data_ptr; int offset1 = (private_data_ptr == 0) ? STACK(1) : private_data_ptr + (int)sizeof(sljit_sw); int tmp_base, tmp_offset; +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 +BOOL use_tmp; +#endif PUSH_BACKTRACK(sizeof(char_iterator_backtrack), cc, NULL); -fast_str_ptr = PRIVATE_DATA(cc + 1); -fast_fail = TRUE; +early_fail_type = (early_fail_ptr & 0x7); +early_fail_ptr >>= 3; -SLJIT_ASSERT(common->fast_forward_bc_ptr == NULL || fast_str_ptr == 0 || cc == common->fast_forward_bc_ptr); +/* During recursion, these optimizations are disabled. */ +if (common->early_fail_start_ptr == 0) + { + early_fail_ptr = 0; + early_fail_type = type_skip; + } -if (cc == common->fast_forward_bc_ptr) - fast_fail = FALSE; -else if (common->fast_fail_start_ptr == 0) - fast_str_ptr = 0; +SLJIT_ASSERT(common->fast_forward_bc_ptr != NULL || early_fail_ptr == 0 + || (early_fail_ptr >= common->early_fail_start_ptr && early_fail_ptr <= common->early_fail_end_ptr)); -SLJIT_ASSERT(common->fast_forward_bc_ptr != NULL || fast_str_ptr == 0 - || (fast_str_ptr >= common->fast_fail_start_ptr && fast_str_ptr <= common->fast_fail_end_ptr)); +if (early_fail_type == type_fail) + add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr)); cc = get_iterator_parameters(common, cc, &opcode, &type, &max, &exact, &end); @@ -10884,13 +11257,11 @@ else tmp_offset = POSSESSIVE0; } -if (fast_fail && fast_str_ptr != 0) - add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), fast_str_ptr)); - /* Handle fixed part first. */ if (exact > 1) { - SLJIT_ASSERT(fast_str_ptr == 0); + SLJIT_ASSERT(early_fail_ptr == 0); + if (common->mode == PCRE2_JIT_COMPLETE #ifdef SUPPORT_UNICODE && !common->utf @@ -10915,18 +11286,31 @@ if (exact > 1) } } else if (exact == 1) + { compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, TRUE); + if (early_fail_type == type_fail_range) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr); + OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + (int)sizeof(sljit_sw)); + OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, TMP2, 0); + OP2(SLJIT_SUB, TMP2, 0, STR_PTR, 0, TMP2, 0); + add_jump(compiler, &backtrack->topbacktracks, CMP(SLJIT_LESS_EQUAL, TMP2, 0, TMP1, 0)); + + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr + (int)sizeof(sljit_sw), STR_PTR, 0); + } + } + switch(opcode) { case OP_STAR: case OP_UPTO: - SLJIT_ASSERT(fast_str_ptr == 0 || opcode == OP_STAR); + SLJIT_ASSERT(early_fail_ptr == 0 || opcode == OP_STAR); if (type == OP_ANYNL || type == OP_EXTUNI) { SLJIT_ASSERT(private_data_ptr == 0); - SLJIT_ASSERT(fast_str_ptr == 0); + SLJIT_ASSERT(early_fail_ptr == 0); allocate_stack(common, 2); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); @@ -10945,7 +11329,7 @@ switch(opcode) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), POSSESSIVE0, TMP1, 0); } - /* We cannot use TMP3 because of this allocate_stack. */ + /* We cannot use TMP3 because of allocate_stack. */ allocate_stack(common, 1); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); JUMPTO(SLJIT_JUMP, label); @@ -10971,8 +11355,8 @@ switch(opcode) OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); process_partial_match(common); - if (fast_str_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_END, 0); + if (early_fail_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_END, 0); BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); break; } @@ -11002,8 +11386,8 @@ switch(opcode) OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - if (fast_str_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + if (early_fail_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); break; } @@ -11030,7 +11414,7 @@ switch(opcode) if (charpos_enabled) { charpos_char = end[1]; - /* Consumpe the OP_CHAR opcode. */ + /* Consume the OP_CHAR opcode. */ end += 2; #if PCRE2_CODE_UNIT_WIDTH == 8 SLJIT_ASSERT((charpos_othercasebit >> 8) == 0); @@ -11062,8 +11446,8 @@ switch(opcode) add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_ZERO)); } compile_char1_matchingpath(common, type, cc, &backtrack->topbacktracks, FALSE); - if (fast_str_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + if (early_fail_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); JUMPHERE(jump); detect_partial_match(common, &backtrack->topbacktracks); @@ -11076,6 +11460,7 @@ switch(opcode) allocate_stack(common, 2); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); + if (opcode == OP_UPTO) { OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); @@ -11085,53 +11470,55 @@ switch(opcode) /* Search the last instance of charpos_char. */ label = LABEL(); compile_char1_matchingpath(common, type, cc, &no_match, FALSE); - if (fast_str_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + if (early_fail_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); detect_partial_match(common, &no_match); OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0)); if (charpos_othercasebit != 0) OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, charpos_othercasebit); + if (opcode == OP_STAR) { CMPTO(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char, label); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + JUMPTO(SLJIT_JUMP, label); } else { jump = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, charpos_char); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); JUMPHERE(jump); - } - - if (opcode == OP_UPTO) - { OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); JUMPTO(SLJIT_NOT_ZERO, label); } - else - JUMPTO(SLJIT_JUMP, label); set_jumps(no_match, LABEL()); - OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + OP2(SLJIT_ADD, STR_PTR, 0, base, offset0, SLJIT_IMM, IN_UCHARS(1)); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); } -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 - else if (common->utf) + else { if (private_data_ptr == 0) allocate_stack(common, 2); - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 + use_tmp = (!HAS_VIRTUAL_REGISTERS && opcode == OP_STAR); + SLJIT_ASSERT(!use_tmp || tmp_base == TMP3); + if (common->utf) + OP1(SLJIT_MOV, use_tmp ? TMP3 : base, use_tmp ? 0 : offset0, STR_PTR, 0); +#endif if (opcode == OP_UPTO) OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); detect_partial_match(common, &no_match); label = LABEL(); - compile_char1_matchingpath(common, type, cc, &no_match, FALSE); - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); + compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 + if (common->utf) + OP1(SLJIT_MOV, use_tmp ? TMP3 : base, use_tmp ? 0 : offset0, STR_PTR, 0); +#endif if (opcode == OP_UPTO) { @@ -11142,39 +11529,29 @@ switch(opcode) detect_partial_match_to(common, label); OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - set_jumps(no_match, LABEL()); - OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); - if (fast_str_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); - } + set_jumps(no_char1_match, LABEL()); +#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 + if (common->utf) + { + set_jumps(no_match, LABEL()); + if (use_tmp) + { + OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); + OP1(SLJIT_MOV, base, offset0, TMP3, 0); + } + else + OP1(SLJIT_MOV, STR_PTR, 0, base, offset0); + } + else #endif - else - { - if (private_data_ptr == 0) - allocate_stack(common, 2); - - OP1(SLJIT_MOV, base, offset1, STR_PTR, 0); - if (opcode == OP_UPTO) - OP1(SLJIT_MOV, tmp_base, tmp_offset, SLJIT_IMM, max); - - detect_partial_match(common, &no_match); - label = LABEL(); - compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); - if (opcode == OP_UPTO) { - OP2(SLJIT_SUB | SLJIT_SET_Z, tmp_base, tmp_offset, tmp_base, tmp_offset, SLJIT_IMM, 1); - add_jump(compiler, &no_match, JUMP(SLJIT_ZERO)); + OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); + set_jumps(no_match, LABEL()); + OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); } - detect_partial_match_to(common, label); - OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - - set_jumps(no_char1_match, LABEL()); - OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); - set_jumps(no_match, LABEL()); - OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); - if (fast_str_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + if (early_fail_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); } BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); @@ -11185,12 +11562,12 @@ switch(opcode) allocate_stack(common, 1); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); BACKTRACK_AS(char_iterator_backtrack)->matchingpath = LABEL(); - if (fast_str_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + if (early_fail_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); break; case OP_MINUPTO: - SLJIT_ASSERT(fast_str_ptr == 0); + SLJIT_ASSERT(early_fail_ptr == 0); if (private_data_ptr == 0) allocate_stack(common, 2); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); @@ -11200,7 +11577,7 @@ switch(opcode) case OP_QUERY: case OP_MINQUERY: - SLJIT_ASSERT(fast_str_ptr == 0); + SLJIT_ASSERT(early_fail_ptr == 0); if (private_data_ptr == 0) allocate_stack(common, 1); OP1(SLJIT_MOV, base, offset0, STR_PTR, 0); @@ -11221,8 +11598,8 @@ switch(opcode) { OP1(SLJIT_MOV, STR_PTR, 0, STR_END, 0); process_partial_match(common); - if (fast_str_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_END, 0); + if (early_fail_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_END, 0); break; } @@ -11238,16 +11615,17 @@ switch(opcode) set_jumps(no_match, LABEL()); OP1(SLJIT_MOV, STR_PTR, 0, tmp_base, tmp_offset); - if (fast_str_ptr != 0) + if (early_fail_ptr != 0) { - if (tmp_base == TMP3) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, TMP3, 0); + if (!HAS_VIRTUAL_REGISTERS && tmp_base == TMP3) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, TMP3, 0); else - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); } break; } #endif + detect_partial_match(common, &no_match); label = LABEL(); compile_char1_matchingpath(common, type, cc, &no_char1_match, FALSE); @@ -11257,12 +11635,12 @@ switch(opcode) set_jumps(no_char1_match, LABEL()); OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1)); set_jumps(no_match, LABEL()); - if (fast_str_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); + if (early_fail_ptr != 0) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), early_fail_ptr, STR_PTR, 0); break; case OP_POSUPTO: - SLJIT_ASSERT(fast_str_ptr == 0); + SLJIT_ASSERT(early_fail_ptr == 0); #if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32 if (common->utf) { @@ -11298,9 +11676,6 @@ switch(opcode) process_partial_match(common); JUMPHERE(jump); } - - if (fast_str_ptr != 0) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), fast_str_ptr, STR_PTR, 0); break; } @@ -11320,7 +11695,7 @@ switch(opcode) break; case OP_POSQUERY: - SLJIT_ASSERT(fast_str_ptr == 0); + SLJIT_ASSERT(early_fail_ptr == 0); OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); compile_char1_matchingpath(common, type, cc, &no_match, TRUE); OP1(SLJIT_MOV, tmp_base, tmp_offset, STR_PTR, 0); @@ -11695,6 +12070,8 @@ while (cc < ccend) count_match(common); break; + case OP_ASSERT_NA: + case OP_ASSERTBACK_NA: case OP_ONCE: case OP_SCRIPT_RUN: case OP_BRA: @@ -12232,6 +12609,7 @@ else if (has_alternatives) SLJIT_ASSERT(CURRENT_AS(bracket_backtrack)->u.matching_put_label); sljit_set_put_label(CURRENT_AS(bracket_backtrack)->u.matching_put_label, LABEL()); + sljit_emit_op0(compiler, SLJIT_ENDBR); } else next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); @@ -12298,6 +12676,9 @@ if (has_alternatives) if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler))) return; + if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA) + OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr); + if (opcode == OP_SCRIPT_RUN) match_script_run_common(common, private_data_ptr, current); } @@ -12379,7 +12760,10 @@ if (has_alternatives) } } else + { sljit_set_put_label(put_label, LABEL()); + sljit_emit_op0(compiler, SLJIT_ENDBR); + } } COMPILE_BACKTRACKINGPATH(current->top); @@ -12427,7 +12811,7 @@ if (offset != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP1, 0); } } -else if (opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND) +else if (opcode == OP_ASSERT_NA || opcode == OP_ASSERTBACK_NA || opcode == OP_SCRIPT_RUN || opcode == OP_SBRA || opcode == OP_SCOND) { OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, SLJIT_MEM1(STACK_TOP), STACK(0)); free_stack(common, 1); @@ -12775,6 +13159,8 @@ while (current) compile_assert_backtrackingpath(common, current); break; + case OP_ASSERT_NA: + case OP_ASSERTBACK_NA: case OP_ONCE: case OP_SCRIPT_RUN: case OP_BRA: @@ -12872,7 +13258,7 @@ jump_list *match = NULL; struct sljit_jump *next_alt = NULL; struct sljit_jump *accept_exit = NULL; struct sljit_label *quit; -struct sljit_put_label *put_label; +struct sljit_put_label *put_label = NULL; /* Recurse captures then. */ common->then_trap = NULL; @@ -12969,6 +13355,7 @@ while (1) { sljit_emit_ijump(compiler, SLJIT_JUMP, TMP1, 0); sljit_set_put_label(put_label, LABEL()); + sljit_emit_op0(compiler, SLJIT_ENDBR); } else next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0); @@ -12977,7 +13364,10 @@ while (1) free_stack(common, has_accept ? 2 : 1); } else if (alt_max > 3) + { sljit_set_put_label(put_label, LABEL()); + sljit_emit_op0(compiler, SLJIT_ENDBR); + } else { JUMPHERE(next_alt); @@ -13011,7 +13401,7 @@ copy_recurse_data(common, ccbegin, ccend, recurse_copy_private_to_global, local_ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1)); free_stack(common, private_data_size + local_size); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); -sljit_emit_fast_return(compiler, TMP2, 0); +OP_SRC(SLJIT_FAST_RETURN, TMP2, 0); if (common->quit != NULL) { @@ -13036,7 +13426,7 @@ if (has_accept) OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1)); free_stack(common, private_data_size + local_size); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0); - sljit_emit_fast_return(compiler, TMP2, 0); + OP_SRC(SLJIT_FAST_RETURN, TMP2, 0); } if (common->accept != NULL) @@ -13060,7 +13450,7 @@ copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, priva OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), STACK(local_size - 1)); OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1); -sljit_emit_fast_return(compiler, TMP2, 0); +OP_SRC(SLJIT_FAST_RETURN, TMP2, 0); } #undef COMPILE_BACKTRACKINGPATH @@ -13092,9 +13482,9 @@ struct sljit_label *reset_match_label; struct sljit_label *quit_label; struct sljit_jump *jump; struct sljit_jump *minlength_check_failed = NULL; -struct sljit_jump *reqbyte_notfound = NULL; struct sljit_jump *empty_match = NULL; struct sljit_jump *end_anchor_failed = NULL; +jump_list *reqcu_not_found = NULL; SLJIT_ASSERT(tables); @@ -13122,8 +13512,8 @@ common->read_only_data_head = NULL; common->fcc = tables + fcc_offset; common->lcc = (sljit_sw)(tables + lcc_offset); common->mode = mode; -common->might_be_empty = re->minlength == 0; -common->allow_empty_partial = (re->max_lookbehind > 0) || (re->flags & PCRE2_MATCH_EMPTY) != 0; +common->might_be_empty = (re->minlength == 0) || (re->flags & PCRE2_MATCH_EMPTY); +common->allow_empty_partial = (re->max_lookbehind > 0) || (re->flags & PCRE2_MATCH_EMPTY); common->nltype = NLTYPE_FIXED; switch(re->newline_convention) { @@ -13160,7 +13550,7 @@ common->alt_circumflex = (re->overall_options & PCRE2_ALT_CIRCUMFLEX) != 0; #ifdef SUPPORT_UNICODE /* PCRE_UTF[16|32] have the same value as PCRE_UTF8. */ common->utf = (re->overall_options & PCRE2_UTF) != 0; -common->use_ucp = (re->overall_options & PCRE2_UCP) != 0; +common->ucp = (re->overall_options & PCRE2_UCP) != 0; if (common->utf) { if (common->nltype == NLTYPE_ANY) @@ -13272,13 +13662,10 @@ memset(common->private_data_ptrs, 0, total_length * sizeof(sljit_s32)); private_data_size = common->cbra_ptr + (re->top_bracket + 1) * sizeof(sljit_sw); set_private_data_ptrs(common, &private_data_size, ccend); -if ((re->overall_options & PCRE2_ANCHORED) == 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0) - { - if (!detect_fast_forward_skip(common, &private_data_size) && !common->has_skip_in_assert_back) - detect_fast_fail(common, common->start, &private_data_size, 4); - } +if ((re->overall_options & PCRE2_ANCHORED) == 0 && (re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0 && !common->has_skip_in_assert_back) + detect_early_fail(common, common->start, &private_data_size, 0, 0); -SLJIT_ASSERT(common->fast_fail_start_ptr <= common->fast_fail_end_ptr); +SLJIT_ASSERT(common->early_fail_start_ptr <= common->early_fail_end_ptr); if (private_data_size > SLJIT_MAX_LOCAL_SIZE) { @@ -13294,7 +13681,7 @@ if (common->has_then) set_then_offsets(common, common->start, NULL); } -compiler = sljit_create_compiler(allocator_data); +compiler = sljit_create_compiler(allocator_data, NULL); if (!compiler) { SLJIT_FREE(common->optimized_cbracket, allocator_data); @@ -13322,8 +13709,8 @@ OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_sta OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0); -if (common->fast_fail_start_ptr < common->fast_fail_end_ptr) - reset_fast_fail(common); +if (common->early_fail_start_ptr < common->early_fail_end_ptr) + reset_early_fail(common); if (mode == PCRE2_JIT_PARTIAL_SOFT) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1); @@ -13360,7 +13747,7 @@ if (mode == PCRE2_JIT_COMPLETE && re->minlength > 0 && (re->overall_options & PC minlength_check_failed = CMP(SLJIT_GREATER, TMP2, 0, STR_END, 0); } if (common->req_char_ptr != 0) - reqbyte_notfound = search_requested_char(common, (PCRE2_UCHAR)(re->last_codeunit), (re->flags & PCRE2_LASTCASELESS) != 0, (re->flags & PCRE2_FIRSTSET) != 0); + reqcu_not_found = search_requested_char(common, (PCRE2_UCHAR)(re->last_codeunit), (re->flags & PCRE2_LASTCASELESS) != 0, (re->flags & PCRE2_FIRSTSET) != 0); /* Store the current STR_PTR in OVECTOR(0). */ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), OVECTOR(0), STR_PTR, 0); @@ -13369,7 +13756,7 @@ OP1(SLJIT_MOV, COUNT_MATCH, 0, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH); if (common->capture_last_ptr != 0) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->capture_last_ptr, SLJIT_IMM, 0); if (common->fast_forward_bc_ptr != NULL) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), PRIVATE_DATA(common->fast_forward_bc_ptr + 1), STR_PTR, 0); + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), PRIVATE_DATA(common->fast_forward_bc_ptr + 1) >> 3, STR_PTR, 0); if (common->start_ptr != OVECTOR(0)) OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->start_ptr, STR_PTR, 0); @@ -13416,6 +13803,8 @@ if (common->abort != NULL) set_jumps(common->abort, common->abort_label); if (minlength_check_failed != NULL) SET_LABEL(minlength_check_failed, common->abort_label); + +sljit_emit_op0(compiler, SLJIT_SKIP_FRAMES_BEFORE_RETURN); sljit_emit_return(compiler, SLJIT_MOV, SLJIT_RETURN_REG, 0); if (common->failed_match != NULL) @@ -13468,7 +13857,7 @@ if ((re->overall_options & PCRE2_ANCHORED) == 0 && common->match_end_ptr != 0) } OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), - (common->fast_forward_bc_ptr != NULL) ? (PRIVATE_DATA(common->fast_forward_bc_ptr + 1)) : common->start_ptr); + (common->fast_forward_bc_ptr != NULL) ? (PRIVATE_DATA(common->fast_forward_bc_ptr + 1) >> 3) : common->start_ptr); if ((re->overall_options & PCRE2_ANCHORED) == 0) { @@ -13493,8 +13882,8 @@ if ((re->overall_options & PCRE2_ANCHORED) == 0) } /* No more remaining characters. */ -if (reqbyte_notfound != NULL) - JUMPHERE(reqbyte_notfound); +if (reqcu_not_found != NULL) + set_jumps(reqcu_not_found, LABEL()); if (mode == PCRE2_JIT_PARTIAL_SOFT) CMPTO(SLJIT_NOT_EQUAL, SLJIT_MEM1(SLJIT_SP), common->hit_start, SLJIT_IMM, -1, common->partialmatchlabel); @@ -13519,8 +13908,8 @@ if (common->might_be_empty) } common->fast_forward_bc_ptr = NULL; -common->fast_fail_start_ptr = 0; -common->fast_fail_end_ptr = 0; +common->early_fail_start_ptr = 0; +common->early_fail_end_ptr = 0; common->currententry = common->entries; common->local_quit_available = TRUE; quit_label = common->quit_label; @@ -13563,7 +13952,7 @@ OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0); OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_RETURN_REG, 0); OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0); OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS1); -sljit_emit_fast_return(compiler, TMP1, 0); +OP_SRC(SLJIT_FAST_RETURN, TMP1, 0); /* Allocation failed. */ JUMPHERE(jump); @@ -13694,7 +14083,7 @@ else { /* This case is highly unlikely since we just recently freed a lot of memory. Not impossible though. */ - sljit_free_code(executable_func); + sljit_free_code(executable_func, NULL); PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data); return PCRE2_ERROR_NOMEMORY; } @@ -13742,11 +14131,6 @@ pcre2_jit_compile(pcre2_code *code, uint32_t options) { pcre2_real_code *re = (pcre2_real_code *)code; -#ifdef SUPPORT_JIT -executable_functions *functions = (executable_functions *)re->executable_jit; -static int executable_allocator_is_working = 0; -#endif - if (code == NULL) return PCRE2_ERROR_NULL; @@ -13779,6 +14163,11 @@ actions are needed: avoid compiler warnings. */ +#ifdef SUPPORT_JIT +executable_functions *functions = (executable_functions *)re->executable_jit; +static int executable_allocator_is_working = 0; +#endif + if ((options & PCRE2_JIT_INVALID_UTF) != 0) { if ((re->overall_options & PCRE2_MATCH_INVALID_UTF) == 0) @@ -13808,13 +14197,13 @@ if (executable_allocator_is_working == 0) /* Checks whether the executable allocator is working. This check might run multiple times in multi-threaded environments, but the result should not be affected by it. */ - void *ptr = SLJIT_MALLOC_EXEC(32); + void *ptr = SLJIT_MALLOC_EXEC(32, NULL); executable_allocator_is_working = -1; if (ptr != NULL) { - SLJIT_FREE_EXEC(((sljit_u8*)(ptr)) + SLJIT_EXEC_OFFSET(ptr)); + SLJIT_FREE_EXEC(((sljit_u8*)(ptr)) + SLJIT_EXEC_OFFSET(ptr), NULL); executable_allocator_is_working = 1; } } diff --git a/thirdparty/pcre2/src/pcre2_jit_misc.c b/thirdparty/pcre2/src/pcre2_jit_misc.c index efdb05580f..ec924e0f9b 100644 --- a/thirdparty/pcre2/src/pcre2_jit_misc.c +++ b/thirdparty/pcre2/src/pcre2_jit_misc.c @@ -89,7 +89,7 @@ int i; for (i = 0; i < JIT_NUMBER_OF_COMPILE_MODES; i++) { if (functions->executable_funcs[i] != NULL) - sljit_free_code(functions->executable_funcs[i]); + sljit_free_code(functions->executable_funcs[i], NULL); PRIV(jit_free_rodata)(functions->read_only_data_heads[i], allocator_data); } @@ -145,6 +145,11 @@ maxsize = (maxsize + STACK_GROWTH_RATE - 1) & ~(STACK_GROWTH_RATE - 1); jit_stack = PRIV(memctl_malloc)(sizeof(pcre2_real_jit_stack), (pcre2_memctl *)gcontext); if (jit_stack == NULL) return NULL; jit_stack->stack = sljit_allocate_stack(startsize, maxsize, &jit_stack->memctl); +if (jit_stack->stack == NULL) + { + jit_stack->memctl.free(jit_stack, jit_stack->memctl.memory_data); + return NULL; + } return jit_stack; #endif diff --git a/thirdparty/pcre2/src/pcre2_jit_neon_inc.h b/thirdparty/pcre2/src/pcre2_jit_neon_inc.h index 55b1f32ac9..150da29eba 100644 --- a/thirdparty/pcre2/src/pcre2_jit_neon_inc.h +++ b/thirdparty/pcre2/src/pcre2_jit_neon_inc.h @@ -87,6 +87,10 @@ static sljit_u8* SLJIT_FUNC FF_FUN(sljit_u8 *str_end, sljit_u8 *str_ptr, sljit_u { quad_word qw; int_char ic; + +SLJIT_UNUSED_ARG(offs1); +SLJIT_UNUSED_ARG(offs2); + ic.x = chars; #if defined(FFCS) @@ -117,11 +121,16 @@ 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; @@ -140,7 +149,10 @@ else } if (char2a == char2b) + { cmp2a = VDUPQ(char2a); + cmp2b = VDUPQ(0); /* to avoid errors on older compilers -Werror=maybe-uninitialized */ + } else { sljit_u32 bit2 = char2a ^ char2b; @@ -208,8 +220,16 @@ if (p1 < str_ptr) else data2 = shift_left_n_lanes(data, offs1 - offs2); -data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b); -data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b); +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 @@ -275,8 +295,14 @@ while (str_ptr < str_end) data = VCEQQ(data, cmp1a); data2 = VCEQQ(data2, cmp2a); # else - data = fast_forward_char_pair_compare(compare1_type, data, cmp1a, cmp1b); - data2 = fast_forward_char_pair_compare(compare2_type, data2, cmp2a, cmp2b); + 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); diff --git a/thirdparty/pcre2/src/pcre2_jit_simd_inc.h b/thirdparty/pcre2/src/pcre2_jit_simd_inc.h index f7d56b29f8..5673d338c0 100644 --- a/thirdparty/pcre2/src/pcre2_jit_simd_inc.h +++ b/thirdparty/pcre2/src/pcre2_jit_simd_inc.h @@ -344,6 +344,136 @@ if (common->utf && offset > 0) #endif } +#define JIT_HAS_FAST_REQUESTED_CHAR_SIMD (sljit_has_cpu_feature(SLJIT_HAS_SSE2)) + +static jump_list *fast_requested_char_simd(compiler_common *common, PCRE2_UCHAR char1, PCRE2_UCHAR char2) +{ +DEFINE_COMPILER; +struct sljit_label *start; +struct sljit_jump *quit; +jump_list *not_found = NULL; +sse2_compare_type compare_type = sse2_compare_match1; +sljit_u8 instruction[8]; +sljit_s32 tmp1_reg_ind = sljit_get_register_index(TMP1); +sljit_s32 str_ptr_reg_ind = sljit_get_register_index(STR_PTR); +sljit_s32 data_ind = 0; +sljit_s32 tmp_ind = 1; +sljit_s32 cmp1_ind = 2; +sljit_s32 cmp2_ind = 3; +sljit_u32 bit = 0; +int i; + +if (char1 != char2) + { + bit = char1 ^ char2; + compare_type = sse2_compare_match1i; + + if (!is_powerof2(bit)) + { + bit = 0; + compare_type = sse2_compare_match2; + } + } + +add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0)); +OP1(SLJIT_MOV, TMP2, 0, TMP1, 0); +OP1(SLJIT_MOV, TMP3, 0, STR_PTR, 0); + +/* First part (unaligned start) */ + +OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(char1 | bit)); + +SLJIT_ASSERT(tmp1_reg_ind < 8); + +/* MOVD xmm, r/m32 */ +instruction[0] = 0x66; +instruction[1] = 0x0f; +instruction[2] = 0x6e; +instruction[3] = 0xc0 | (cmp1_ind << 3) | tmp1_reg_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +if (char1 != char2) + { + OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, character_to_int32(bit != 0 ? bit : char2)); + + /* MOVD xmm, r/m32 */ + instruction[3] = 0xc0 | (cmp2_ind << 3) | tmp1_reg_ind; + sljit_emit_op_custom(compiler, instruction, 4); + } + +OP1(SLJIT_MOV, STR_PTR, 0, TMP2, 0); + +/* PSHUFD xmm1, xmm2/m128, imm8 */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0x70; +instruction[3] = 0xc0 | (cmp1_ind << 3) | cmp1_ind; +instruction[4] = 0; +sljit_emit_op_custom(compiler, instruction, 5); + +if (char1 != char2) + { + /* PSHUFD xmm1, xmm2/m128, imm8 */ + instruction[3] = 0xc0 | (cmp2_ind << 3) | cmp2_ind; + sljit_emit_op_custom(compiler, instruction, 5); + } + +OP2(SLJIT_AND, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, ~0xf); +OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xf); + +load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0); +for (i = 0; i < 4; i++) + fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind); + +/* PMOVMSKB reg, xmm */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0xd7; +instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP2, 0); +OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, TMP2, 0); + +quit = CMP(SLJIT_NOT_ZERO, TMP1, 0, SLJIT_IMM, 0); + +OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP2, 0); + +/* Second part (aligned) */ +start = LABEL(); + +OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, 16); + +add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0)); + +load_from_mem_sse2(compiler, data_ind, str_ptr_reg_ind, 0); +for (i = 0; i < 4; i++) + fast_forward_char_pair_sse2_compare(compiler, compare_type, i, data_ind, cmp1_ind, cmp2_ind, tmp_ind); + +/* PMOVMSKB reg, xmm */ +/* instruction[0] = 0x66; */ +/* instruction[1] = 0x0f; */ +instruction[2] = 0xd7; +instruction[3] = 0xc0 | (tmp1_reg_ind << 3) | data_ind; +sljit_emit_op_custom(compiler, instruction, 4); + +CMPTO(SLJIT_ZERO, TMP1, 0, SLJIT_IMM, 0, start); + +JUMPHERE(quit); + +/* BSF r32, r/m32 */ +instruction[0] = 0x0f; +instruction[1] = 0xbc; +instruction[2] = 0xc0 | (tmp1_reg_ind << 3) | tmp1_reg_ind; +sljit_emit_op_custom(compiler, instruction, 3); + +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, STR_PTR, 0); +add_jump(compiler, ¬_found, CMP(SLJIT_GREATER_EQUAL, TMP1, 0, STR_END, 0)); + +OP1(SLJIT_MOV, STR_PTR, 0, TMP3, 0); +return not_found; +} + #ifndef _WIN64 static SLJIT_INLINE sljit_u32 max_fast_forward_char_pair_offset(void) diff --git a/thirdparty/pcre2/src/pcre2_maketables.c b/thirdparty/pcre2/src/pcre2_maketables.c index 8c93b4b573..56d2494023 100644 --- a/thirdparty/pcre2/src/pcre2_maketables.c +++ b/thirdparty/pcre2/src/pcre2_maketables.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2019 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -41,10 +41,11 @@ POSSIBILITY OF SUCH DAMAGE. /* This module contains the external function pcre2_maketables(), which builds character tables for PCRE2 in the current locale. The file is compiled on its -own as part of the PCRE2 library. However, it is also included in the -compilation of dftables.c, in which case the macro DFTABLES is defined. */ +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 DFTABLES +#ifndef PCRE2_DFTABLES /* Compiling the library */ # ifdef HAVE_CONFIG_H # include "config.h" # endif @@ -61,28 +62,29 @@ compilation of dftables.c, in which case the macro DFTABLES is defined. */ a pointer to them. They are build using the ctype functions, and consequently their contents will depend upon the current locale setting. When compiled as part of the library, the store is obtained via a general context malloc, if -supplied, but when DFTABLES is defined (when compiling the dftables auxiliary -program) malloc() is used, and the function has a different name so as not to -clash with the prototype in pcre2.h. +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 DFTABLES is defined - else a PCRE2 general context or NULL +Arguments: none when PCRE2_DFTABLES is defined + else a PCRE2 general context or NULL Returns: pointer to the contiguous block of data + else NULL if memory allocation failed */ -#ifdef DFTABLES /* Included in freestanding dftables.c program */ +#ifdef PCRE2_DFTABLES /* Included in freestanding pcre2_dftables program */ static const uint8_t *maketables(void) { -uint8_t *yield = (uint8_t *)malloc(tables_length); +uint8_t *yield = (uint8_t *)malloc(TABLES_LENGTH); -#else /* Not DFTABLES, compiling the library */ +#else /* Not PCRE2_DFTABLES, that is, compiling the library */ PCRE2_EXP_DEFN const uint8_t * PCRE2_CALL_CONVENTION pcre2_maketables(pcre2_general_context *gcontext) { uint8_t *yield = (uint8_t *)((gcontext != NULL)? - gcontext->memctl.malloc(tables_length, gcontext->memctl.memory_data) : - malloc(tables_length)); -#endif /* DFTABLES */ + gcontext->memctl.malloc(TABLES_LENGTH, gcontext->memctl.memory_data) : + malloc(TABLES_LENGTH)); +#endif /* PCRE2_DFTABLES */ int i; uint8_t *p; @@ -103,8 +105,8 @@ exclusive ones - in some locales things may be different. Note that the table for "space" includes everything "isspace" gives, including VT in the default locale. This makes it work for the POSIX class [:space:]. -From release 8.34 is is also correct for Perl space, because Perl added VT at -release 5.18. +From PCRE1 release 8.34 and for all PCRE2 releases it is also correct for Perl +space, because Perl added VT at release 5.18. Note also that it is possible for a character to be alnum or alpha without being lower or upper, such as "male and female ordinals" (\xAA and \xBA) in the @@ -114,24 +116,24 @@ 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(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); } p += cbit_length; /* Finally, the character type table. In this, we used to exclude VT from the white space chars, because Perl didn't recognize it as such for \s and for -comments within regexes. However, Perl changed at release 5.18, so PCRE changed -at release 8.34. */ +comments within regexes. However, Perl changed at release 5.18, so PCRE1 +changed at release 8.34 and it's always been this way for PCRE2. */ for (i = 0; i < 256; i++) { @@ -147,7 +149,7 @@ for (i = 0; i < 256; i++) return yield; } -#ifndef DFTABLES +#ifndef PCRE2_DFTABLES /* Compiling the library */ PCRE2_EXP_DEFN void PCRE2_CALL_CONVENTION pcre2_maketables_free(pcre2_general_context *gcontext, const uint8_t *tables) { diff --git a/thirdparty/pcre2/src/pcre2_match.c b/thirdparty/pcre2/src/pcre2_match.c index 48e7b9dbb2..e3f78c2ca3 100644 --- a/thirdparty/pcre2/src/pcre2_match.c +++ b/thirdparty/pcre2/src/pcre2_match.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2015-2019 University of Cambridge + New API code Copyright (c) 2015-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -381,8 +381,12 @@ length = Fovector[offset+1] - Fovector[offset]; if (caseless) { #if defined SUPPORT_UNICODE - if ((mb->poptions & PCRE2_UTF) != 0) + BOOL utf = (mb->poptions & PCRE2_UTF) != 0; + + if (utf || (mb->poptions & PCRE2_UCP) != 0) { + PCRE2_SPTR endptr = p + length; + /* Match characters up to the end of the reference. NOTE: the number of code units matched may differ, because in UTF-8 there are some characters whose upper and lower case codes have different numbers of bytes. For @@ -390,16 +394,25 @@ 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). */ + wrong). UCP without uses Unicode properties but without UTF encoding. */ - PCRE2_SPTR endptr = p + length; while (p < endptr) { uint32_t c, d; const ucd_record *ur; if (eptr >= mb->end_subject) return 1; /* Partial match */ - GETCHARINC(c, eptr); - GETCHARINC(d, p); + + if (utf) + { + GETCHARINC(c, eptr); + GETCHARINC(d, p); + } + else + { + c = *eptr++; + d = *p++; + } + ur = GET_UCD(d); if (c != d && c != (uint32_t)((int)d + ur->other_case)) { @@ -415,7 +428,7 @@ if (caseless) else #endif - /* Not in UTF mode */ + /* Not in UTF or UCP mode */ { for (; length > 0; length--) { @@ -432,7 +445,8 @@ if (caseless) } /* In the caseful case, we can just compare the code units, whether or not we -are in UTF mode. When partial matching, we have to do this unit-by-unit. */ +are in UTF and/or UCP mode. When partial matching, we have to do this unit by +unit. */ else { @@ -574,8 +588,8 @@ match(PCRE2_SPTR start_eptr, PCRE2_SPTR start_ecode, PCRE2_SIZE *ovector, heapframe *F; /* Current frame pointer */ heapframe *N = NULL; /* Temporary frame pointers */ heapframe *P = NULL; -heapframe *assert_accept_frame; /* For passing back the frame with captures */ -PCRE2_SIZE frame_copy_size; /* Amount to copy when creating a new frame */ +heapframe *assert_accept_frame = NULL; /* For passing back a frame with captures */ +PCRE2_SIZE frame_copy_size; /* Amount to copy when creating a new frame */ /* Local variables that do not need to be preserved over calls to RRMATCH(). */ @@ -598,12 +612,13 @@ BOOL condition; /* Used in conditional groups */ BOOL cur_is_word; /* Used in "word" tests */ BOOL prev_is_word; /* Used in "word" tests */ -/* UTF flag */ +/* UTF and UCP flags */ #ifdef SUPPORT_UNICODE BOOL utf = (mb->poptions & PCRE2_UTF) != 0; +BOOL ucp = (mb->poptions & PCRE2_UCP) != 0; #else -BOOL utf = FALSE; +BOOL utf = FALSE; /* Required for convenience even when no Unicode support */ #endif /* This is the length of the last part of a backtracking frame that must be @@ -928,6 +943,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode); } else #endif + /* Not UTF mode */ { if (mb->end_subject - Feptr < 1) @@ -987,10 +1003,30 @@ fprintf(stderr, "++ op=%d\n", *Fecode); if (dc != fc && dc != UCD_OTHERCASE(fc)) RRETURN(MATCH_NOMATCH); } } + + /* If UCP is set without UTF we must do the same as above, but with one + character per code unit. */ + + else if (ucp) + { + uint32_t cc = UCHAR21(Feptr); + fc = Fecode[1]; + if (fc < 128) + { + if (mb->lcc[fc] != TABLE_GET(cc, mb->lcc, cc)) RRETURN(MATCH_NOMATCH); + } + else + { + if (cc != fc && cc != UCD_OTHERCASE(fc)) RRETURN(MATCH_NOMATCH); + } + Feptr++; + Fecode += 2; + } + else #endif /* SUPPORT_UNICODE */ - /* Not UTF mode; use the table for characters < 256. */ + /* Not UTF or UCP mode; use the table for characters < 256. */ { if (TABLE_GET(Fecode[1], mb->lcc, Fecode[1]) != TABLE_GET(*Feptr, mb->lcc, *Feptr)) RRETURN(MATCH_NOMATCH); @@ -1010,6 +1046,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode); SCHECK_PARTIAL(); RRETURN(MATCH_NOMATCH); } + #ifdef SUPPORT_UNICODE if (utf) { @@ -1026,15 +1063,42 @@ fprintf(stderr, "++ op=%d\n", *Fecode); if (ch > 127) ch = UCD_OTHERCASE(ch); else - ch = TABLE_GET(ch, mb->fcc, ch); + ch = (mb->fcc)[ch]; + if (ch == fc) RRETURN(MATCH_NOMATCH); + } + } + + /* UCP without UTF is as above, but with one character per code unit. */ + + else if (ucp) + { + uint32_t ch; + fc = UCHAR21INC(Feptr); + ch = Fecode[1]; + Fecode += 2; + + if (ch == fc) + { + RRETURN(MATCH_NOMATCH); /* Caseful match */ + } + else if (Fop == OP_NOTI) /* If caseless */ + { + if (ch > 127) + ch = UCD_OTHERCASE(ch); + else + ch = (mb->fcc)[ch]; if (ch == fc) RRETURN(MATCH_NOMATCH); } } + else #endif /* SUPPORT_UNICODE */ + + /* Neither UTF nor UCP is set */ + { uint32_t ch = Fecode[1]; - fc = *Feptr++; + fc = UCHAR21INC(Feptr); if (ch == fc || (Fop == OP_NOTI && TABLE_GET(ch, mb->fcc, ch) == fc)) RRETURN(MATCH_NOMATCH); Fecode += 2; @@ -1244,7 +1308,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode); #endif /* SUPPORT_UNICODE */ /* When not in UTF mode, load a single-code-unit character. Then proceed as - above. */ + above, using Unicode casing if either UTF or UCP is set. */ Lc = *Fecode++; @@ -1253,11 +1317,15 @@ fprintf(stderr, "++ op=%d\n", *Fecode); if (Fop >= OP_STARI) { #if PCRE2_CODE_UNIT_WIDTH == 8 - /* Lc must be < 128 in UTF-8 mode. */ +#ifdef SUPPORT_UNICODE + if (ucp && !utf && Lc > 127) Loc = UCD_OTHERCASE(Lc); + else +#endif /* SUPPORT_UNICODE */ + /* Lc will be < 128 in UTF-8 mode. */ Loc = mb->fcc[Lc]; #else /* 16-bit & 32-bit */ #ifdef SUPPORT_UNICODE - if (utf && Lc > 127) Loc = UCD_OTHERCASE(Lc); + if ((utf || ucp) && Lc > 127) Loc = UCD_OTHERCASE(Lc); else #endif /* SUPPORT_UNICODE */ Loc = TABLE_GET(Lc, mb->fcc, Lc); @@ -1490,7 +1558,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode); if (Fop >= OP_NOTSTARI) /* Caseless */ { #ifdef SUPPORT_UNICODE - if (utf && Lc > 127) + if ((utf || ucp) && Lc > 127) Loc = UCD_OTHERCASE(Lc); else #endif /* SUPPORT_UNICODE */ @@ -6045,11 +6113,10 @@ BOOL firstline; BOOL has_first_cu = FALSE; BOOL has_req_cu = FALSE; BOOL startline; -BOOL utf; #if PCRE2_CODE_UNIT_WIDTH == 8 -BOOL memchr_not_found_first_cu = FALSE; -BOOL memchr_not_found_first_cu2 = FALSE; +BOOL memchr_not_found_first_cu; +BOOL memchr_not_found_first_cu2; #endif PCRE2_UCHAR first_cu = 0; @@ -6069,13 +6136,19 @@ PCRE2_SPTR match_partial; BOOL use_jit; #endif +/* This flag is needed even when Unicode is not supported for convenience +(it is used by the IS_NEWLINE macro). */ + +BOOL utf = FALSE; + #ifdef SUPPORT_UNICODE +BOOL ucp = FALSE; BOOL allow_invalid; uint32_t fragment_options = 0; #ifdef SUPPORT_JIT BOOL jit_checked_utf = FALSE; #endif -#endif +#endif /* SUPPORT_UNICODE */ PCRE2_SIZE frame_size; @@ -6091,7 +6164,8 @@ proves to be too small, it is replaced by a larger one on the heap. To get a vector of the size required that is aligned for pointers, allocate it as a vector of pointers. */ -PCRE2_SPTR stack_frames_vector[START_FRAMES_SIZE/sizeof(PCRE2_SPTR)]; +PCRE2_SPTR stack_frames_vector[START_FRAMES_SIZE/sizeof(PCRE2_SPTR)] + PCRE2_KEEP_UNINITIALIZED; mb->stack_frames = (heapframe *)stack_frames_vector; /* A length equal to PCRE2_ZERO_TERMINATED implies a zero-terminated @@ -6147,12 +6221,13 @@ use_jit = (re->executable_jit != NULL && (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0); #endif -/* Initialize UTF parameters. */ +/* Initialize UTF/UCP parameters. */ -utf = (re->overall_options & PCRE2_UTF) != 0; #ifdef SUPPORT_UNICODE +utf = (re->overall_options & PCRE2_UTF) != 0; allow_invalid = (re->overall_options & PCRE2_MATCH_INVALID_UTF) != 0; -#endif +ucp = (re->overall_options & PCRE2_UCP) != 0; +#endif /* SUPPORT_UNICODE */ /* Convert the partial matching flags into an integer. */ @@ -6589,9 +6664,13 @@ if ((re->flags & PCRE2_FIRSTSET) != 0) if ((re->flags & PCRE2_FIRSTCASELESS) != 0) { first_cu2 = TABLE_GET(first_cu, mb->fcc, first_cu); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 - if (utf && first_cu > 127) first_cu2 = UCD_OTHERCASE(first_cu); +#ifdef SUPPORT_UNICODE +#if PCRE2_CODE_UNIT_WIDTH == 8 + if (first_cu > 127 && ucp && !utf) first_cu2 = UCD_OTHERCASE(first_cu); +#else + if (first_cu > 127 && (utf || ucp)) first_cu2 = UCD_OTHERCASE(first_cu); #endif +#endif /* SUPPORT_UNICODE */ } } else @@ -6607,9 +6686,13 @@ if ((re->flags & PCRE2_LASTSET) != 0) if ((re->flags & PCRE2_LASTCASELESS) != 0) { req_cu2 = TABLE_GET(req_cu, mb->fcc, req_cu); -#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 8 - if (utf && req_cu > 127) req_cu2 = UCD_OTHERCASE(req_cu); +#ifdef SUPPORT_UNICODE +#if PCRE2_CODE_UNIT_WIDTH == 8 + if (req_cu > 127 && ucp && !utf) req_cu2 = UCD_OTHERCASE(req_cu); +#else + if (req_cu > 127 && (utf || ucp)) req_cu2 = UCD_OTHERCASE(req_cu); #endif +#endif /* SUPPORT_UNICODE */ } } @@ -6626,6 +6709,11 @@ FRAGMENT_RESTART: start_partial = match_partial = NULL; mb->hitend = FALSE; +#if PCRE2_CODE_UNIT_WIDTH == 8 +memchr_not_found_first_cu = FALSE; +memchr_not_found_first_cu2 = FALSE; +#endif + for(;;) { PCRE2_SPTR new_start_match; @@ -6756,15 +6844,16 @@ for(;;) #endif } - /* If we can't find the required code unit, having reached the true end - of the subject, break the bumpalong loop, to force a match failure, - except when doing partial matching, when we let the next cycle run at - the end of the subject. To see why, consider the pattern /(?<=abc)def/, - which partially matches "abc", even though the string does not contain - the starting character "d". If we have not reached the true end of the - subject (PCRE2_FIRSTLINE caused end_subject to be temporarily modified) - we also let the cycle run, because the matching string is legitimately - allowed to start with the first code unit of a newline. */ + /* If we can't find the required first code unit, having reached the + true end of the subject, break the bumpalong loop, to force a match + failure, except when doing partial matching, when we let the next cycle + run at the end of the subject. To see why, consider the pattern + /(?<=abc)def/, which partially matches "abc", even though the string + does not contain the starting character "d". If we have not reached the + true end of the subject (PCRE2_FIRSTLINE caused end_subject to be + temporarily modified) we also let the cycle run, because the matching + string is legitimately allowed to start with the first code unit of a + newline. */ if (mb->partial == 0 && start_match >= mb->end_subject) { @@ -7103,6 +7192,7 @@ if (utf && end_subject != true_end_subject && starting code units in 8-bit and 16-bit modes. */ start_match = end_subject + 1; + #if PCRE2_CODE_UNIT_WIDTH != 32 while (start_match < true_end_subject && NOT_FIRSTCU(*start_match)) start_match++; diff --git a/thirdparty/pcre2/src/pcre2_serialize.c b/thirdparty/pcre2/src/pcre2_serialize.c index cec1a035d1..ba17a26d2e 100644 --- a/thirdparty/pcre2/src/pcre2_serialize.c +++ b/thirdparty/pcre2/src/pcre2_serialize.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2018 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -90,7 +90,7 @@ if (codes == NULL || serialized_bytes == NULL || serialized_size == NULL) if (number_of_codes <= 0) return PCRE2_ERROR_BADDATA; /* Compute total size. */ -total_size = sizeof(pcre2_serialized_data) + tables_length; +total_size = sizeof(pcre2_serialized_data) + TABLES_LENGTH; tables = NULL; for (i = 0; i < number_of_codes; i++) @@ -121,8 +121,8 @@ data->number_of_codes = number_of_codes; /* Copy all compiled code data. */ dst_bytes = bytes + sizeof(pcre2_serialized_data); -memcpy(dst_bytes, tables, tables_length); -dst_bytes += tables_length; +memcpy(dst_bytes, tables, TABLES_LENGTH); +dst_bytes += TABLES_LENGTH; for (i = 0; i < number_of_codes; i++) { @@ -189,12 +189,12 @@ src_bytes = bytes + sizeof(pcre2_serialized_data); /* Decode tables. The reference count for the tables is stored immediately following them. */ -tables = memctl->malloc(tables_length + sizeof(PCRE2_SIZE), memctl->memory_data); +tables = memctl->malloc(TABLES_LENGTH + sizeof(PCRE2_SIZE), memctl->memory_data); if (tables == NULL) return PCRE2_ERROR_NOMEMORY; -memcpy(tables, src_bytes, tables_length); -*(PCRE2_SIZE *)(tables + tables_length) = number_of_codes; -src_bytes += tables_length; +memcpy(tables, src_bytes, TABLES_LENGTH); +*(PCRE2_SIZE *)(tables + TABLES_LENGTH) = number_of_codes; +src_bytes += TABLES_LENGTH; /* Decode the byte stream. We must not try to read the size from the compiled code block in the stream, because it might be unaligned, which causes errors on diff --git a/thirdparty/pcre2/src/pcre2_study.c b/thirdparty/pcre2/src/pcre2_study.c index 2883868618..9bbb37570f 100644 --- a/thirdparty/pcre2/src/pcre2_study.c +++ b/thirdparty/pcre2/src/pcre2_study.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2019 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -58,7 +58,7 @@ collecting data (e.g. minimum matching length). */ /* Returns from set_start_bits() */ -enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE, SSB_UNKNOWN }; +enum { SSB_FAIL, SSB_DONE, SSB_CONTINUE, SSB_UNKNOWN, SSB_TOODEEP }; /************************************************* @@ -772,15 +772,19 @@ Arguments: p points to the first code unit of the character caseless TRUE if caseless utf TRUE for UTF mode + ucp TRUE for UCP mode Returns: pointer after the character */ static PCRE2_SPTR -set_table_bit(pcre2_real_code *re, PCRE2_SPTR p, BOOL caseless, BOOL utf) +set_table_bit(pcre2_real_code *re, PCRE2_SPTR p, BOOL caseless, BOOL utf, + BOOL ucp) { uint32_t c = *p++; /* First code unit */ -(void)utf; /* Stop compiler warning when UTF not supported */ + +(void)utf; /* Stop compiler warnings when UTF not supported */ +(void)ucp; /* In 16-bit and 32-bit modes, code units greater than 0xff set the bit for 0xff. */ @@ -810,22 +814,26 @@ if (utf) if (caseless) { #ifdef SUPPORT_UNICODE - if (utf) + if (utf || ucp) { -#if PCRE2_CODE_UNIT_WIDTH == 8 - PCRE2_UCHAR buff[6]; c = UCD_OTHERCASE(c); - (void)PRIV(ord2utf)(c, buff); - SET_BIT(buff[0]); +#if PCRE2_CODE_UNIT_WIDTH == 8 + if (utf) + { + PCRE2_UCHAR buff[6]; + (void)PRIV(ord2utf)(c, buff); + SET_BIT(buff[0]); + } + else if (c < 256) SET_BIT(c); #else /* 16-bit or 32-bit mode */ - c = UCD_OTHERCASE(c); if (c > 0xff) SET_BIT(0xff); else SET_BIT(c); #endif } + else #endif /* SUPPORT_UNICODE */ - /* Not UTF */ + /* Not UTF or UCP */ if (MAX_255(c)) SET_BIT(re->tables[fcc_offset + c]); } @@ -924,19 +932,26 @@ The SSB_CONTINUE return is useful for parenthesized groups in patterns such as must continue at the outer level to find at least one mandatory code unit. At the outermost level, this function fails unless the result is SSB_DONE. +We restrict recursion (for nested groups) to 1000 to avoid stack overflow +issues. + Arguments: re points to the compiled regex block code points to an expression utf TRUE if in UTF mode + ucp TRUE if in UCP mode + depthptr pointer to recurse depth Returns: SSB_FAIL => Failed to find any starting code units SSB_DONE => Found mandatory starting code units SSB_CONTINUE => Found optional starting code units SSB_UNKNOWN => Hit an unrecognized opcode + SSB_TOODEEP => Recursion is too deep */ static int -set_start_bits(pcre2_real_code *re, PCRE2_SPTR code, BOOL utf) +set_start_bits(pcre2_real_code *re, PCRE2_SPTR code, BOOL utf, BOOL ucp, + int *depthptr) { uint32_t c; int yield = SSB_DONE; @@ -947,6 +962,9 @@ int table_limit = utf? 16:32; int table_limit = 32; #endif +*depthptr += 1; +if (*depthptr > 1000) return SSB_TOODEEP; + do { BOOL try_next = TRUE; @@ -1103,13 +1121,17 @@ do case OP_SCRIPT_RUN: case OP_ASSERT: case OP_ASSERT_NA: - rc = set_start_bits(re, tcode, utf); - if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc; - if (rc == SSB_DONE) try_next = FALSE; else + rc = set_start_bits(re, tcode, utf, ucp, depthptr); + if (rc == SSB_DONE) + { + try_next = FALSE; + } + else if (rc == SSB_CONTINUE) { do tcode += GET(tcode, 1); while (*tcode == OP_ALT); tcode += 1 + LINK_SIZE; } + else return rc; /* FAIL, UNKNOWN, or TOODEEP */ break; /* If we hit ALT or KET, it means we haven't found anything mandatory in @@ -1155,8 +1177,8 @@ do case OP_BRAZERO: case OP_BRAMINZERO: case OP_BRAPOSZERO: - rc = set_start_bits(re, ++tcode, utf); - if (rc == SSB_FAIL || rc == SSB_UNKNOWN) return rc; + rc = set_start_bits(re, ++tcode, utf, ucp, depthptr); + if (rc == SSB_FAIL || rc == SSB_UNKNOWN || rc == SSB_TOODEEP) return rc; do tcode += GET(tcode,1); while (*tcode == OP_ALT); tcode += 1 + LINK_SIZE; break; @@ -1177,7 +1199,7 @@ do case OP_QUERY: case OP_MINQUERY: case OP_POSQUERY: - tcode = set_table_bit(re, tcode + 1, FALSE, utf); + tcode = set_table_bit(re, tcode + 1, FALSE, utf, ucp); break; case OP_STARI: @@ -1186,7 +1208,7 @@ do case OP_QUERYI: case OP_MINQUERYI: case OP_POSQUERYI: - tcode = set_table_bit(re, tcode + 1, TRUE, utf); + tcode = set_table_bit(re, tcode + 1, TRUE, utf, ucp); break; /* Single-char upto sets the bit and tries the next */ @@ -1194,13 +1216,13 @@ do case OP_UPTO: case OP_MINUPTO: case OP_POSUPTO: - tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, FALSE, utf); + tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, FALSE, utf, ucp); break; case OP_UPTOI: case OP_MINUPTOI: case OP_POSUPTOI: - tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, TRUE, utf); + tcode = set_table_bit(re, tcode + 1 + IMM2_SIZE, TRUE, utf, ucp); break; /* At least one single char sets the bit and stops */ @@ -1212,7 +1234,7 @@ do case OP_PLUS: case OP_MINPLUS: case OP_POSPLUS: - (void)set_table_bit(re, tcode + 1, FALSE, utf); + (void)set_table_bit(re, tcode + 1, FALSE, utf, ucp); try_next = FALSE; break; @@ -1223,7 +1245,7 @@ do case OP_PLUSI: case OP_MINPLUSI: case OP_POSPLUSI: - (void)set_table_bit(re, tcode + 1, TRUE, utf); + (void)set_table_bit(re, tcode + 1, TRUE, utf, ucp); try_next = FALSE; break; @@ -1652,6 +1674,7 @@ PRIV(study)(pcre2_real_code *re) int count = 0; PCRE2_UCHAR *code; BOOL utf = (re->overall_options & PCRE2_UTF) != 0; +BOOL ucp = (re->overall_options & PCRE2_UCP) != 0; /* Find start of compiled code */ @@ -1664,7 +1687,8 @@ code units. */ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0) { - int rc = set_start_bits(re, code, utf); + int depth = 0; + int rc = set_start_bits(re, code, utf, ucp, &depth); if (rc == SSB_UNKNOWN) return 1; /* If a list of starting code units was set up, scan the list to see if only @@ -1712,27 +1736,27 @@ if ((re->flags & (PCRE2_FIRSTSET|PCRE2_STARTLINE)) == 0) } /* c contains the code unit value, in the range 0-255. In 8-bit UTF - mode, only values < 128 can be used. */ + mode, only values < 128 can be used. In all the other cases, c is a + character value. */ #if PCRE2_CODE_UNIT_WIDTH == 8 - if (c > 127) goto DONE; + if (utf && c > 127) goto DONE; #endif - if (a < 0) a = c; /* First one found */ + if (a < 0) a = c; /* First one found, save in a */ else if (b < 0) /* Second one found */ { int d = TABLE_GET((unsigned int)c, re->tables + fcc_offset, c); #ifdef SUPPORT_UNICODE -#if PCRE2_CODE_UNIT_WIDTH == 8 - if (utf && UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */ -#else /* 16-bit or 32-bit */ - if (UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */ - if (utf && c > 127) d = UCD_OTHERCASE(c); -#endif /* Code width */ + if (utf || ucp) + { + if (UCD_CASESET(c) != 0) goto DONE; /* Multiple case set */ + if (c > 127) d = UCD_OTHERCASE(c); + } #endif /* SUPPORT_UNICODE */ - if (d != a) goto DONE; /* Not other case of a */ - b = c; + if (d != a) goto DONE; /* Not the other case of a */ + b = c; /* Save second in b */ } else goto DONE; /* More than two characters found */ } diff --git a/thirdparty/pcre2/src/pcre2_substitute.c b/thirdparty/pcre2/src/pcre2_substitute.c index ec3dd66df9..981a106a9f 100644 --- a/thirdparty/pcre2/src/pcre2_substitute.c +++ b/thirdparty/pcre2/src/pcre2_substitute.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2019 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -49,8 +49,9 @@ POSSIBILITY OF SUCH DAMAGE. #define SUBSTITUTE_OPTIONS \ (PCRE2_SUBSTITUTE_EXTENDED|PCRE2_SUBSTITUTE_GLOBAL| \ - PCRE2_SUBSTITUTE_OVERFLOW_LENGTH|PCRE2_SUBSTITUTE_UNKNOWN_UNSET| \ - PCRE2_SUBSTITUTE_UNSET_EMPTY) + PCRE2_SUBSTITUTE_LITERAL|PCRE2_SUBSTITUTE_MATCHED| \ + PCRE2_SUBSTITUTE_OVERFLOW_LENGTH|PCRE2_SUBSTITUTE_REPLACEMENT_ONLY| \ + PCRE2_SUBSTITUTE_UNKNOWN_UNSET|PCRE2_SUBSTITUTE_UNSET_EMPTY) @@ -194,6 +195,7 @@ overflow, either give an error immediately, or keep on, accumulating the length. */ #define CHECKMEMCPY(from,length) \ + { \ if (!overflowed && lengthleft < length) \ { \ if ((suboptions & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH) == 0) goto NOROOM; \ @@ -209,7 +211,8 @@ length. */ memcpy(buffer + buff_offset, from, CU2BYTES(length)); \ buff_offset += length; \ lengthleft -= length; \ - } + } \ + } /* Here's the function */ @@ -226,11 +229,14 @@ int forcecasereset = 0; uint32_t ovector_count; uint32_t goptions = 0; uint32_t suboptions; -BOOL match_data_created = FALSE; -BOOL literal = FALSE; +pcre2_match_data *internal_match_data = NULL; +BOOL escaped_literal = FALSE; BOOL overflowed = FALSE; +BOOL use_existing_match; +BOOL replacement_only; #ifdef SUPPORT_UNICODE BOOL utf = (code->overall_options & PCRE2_UTF) != 0; +BOOL ucp = (code->overall_options & PCRE2_UCP) != 0; #endif PCRE2_UCHAR temp[6]; PCRE2_SPTR ptr; @@ -248,23 +254,54 @@ lengthleft = buff_length = *blength; *blength = PCRE2_UNSET; ovecsave[0] = ovecsave[1] = ovecsave[2] = PCRE2_UNSET; -/* Partial matching is not valid. This must come after setting *blength to +/* Partial matching is not valid. This must come after setting *blength to PCRE2_UNSET, so as not to imply an offset in the replacement. */ if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0) return PCRE2_ERROR_BADOPTION; -/* If no match data block is provided, create one. */ +/* Check for using a match that has already happened. Note that the subject +pointer in the match data may be NULL after a no-match. */ + +use_existing_match = ((options & PCRE2_SUBSTITUTE_MATCHED) != 0); +replacement_only = ((options & PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) != 0); + +/* If starting from an existing match, there must be an externally provided +match data block. We create an internal match_data block in two cases: (a) an +external one is not supplied (and we are not starting from an existing match); +(b) an existing match is to be used for the first substitution. In the latter +case, we copy the existing match into the internal block. This ensures that no +changes are made to the existing match data block. */ if (match_data == NULL) { + pcre2_general_context *gcontext; + if (use_existing_match) return PCRE2_ERROR_NULL; + gcontext = (mcontext == NULL)? + (pcre2_general_context *)code : + (pcre2_general_context *)mcontext; + match_data = internal_match_data = + pcre2_match_data_create_from_pattern(code, gcontext); + if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY; + } + +else if (use_existing_match) + { pcre2_general_context *gcontext = (mcontext == NULL)? (pcre2_general_context *)code : (pcre2_general_context *)mcontext; - match_data = pcre2_match_data_create_from_pattern(code, gcontext); - if (match_data == NULL) return PCRE2_ERROR_NOMEMORY; - match_data_created = TRUE; + int pairs = (code->top_bracket + 1 < match_data->oveccount)? + code->top_bracket + 1 : match_data->oveccount; + internal_match_data = pcre2_match_data_create(match_data->oveccount, + gcontext); + if (internal_match_data == NULL) return PCRE2_ERROR_NOMEMORY; + memcpy(internal_match_data, match_data, offsetof(pcre2_match_data, ovector) + + 2*pairs*sizeof(PCRE2_SIZE)); + match_data = internal_match_data; } + +/* Remember ovector details */ + ovector = pcre2_get_ovector_pointer(match_data); ovector_count = pcre2_get_ovector_count(match_data); @@ -286,7 +323,7 @@ repend = replacement + rlength; #ifdef SUPPORT_UNICODE if (utf && (options & PCRE2_NO_UTF_CHECK) == 0) { - rc = PRIV(valid_utf)(replacement, rlength, &(match_data->rightchar)); + rc = PRIV(valid_utf)(replacement, rlength, &(match_data->startchar)); if (rc != 0) { match_data->leftchar = 0; @@ -300,7 +337,7 @@ if (utf && (options & PCRE2_NO_UTF_CHECK) == 0) suboptions = options & SUBSTITUTE_OPTIONS; options &= ~SUBSTITUTE_OPTIONS; -/* Copy up to the start offset */ +/* Error if the start match offset is greater than the length of the subject. */ if (start_offset > length) { @@ -308,9 +345,13 @@ if (start_offset > length) rc = PCRE2_ERROR_BADOFFSET; goto EXIT; } -CHECKMEMCPY(subject, start_offset); -/* Loop for global substituting. */ +/* Copy up to the start offset, unless only the replacement is required. */ + +if (!replacement_only) CHECKMEMCPY(subject, start_offset); + +/* Loop for global substituting. If PCRE2_SUBSTITUTE_MATCHED is set, the first +match is taken from the match_data that was passed in. */ subs = 0; do @@ -318,7 +359,12 @@ do PCRE2_SPTR ptrstack[PTR_STACK_SIZE]; uint32_t ptrstackptr = 0; - rc = pcre2_match(code, subject, length, start_offset, options|goptions, + if (use_existing_match) + { + rc = match_data->rc; + use_existing_match = FALSE; + } + else rc = pcre2_match(code, subject, length, start_offset, options|goptions, match_data, mcontext); #ifdef SUPPORT_UNICODE @@ -364,44 +410,44 @@ do #endif } - /* Copy what we have advanced past, reset the special global options, and - continue to the next match. */ + /* 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; - CHECKMEMCPY(subject + save_start, fraglength); + if (!replacement_only) CHECKMEMCPY(subject + save_start, fraglength); goptions = 0; continue; } /* 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. */ - + if (ovector[1] < ovector[0] || ovector[0] < start_offset) { rc = PCRE2_ERROR_BADSUBSPATTERN; goto EXIT; } - - /* Check for the same match as previous. This is legitimate after matching an + + /* 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. */ - + if (ovecsave[0] == ovector[0] && ovecsave[1] == ovector[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 */ + { + 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 */ } rc = PCRE2_ERROR_INTERNAL_DUPMATCH; - goto EXIT; - } - + goto EXIT; + } + /* Count substitutions with a paranoid check for integer overflow; surely no real call to this function would ever hit this! */ @@ -412,21 +458,30 @@ do } subs++; - /* Copy the text leading up to the match, and remember where the insert - begins and how many ovector pairs are set. */ + /* Copy the text leading up to the match (unless not required), and remember + where the insert begins and how many ovector pairs are set. */ if (rc == 0) rc = ovector_count; fraglength = ovector[0] - start_offset; - CHECKMEMCPY(subject + start_offset, fraglength); + if (!replacement_only) CHECKMEMCPY(subject + start_offset, fraglength); scb.output_offsets[0] = buff_offset; scb.oveccount = rc; - /* Process the replacement string. Literal mode is set by \Q, but only in - extended mode when backslashes are being interpreted. In extended mode we - must handle nested substrings that are to be reprocessed. */ + /* Process the replacement string. If the entire replacement is literal, just + copy it with length check. */ ptr = replacement; - for (;;) + if ((suboptions & PCRE2_SUBSTITUTE_LITERAL) != 0) + { + CHECKMEMCPY(ptr, rlength); + } + + /* Within a non-literal replacement, which must be scanned character by + character, local literal mode can be set by \Q, but only in extended mode + when backslashes are being interpreted. In extended mode we must handle + nested substrings that are to be reprocessed. */ + + else for (;;) { uint32_t ch; unsigned int chlen; @@ -443,11 +498,11 @@ do /* Handle the next character */ - if (literal) + if (escaped_literal) { if (ptr[0] == CHAR_BACKSLASH && ptr < repend - 1 && ptr[1] == CHAR_E) { - literal = FALSE; + escaped_literal = FALSE; ptr += 2; continue; } @@ -704,7 +759,7 @@ do if (forcecase != 0) { #ifdef SUPPORT_UNICODE - if (utf) + if (utf || ucp) { uint32_t type = UCD_CHARTYPE(ch); if (PRIV(ucp_gentype)[type] == ucp_L && @@ -784,7 +839,7 @@ do continue; case ESC_Q: - literal = TRUE; + escaped_literal = TRUE; continue; case 0: /* Data character */ @@ -806,7 +861,7 @@ do if (forcecase != 0) { #ifdef SUPPORT_UNICODE - if (utf) + if (utf || ucp) { uint32_t type = UCD_CHARTYPE(ch); if (PRIV(ucp_gentype)[type] == ucp_L && @@ -835,53 +890,59 @@ do } /* End handling a literal code unit */ } /* End of loop for scanning the replacement. */ - /* The replacement has been copied to the output, or its size has been - remembered. Do the callout if there is one and we have done an actual + /* The replacement has been copied to the output, or its size has been + remembered. Do the callout if there is one and we have done an actual replacement. */ - + if (!overflowed && mcontext != NULL && mcontext->substitute_callout != NULL) { - scb.subscount = subs; + scb.subscount = subs; scb.output_offsets[1] = buff_offset; - rc = mcontext->substitute_callout(&scb, mcontext->substitute_callout_data); + rc = mcontext->substitute_callout(&scb, mcontext->substitute_callout_data); - /* A non-zero return means cancel this substitution. Instead, copy the + /* A non-zero return means cancel this substitution. Instead, copy the matched string fragment. */ if (rc != 0) { PCRE2_SIZE newlength = scb.output_offsets[1] - scb.output_offsets[0]; PCRE2_SIZE oldlength = ovector[1] - ovector[0]; - + buff_offset -= newlength; lengthleft += newlength; - CHECKMEMCPY(subject + ovector[0], oldlength); - + if (!replacement_only) CHECKMEMCPY(subject + ovector[0], oldlength); + /* A negative return means do not do any more. */ - + if (rc < 0) suboptions &= (~PCRE2_SUBSTITUTE_GLOBAL); } - } - + } + /* 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. Finally, update the - start offset to point to the rest of the subject string. */ - - ovecsave[0] = ovector[0]; - ovecsave[1] = ovector[1]; + 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. */ + + ovecsave[0] = ovector[0]; + ovecsave[1] = ovector[1]; ovecsave[2] = start_offset; - + 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 */ -/* Copy the rest of the subject. */ +/* Copy the rest of the subject unless not required, and terminate the output +with a binary zero. */ + +if (!replacement_only) + { + fraglength = length - start_offset; + CHECKMEMCPY(subject + start_offset, fraglength); + } -fraglength = length - start_offset; -CHECKMEMCPY(subject + start_offset, fraglength); temp[0] = 0; -CHECKMEMCPY(temp , 1); +CHECKMEMCPY(temp, 1); /* If overflowed is set it means the PCRE2_SUBSTITUTE_OVERFLOW_LENGTH is set, and matching has carried on after a full buffer, in order to compute the length @@ -903,7 +964,7 @@ else } EXIT: -if (match_data_created) pcre2_match_data_free(match_data); +if (internal_match_data != NULL) pcre2_match_data_free(internal_match_data); else match_data->rc = rc; return rc; diff --git a/thirdparty/pcre2/src/pcre2_tables.c b/thirdparty/pcre2/src/pcre2_tables.c index 25531d98c6..b10de45efb 100644 --- a/thirdparty/pcre2/src/pcre2_tables.c +++ b/thirdparty/pcre2/src/pcre2_tables.c @@ -265,6 +265,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Chakma0 STR_C STR_h STR_a STR_k STR_m STR_a "\0" #define STRING_Cham0 STR_C STR_h STR_a STR_m "\0" #define STRING_Cherokee0 STR_C STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0" +#define STRING_Chorasmian0 STR_C STR_h STR_o STR_r STR_a STR_s STR_m STR_i STR_a STR_n "\0" #define STRING_Cn0 STR_C STR_n "\0" #define STRING_Co0 STR_C STR_o "\0" #define STRING_Common0 STR_C STR_o STR_m STR_m STR_o STR_n "\0" @@ -275,6 +276,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Cyrillic0 STR_C STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0" #define STRING_Deseret0 STR_D STR_e STR_s STR_e STR_r STR_e STR_t "\0" #define STRING_Devanagari0 STR_D STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0" +#define STRING_Dives_Akuru0 STR_D STR_i STR_v STR_e STR_s STR_UNDERSCORE STR_A STR_k STR_u STR_r STR_u "\0" #define STRING_Dogra0 STR_D STR_o STR_g STR_r STR_a "\0" #define STRING_Duployan0 STR_D STR_u STR_p STR_l STR_o STR_y STR_a STR_n "\0" #define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0" @@ -306,6 +308,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Katakana0 STR_K STR_a STR_t STR_a STR_k STR_a STR_n STR_a "\0" #define STRING_Kayah_Li0 STR_K STR_a STR_y STR_a STR_h STR_UNDERSCORE STR_L STR_i "\0" #define STRING_Kharoshthi0 STR_K STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0" +#define STRING_Khitan_Small_Script0 STR_K STR_h STR_i STR_t STR_a STR_n STR_UNDERSCORE STR_S STR_m STR_a STR_l STR_l STR_UNDERSCORE STR_S STR_c STR_r STR_i STR_p STR_t "\0" #define STRING_Khmer0 STR_K STR_h STR_m STR_e STR_r "\0" #define STRING_Khojki0 STR_K STR_h STR_o STR_j STR_k STR_i "\0" #define STRING_Khudawadi0 STR_K STR_h STR_u STR_d STR_a STR_w STR_a STR_d STR_i "\0" @@ -429,6 +432,7 @@ strings to make sure that UTF-8 support works on EBCDIC platforms. */ #define STRING_Xsp0 STR_X STR_s STR_p "\0" #define STRING_Xuc0 STR_X STR_u STR_c "\0" #define STRING_Xwd0 STR_X STR_w STR_d "\0" +#define STRING_Yezidi0 STR_Y STR_e STR_z STR_i STR_d STR_i "\0" #define STRING_Yi0 STR_Y STR_i "\0" #define STRING_Z0 STR_Z "\0" #define STRING_Zanabazar_Square0 STR_Z STR_a STR_n STR_a STR_b STR_a STR_z STR_a STR_r STR_UNDERSCORE STR_S STR_q STR_u STR_a STR_r STR_e "\0" @@ -464,6 +468,7 @@ const char PRIV(utt_names)[] = STRING_Chakma0 STRING_Cham0 STRING_Cherokee0 + STRING_Chorasmian0 STRING_Cn0 STRING_Co0 STRING_Common0 @@ -474,6 +479,7 @@ const char PRIV(utt_names)[] = STRING_Cyrillic0 STRING_Deseret0 STRING_Devanagari0 + STRING_Dives_Akuru0 STRING_Dogra0 STRING_Duployan0 STRING_Egyptian_Hieroglyphs0 @@ -505,6 +511,7 @@ const char PRIV(utt_names)[] = STRING_Katakana0 STRING_Kayah_Li0 STRING_Kharoshthi0 + STRING_Khitan_Small_Script0 STRING_Khmer0 STRING_Khojki0 STRING_Khudawadi0 @@ -628,6 +635,7 @@ const char PRIV(utt_names)[] = STRING_Xsp0 STRING_Xuc0 STRING_Xwd0 + STRING_Yezidi0 STRING_Yi0 STRING_Z0 STRING_Zanabazar_Square0 @@ -663,176 +671,180 @@ const ucp_type_table PRIV(utt)[] = { { 203, PT_SC, ucp_Chakma }, { 210, PT_SC, ucp_Cham }, { 215, PT_SC, ucp_Cherokee }, - { 224, PT_PC, ucp_Cn }, - { 227, PT_PC, ucp_Co }, - { 230, PT_SC, ucp_Common }, - { 237, PT_SC, ucp_Coptic }, - { 244, PT_PC, ucp_Cs }, - { 247, PT_SC, ucp_Cuneiform }, - { 257, PT_SC, ucp_Cypriot }, - { 265, PT_SC, ucp_Cyrillic }, - { 274, PT_SC, ucp_Deseret }, - { 282, PT_SC, ucp_Devanagari }, - { 293, PT_SC, ucp_Dogra }, - { 299, PT_SC, ucp_Duployan }, - { 308, PT_SC, ucp_Egyptian_Hieroglyphs }, - { 329, PT_SC, ucp_Elbasan }, - { 337, PT_SC, ucp_Elymaic }, - { 345, PT_SC, ucp_Ethiopic }, - { 354, PT_SC, ucp_Georgian }, - { 363, PT_SC, ucp_Glagolitic }, - { 374, PT_SC, ucp_Gothic }, - { 381, PT_SC, ucp_Grantha }, - { 389, PT_SC, ucp_Greek }, - { 395, PT_SC, ucp_Gujarati }, - { 404, PT_SC, ucp_Gunjala_Gondi }, - { 418, PT_SC, ucp_Gurmukhi }, - { 427, PT_SC, ucp_Han }, - { 431, PT_SC, ucp_Hangul }, - { 438, PT_SC, ucp_Hanifi_Rohingya }, - { 454, PT_SC, ucp_Hanunoo }, - { 462, PT_SC, ucp_Hatran }, - { 469, PT_SC, ucp_Hebrew }, - { 476, PT_SC, ucp_Hiragana }, - { 485, PT_SC, ucp_Imperial_Aramaic }, - { 502, PT_SC, ucp_Inherited }, - { 512, PT_SC, ucp_Inscriptional_Pahlavi }, - { 534, PT_SC, ucp_Inscriptional_Parthian }, - { 557, PT_SC, ucp_Javanese }, - { 566, PT_SC, ucp_Kaithi }, - { 573, PT_SC, ucp_Kannada }, - { 581, PT_SC, ucp_Katakana }, - { 590, PT_SC, ucp_Kayah_Li }, - { 599, PT_SC, ucp_Kharoshthi }, - { 610, PT_SC, ucp_Khmer }, - { 616, PT_SC, ucp_Khojki }, - { 623, PT_SC, ucp_Khudawadi }, - { 633, PT_GC, ucp_L }, - { 635, PT_LAMP, 0 }, - { 638, PT_SC, ucp_Lao }, - { 642, PT_SC, ucp_Latin }, - { 648, PT_SC, ucp_Lepcha }, - { 655, PT_SC, ucp_Limbu }, - { 661, PT_SC, ucp_Linear_A }, - { 670, PT_SC, ucp_Linear_B }, - { 679, PT_SC, ucp_Lisu }, - { 684, PT_PC, ucp_Ll }, - { 687, PT_PC, ucp_Lm }, - { 690, PT_PC, ucp_Lo }, - { 693, PT_PC, ucp_Lt }, - { 696, PT_PC, ucp_Lu }, - { 699, PT_SC, ucp_Lycian }, - { 706, PT_SC, ucp_Lydian }, - { 713, PT_GC, ucp_M }, - { 715, PT_SC, ucp_Mahajani }, - { 724, PT_SC, ucp_Makasar }, - { 732, PT_SC, ucp_Malayalam }, - { 742, PT_SC, ucp_Mandaic }, - { 750, PT_SC, ucp_Manichaean }, - { 761, PT_SC, ucp_Marchen }, - { 769, PT_SC, ucp_Masaram_Gondi }, - { 783, PT_PC, ucp_Mc }, - { 786, PT_PC, ucp_Me }, - { 789, PT_SC, ucp_Medefaidrin }, - { 801, PT_SC, ucp_Meetei_Mayek }, - { 814, PT_SC, ucp_Mende_Kikakui }, - { 828, PT_SC, ucp_Meroitic_Cursive }, - { 845, PT_SC, ucp_Meroitic_Hieroglyphs }, - { 866, PT_SC, ucp_Miao }, - { 871, PT_PC, ucp_Mn }, - { 874, PT_SC, ucp_Modi }, - { 879, PT_SC, ucp_Mongolian }, - { 889, PT_SC, ucp_Mro }, - { 893, PT_SC, ucp_Multani }, - { 901, PT_SC, ucp_Myanmar }, - { 909, PT_GC, ucp_N }, - { 911, PT_SC, ucp_Nabataean }, - { 921, PT_SC, ucp_Nandinagari }, - { 933, PT_PC, ucp_Nd }, - { 936, PT_SC, ucp_New_Tai_Lue }, - { 948, PT_SC, ucp_Newa }, - { 953, PT_SC, ucp_Nko }, - { 957, PT_PC, ucp_Nl }, - { 960, PT_PC, ucp_No }, - { 963, PT_SC, ucp_Nushu }, - { 969, PT_SC, ucp_Nyiakeng_Puachue_Hmong }, - { 992, PT_SC, ucp_Ogham }, - { 998, PT_SC, ucp_Ol_Chiki }, - { 1007, PT_SC, ucp_Old_Hungarian }, - { 1021, PT_SC, ucp_Old_Italic }, - { 1032, PT_SC, ucp_Old_North_Arabian }, - { 1050, PT_SC, ucp_Old_Permic }, - { 1061, PT_SC, ucp_Old_Persian }, - { 1073, PT_SC, ucp_Old_Sogdian }, - { 1085, PT_SC, ucp_Old_South_Arabian }, - { 1103, PT_SC, ucp_Old_Turkic }, - { 1114, PT_SC, ucp_Oriya }, - { 1120, PT_SC, ucp_Osage }, - { 1126, PT_SC, ucp_Osmanya }, - { 1134, PT_GC, ucp_P }, - { 1136, PT_SC, ucp_Pahawh_Hmong }, - { 1149, PT_SC, ucp_Palmyrene }, - { 1159, PT_SC, ucp_Pau_Cin_Hau }, - { 1171, PT_PC, ucp_Pc }, - { 1174, PT_PC, ucp_Pd }, - { 1177, PT_PC, ucp_Pe }, - { 1180, PT_PC, ucp_Pf }, - { 1183, PT_SC, ucp_Phags_Pa }, - { 1192, PT_SC, ucp_Phoenician }, - { 1203, PT_PC, ucp_Pi }, - { 1206, PT_PC, ucp_Po }, - { 1209, PT_PC, ucp_Ps }, - { 1212, PT_SC, ucp_Psalter_Pahlavi }, - { 1228, PT_SC, ucp_Rejang }, - { 1235, PT_SC, ucp_Runic }, - { 1241, PT_GC, ucp_S }, - { 1243, PT_SC, ucp_Samaritan }, - { 1253, PT_SC, ucp_Saurashtra }, - { 1264, PT_PC, ucp_Sc }, - { 1267, PT_SC, ucp_Sharada }, - { 1275, PT_SC, ucp_Shavian }, - { 1283, PT_SC, ucp_Siddham }, - { 1291, PT_SC, ucp_SignWriting }, - { 1303, PT_SC, ucp_Sinhala }, - { 1311, PT_PC, ucp_Sk }, - { 1314, PT_PC, ucp_Sm }, - { 1317, PT_PC, ucp_So }, - { 1320, PT_SC, ucp_Sogdian }, - { 1328, PT_SC, ucp_Sora_Sompeng }, - { 1341, PT_SC, ucp_Soyombo }, - { 1349, PT_SC, ucp_Sundanese }, - { 1359, PT_SC, ucp_Syloti_Nagri }, - { 1372, PT_SC, ucp_Syriac }, - { 1379, PT_SC, ucp_Tagalog }, - { 1387, PT_SC, ucp_Tagbanwa }, - { 1396, PT_SC, ucp_Tai_Le }, - { 1403, PT_SC, ucp_Tai_Tham }, - { 1412, PT_SC, ucp_Tai_Viet }, - { 1421, PT_SC, ucp_Takri }, - { 1427, PT_SC, ucp_Tamil }, - { 1433, PT_SC, ucp_Tangut }, - { 1440, PT_SC, ucp_Telugu }, - { 1447, PT_SC, ucp_Thaana }, - { 1454, PT_SC, ucp_Thai }, - { 1459, PT_SC, ucp_Tibetan }, - { 1467, PT_SC, ucp_Tifinagh }, - { 1476, PT_SC, ucp_Tirhuta }, - { 1484, PT_SC, ucp_Ugaritic }, - { 1493, PT_SC, ucp_Unknown }, - { 1501, PT_SC, ucp_Vai }, - { 1505, PT_SC, ucp_Wancho }, - { 1512, PT_SC, ucp_Warang_Citi }, - { 1524, PT_ALNUM, 0 }, - { 1528, PT_PXSPACE, 0 }, - { 1532, PT_SPACE, 0 }, - { 1536, PT_UCNC, 0 }, - { 1540, PT_WORD, 0 }, - { 1544, PT_SC, ucp_Yi }, - { 1547, PT_GC, ucp_Z }, - { 1549, PT_SC, ucp_Zanabazar_Square }, - { 1566, PT_PC, ucp_Zl }, - { 1569, PT_PC, ucp_Zp }, - { 1572, PT_PC, ucp_Zs } + { 224, PT_SC, ucp_Chorasmian }, + { 235, PT_PC, ucp_Cn }, + { 238, PT_PC, ucp_Co }, + { 241, PT_SC, ucp_Common }, + { 248, PT_SC, ucp_Coptic }, + { 255, PT_PC, ucp_Cs }, + { 258, PT_SC, ucp_Cuneiform }, + { 268, PT_SC, ucp_Cypriot }, + { 276, PT_SC, ucp_Cyrillic }, + { 285, PT_SC, ucp_Deseret }, + { 293, PT_SC, ucp_Devanagari }, + { 304, PT_SC, ucp_Dives_Akuru }, + { 316, PT_SC, ucp_Dogra }, + { 322, PT_SC, ucp_Duployan }, + { 331, PT_SC, ucp_Egyptian_Hieroglyphs }, + { 352, PT_SC, ucp_Elbasan }, + { 360, PT_SC, ucp_Elymaic }, + { 368, PT_SC, ucp_Ethiopic }, + { 377, PT_SC, ucp_Georgian }, + { 386, PT_SC, ucp_Glagolitic }, + { 397, PT_SC, ucp_Gothic }, + { 404, PT_SC, ucp_Grantha }, + { 412, PT_SC, ucp_Greek }, + { 418, PT_SC, ucp_Gujarati }, + { 427, PT_SC, ucp_Gunjala_Gondi }, + { 441, PT_SC, ucp_Gurmukhi }, + { 450, PT_SC, ucp_Han }, + { 454, PT_SC, ucp_Hangul }, + { 461, PT_SC, ucp_Hanifi_Rohingya }, + { 477, PT_SC, ucp_Hanunoo }, + { 485, PT_SC, ucp_Hatran }, + { 492, PT_SC, ucp_Hebrew }, + { 499, PT_SC, ucp_Hiragana }, + { 508, PT_SC, ucp_Imperial_Aramaic }, + { 525, PT_SC, ucp_Inherited }, + { 535, PT_SC, ucp_Inscriptional_Pahlavi }, + { 557, PT_SC, ucp_Inscriptional_Parthian }, + { 580, PT_SC, ucp_Javanese }, + { 589, PT_SC, ucp_Kaithi }, + { 596, PT_SC, ucp_Kannada }, + { 604, PT_SC, ucp_Katakana }, + { 613, PT_SC, ucp_Kayah_Li }, + { 622, PT_SC, ucp_Kharoshthi }, + { 633, PT_SC, ucp_Khitan_Small_Script }, + { 653, PT_SC, ucp_Khmer }, + { 659, PT_SC, ucp_Khojki }, + { 666, PT_SC, ucp_Khudawadi }, + { 676, PT_GC, ucp_L }, + { 678, PT_LAMP, 0 }, + { 681, PT_SC, ucp_Lao }, + { 685, PT_SC, ucp_Latin }, + { 691, PT_SC, ucp_Lepcha }, + { 698, PT_SC, ucp_Limbu }, + { 704, PT_SC, ucp_Linear_A }, + { 713, PT_SC, ucp_Linear_B }, + { 722, PT_SC, ucp_Lisu }, + { 727, PT_PC, ucp_Ll }, + { 730, PT_PC, ucp_Lm }, + { 733, PT_PC, ucp_Lo }, + { 736, PT_PC, ucp_Lt }, + { 739, PT_PC, ucp_Lu }, + { 742, PT_SC, ucp_Lycian }, + { 749, PT_SC, ucp_Lydian }, + { 756, PT_GC, ucp_M }, + { 758, PT_SC, ucp_Mahajani }, + { 767, PT_SC, ucp_Makasar }, + { 775, PT_SC, ucp_Malayalam }, + { 785, PT_SC, ucp_Mandaic }, + { 793, PT_SC, ucp_Manichaean }, + { 804, PT_SC, ucp_Marchen }, + { 812, PT_SC, ucp_Masaram_Gondi }, + { 826, PT_PC, ucp_Mc }, + { 829, PT_PC, ucp_Me }, + { 832, PT_SC, ucp_Medefaidrin }, + { 844, PT_SC, ucp_Meetei_Mayek }, + { 857, PT_SC, ucp_Mende_Kikakui }, + { 871, PT_SC, ucp_Meroitic_Cursive }, + { 888, PT_SC, ucp_Meroitic_Hieroglyphs }, + { 909, PT_SC, ucp_Miao }, + { 914, PT_PC, ucp_Mn }, + { 917, PT_SC, ucp_Modi }, + { 922, PT_SC, ucp_Mongolian }, + { 932, PT_SC, ucp_Mro }, + { 936, PT_SC, ucp_Multani }, + { 944, PT_SC, ucp_Myanmar }, + { 952, PT_GC, ucp_N }, + { 954, PT_SC, ucp_Nabataean }, + { 964, PT_SC, ucp_Nandinagari }, + { 976, PT_PC, ucp_Nd }, + { 979, PT_SC, ucp_New_Tai_Lue }, + { 991, PT_SC, ucp_Newa }, + { 996, PT_SC, ucp_Nko }, + { 1000, PT_PC, ucp_Nl }, + { 1003, PT_PC, ucp_No }, + { 1006, PT_SC, ucp_Nushu }, + { 1012, PT_SC, ucp_Nyiakeng_Puachue_Hmong }, + { 1035, PT_SC, ucp_Ogham }, + { 1041, PT_SC, ucp_Ol_Chiki }, + { 1050, PT_SC, ucp_Old_Hungarian }, + { 1064, PT_SC, ucp_Old_Italic }, + { 1075, PT_SC, ucp_Old_North_Arabian }, + { 1093, PT_SC, ucp_Old_Permic }, + { 1104, PT_SC, ucp_Old_Persian }, + { 1116, PT_SC, ucp_Old_Sogdian }, + { 1128, PT_SC, ucp_Old_South_Arabian }, + { 1146, PT_SC, ucp_Old_Turkic }, + { 1157, PT_SC, ucp_Oriya }, + { 1163, PT_SC, ucp_Osage }, + { 1169, PT_SC, ucp_Osmanya }, + { 1177, PT_GC, ucp_P }, + { 1179, PT_SC, ucp_Pahawh_Hmong }, + { 1192, PT_SC, ucp_Palmyrene }, + { 1202, PT_SC, ucp_Pau_Cin_Hau }, + { 1214, PT_PC, ucp_Pc }, + { 1217, PT_PC, ucp_Pd }, + { 1220, PT_PC, ucp_Pe }, + { 1223, PT_PC, ucp_Pf }, + { 1226, PT_SC, ucp_Phags_Pa }, + { 1235, PT_SC, ucp_Phoenician }, + { 1246, PT_PC, ucp_Pi }, + { 1249, PT_PC, ucp_Po }, + { 1252, PT_PC, ucp_Ps }, + { 1255, PT_SC, ucp_Psalter_Pahlavi }, + { 1271, PT_SC, ucp_Rejang }, + { 1278, PT_SC, ucp_Runic }, + { 1284, PT_GC, ucp_S }, + { 1286, PT_SC, ucp_Samaritan }, + { 1296, PT_SC, ucp_Saurashtra }, + { 1307, PT_PC, ucp_Sc }, + { 1310, PT_SC, ucp_Sharada }, + { 1318, PT_SC, ucp_Shavian }, + { 1326, PT_SC, ucp_Siddham }, + { 1334, PT_SC, ucp_SignWriting }, + { 1346, PT_SC, ucp_Sinhala }, + { 1354, PT_PC, ucp_Sk }, + { 1357, PT_PC, ucp_Sm }, + { 1360, PT_PC, ucp_So }, + { 1363, PT_SC, ucp_Sogdian }, + { 1371, PT_SC, ucp_Sora_Sompeng }, + { 1384, PT_SC, ucp_Soyombo }, + { 1392, PT_SC, ucp_Sundanese }, + { 1402, PT_SC, ucp_Syloti_Nagri }, + { 1415, PT_SC, ucp_Syriac }, + { 1422, PT_SC, ucp_Tagalog }, + { 1430, PT_SC, ucp_Tagbanwa }, + { 1439, PT_SC, ucp_Tai_Le }, + { 1446, PT_SC, ucp_Tai_Tham }, + { 1455, PT_SC, ucp_Tai_Viet }, + { 1464, PT_SC, ucp_Takri }, + { 1470, PT_SC, ucp_Tamil }, + { 1476, PT_SC, ucp_Tangut }, + { 1483, PT_SC, ucp_Telugu }, + { 1490, PT_SC, ucp_Thaana }, + { 1497, PT_SC, ucp_Thai }, + { 1502, PT_SC, ucp_Tibetan }, + { 1510, PT_SC, ucp_Tifinagh }, + { 1519, PT_SC, ucp_Tirhuta }, + { 1527, PT_SC, ucp_Ugaritic }, + { 1536, PT_SC, ucp_Unknown }, + { 1544, PT_SC, ucp_Vai }, + { 1548, PT_SC, ucp_Wancho }, + { 1555, PT_SC, ucp_Warang_Citi }, + { 1567, PT_ALNUM, 0 }, + { 1571, PT_PXSPACE, 0 }, + { 1575, PT_SPACE, 0 }, + { 1579, PT_UCNC, 0 }, + { 1583, PT_WORD, 0 }, + { 1587, PT_SC, ucp_Yezidi }, + { 1594, PT_SC, ucp_Yi }, + { 1597, PT_GC, ucp_Z }, + { 1599, PT_SC, ucp_Zanabazar_Square }, + { 1616, PT_PC, ucp_Zl }, + { 1619, PT_PC, ucp_Zp }, + { 1622, PT_PC, ucp_Zs } }; const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table); diff --git a/thirdparty/pcre2/src/pcre2_ucd.c b/thirdparty/pcre2/src/pcre2_ucd.c index 55ba03bd43..46e23ff06b 100644 --- a/thirdparty/pcre2/src/pcre2_ucd.c +++ b/thirdparty/pcre2/src/pcre2_ucd.c @@ -20,7 +20,7 @@ needed. */ /* Unicode character database. */ /* This file was autogenerated by the MultiStage2.py script. */ -/* Total size: 99316 bytes, block size: 128. */ +/* Total size: 101044 bytes, block size: 128. */ /* The tables herein are needed only when UCP support is built, and in PCRE2 that happens automatically with UTF support. @@ -39,7 +39,7 @@ const uint16_t PRIV(ucd_stage2)[] = {0}; const uint32_t PRIV(ucd_caseless_sets)[] = {0}; #else -const char *PRIV(unicode_version) = "12.1.0"; +const char *PRIV(unicode_version) = "13.0.0"; /* If the 32-bit library is run in non-32-bit mode, character values greater than 0x10ffff may be encountered. For these we set up a @@ -116,15 +116,16 @@ set of decimal digits. It is used to ensure that all the digits in a script run come from the same set. */ const uint32_t PRIV(ucd_digit_sets)[] = { - 63, /* Number of subsequent values */ + 65, /* Number of subsequent values */ 0x00039, 0x00669, 0x006f9, 0x007c9, 0x0096f, 0x009ef, 0x00a6f, 0x00aef, 0x00b6f, 0x00bef, 0x00c6f, 0x00cef, 0x00d6f, 0x00def, 0x00e59, 0x00ed9, 0x00f29, 0x01049, 0x01099, 0x017e9, 0x01819, 0x0194f, 0x019d9, 0x01a89, 0x01a99, 0x01b59, 0x01bb9, 0x01c49, 0x01c59, 0x0a629, 0x0a8d9, 0x0a909, 0x0a9d9, 0x0a9f9, 0x0aa59, 0x0abf9, 0x0ff19, 0x104a9, 0x10d39, 0x1106f, 0x110f9, 0x1113f, 0x111d9, 0x112f9, 0x11459, 0x114d9, 0x11659, 0x116c9, - 0x11739, 0x118e9, 0x11c59, 0x11d59, 0x11da9, 0x16a69, 0x16b59, 0x1d7d7, - 0x1d7e1, 0x1d7eb, 0x1d7f5, 0x1d7ff, 0x1e149, 0x1e2f9, 0x1e959, + 0x11739, 0x118e9, 0x11959, 0x11c59, 0x11d59, 0x11da9, 0x16a69, 0x16b59, + 0x1d7d7, 0x1d7e1, 0x1d7eb, 0x1d7f5, 0x1d7ff, 0x1e149, 0x1e2f9, 0x1e959, + 0x1fbf9, }; /* This vector is a list of lists of scripts for the Script Extension @@ -136,14 +137,14 @@ const uint8_t PRIV(ucd_script_sets)[] = { /* 4 */ 1, 144, 0, /* 7 */ 1, 50, 0, /* 10 */ 1, 56, 0, - /* 13 */ 2, 17, 0, - /* 16 */ 3, 15, 0, - /* 19 */ 4, 23, 0, - /* 22 */ 6, 84, 0, - /* 25 */ 12, 36, 0, - /* 28 */ 13, 18, 0, - /* 31 */ 13, 34, 0, - /* 34 */ 13, 118, 0, + /* 13 */ 3, 15, 0, + /* 16 */ 4, 23, 0, + /* 19 */ 6, 84, 0, + /* 22 */ 12, 36, 0, + /* 25 */ 13, 18, 0, + /* 28 */ 13, 34, 0, + /* 31 */ 13, 118, 0, + /* 34 */ 13, 50, 0, /* 37 */ 15, 107, 0, /* 40 */ 15, 150, 0, /* 43 */ 15, 100, 0, @@ -152,35 +153,37 @@ const uint8_t PRIV(ucd_script_sets)[] = { /* 52 */ 107, 54, 0, /* 55 */ 21, 108, 0, /* 58 */ 22, 129, 0, - /* 61 */ 27, 30, 0, - /* 64 */ 29, 150, 0, - /* 67 */ 34, 38, 0, - /* 70 */ 38, 65, 0, - /* 73 */ 1, 50, 56, 0, - /* 77 */ 3, 96, 49, 0, - /* 81 */ 96, 39, 53, 0, - /* 85 */ 12, 110, 36, 0, - /* 89 */ 15, 107, 29, 0, - /* 93 */ 15, 107, 34, 0, - /* 97 */ 23, 27, 30, 0, - /* 101 */ 69, 34, 39, 0, - /* 105 */ 1, 144, 50, 56, 0, - /* 110 */ 3, 15, 107, 29, 0, - /* 115 */ 7, 25, 52, 51, 0, - /* 120 */ 15, 142, 85, 111, 0, - /* 125 */ 4, 24, 23, 27, 30, 0, - /* 131 */ 4, 24, 23, 27, 30, 61, 0, - /* 138 */ 15, 29, 37, 44, 54, 55, 0, - /* 145 */ 132, 1, 95, 112, 121, 144, 148, 50, 0, - /* 154 */ 3, 15, 107, 29, 150, 44, 55, 124, 0, - /* 163 */ 15, 142, 21, 22, 108, 85, 111, 114, 109, 102, 124, 0, - /* 175 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 54, 55, 124, 0, - /* 188 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 100, 54, 55, 124, 0, - /* 202 */ 15, 142, 21, 22, 108, 29, 85, 111, 114, 150, 109, 102, 124, 0, - /* 216 */ 15, 142, 21, 22, 108, 29, 85, 111, 37, 114, 150, 109, 102, 124, 0, - /* 231 */ 3, 15, 142, 143, 138, 107, 21, 22, 29, 111, 37, 150, 44, 109, 48, 49, 102, 54, 55, 124, 0, - /* 252 */ 3, 15, 142, 143, 138, 107, 21, 22, 29, 35, 111, 37, 150, 44, 109, 48, 49, 102, 54, 55, 124, 0, - /* 274 */ + /* 61 */ 23, 34, 0, + /* 64 */ 27, 30, 0, + /* 67 */ 29, 150, 0, + /* 70 */ 34, 38, 0, + /* 73 */ 38, 65, 0, + /* 76 */ 1, 50, 56, 0, + /* 80 */ 1, 56, 156, 0, + /* 84 */ 3, 96, 49, 0, + /* 88 */ 96, 39, 53, 0, + /* 92 */ 12, 110, 36, 0, + /* 96 */ 15, 107, 29, 0, + /* 100 */ 15, 107, 34, 0, + /* 104 */ 23, 27, 30, 0, + /* 108 */ 69, 34, 39, 0, + /* 112 */ 3, 15, 107, 29, 0, + /* 117 */ 7, 25, 52, 51, 0, + /* 122 */ 15, 142, 85, 111, 0, + /* 127 */ 1, 144, 50, 56, 156, 0, + /* 133 */ 4, 24, 23, 27, 30, 0, + /* 139 */ 4, 24, 23, 27, 30, 61, 0, + /* 146 */ 15, 29, 37, 44, 54, 55, 0, + /* 153 */ 132, 1, 95, 112, 121, 144, 148, 50, 0, + /* 162 */ 3, 15, 107, 29, 150, 44, 55, 124, 0, + /* 171 */ 15, 142, 21, 22, 108, 85, 111, 114, 109, 102, 124, 0, + /* 183 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 54, 55, 124, 0, + /* 196 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 100, 54, 55, 124, 0, + /* 210 */ 15, 142, 21, 22, 108, 29, 85, 111, 114, 150, 109, 102, 124, 0, + /* 224 */ 15, 142, 21, 22, 108, 29, 85, 111, 37, 114, 150, 109, 102, 124, 0, + /* 239 */ 3, 15, 142, 143, 138, 107, 21, 22, 29, 111, 37, 150, 44, 109, 48, 49, 102, 54, 55, 124, 0, + /* 260 */ 3, 15, 142, 143, 138, 107, 21, 22, 29, 35, 111, 37, 150, 44, 109, 48, 49, 102, 54, 55, 124, 0, + /* 282 */ }; /* These are the main two-stage UCD tables. The fields in each record are: @@ -189,7 +192,7 @@ offset to multichar other cases or zero (8 bits), offset to other case or zero (32 bits, signed), script extension (16 bits, signed), and a dummy 16-bit field to make the whole thing a multiple of 4 bytes. */ -const ucd_record PRIV(ucd_records)[] = { /* 11508 bytes, record size 12 */ +const ucd_record PRIV(ucd_records)[] = { /* 11700 bytes, record size 12 */ { 10, 0, 2, 0, 0, 10, 256, }, /* 0 */ { 10, 0, 2, 0, 0, 10, 0, }, /* 1 */ { 10, 0, 1, 0, 0, 10, 0, }, /* 2 */ @@ -387,9 +390,9 @@ const ucd_record PRIV(ucd_records)[] = { /* 11508 bytes, record size 12 */ { 13, 9, 12, 88, 1, 13, 0, }, /* 194 */ { 13, 5, 12, 88, -1, 13, 0, }, /* 195 */ { 13, 26, 12, 0, 0, 13, 0, }, /* 196 */ - { 13, 12, 3, 0, 0, -34, 0, }, /* 197 */ - { 13, 12, 3, 0, 0, -28, 0, }, /* 198 */ - { 28, 12, 3, 0, 0, -31, 0, }, /* 199 */ + { 13, 12, 3, 0, 0, -31, 0, }, /* 197 */ + { 13, 12, 3, 0, 0, -25, 0, }, /* 198 */ + { 28, 12, 3, 0, 0, -28, 0, }, /* 199 */ { 13, 11, 3, 0, 0, 13, 0, }, /* 200 */ { 13, 9, 12, 0, 15, 13, 0, }, /* 201 */ { 13, 5, 12, 0, -15, 13, 0, }, /* 202 */ @@ -398,281 +401,281 @@ const ucd_record PRIV(ucd_records)[] = { /* 11508 bytes, record size 12 */ { 2, 21, 12, 0, 0, 2, 0, }, /* 205 */ { 2, 5, 12, 0, 0, 2, 0, }, /* 206 */ { 2, 5, 12, 0, -48, 2, 0, }, /* 207 */ - { 10, 21, 12, 0, 0, -13, 0, }, /* 208 */ - { 2, 17, 12, 0, 0, 2, 0, }, /* 209 */ - { 2, 26, 12, 0, 0, 2, 0, }, /* 210 */ - { 2, 23, 12, 0, 0, 2, 0, }, /* 211 */ - { 26, 12, 3, 0, 0, 26, 0, }, /* 212 */ - { 26, 17, 12, 0, 0, 26, 0, }, /* 213 */ - { 26, 21, 12, 0, 0, 26, 0, }, /* 214 */ - { 26, 7, 12, 0, 0, 26, 0, }, /* 215 */ - { 1, 1, 4, 0, 0, 1, 0, }, /* 216 */ - { 10, 1, 4, 0, 0, 10, 0, }, /* 217 */ - { 1, 25, 12, 0, 0, 1, 0, }, /* 218 */ - { 1, 21, 12, 0, 0, 1, 0, }, /* 219 */ - { 1, 23, 12, 0, 0, 1, 0, }, /* 220 */ - { 10, 21, 12, 0, 0, -105, 0, }, /* 221 */ - { 1, 26, 12, 0, 0, 1, 0, }, /* 222 */ - { 1, 12, 3, 0, 0, 1, 0, }, /* 223 */ - { 1, 1, 2, 0, 0, -73, 0, }, /* 224 */ - { 1, 7, 12, 0, 0, 1, 0, }, /* 225 */ - { 10, 6, 12, 0, 0, -145, 0, }, /* 226 */ - { 28, 12, 3, 0, 0, -7, 0, }, /* 227 */ - { 1, 13, 12, 0, 0, -10, 0, }, /* 228 */ - { 1, 21, 12, 0, 0, -4, 0, }, /* 229 */ - { 1, 6, 12, 0, 0, 1, 0, }, /* 230 */ - { 1, 13, 12, 0, 0, 1, 0, }, /* 231 */ - { 50, 21, 12, 0, 0, 50, 0, }, /* 232 */ - { 50, 1, 4, 0, 0, 50, 0, }, /* 233 */ - { 50, 7, 12, 0, 0, 50, 0, }, /* 234 */ - { 50, 12, 3, 0, 0, 50, 0, }, /* 235 */ - { 56, 7, 12, 0, 0, 56, 0, }, /* 236 */ - { 56, 12, 3, 0, 0, 56, 0, }, /* 237 */ - { 64, 13, 12, 0, 0, 64, 0, }, /* 238 */ - { 64, 7, 12, 0, 0, 64, 0, }, /* 239 */ - { 64, 12, 3, 0, 0, 64, 0, }, /* 240 */ - { 64, 6, 12, 0, 0, 64, 0, }, /* 241 */ - { 64, 26, 12, 0, 0, 64, 0, }, /* 242 */ - { 64, 21, 12, 0, 0, 64, 0, }, /* 243 */ - { 64, 23, 12, 0, 0, 64, 0, }, /* 244 */ - { 90, 7, 12, 0, 0, 90, 0, }, /* 245 */ - { 90, 12, 3, 0, 0, 90, 0, }, /* 246 */ - { 90, 6, 12, 0, 0, 90, 0, }, /* 247 */ - { 90, 21, 12, 0, 0, 90, 0, }, /* 248 */ - { 95, 7, 12, 0, 0, 95, 0, }, /* 249 */ - { 95, 12, 3, 0, 0, 95, 0, }, /* 250 */ - { 95, 21, 12, 0, 0, 95, 0, }, /* 251 */ - { 15, 12, 3, 0, 0, 15, 0, }, /* 252 */ - { 15, 10, 5, 0, 0, 15, 0, }, /* 253 */ - { 15, 7, 12, 0, 0, 15, 0, }, /* 254 */ - { 28, 12, 3, 0, 0, -188, 0, }, /* 255 */ - { 28, 12, 3, 0, 0, -175, 0, }, /* 256 */ - { 10, 21, 12, 0, 0, -231, 0, }, /* 257 */ - { 10, 21, 12, 0, 0, -252, 0, }, /* 258 */ - { 15, 13, 12, 0, 0, -120, 0, }, /* 259 */ - { 15, 21, 12, 0, 0, 15, 0, }, /* 260 */ - { 15, 6, 12, 0, 0, 15, 0, }, /* 261 */ - { 3, 7, 12, 0, 0, 3, 0, }, /* 262 */ - { 3, 12, 3, 0, 0, 3, 0, }, /* 263 */ - { 3, 10, 5, 0, 0, 3, 0, }, /* 264 */ - { 3, 10, 3, 0, 0, 3, 0, }, /* 265 */ - { 3, 13, 12, 0, 0, -77, 0, }, /* 266 */ - { 3, 23, 12, 0, 0, 3, 0, }, /* 267 */ - { 3, 15, 12, 0, 0, 3, 0, }, /* 268 */ - { 3, 26, 12, 0, 0, 3, 0, }, /* 269 */ - { 3, 21, 12, 0, 0, 3, 0, }, /* 270 */ - { 22, 12, 3, 0, 0, 22, 0, }, /* 271 */ - { 22, 10, 5, 0, 0, 22, 0, }, /* 272 */ - { 22, 7, 12, 0, 0, 22, 0, }, /* 273 */ - { 22, 13, 12, 0, 0, -58, 0, }, /* 274 */ - { 22, 21, 12, 0, 0, 22, 0, }, /* 275 */ - { 21, 12, 3, 0, 0, 21, 0, }, /* 276 */ - { 21, 10, 5, 0, 0, 21, 0, }, /* 277 */ - { 21, 7, 12, 0, 0, 21, 0, }, /* 278 */ - { 21, 13, 12, 0, 0, -55, 0, }, /* 279 */ - { 21, 21, 12, 0, 0, 21, 0, }, /* 280 */ - { 21, 23, 12, 0, 0, 21, 0, }, /* 281 */ - { 44, 12, 3, 0, 0, 44, 0, }, /* 282 */ - { 44, 10, 5, 0, 0, 44, 0, }, /* 283 */ - { 44, 7, 12, 0, 0, 44, 0, }, /* 284 */ - { 44, 10, 3, 0, 0, 44, 0, }, /* 285 */ - { 44, 13, 12, 0, 0, 44, 0, }, /* 286 */ - { 44, 26, 12, 0, 0, 44, 0, }, /* 287 */ - { 44, 15, 12, 0, 0, 44, 0, }, /* 288 */ - { 54, 12, 3, 0, 0, 54, 0, }, /* 289 */ - { 54, 7, 12, 0, 0, 54, 0, }, /* 290 */ - { 54, 10, 3, 0, 0, 54, 0, }, /* 291 */ - { 54, 10, 5, 0, 0, 54, 0, }, /* 292 */ - { 54, 13, 12, 0, 0, -52, 0, }, /* 293 */ - { 54, 15, 12, 0, 0, -52, 0, }, /* 294 */ - { 54, 26, 12, 0, 0, -52, 0, }, /* 295 */ - { 54, 26, 12, 0, 0, 54, 0, }, /* 296 */ - { 54, 23, 12, 0, 0, 54, 0, }, /* 297 */ - { 55, 12, 3, 0, 0, 55, 0, }, /* 298 */ - { 55, 10, 5, 0, 0, 55, 0, }, /* 299 */ - { 55, 7, 12, 0, 0, 55, 0, }, /* 300 */ - { 55, 13, 12, 0, 0, 55, 0, }, /* 301 */ - { 55, 21, 12, 0, 0, 55, 0, }, /* 302 */ - { 55, 15, 12, 0, 0, 55, 0, }, /* 303 */ - { 55, 26, 12, 0, 0, 55, 0, }, /* 304 */ - { 29, 7, 12, 0, 0, 29, 0, }, /* 305 */ - { 29, 12, 3, 0, 0, 29, 0, }, /* 306 */ - { 29, 10, 5, 0, 0, 29, 0, }, /* 307 */ - { 29, 21, 12, 0, 0, 29, 0, }, /* 308 */ - { 29, 10, 3, 0, 0, 29, 0, }, /* 309 */ - { 29, 13, 12, 0, 0, -64, 0, }, /* 310 */ - { 37, 12, 3, 0, 0, 37, 0, }, /* 311 */ - { 37, 10, 5, 0, 0, 37, 0, }, /* 312 */ - { 37, 7, 12, 0, 0, 37, 0, }, /* 313 */ - { 37, 10, 3, 0, 0, 37, 0, }, /* 314 */ - { 37, 7, 4, 0, 0, 37, 0, }, /* 315 */ - { 37, 26, 12, 0, 0, 37, 0, }, /* 316 */ - { 37, 15, 12, 0, 0, 37, 0, }, /* 317 */ - { 37, 13, 12, 0, 0, 37, 0, }, /* 318 */ + { 2, 17, 12, 0, 0, 2, 0, }, /* 208 */ + { 2, 26, 12, 0, 0, 2, 0, }, /* 209 */ + { 2, 23, 12, 0, 0, 2, 0, }, /* 210 */ + { 26, 12, 3, 0, 0, 26, 0, }, /* 211 */ + { 26, 17, 12, 0, 0, 26, 0, }, /* 212 */ + { 26, 21, 12, 0, 0, 26, 0, }, /* 213 */ + { 26, 7, 12, 0, 0, 26, 0, }, /* 214 */ + { 1, 1, 4, 0, 0, 1, 0, }, /* 215 */ + { 10, 1, 4, 0, 0, 10, 0, }, /* 216 */ + { 1, 25, 12, 0, 0, 1, 0, }, /* 217 */ + { 1, 21, 12, 0, 0, 1, 0, }, /* 218 */ + { 1, 23, 12, 0, 0, 1, 0, }, /* 219 */ + { 10, 21, 12, 0, 0, -127, 0, }, /* 220 */ + { 1, 26, 12, 0, 0, 1, 0, }, /* 221 */ + { 1, 12, 3, 0, 0, 1, 0, }, /* 222 */ + { 1, 1, 2, 0, 0, -76, 0, }, /* 223 */ + { 1, 7, 12, 0, 0, 1, 0, }, /* 224 */ + { 10, 6, 12, 0, 0, -153, 0, }, /* 225 */ + { 28, 12, 3, 0, 0, -7, 0, }, /* 226 */ + { 1, 13, 12, 0, 0, -80, 0, }, /* 227 */ + { 1, 21, 12, 0, 0, -4, 0, }, /* 228 */ + { 1, 6, 12, 0, 0, 1, 0, }, /* 229 */ + { 1, 13, 12, 0, 0, 1, 0, }, /* 230 */ + { 50, 21, 12, 0, 0, 50, 0, }, /* 231 */ + { 50, 1, 4, 0, 0, 50, 0, }, /* 232 */ + { 50, 7, 12, 0, 0, 50, 0, }, /* 233 */ + { 50, 12, 3, 0, 0, 50, 0, }, /* 234 */ + { 56, 7, 12, 0, 0, 56, 0, }, /* 235 */ + { 56, 12, 3, 0, 0, 56, 0, }, /* 236 */ + { 64, 13, 12, 0, 0, 64, 0, }, /* 237 */ + { 64, 7, 12, 0, 0, 64, 0, }, /* 238 */ + { 64, 12, 3, 0, 0, 64, 0, }, /* 239 */ + { 64, 6, 12, 0, 0, 64, 0, }, /* 240 */ + { 64, 26, 12, 0, 0, 64, 0, }, /* 241 */ + { 64, 21, 12, 0, 0, 64, 0, }, /* 242 */ + { 64, 23, 12, 0, 0, 64, 0, }, /* 243 */ + { 90, 7, 12, 0, 0, 90, 0, }, /* 244 */ + { 90, 12, 3, 0, 0, 90, 0, }, /* 245 */ + { 90, 6, 12, 0, 0, 90, 0, }, /* 246 */ + { 90, 21, 12, 0, 0, 90, 0, }, /* 247 */ + { 95, 7, 12, 0, 0, 95, 0, }, /* 248 */ + { 95, 12, 3, 0, 0, 95, 0, }, /* 249 */ + { 95, 21, 12, 0, 0, 95, 0, }, /* 250 */ + { 15, 12, 3, 0, 0, 15, 0, }, /* 251 */ + { 15, 10, 5, 0, 0, 15, 0, }, /* 252 */ + { 15, 7, 12, 0, 0, 15, 0, }, /* 253 */ + { 28, 12, 3, 0, 0, -196, 0, }, /* 254 */ + { 28, 12, 3, 0, 0, -183, 0, }, /* 255 */ + { 10, 21, 12, 0, 0, -239, 0, }, /* 256 */ + { 10, 21, 12, 0, 0, -260, 0, }, /* 257 */ + { 15, 13, 12, 0, 0, -122, 0, }, /* 258 */ + { 15, 21, 12, 0, 0, 15, 0, }, /* 259 */ + { 15, 6, 12, 0, 0, 15, 0, }, /* 260 */ + { 3, 7, 12, 0, 0, 3, 0, }, /* 261 */ + { 3, 12, 3, 0, 0, 3, 0, }, /* 262 */ + { 3, 10, 5, 0, 0, 3, 0, }, /* 263 */ + { 3, 10, 3, 0, 0, 3, 0, }, /* 264 */ + { 3, 13, 12, 0, 0, -84, 0, }, /* 265 */ + { 3, 23, 12, 0, 0, 3, 0, }, /* 266 */ + { 3, 15, 12, 0, 0, 3, 0, }, /* 267 */ + { 3, 26, 12, 0, 0, 3, 0, }, /* 268 */ + { 3, 21, 12, 0, 0, 3, 0, }, /* 269 */ + { 22, 12, 3, 0, 0, 22, 0, }, /* 270 */ + { 22, 10, 5, 0, 0, 22, 0, }, /* 271 */ + { 22, 7, 12, 0, 0, 22, 0, }, /* 272 */ + { 22, 13, 12, 0, 0, -58, 0, }, /* 273 */ + { 22, 21, 12, 0, 0, 22, 0, }, /* 274 */ + { 21, 12, 3, 0, 0, 21, 0, }, /* 275 */ + { 21, 10, 5, 0, 0, 21, 0, }, /* 276 */ + { 21, 7, 12, 0, 0, 21, 0, }, /* 277 */ + { 21, 13, 12, 0, 0, -55, 0, }, /* 278 */ + { 21, 21, 12, 0, 0, 21, 0, }, /* 279 */ + { 21, 23, 12, 0, 0, 21, 0, }, /* 280 */ + { 44, 12, 3, 0, 0, 44, 0, }, /* 281 */ + { 44, 10, 5, 0, 0, 44, 0, }, /* 282 */ + { 44, 7, 12, 0, 0, 44, 0, }, /* 283 */ + { 44, 10, 3, 0, 0, 44, 0, }, /* 284 */ + { 44, 13, 12, 0, 0, 44, 0, }, /* 285 */ + { 44, 26, 12, 0, 0, 44, 0, }, /* 286 */ + { 44, 15, 12, 0, 0, 44, 0, }, /* 287 */ + { 54, 12, 3, 0, 0, 54, 0, }, /* 288 */ + { 54, 7, 12, 0, 0, 54, 0, }, /* 289 */ + { 54, 10, 3, 0, 0, 54, 0, }, /* 290 */ + { 54, 10, 5, 0, 0, 54, 0, }, /* 291 */ + { 54, 13, 12, 0, 0, -52, 0, }, /* 292 */ + { 54, 15, 12, 0, 0, -52, 0, }, /* 293 */ + { 54, 26, 12, 0, 0, -52, 0, }, /* 294 */ + { 54, 26, 12, 0, 0, 54, 0, }, /* 295 */ + { 54, 23, 12, 0, 0, 54, 0, }, /* 296 */ + { 55, 12, 3, 0, 0, 55, 0, }, /* 297 */ + { 55, 10, 5, 0, 0, 55, 0, }, /* 298 */ + { 55, 7, 12, 0, 0, 55, 0, }, /* 299 */ + { 55, 13, 12, 0, 0, 55, 0, }, /* 300 */ + { 55, 21, 12, 0, 0, 55, 0, }, /* 301 */ + { 55, 15, 12, 0, 0, 55, 0, }, /* 302 */ + { 55, 26, 12, 0, 0, 55, 0, }, /* 303 */ + { 29, 7, 12, 0, 0, 29, 0, }, /* 304 */ + { 29, 12, 3, 0, 0, 29, 0, }, /* 305 */ + { 29, 10, 5, 0, 0, 29, 0, }, /* 306 */ + { 29, 21, 12, 0, 0, 29, 0, }, /* 307 */ + { 29, 10, 3, 0, 0, 29, 0, }, /* 308 */ + { 29, 13, 12, 0, 0, -67, 0, }, /* 309 */ + { 37, 12, 3, 0, 0, 37, 0, }, /* 310 */ + { 37, 10, 5, 0, 0, 37, 0, }, /* 311 */ + { 37, 7, 12, 0, 0, 37, 0, }, /* 312 */ + { 37, 10, 3, 0, 0, 37, 0, }, /* 313 */ + { 37, 7, 4, 0, 0, 37, 0, }, /* 314 */ + { 37, 26, 12, 0, 0, 37, 0, }, /* 315 */ + { 37, 15, 12, 0, 0, 37, 0, }, /* 316 */ + { 37, 13, 12, 0, 0, 37, 0, }, /* 317 */ + { 48, 12, 3, 0, 0, 48, 0, }, /* 318 */ { 48, 10, 5, 0, 0, 48, 0, }, /* 319 */ { 48, 7, 12, 0, 0, 48, 0, }, /* 320 */ - { 48, 12, 3, 0, 0, 48, 0, }, /* 321 */ - { 48, 10, 3, 0, 0, 48, 0, }, /* 322 */ - { 48, 13, 12, 0, 0, 48, 0, }, /* 323 */ - { 48, 21, 12, 0, 0, 48, 0, }, /* 324 */ - { 57, 7, 12, 0, 0, 57, 0, }, /* 325 */ - { 57, 12, 3, 0, 0, 57, 0, }, /* 326 */ - { 57, 7, 5, 0, 0, 57, 0, }, /* 327 */ - { 57, 6, 12, 0, 0, 57, 0, }, /* 328 */ - { 57, 21, 12, 0, 0, 57, 0, }, /* 329 */ - { 57, 13, 12, 0, 0, 57, 0, }, /* 330 */ - { 33, 7, 12, 0, 0, 33, 0, }, /* 331 */ - { 33, 12, 3, 0, 0, 33, 0, }, /* 332 */ - { 33, 7, 5, 0, 0, 33, 0, }, /* 333 */ - { 33, 6, 12, 0, 0, 33, 0, }, /* 334 */ - { 33, 13, 12, 0, 0, 33, 0, }, /* 335 */ - { 58, 7, 12, 0, 0, 58, 0, }, /* 336 */ - { 58, 26, 12, 0, 0, 58, 0, }, /* 337 */ - { 58, 21, 12, 0, 0, 58, 0, }, /* 338 */ - { 58, 12, 3, 0, 0, 58, 0, }, /* 339 */ - { 58, 13, 12, 0, 0, 58, 0, }, /* 340 */ - { 58, 15, 12, 0, 0, 58, 0, }, /* 341 */ - { 58, 22, 12, 0, 0, 58, 0, }, /* 342 */ - { 58, 18, 12, 0, 0, 58, 0, }, /* 343 */ - { 58, 10, 5, 0, 0, 58, 0, }, /* 344 */ - { 39, 7, 12, 0, 0, 39, 0, }, /* 345 */ - { 39, 10, 12, 0, 0, 39, 0, }, /* 346 */ - { 39, 12, 3, 0, 0, 39, 0, }, /* 347 */ - { 39, 10, 5, 0, 0, 39, 0, }, /* 348 */ - { 39, 13, 12, 0, 0, -81, 0, }, /* 349 */ - { 39, 21, 12, 0, 0, 39, 0, }, /* 350 */ - { 39, 13, 12, 0, 0, 39, 0, }, /* 351 */ - { 39, 26, 12, 0, 0, 39, 0, }, /* 352 */ - { 17, 9, 12, 0, 7264, 17, 0, }, /* 353 */ - { 17, 5, 12, 0, 3008, 17, 0, }, /* 354 */ - { 10, 21, 12, 0, 0, -49, 0, }, /* 355 */ - { 17, 6, 12, 0, 0, 17, 0, }, /* 356 */ - { 24, 7, 6, 0, 0, 24, 0, }, /* 357 */ - { 24, 7, 7, 0, 0, 24, 0, }, /* 358 */ - { 24, 7, 8, 0, 0, 24, 0, }, /* 359 */ - { 16, 7, 12, 0, 0, 16, 0, }, /* 360 */ - { 16, 12, 3, 0, 0, 16, 0, }, /* 361 */ - { 16, 21, 12, 0, 0, 16, 0, }, /* 362 */ - { 16, 15, 12, 0, 0, 16, 0, }, /* 363 */ - { 16, 26, 12, 0, 0, 16, 0, }, /* 364 */ - { 9, 9, 12, 0, 38864, 9, 0, }, /* 365 */ - { 9, 9, 12, 0, 8, 9, 0, }, /* 366 */ - { 9, 5, 12, 0, -8, 9, 0, }, /* 367 */ - { 8, 17, 12, 0, 0, 8, 0, }, /* 368 */ - { 8, 7, 12, 0, 0, 8, 0, }, /* 369 */ - { 8, 26, 12, 0, 0, 8, 0, }, /* 370 */ - { 8, 21, 12, 0, 0, 8, 0, }, /* 371 */ - { 41, 29, 12, 0, 0, 41, 0, }, /* 372 */ - { 41, 7, 12, 0, 0, 41, 0, }, /* 373 */ - { 41, 22, 12, 0, 0, 41, 0, }, /* 374 */ - { 41, 18, 12, 0, 0, 41, 0, }, /* 375 */ - { 46, 7, 12, 0, 0, 46, 0, }, /* 376 */ - { 46, 14, 12, 0, 0, 46, 0, }, /* 377 */ - { 51, 7, 12, 0, 0, 51, 0, }, /* 378 */ - { 51, 12, 3, 0, 0, 51, 0, }, /* 379 */ - { 25, 7, 12, 0, 0, 25, 0, }, /* 380 */ - { 25, 12, 3, 0, 0, 25, 0, }, /* 381 */ - { 10, 21, 12, 0, 0, -115, 0, }, /* 382 */ - { 7, 7, 12, 0, 0, 7, 0, }, /* 383 */ - { 7, 12, 3, 0, 0, 7, 0, }, /* 384 */ - { 52, 7, 12, 0, 0, 52, 0, }, /* 385 */ - { 52, 12, 3, 0, 0, 52, 0, }, /* 386 */ - { 32, 7, 12, 0, 0, 32, 0, }, /* 387 */ - { 32, 12, 3, 0, 0, 32, 0, }, /* 388 */ - { 32, 10, 5, 0, 0, 32, 0, }, /* 389 */ - { 32, 21, 12, 0, 0, 32, 0, }, /* 390 */ - { 32, 6, 12, 0, 0, 32, 0, }, /* 391 */ - { 32, 23, 12, 0, 0, 32, 0, }, /* 392 */ - { 32, 13, 12, 0, 0, 32, 0, }, /* 393 */ - { 32, 15, 12, 0, 0, 32, 0, }, /* 394 */ - { 38, 21, 12, 0, 0, 38, 0, }, /* 395 */ - { 10, 21, 12, 0, 0, -70, 0, }, /* 396 */ - { 38, 17, 12, 0, 0, 38, 0, }, /* 397 */ - { 38, 12, 3, 0, 0, 38, 0, }, /* 398 */ - { 38, 1, 2, 0, 0, 38, 0, }, /* 399 */ - { 38, 13, 12, 0, 0, 38, 0, }, /* 400 */ - { 38, 7, 12, 0, 0, 38, 0, }, /* 401 */ - { 38, 6, 12, 0, 0, 38, 0, }, /* 402 */ - { 35, 7, 12, 0, 0, 35, 0, }, /* 403 */ - { 35, 12, 3, 0, 0, 35, 0, }, /* 404 */ - { 35, 10, 5, 0, 0, 35, 0, }, /* 405 */ - { 35, 26, 12, 0, 0, 35, 0, }, /* 406 */ - { 35, 21, 12, 0, 0, 35, 0, }, /* 407 */ - { 35, 13, 12, 0, 0, 35, 0, }, /* 408 */ - { 53, 7, 12, 0, 0, 53, 0, }, /* 409 */ - { 40, 7, 12, 0, 0, 40, 0, }, /* 410 */ - { 40, 13, 12, 0, 0, 40, 0, }, /* 411 */ - { 40, 15, 12, 0, 0, 40, 0, }, /* 412 */ - { 40, 26, 12, 0, 0, 40, 0, }, /* 413 */ - { 32, 26, 12, 0, 0, 32, 0, }, /* 414 */ - { 6, 7, 12, 0, 0, 6, 0, }, /* 415 */ - { 6, 12, 3, 0, 0, 6, 0, }, /* 416 */ - { 6, 10, 5, 0, 0, 6, 0, }, /* 417 */ - { 6, 21, 12, 0, 0, 6, 0, }, /* 418 */ - { 91, 7, 12, 0, 0, 91, 0, }, /* 419 */ - { 91, 10, 5, 0, 0, 91, 0, }, /* 420 */ - { 91, 12, 3, 0, 0, 91, 0, }, /* 421 */ - { 91, 10, 12, 0, 0, 91, 0, }, /* 422 */ - { 91, 13, 12, 0, 0, 91, 0, }, /* 423 */ - { 91, 21, 12, 0, 0, 91, 0, }, /* 424 */ - { 91, 6, 12, 0, 0, 91, 0, }, /* 425 */ - { 28, 11, 3, 0, 0, 28, 0, }, /* 426 */ - { 62, 12, 3, 0, 0, 62, 0, }, /* 427 */ - { 62, 10, 5, 0, 0, 62, 0, }, /* 428 */ - { 62, 7, 12, 0, 0, 62, 0, }, /* 429 */ - { 62, 10, 3, 0, 0, 62, 0, }, /* 430 */ - { 62, 13, 12, 0, 0, 62, 0, }, /* 431 */ - { 62, 21, 12, 0, 0, 62, 0, }, /* 432 */ - { 62, 26, 12, 0, 0, 62, 0, }, /* 433 */ - { 76, 12, 3, 0, 0, 76, 0, }, /* 434 */ - { 76, 10, 5, 0, 0, 76, 0, }, /* 435 */ - { 76, 7, 12, 0, 0, 76, 0, }, /* 436 */ - { 76, 13, 12, 0, 0, 76, 0, }, /* 437 */ - { 93, 7, 12, 0, 0, 93, 0, }, /* 438 */ - { 93, 12, 3, 0, 0, 93, 0, }, /* 439 */ - { 93, 10, 5, 0, 0, 93, 0, }, /* 440 */ - { 93, 21, 12, 0, 0, 93, 0, }, /* 441 */ - { 70, 7, 12, 0, 0, 70, 0, }, /* 442 */ - { 70, 10, 5, 0, 0, 70, 0, }, /* 443 */ - { 70, 12, 3, 0, 0, 70, 0, }, /* 444 */ - { 70, 21, 12, 0, 0, 70, 0, }, /* 445 */ - { 70, 13, 12, 0, 0, 70, 0, }, /* 446 */ - { 73, 13, 12, 0, 0, 73, 0, }, /* 447 */ - { 73, 7, 12, 0, 0, 73, 0, }, /* 448 */ - { 73, 6, 12, 0, 0, 73, 0, }, /* 449 */ - { 73, 21, 12, 0, 0, 73, 0, }, /* 450 */ - { 13, 5, 12, 63, -6222, 13, 0, }, /* 451 */ - { 13, 5, 12, 67, -6221, 13, 0, }, /* 452 */ - { 13, 5, 12, 71, -6212, 13, 0, }, /* 453 */ - { 13, 5, 12, 75, -6210, 13, 0, }, /* 454 */ - { 13, 5, 12, 79, -6210, 13, 0, }, /* 455 */ - { 13, 5, 12, 79, -6211, 13, 0, }, /* 456 */ - { 13, 5, 12, 84, -6204, 13, 0, }, /* 457 */ - { 13, 5, 12, 88, -6180, 13, 0, }, /* 458 */ - { 13, 5, 12, 108, 35267, 13, 0, }, /* 459 */ - { 17, 9, 12, 0, -3008, 17, 0, }, /* 460 */ - { 76, 21, 12, 0, 0, 76, 0, }, /* 461 */ - { 28, 12, 3, 0, 0, -110, 0, }, /* 462 */ - { 28, 12, 3, 0, 0, 15, 0, }, /* 463 */ - { 10, 21, 12, 0, 0, -37, 0, }, /* 464 */ - { 28, 12, 3, 0, 0, -16, 0, }, /* 465 */ - { 28, 12, 3, 0, 0, -43, 0, }, /* 466 */ - { 28, 12, 3, 0, 0, -138, 0, }, /* 467 */ - { 10, 10, 5, 0, 0, -16, 0, }, /* 468 */ - { 10, 7, 12, 0, 0, -40, 0, }, /* 469 */ - { 10, 7, 12, 0, 0, -16, 0, }, /* 470 */ - { 10, 7, 12, 0, 0, 15, 0, }, /* 471 */ - { 10, 7, 12, 0, 0, -154, 0, }, /* 472 */ - { 10, 7, 12, 0, 0, -37, 0, }, /* 473 */ - { 28, 12, 3, 0, 0, -89, 0, }, /* 474 */ - { 10, 10, 5, 0, 0, 3, 0, }, /* 475 */ - { 28, 12, 3, 0, 0, -37, 0, }, /* 476 */ - { 10, 7, 12, 0, 0, 150, 0, }, /* 477 */ - { 13, 5, 12, 0, 0, 13, 0, }, /* 478 */ - { 13, 6, 12, 0, 0, 13, 0, }, /* 479 */ - { 34, 5, 12, 0, 35332, 34, 0, }, /* 480 */ - { 34, 5, 12, 0, 3814, 34, 0, }, /* 481 */ - { 34, 5, 12, 0, 35384, 34, 0, }, /* 482 */ + { 48, 10, 3, 0, 0, 48, 0, }, /* 321 */ + { 48, 13, 12, 0, 0, 48, 0, }, /* 322 */ + { 48, 21, 12, 0, 0, 48, 0, }, /* 323 */ + { 57, 7, 12, 0, 0, 57, 0, }, /* 324 */ + { 57, 12, 3, 0, 0, 57, 0, }, /* 325 */ + { 57, 7, 5, 0, 0, 57, 0, }, /* 326 */ + { 57, 6, 12, 0, 0, 57, 0, }, /* 327 */ + { 57, 21, 12, 0, 0, 57, 0, }, /* 328 */ + { 57, 13, 12, 0, 0, 57, 0, }, /* 329 */ + { 33, 7, 12, 0, 0, 33, 0, }, /* 330 */ + { 33, 12, 3, 0, 0, 33, 0, }, /* 331 */ + { 33, 7, 5, 0, 0, 33, 0, }, /* 332 */ + { 33, 6, 12, 0, 0, 33, 0, }, /* 333 */ + { 33, 13, 12, 0, 0, 33, 0, }, /* 334 */ + { 58, 7, 12, 0, 0, 58, 0, }, /* 335 */ + { 58, 26, 12, 0, 0, 58, 0, }, /* 336 */ + { 58, 21, 12, 0, 0, 58, 0, }, /* 337 */ + { 58, 12, 3, 0, 0, 58, 0, }, /* 338 */ + { 58, 13, 12, 0, 0, 58, 0, }, /* 339 */ + { 58, 15, 12, 0, 0, 58, 0, }, /* 340 */ + { 58, 22, 12, 0, 0, 58, 0, }, /* 341 */ + { 58, 18, 12, 0, 0, 58, 0, }, /* 342 */ + { 58, 10, 5, 0, 0, 58, 0, }, /* 343 */ + { 39, 7, 12, 0, 0, 39, 0, }, /* 344 */ + { 39, 10, 12, 0, 0, 39, 0, }, /* 345 */ + { 39, 12, 3, 0, 0, 39, 0, }, /* 346 */ + { 39, 10, 5, 0, 0, 39, 0, }, /* 347 */ + { 39, 13, 12, 0, 0, -88, 0, }, /* 348 */ + { 39, 21, 12, 0, 0, 39, 0, }, /* 349 */ + { 39, 13, 12, 0, 0, 39, 0, }, /* 350 */ + { 39, 26, 12, 0, 0, 39, 0, }, /* 351 */ + { 17, 9, 12, 0, 7264, 17, 0, }, /* 352 */ + { 17, 5, 12, 0, 3008, 17, 0, }, /* 353 */ + { 10, 21, 12, 0, 0, -49, 0, }, /* 354 */ + { 17, 6, 12, 0, 0, 17, 0, }, /* 355 */ + { 24, 7, 6, 0, 0, 24, 0, }, /* 356 */ + { 24, 7, 7, 0, 0, 24, 0, }, /* 357 */ + { 24, 7, 8, 0, 0, 24, 0, }, /* 358 */ + { 16, 7, 12, 0, 0, 16, 0, }, /* 359 */ + { 16, 12, 3, 0, 0, 16, 0, }, /* 360 */ + { 16, 21, 12, 0, 0, 16, 0, }, /* 361 */ + { 16, 15, 12, 0, 0, 16, 0, }, /* 362 */ + { 16, 26, 12, 0, 0, 16, 0, }, /* 363 */ + { 9, 9, 12, 0, 38864, 9, 0, }, /* 364 */ + { 9, 9, 12, 0, 8, 9, 0, }, /* 365 */ + { 9, 5, 12, 0, -8, 9, 0, }, /* 366 */ + { 8, 17, 12, 0, 0, 8, 0, }, /* 367 */ + { 8, 7, 12, 0, 0, 8, 0, }, /* 368 */ + { 8, 26, 12, 0, 0, 8, 0, }, /* 369 */ + { 8, 21, 12, 0, 0, 8, 0, }, /* 370 */ + { 41, 29, 12, 0, 0, 41, 0, }, /* 371 */ + { 41, 7, 12, 0, 0, 41, 0, }, /* 372 */ + { 41, 22, 12, 0, 0, 41, 0, }, /* 373 */ + { 41, 18, 12, 0, 0, 41, 0, }, /* 374 */ + { 46, 7, 12, 0, 0, 46, 0, }, /* 375 */ + { 46, 14, 12, 0, 0, 46, 0, }, /* 376 */ + { 51, 7, 12, 0, 0, 51, 0, }, /* 377 */ + { 51, 12, 3, 0, 0, 51, 0, }, /* 378 */ + { 25, 7, 12, 0, 0, 25, 0, }, /* 379 */ + { 25, 12, 3, 0, 0, 25, 0, }, /* 380 */ + { 10, 21, 12, 0, 0, -117, 0, }, /* 381 */ + { 7, 7, 12, 0, 0, 7, 0, }, /* 382 */ + { 7, 12, 3, 0, 0, 7, 0, }, /* 383 */ + { 52, 7, 12, 0, 0, 52, 0, }, /* 384 */ + { 52, 12, 3, 0, 0, 52, 0, }, /* 385 */ + { 32, 7, 12, 0, 0, 32, 0, }, /* 386 */ + { 32, 12, 3, 0, 0, 32, 0, }, /* 387 */ + { 32, 10, 5, 0, 0, 32, 0, }, /* 388 */ + { 32, 21, 12, 0, 0, 32, 0, }, /* 389 */ + { 32, 6, 12, 0, 0, 32, 0, }, /* 390 */ + { 32, 23, 12, 0, 0, 32, 0, }, /* 391 */ + { 32, 13, 12, 0, 0, 32, 0, }, /* 392 */ + { 32, 15, 12, 0, 0, 32, 0, }, /* 393 */ + { 38, 21, 12, 0, 0, 38, 0, }, /* 394 */ + { 10, 21, 12, 0, 0, -73, 0, }, /* 395 */ + { 38, 17, 12, 0, 0, 38, 0, }, /* 396 */ + { 38, 12, 3, 0, 0, 38, 0, }, /* 397 */ + { 38, 1, 2, 0, 0, 38, 0, }, /* 398 */ + { 38, 13, 12, 0, 0, 38, 0, }, /* 399 */ + { 38, 7, 12, 0, 0, 38, 0, }, /* 400 */ + { 38, 6, 12, 0, 0, 38, 0, }, /* 401 */ + { 35, 7, 12, 0, 0, 35, 0, }, /* 402 */ + { 35, 12, 3, 0, 0, 35, 0, }, /* 403 */ + { 35, 10, 5, 0, 0, 35, 0, }, /* 404 */ + { 35, 26, 12, 0, 0, 35, 0, }, /* 405 */ + { 35, 21, 12, 0, 0, 35, 0, }, /* 406 */ + { 35, 13, 12, 0, 0, 35, 0, }, /* 407 */ + { 53, 7, 12, 0, 0, 53, 0, }, /* 408 */ + { 40, 7, 12, 0, 0, 40, 0, }, /* 409 */ + { 40, 13, 12, 0, 0, 40, 0, }, /* 410 */ + { 40, 15, 12, 0, 0, 40, 0, }, /* 411 */ + { 40, 26, 12, 0, 0, 40, 0, }, /* 412 */ + { 32, 26, 12, 0, 0, 32, 0, }, /* 413 */ + { 6, 7, 12, 0, 0, 6, 0, }, /* 414 */ + { 6, 12, 3, 0, 0, 6, 0, }, /* 415 */ + { 6, 10, 5, 0, 0, 6, 0, }, /* 416 */ + { 6, 21, 12, 0, 0, 6, 0, }, /* 417 */ + { 91, 7, 12, 0, 0, 91, 0, }, /* 418 */ + { 91, 10, 5, 0, 0, 91, 0, }, /* 419 */ + { 91, 12, 3, 0, 0, 91, 0, }, /* 420 */ + { 91, 10, 12, 0, 0, 91, 0, }, /* 421 */ + { 91, 13, 12, 0, 0, 91, 0, }, /* 422 */ + { 91, 21, 12, 0, 0, 91, 0, }, /* 423 */ + { 91, 6, 12, 0, 0, 91, 0, }, /* 424 */ + { 28, 11, 3, 0, 0, 28, 0, }, /* 425 */ + { 62, 12, 3, 0, 0, 62, 0, }, /* 426 */ + { 62, 10, 5, 0, 0, 62, 0, }, /* 427 */ + { 62, 7, 12, 0, 0, 62, 0, }, /* 428 */ + { 62, 10, 3, 0, 0, 62, 0, }, /* 429 */ + { 62, 13, 12, 0, 0, 62, 0, }, /* 430 */ + { 62, 21, 12, 0, 0, 62, 0, }, /* 431 */ + { 62, 26, 12, 0, 0, 62, 0, }, /* 432 */ + { 76, 12, 3, 0, 0, 76, 0, }, /* 433 */ + { 76, 10, 5, 0, 0, 76, 0, }, /* 434 */ + { 76, 7, 12, 0, 0, 76, 0, }, /* 435 */ + { 76, 13, 12, 0, 0, 76, 0, }, /* 436 */ + { 93, 7, 12, 0, 0, 93, 0, }, /* 437 */ + { 93, 12, 3, 0, 0, 93, 0, }, /* 438 */ + { 93, 10, 5, 0, 0, 93, 0, }, /* 439 */ + { 93, 21, 12, 0, 0, 93, 0, }, /* 440 */ + { 70, 7, 12, 0, 0, 70, 0, }, /* 441 */ + { 70, 10, 5, 0, 0, 70, 0, }, /* 442 */ + { 70, 12, 3, 0, 0, 70, 0, }, /* 443 */ + { 70, 21, 12, 0, 0, 70, 0, }, /* 444 */ + { 70, 13, 12, 0, 0, 70, 0, }, /* 445 */ + { 73, 13, 12, 0, 0, 73, 0, }, /* 446 */ + { 73, 7, 12, 0, 0, 73, 0, }, /* 447 */ + { 73, 6, 12, 0, 0, 73, 0, }, /* 448 */ + { 73, 21, 12, 0, 0, 73, 0, }, /* 449 */ + { 13, 5, 12, 63, -6222, 13, 0, }, /* 450 */ + { 13, 5, 12, 67, -6221, 13, 0, }, /* 451 */ + { 13, 5, 12, 71, -6212, 13, 0, }, /* 452 */ + { 13, 5, 12, 75, -6210, 13, 0, }, /* 453 */ + { 13, 5, 12, 79, -6210, 13, 0, }, /* 454 */ + { 13, 5, 12, 79, -6211, 13, 0, }, /* 455 */ + { 13, 5, 12, 84, -6204, 13, 0, }, /* 456 */ + { 13, 5, 12, 88, -6180, 13, 0, }, /* 457 */ + { 13, 5, 12, 108, 35267, 13, 0, }, /* 458 */ + { 17, 9, 12, 0, -3008, 17, 0, }, /* 459 */ + { 76, 21, 12, 0, 0, 76, 0, }, /* 460 */ + { 28, 12, 3, 0, 0, -112, 0, }, /* 461 */ + { 28, 12, 3, 0, 0, 15, 0, }, /* 462 */ + { 10, 21, 12, 0, 0, -37, 0, }, /* 463 */ + { 28, 12, 3, 0, 0, -13, 0, }, /* 464 */ + { 28, 12, 3, 0, 0, -43, 0, }, /* 465 */ + { 28, 12, 3, 0, 0, -146, 0, }, /* 466 */ + { 10, 10, 5, 0, 0, -13, 0, }, /* 467 */ + { 10, 7, 12, 0, 0, -40, 0, }, /* 468 */ + { 10, 7, 12, 0, 0, -13, 0, }, /* 469 */ + { 10, 7, 12, 0, 0, 15, 0, }, /* 470 */ + { 10, 7, 12, 0, 0, -162, 0, }, /* 471 */ + { 10, 7, 12, 0, 0, -37, 0, }, /* 472 */ + { 28, 12, 3, 0, 0, -96, 0, }, /* 473 */ + { 10, 10, 5, 0, 0, 3, 0, }, /* 474 */ + { 28, 12, 3, 0, 0, -37, 0, }, /* 475 */ + { 10, 7, 12, 0, 0, 150, 0, }, /* 476 */ + { 13, 5, 12, 0, 0, 13, 0, }, /* 477 */ + { 13, 6, 12, 0, 0, 13, 0, }, /* 478 */ + { 34, 5, 12, 0, 35332, 34, 0, }, /* 479 */ + { 34, 5, 12, 0, 3814, 34, 0, }, /* 480 */ + { 34, 5, 12, 0, 35384, 34, 0, }, /* 481 */ + { 28, 12, 3, 0, 0, -34, 0, }, /* 482 */ { 34, 9, 12, 92, 1, 34, 0, }, /* 483 */ { 34, 5, 12, 92, -1, 34, 0, }, /* 484 */ { 34, 5, 12, 92, -58, 34, 0, }, /* 485 */ @@ -699,10 +702,10 @@ const ucd_record PRIV(ucd_records)[] = { /* 11508 bytes, record size 12 */ { 28, 1, 13, 0, 0, 28, 0, }, /* 506 */ { 10, 27, 2, 0, 0, 10, 0, }, /* 507 */ { 10, 28, 2, 0, 0, 10, 0, }, /* 508 */ - { 10, 29, 12, 0, 0, -67, 0, }, /* 509 */ + { 10, 29, 12, 0, 0, -70, 0, }, /* 509 */ { 10, 21, 14, 0, 0, 10, 0, }, /* 510 */ { 0, 2, 2, 0, 0, 0, 0, }, /* 511 */ - { 28, 12, 3, 0, 0, -93, 0, }, /* 512 */ + { 28, 12, 3, 0, 0, -100, 0, }, /* 512 */ { 10, 9, 12, 0, 0, 10, 0, }, /* 513 */ { 10, 5, 12, 0, 0, 10, 0, }, /* 514 */ { 20, 9, 12, 96, -7517, 20, 0, }, /* 515 */ @@ -743,31 +746,31 @@ const ucd_record PRIV(ucd_records)[] = { /* 11508 bytes, record size 12 */ { 59, 21, 12, 0, 0, 59, 0, }, /* 550 */ { 59, 12, 3, 0, 0, 59, 0, }, /* 551 */ { 13, 12, 3, 0, 0, 13, 0, }, /* 552 */ - { 10, 21, 12, 0, 0, -28, 0, }, /* 553 */ + { 10, 21, 12, 0, 0, -25, 0, }, /* 553 */ { 23, 26, 12, 0, 0, 23, 0, }, /* 554 */ - { 10, 21, 12, 0, 0, -131, 0, }, /* 555 */ - { 10, 21, 12, 0, 0, -125, 0, }, /* 556 */ + { 10, 21, 12, 0, 0, -139, 0, }, /* 555 */ + { 10, 21, 12, 0, 0, -133, 0, }, /* 556 */ { 23, 6, 12, 0, 0, 23, 0, }, /* 557 */ { 10, 7, 12, 0, 0, 23, 0, }, /* 558 */ { 23, 14, 12, 0, 0, 23, 0, }, /* 559 */ - { 10, 22, 12, 0, 0, -131, 0, }, /* 560 */ - { 10, 18, 12, 0, 0, -131, 0, }, /* 561 */ - { 10, 26, 12, 0, 0, -125, 0, }, /* 562 */ - { 10, 17, 12, 0, 0, -125, 0, }, /* 563 */ - { 10, 22, 12, 0, 0, -125, 0, }, /* 564 */ - { 10, 18, 12, 0, 0, -125, 0, }, /* 565 */ - { 28, 12, 3, 0, 0, -19, 0, }, /* 566 */ + { 10, 22, 12, 0, 0, -139, 0, }, /* 560 */ + { 10, 18, 12, 0, 0, -139, 0, }, /* 561 */ + { 10, 26, 12, 0, 0, -133, 0, }, /* 562 */ + { 10, 17, 12, 0, 0, -133, 0, }, /* 563 */ + { 10, 22, 12, 0, 0, -133, 0, }, /* 564 */ + { 10, 18, 12, 0, 0, -133, 0, }, /* 565 */ + { 28, 12, 3, 0, 0, -16, 0, }, /* 566 */ { 24, 10, 3, 0, 0, 24, 0, }, /* 567 */ - { 10, 17, 14, 0, 0, -125, 0, }, /* 568 */ - { 10, 6, 12, 0, 0, -61, 0, }, /* 569 */ - { 10, 7, 12, 0, 0, -97, 0, }, /* 570 */ - { 10, 21, 14, 0, 0, -97, 0, }, /* 571 */ + { 10, 17, 14, 0, 0, -133, 0, }, /* 568 */ + { 10, 6, 12, 0, 0, -64, 0, }, /* 569 */ + { 10, 7, 12, 0, 0, -104, 0, }, /* 570 */ + { 10, 21, 14, 0, 0, -104, 0, }, /* 571 */ { 10, 26, 12, 0, 0, 23, 0, }, /* 572 */ { 27, 7, 12, 0, 0, 27, 0, }, /* 573 */ - { 28, 12, 3, 0, 0, -61, 0, }, /* 574 */ - { 10, 24, 12, 0, 0, -61, 0, }, /* 575 */ + { 28, 12, 3, 0, 0, -64, 0, }, /* 574 */ + { 10, 24, 12, 0, 0, -64, 0, }, /* 575 */ { 27, 6, 12, 0, 0, 27, 0, }, /* 576 */ - { 10, 17, 12, 0, 0, -61, 0, }, /* 577 */ + { 10, 17, 12, 0, 0, -64, 0, }, /* 577 */ { 30, 7, 12, 0, 0, 30, 0, }, /* 578 */ { 30, 6, 12, 0, 0, 30, 0, }, /* 579 */ { 4, 7, 12, 0, 0, 4, 0, }, /* 580 */ @@ -795,360 +798,376 @@ const ucd_record PRIV(ucd_records)[] = { /* 11508 bytes, record size 12 */ { 79, 14, 12, 0, 0, 79, 0, }, /* 602 */ { 79, 12, 3, 0, 0, 79, 0, }, /* 603 */ { 79, 21, 12, 0, 0, 79, 0, }, /* 604 */ - { 34, 9, 12, 0, -35332, 34, 0, }, /* 605 */ - { 34, 9, 12, 0, -42280, 34, 0, }, /* 606 */ - { 34, 5, 12, 0, 48, 34, 0, }, /* 607 */ - { 34, 9, 12, 0, -42308, 34, 0, }, /* 608 */ - { 34, 9, 12, 0, -42319, 34, 0, }, /* 609 */ - { 34, 9, 12, 0, -42315, 34, 0, }, /* 610 */ - { 34, 9, 12, 0, -42305, 34, 0, }, /* 611 */ - { 34, 9, 12, 0, -42258, 34, 0, }, /* 612 */ - { 34, 9, 12, 0, -42282, 34, 0, }, /* 613 */ - { 34, 9, 12, 0, -42261, 34, 0, }, /* 614 */ - { 34, 9, 12, 0, 928, 34, 0, }, /* 615 */ - { 34, 9, 12, 0, -48, 34, 0, }, /* 616 */ - { 34, 9, 12, 0, -42307, 34, 0, }, /* 617 */ - { 34, 9, 12, 0, -35384, 34, 0, }, /* 618 */ - { 49, 7, 12, 0, 0, 49, 0, }, /* 619 */ - { 49, 12, 3, 0, 0, 49, 0, }, /* 620 */ - { 49, 10, 5, 0, 0, 49, 0, }, /* 621 */ - { 49, 26, 12, 0, 0, 49, 0, }, /* 622 */ - { 10, 15, 12, 0, 0, -216, 0, }, /* 623 */ - { 10, 15, 12, 0, 0, -202, 0, }, /* 624 */ - { 10, 26, 12, 0, 0, -163, 0, }, /* 625 */ - { 10, 23, 12, 0, 0, -163, 0, }, /* 626 */ - { 65, 7, 12, 0, 0, 65, 0, }, /* 627 */ - { 65, 21, 12, 0, 0, 65, 0, }, /* 628 */ - { 75, 10, 5, 0, 0, 75, 0, }, /* 629 */ - { 75, 7, 12, 0, 0, 75, 0, }, /* 630 */ - { 75, 12, 3, 0, 0, 75, 0, }, /* 631 */ - { 75, 21, 12, 0, 0, 75, 0, }, /* 632 */ - { 75, 13, 12, 0, 0, 75, 0, }, /* 633 */ - { 15, 12, 3, 0, 0, -16, 0, }, /* 634 */ - { 15, 7, 12, 0, 0, -46, 0, }, /* 635 */ - { 69, 13, 12, 0, 0, 69, 0, }, /* 636 */ - { 69, 7, 12, 0, 0, 69, 0, }, /* 637 */ - { 69, 12, 3, 0, 0, 69, 0, }, /* 638 */ - { 10, 21, 12, 0, 0, -101, 0, }, /* 639 */ - { 69, 21, 12, 0, 0, 69, 0, }, /* 640 */ - { 74, 7, 12, 0, 0, 74, 0, }, /* 641 */ - { 74, 12, 3, 0, 0, 74, 0, }, /* 642 */ - { 74, 10, 5, 0, 0, 74, 0, }, /* 643 */ - { 74, 21, 12, 0, 0, 74, 0, }, /* 644 */ - { 84, 12, 3, 0, 0, 84, 0, }, /* 645 */ - { 84, 10, 5, 0, 0, 84, 0, }, /* 646 */ - { 84, 7, 12, 0, 0, 84, 0, }, /* 647 */ - { 84, 21, 12, 0, 0, 84, 0, }, /* 648 */ - { 10, 6, 12, 0, 0, -22, 0, }, /* 649 */ - { 84, 13, 12, 0, 0, 84, 0, }, /* 650 */ - { 39, 6, 12, 0, 0, 39, 0, }, /* 651 */ - { 68, 7, 12, 0, 0, 68, 0, }, /* 652 */ - { 68, 12, 3, 0, 0, 68, 0, }, /* 653 */ - { 68, 10, 5, 0, 0, 68, 0, }, /* 654 */ - { 68, 13, 12, 0, 0, 68, 0, }, /* 655 */ - { 68, 21, 12, 0, 0, 68, 0, }, /* 656 */ - { 92, 7, 12, 0, 0, 92, 0, }, /* 657 */ - { 92, 12, 3, 0, 0, 92, 0, }, /* 658 */ - { 92, 6, 12, 0, 0, 92, 0, }, /* 659 */ - { 92, 21, 12, 0, 0, 92, 0, }, /* 660 */ - { 87, 7, 12, 0, 0, 87, 0, }, /* 661 */ - { 87, 10, 5, 0, 0, 87, 0, }, /* 662 */ - { 87, 12, 3, 0, 0, 87, 0, }, /* 663 */ - { 87, 21, 12, 0, 0, 87, 0, }, /* 664 */ - { 87, 6, 12, 0, 0, 87, 0, }, /* 665 */ - { 34, 5, 12, 0, -928, 34, 0, }, /* 666 */ - { 9, 5, 12, 0, -38864, 9, 0, }, /* 667 */ - { 87, 13, 12, 0, 0, 87, 0, }, /* 668 */ - { 24, 7, 9, 0, 0, 24, 0, }, /* 669 */ - { 24, 7, 10, 0, 0, 24, 0, }, /* 670 */ - { 0, 4, 12, 0, 0, 0, 0, }, /* 671 */ - { 0, 3, 12, 0, 0, 0, 0, }, /* 672 */ - { 26, 25, 12, 0, 0, 26, 0, }, /* 673 */ - { 1, 24, 12, 0, 0, 1, 0, }, /* 674 */ - { 1, 7, 12, 0, 0, -10, 0, }, /* 675 */ - { 1, 26, 12, 0, 0, -10, 0, }, /* 676 */ - { 10, 6, 3, 0, 0, -61, 0, }, /* 677 */ - { 36, 7, 12, 0, 0, 36, 0, }, /* 678 */ - { 10, 21, 12, 0, 0, -25, 0, }, /* 679 */ - { 10, 15, 12, 0, 0, -85, 0, }, /* 680 */ - { 10, 26, 12, 0, 0, -25, 0, }, /* 681 */ - { 20, 14, 12, 0, 0, 20, 0, }, /* 682 */ - { 20, 15, 12, 0, 0, 20, 0, }, /* 683 */ - { 20, 26, 12, 0, 0, 20, 0, }, /* 684 */ - { 71, 7, 12, 0, 0, 71, 0, }, /* 685 */ - { 67, 7, 12, 0, 0, 67, 0, }, /* 686 */ - { 28, 12, 3, 0, 0, -1, 0, }, /* 687 */ - { 10, 15, 12, 0, 0, -1, 0, }, /* 688 */ - { 42, 7, 12, 0, 0, 42, 0, }, /* 689 */ - { 42, 15, 12, 0, 0, 42, 0, }, /* 690 */ - { 19, 7, 12, 0, 0, 19, 0, }, /* 691 */ - { 19, 14, 12, 0, 0, 19, 0, }, /* 692 */ - { 118, 7, 12, 0, 0, 118, 0, }, /* 693 */ - { 118, 12, 3, 0, 0, 118, 0, }, /* 694 */ - { 60, 7, 12, 0, 0, 60, 0, }, /* 695 */ - { 60, 21, 12, 0, 0, 60, 0, }, /* 696 */ - { 43, 7, 12, 0, 0, 43, 0, }, /* 697 */ - { 43, 21, 12, 0, 0, 43, 0, }, /* 698 */ - { 43, 14, 12, 0, 0, 43, 0, }, /* 699 */ - { 14, 9, 12, 0, 40, 14, 0, }, /* 700 */ - { 14, 5, 12, 0, -40, 14, 0, }, /* 701 */ - { 47, 7, 12, 0, 0, 47, 0, }, /* 702 */ - { 45, 7, 12, 0, 0, 45, 0, }, /* 703 */ - { 45, 13, 12, 0, 0, 45, 0, }, /* 704 */ - { 136, 9, 12, 0, 40, 136, 0, }, /* 705 */ - { 136, 5, 12, 0, -40, 136, 0, }, /* 706 */ - { 106, 7, 12, 0, 0, 106, 0, }, /* 707 */ - { 104, 7, 12, 0, 0, 104, 0, }, /* 708 */ - { 104, 21, 12, 0, 0, 104, 0, }, /* 709 */ - { 110, 7, 12, 0, 0, 110, 0, }, /* 710 */ - { 12, 7, 12, 0, 0, 12, 0, }, /* 711 */ - { 81, 7, 12, 0, 0, 81, 0, }, /* 712 */ - { 81, 21, 12, 0, 0, 81, 0, }, /* 713 */ - { 81, 15, 12, 0, 0, 81, 0, }, /* 714 */ - { 120, 7, 12, 0, 0, 120, 0, }, /* 715 */ - { 120, 26, 12, 0, 0, 120, 0, }, /* 716 */ - { 120, 15, 12, 0, 0, 120, 0, }, /* 717 */ - { 116, 7, 12, 0, 0, 116, 0, }, /* 718 */ - { 116, 15, 12, 0, 0, 116, 0, }, /* 719 */ - { 128, 7, 12, 0, 0, 128, 0, }, /* 720 */ - { 128, 15, 12, 0, 0, 128, 0, }, /* 721 */ - { 66, 7, 12, 0, 0, 66, 0, }, /* 722 */ - { 66, 15, 12, 0, 0, 66, 0, }, /* 723 */ - { 66, 21, 12, 0, 0, 66, 0, }, /* 724 */ - { 72, 7, 12, 0, 0, 72, 0, }, /* 725 */ - { 72, 21, 12, 0, 0, 72, 0, }, /* 726 */ - { 98, 7, 12, 0, 0, 98, 0, }, /* 727 */ - { 97, 7, 12, 0, 0, 97, 0, }, /* 728 */ - { 97, 15, 12, 0, 0, 97, 0, }, /* 729 */ - { 31, 7, 12, 0, 0, 31, 0, }, /* 730 */ - { 31, 12, 3, 0, 0, 31, 0, }, /* 731 */ - { 31, 15, 12, 0, 0, 31, 0, }, /* 732 */ - { 31, 21, 12, 0, 0, 31, 0, }, /* 733 */ - { 88, 7, 12, 0, 0, 88, 0, }, /* 734 */ - { 88, 15, 12, 0, 0, 88, 0, }, /* 735 */ - { 88, 21, 12, 0, 0, 88, 0, }, /* 736 */ - { 117, 7, 12, 0, 0, 117, 0, }, /* 737 */ - { 117, 15, 12, 0, 0, 117, 0, }, /* 738 */ - { 112, 7, 12, 0, 0, 112, 0, }, /* 739 */ - { 112, 26, 12, 0, 0, 112, 0, }, /* 740 */ - { 112, 12, 3, 0, 0, 112, 0, }, /* 741 */ - { 112, 15, 12, 0, 0, 112, 0, }, /* 742 */ - { 112, 21, 12, 0, 0, 112, 0, }, /* 743 */ - { 78, 7, 12, 0, 0, 78, 0, }, /* 744 */ - { 78, 21, 12, 0, 0, 78, 0, }, /* 745 */ - { 83, 7, 12, 0, 0, 83, 0, }, /* 746 */ - { 83, 15, 12, 0, 0, 83, 0, }, /* 747 */ - { 82, 7, 12, 0, 0, 82, 0, }, /* 748 */ - { 82, 15, 12, 0, 0, 82, 0, }, /* 749 */ - { 121, 7, 12, 0, 0, 121, 0, }, /* 750 */ - { 121, 21, 12, 0, 0, 121, 0, }, /* 751 */ - { 121, 15, 12, 0, 0, 121, 0, }, /* 752 */ - { 89, 7, 12, 0, 0, 89, 0, }, /* 753 */ - { 130, 9, 12, 0, 64, 130, 0, }, /* 754 */ - { 130, 5, 12, 0, -64, 130, 0, }, /* 755 */ - { 130, 15, 12, 0, 0, 130, 0, }, /* 756 */ - { 144, 7, 12, 0, 0, 144, 0, }, /* 757 */ - { 144, 12, 3, 0, 0, 144, 0, }, /* 758 */ - { 144, 13, 12, 0, 0, 144, 0, }, /* 759 */ - { 1, 15, 12, 0, 0, 1, 0, }, /* 760 */ - { 147, 7, 12, 0, 0, 147, 0, }, /* 761 */ - { 147, 15, 12, 0, 0, 147, 0, }, /* 762 */ - { 148, 7, 12, 0, 0, 148, 0, }, /* 763 */ - { 148, 12, 3, 0, 0, 148, 0, }, /* 764 */ - { 148, 15, 12, 0, 0, 148, 0, }, /* 765 */ - { 148, 21, 12, 0, 0, 148, 0, }, /* 766 */ - { 149, 7, 12, 0, 0, 149, 0, }, /* 767 */ - { 94, 10, 5, 0, 0, 94, 0, }, /* 768 */ - { 94, 12, 3, 0, 0, 94, 0, }, /* 769 */ - { 94, 7, 12, 0, 0, 94, 0, }, /* 770 */ - { 94, 21, 12, 0, 0, 94, 0, }, /* 771 */ - { 94, 15, 12, 0, 0, 94, 0, }, /* 772 */ - { 94, 13, 12, 0, 0, 94, 0, }, /* 773 */ - { 85, 12, 3, 0, 0, 85, 0, }, /* 774 */ - { 85, 10, 5, 0, 0, 85, 0, }, /* 775 */ - { 85, 7, 12, 0, 0, 85, 0, }, /* 776 */ - { 85, 21, 12, 0, 0, 85, 0, }, /* 777 */ - { 85, 1, 4, 0, 0, 85, 0, }, /* 778 */ - { 101, 7, 12, 0, 0, 101, 0, }, /* 779 */ - { 101, 13, 12, 0, 0, 101, 0, }, /* 780 */ - { 96, 12, 3, 0, 0, 96, 0, }, /* 781 */ - { 96, 7, 12, 0, 0, 96, 0, }, /* 782 */ - { 96, 10, 5, 0, 0, 96, 0, }, /* 783 */ - { 96, 13, 12, 0, 0, 96, 0, }, /* 784 */ - { 96, 21, 12, 0, 0, 96, 0, }, /* 785 */ - { 111, 7, 12, 0, 0, 111, 0, }, /* 786 */ - { 111, 12, 3, 0, 0, 111, 0, }, /* 787 */ - { 111, 21, 12, 0, 0, 111, 0, }, /* 788 */ - { 100, 12, 3, 0, 0, 100, 0, }, /* 789 */ - { 100, 10, 5, 0, 0, 100, 0, }, /* 790 */ - { 100, 7, 12, 0, 0, 100, 0, }, /* 791 */ - { 100, 7, 4, 0, 0, 100, 0, }, /* 792 */ - { 100, 21, 12, 0, 0, 100, 0, }, /* 793 */ - { 100, 13, 12, 0, 0, 100, 0, }, /* 794 */ - { 48, 15, 12, 0, 0, 48, 0, }, /* 795 */ - { 108, 7, 12, 0, 0, 108, 0, }, /* 796 */ - { 108, 10, 5, 0, 0, 108, 0, }, /* 797 */ - { 108, 12, 3, 0, 0, 108, 0, }, /* 798 */ - { 108, 21, 12, 0, 0, 108, 0, }, /* 799 */ - { 129, 7, 12, 0, 0, 129, 0, }, /* 800 */ - { 129, 21, 12, 0, 0, 129, 0, }, /* 801 */ - { 109, 7, 12, 0, 0, 109, 0, }, /* 802 */ - { 109, 12, 3, 0, 0, 109, 0, }, /* 803 */ - { 109, 10, 5, 0, 0, 109, 0, }, /* 804 */ - { 109, 13, 12, 0, 0, 109, 0, }, /* 805 */ - { 107, 12, 3, 0, 0, 107, 0, }, /* 806 */ - { 107, 12, 3, 0, 0, -52, 0, }, /* 807 */ - { 107, 10, 5, 0, 0, 107, 0, }, /* 808 */ - { 107, 10, 5, 0, 0, -52, 0, }, /* 809 */ - { 107, 7, 12, 0, 0, 107, 0, }, /* 810 */ - { 28, 12, 3, 0, 0, -52, 0, }, /* 811 */ - { 107, 10, 3, 0, 0, 107, 0, }, /* 812 */ - { 135, 7, 12, 0, 0, 135, 0, }, /* 813 */ - { 135, 10, 5, 0, 0, 135, 0, }, /* 814 */ - { 135, 12, 3, 0, 0, 135, 0, }, /* 815 */ - { 135, 21, 12, 0, 0, 135, 0, }, /* 816 */ - { 135, 13, 12, 0, 0, 135, 0, }, /* 817 */ - { 124, 7, 12, 0, 0, 124, 0, }, /* 818 */ - { 124, 10, 3, 0, 0, 124, 0, }, /* 819 */ - { 124, 10, 5, 0, 0, 124, 0, }, /* 820 */ - { 124, 12, 3, 0, 0, 124, 0, }, /* 821 */ - { 124, 21, 12, 0, 0, 124, 0, }, /* 822 */ - { 124, 13, 12, 0, 0, 124, 0, }, /* 823 */ - { 123, 7, 12, 0, 0, 123, 0, }, /* 824 */ - { 123, 10, 3, 0, 0, 123, 0, }, /* 825 */ - { 123, 10, 5, 0, 0, 123, 0, }, /* 826 */ - { 123, 12, 3, 0, 0, 123, 0, }, /* 827 */ - { 123, 21, 12, 0, 0, 123, 0, }, /* 828 */ - { 114, 7, 12, 0, 0, 114, 0, }, /* 829 */ - { 114, 10, 5, 0, 0, 114, 0, }, /* 830 */ - { 114, 12, 3, 0, 0, 114, 0, }, /* 831 */ - { 114, 21, 12, 0, 0, 114, 0, }, /* 832 */ - { 114, 13, 12, 0, 0, 114, 0, }, /* 833 */ - { 102, 7, 12, 0, 0, 102, 0, }, /* 834 */ - { 102, 12, 3, 0, 0, 102, 0, }, /* 835 */ - { 102, 10, 5, 0, 0, 102, 0, }, /* 836 */ - { 102, 13, 12, 0, 0, 102, 0, }, /* 837 */ - { 126, 7, 12, 0, 0, 126, 0, }, /* 838 */ - { 126, 12, 3, 0, 0, 126, 0, }, /* 839 */ - { 126, 10, 5, 0, 0, 126, 0, }, /* 840 */ - { 126, 13, 12, 0, 0, 126, 0, }, /* 841 */ - { 126, 15, 12, 0, 0, 126, 0, }, /* 842 */ - { 126, 21, 12, 0, 0, 126, 0, }, /* 843 */ - { 126, 26, 12, 0, 0, 126, 0, }, /* 844 */ - { 142, 7, 12, 0, 0, 142, 0, }, /* 845 */ - { 142, 10, 5, 0, 0, 142, 0, }, /* 846 */ - { 142, 12, 3, 0, 0, 142, 0, }, /* 847 */ - { 142, 21, 12, 0, 0, 142, 0, }, /* 848 */ - { 125, 9, 12, 0, 32, 125, 0, }, /* 849 */ - { 125, 5, 12, 0, -32, 125, 0, }, /* 850 */ - { 125, 13, 12, 0, 0, 125, 0, }, /* 851 */ - { 125, 15, 12, 0, 0, 125, 0, }, /* 852 */ - { 125, 7, 12, 0, 0, 125, 0, }, /* 853 */ - { 150, 7, 12, 0, 0, 150, 0, }, /* 854 */ - { 150, 10, 5, 0, 0, 150, 0, }, /* 855 */ - { 150, 12, 3, 0, 0, 150, 0, }, /* 856 */ - { 150, 21, 12, 0, 0, 150, 0, }, /* 857 */ - { 141, 7, 12, 0, 0, 141, 0, }, /* 858 */ - { 141, 12, 3, 0, 0, 141, 0, }, /* 859 */ - { 141, 10, 5, 0, 0, 141, 0, }, /* 860 */ - { 141, 7, 4, 0, 0, 141, 0, }, /* 861 */ - { 141, 21, 12, 0, 0, 141, 0, }, /* 862 */ - { 140, 7, 12, 0, 0, 140, 0, }, /* 863 */ - { 140, 12, 3, 0, 0, 140, 0, }, /* 864 */ - { 140, 10, 5, 0, 0, 140, 0, }, /* 865 */ - { 140, 7, 4, 0, 0, 140, 0, }, /* 866 */ - { 140, 21, 12, 0, 0, 140, 0, }, /* 867 */ - { 122, 7, 12, 0, 0, 122, 0, }, /* 868 */ - { 133, 7, 12, 0, 0, 133, 0, }, /* 869 */ - { 133, 10, 5, 0, 0, 133, 0, }, /* 870 */ - { 133, 12, 3, 0, 0, 133, 0, }, /* 871 */ - { 133, 21, 12, 0, 0, 133, 0, }, /* 872 */ - { 133, 13, 12, 0, 0, 133, 0, }, /* 873 */ - { 133, 15, 12, 0, 0, 133, 0, }, /* 874 */ - { 134, 21, 12, 0, 0, 134, 0, }, /* 875 */ - { 134, 7, 12, 0, 0, 134, 0, }, /* 876 */ - { 134, 12, 3, 0, 0, 134, 0, }, /* 877 */ - { 134, 10, 5, 0, 0, 134, 0, }, /* 878 */ - { 138, 7, 12, 0, 0, 138, 0, }, /* 879 */ - { 138, 12, 3, 0, 0, 138, 0, }, /* 880 */ - { 138, 7, 4, 0, 0, 138, 0, }, /* 881 */ - { 138, 13, 12, 0, 0, 138, 0, }, /* 882 */ - { 143, 7, 12, 0, 0, 143, 0, }, /* 883 */ - { 143, 10, 5, 0, 0, 143, 0, }, /* 884 */ - { 143, 12, 3, 0, 0, 143, 0, }, /* 885 */ - { 143, 13, 12, 0, 0, 143, 0, }, /* 886 */ - { 145, 7, 12, 0, 0, 145, 0, }, /* 887 */ - { 145, 12, 3, 0, 0, 145, 0, }, /* 888 */ - { 145, 10, 5, 0, 0, 145, 0, }, /* 889 */ - { 145, 21, 12, 0, 0, 145, 0, }, /* 890 */ - { 54, 15, 12, 0, 0, 54, 0, }, /* 891 */ - { 54, 21, 12, 0, 0, 54, 0, }, /* 892 */ - { 63, 7, 12, 0, 0, 63, 0, }, /* 893 */ - { 63, 14, 12, 0, 0, 63, 0, }, /* 894 */ - { 63, 21, 12, 0, 0, 63, 0, }, /* 895 */ - { 80, 7, 12, 0, 0, 80, 0, }, /* 896 */ - { 80, 1, 2, 0, 0, 80, 0, }, /* 897 */ - { 127, 7, 12, 0, 0, 127, 0, }, /* 898 */ - { 115, 7, 12, 0, 0, 115, 0, }, /* 899 */ - { 115, 13, 12, 0, 0, 115, 0, }, /* 900 */ - { 115, 21, 12, 0, 0, 115, 0, }, /* 901 */ - { 103, 7, 12, 0, 0, 103, 0, }, /* 902 */ - { 103, 12, 3, 0, 0, 103, 0, }, /* 903 */ - { 103, 21, 12, 0, 0, 103, 0, }, /* 904 */ - { 119, 7, 12, 0, 0, 119, 0, }, /* 905 */ - { 119, 12, 3, 0, 0, 119, 0, }, /* 906 */ - { 119, 21, 12, 0, 0, 119, 0, }, /* 907 */ - { 119, 26, 12, 0, 0, 119, 0, }, /* 908 */ - { 119, 6, 12, 0, 0, 119, 0, }, /* 909 */ - { 119, 13, 12, 0, 0, 119, 0, }, /* 910 */ - { 119, 15, 12, 0, 0, 119, 0, }, /* 911 */ - { 146, 9, 12, 0, 32, 146, 0, }, /* 912 */ - { 146, 5, 12, 0, -32, 146, 0, }, /* 913 */ - { 146, 15, 12, 0, 0, 146, 0, }, /* 914 */ - { 146, 21, 12, 0, 0, 146, 0, }, /* 915 */ - { 99, 7, 12, 0, 0, 99, 0, }, /* 916 */ - { 99, 12, 3, 0, 0, 99, 0, }, /* 917 */ - { 99, 10, 5, 0, 0, 99, 0, }, /* 918 */ - { 99, 6, 12, 0, 0, 99, 0, }, /* 919 */ - { 137, 6, 12, 0, 0, 137, 0, }, /* 920 */ - { 139, 6, 12, 0, 0, 139, 0, }, /* 921 */ - { 137, 7, 12, 0, 0, 137, 0, }, /* 922 */ - { 139, 7, 12, 0, 0, 139, 0, }, /* 923 */ - { 105, 7, 12, 0, 0, 105, 0, }, /* 924 */ - { 105, 26, 12, 0, 0, 105, 0, }, /* 925 */ - { 105, 12, 3, 0, 0, 105, 0, }, /* 926 */ - { 105, 21, 12, 0, 0, 105, 0, }, /* 927 */ - { 10, 1, 2, 0, 0, 105, 0, }, /* 928 */ - { 10, 10, 3, 0, 0, 10, 0, }, /* 929 */ - { 10, 10, 5, 0, 0, 10, 0, }, /* 930 */ - { 20, 12, 3, 0, 0, 20, 0, }, /* 931 */ - { 131, 26, 12, 0, 0, 131, 0, }, /* 932 */ - { 131, 12, 3, 0, 0, 131, 0, }, /* 933 */ - { 131, 21, 12, 0, 0, 131, 0, }, /* 934 */ - { 18, 12, 3, 0, 0, 18, 0, }, /* 935 */ - { 151, 7, 12, 0, 0, 151, 0, }, /* 936 */ - { 151, 12, 3, 0, 0, 151, 0, }, /* 937 */ - { 151, 6, 12, 0, 0, 151, 0, }, /* 938 */ - { 151, 13, 12, 0, 0, 151, 0, }, /* 939 */ - { 151, 26, 12, 0, 0, 151, 0, }, /* 940 */ - { 152, 7, 12, 0, 0, 152, 0, }, /* 941 */ - { 152, 12, 3, 0, 0, 152, 0, }, /* 942 */ - { 152, 13, 12, 0, 0, 152, 0, }, /* 943 */ - { 152, 23, 12, 0, 0, 152, 0, }, /* 944 */ - { 113, 7, 12, 0, 0, 113, 0, }, /* 945 */ - { 113, 15, 12, 0, 0, 113, 0, }, /* 946 */ - { 113, 12, 3, 0, 0, 113, 0, }, /* 947 */ - { 132, 9, 12, 0, 34, 132, 0, }, /* 948 */ - { 132, 5, 12, 0, -34, 132, 0, }, /* 949 */ - { 132, 12, 3, 0, 0, 132, 0, }, /* 950 */ - { 132, 6, 12, 0, 0, 132, 0, }, /* 951 */ - { 132, 13, 12, 0, 0, 132, 0, }, /* 952 */ - { 132, 21, 12, 0, 0, 132, 0, }, /* 953 */ - { 0, 2, 14, 0, 0, 0, 0, }, /* 954 */ - { 10, 26, 11, 0, 0, 10, 0, }, /* 955 */ - { 27, 26, 12, 0, 0, 27, 0, }, /* 956 */ - { 10, 24, 3, 0, 0, 10, 0, }, /* 957 */ - { 10, 1, 3, 0, 0, 10, 0, }, /* 958 */ + { 10, 24, 12, 0, 0, -61, 0, }, /* 605 */ + { 34, 9, 12, 0, -35332, 34, 0, }, /* 606 */ + { 34, 9, 12, 0, -42280, 34, 0, }, /* 607 */ + { 34, 5, 12, 0, 48, 34, 0, }, /* 608 */ + { 34, 9, 12, 0, -42308, 34, 0, }, /* 609 */ + { 34, 9, 12, 0, -42319, 34, 0, }, /* 610 */ + { 34, 9, 12, 0, -42315, 34, 0, }, /* 611 */ + { 34, 9, 12, 0, -42305, 34, 0, }, /* 612 */ + { 34, 9, 12, 0, -42258, 34, 0, }, /* 613 */ + { 34, 9, 12, 0, -42282, 34, 0, }, /* 614 */ + { 34, 9, 12, 0, -42261, 34, 0, }, /* 615 */ + { 34, 9, 12, 0, 928, 34, 0, }, /* 616 */ + { 34, 9, 12, 0, -48, 34, 0, }, /* 617 */ + { 34, 9, 12, 0, -42307, 34, 0, }, /* 618 */ + { 34, 9, 12, 0, -35384, 34, 0, }, /* 619 */ + { 49, 7, 12, 0, 0, 49, 0, }, /* 620 */ + { 49, 12, 3, 0, 0, 49, 0, }, /* 621 */ + { 49, 10, 5, 0, 0, 49, 0, }, /* 622 */ + { 49, 26, 12, 0, 0, 49, 0, }, /* 623 */ + { 10, 15, 12, 0, 0, -224, 0, }, /* 624 */ + { 10, 15, 12, 0, 0, -210, 0, }, /* 625 */ + { 10, 26, 12, 0, 0, -171, 0, }, /* 626 */ + { 10, 23, 12, 0, 0, -171, 0, }, /* 627 */ + { 65, 7, 12, 0, 0, 65, 0, }, /* 628 */ + { 65, 21, 12, 0, 0, 65, 0, }, /* 629 */ + { 75, 10, 5, 0, 0, 75, 0, }, /* 630 */ + { 75, 7, 12, 0, 0, 75, 0, }, /* 631 */ + { 75, 12, 3, 0, 0, 75, 0, }, /* 632 */ + { 75, 21, 12, 0, 0, 75, 0, }, /* 633 */ + { 75, 13, 12, 0, 0, 75, 0, }, /* 634 */ + { 15, 12, 3, 0, 0, -13, 0, }, /* 635 */ + { 15, 7, 12, 0, 0, -46, 0, }, /* 636 */ + { 69, 13, 12, 0, 0, 69, 0, }, /* 637 */ + { 69, 7, 12, 0, 0, 69, 0, }, /* 638 */ + { 69, 12, 3, 0, 0, 69, 0, }, /* 639 */ + { 10, 21, 12, 0, 0, -108, 0, }, /* 640 */ + { 69, 21, 12, 0, 0, 69, 0, }, /* 641 */ + { 74, 7, 12, 0, 0, 74, 0, }, /* 642 */ + { 74, 12, 3, 0, 0, 74, 0, }, /* 643 */ + { 74, 10, 5, 0, 0, 74, 0, }, /* 644 */ + { 74, 21, 12, 0, 0, 74, 0, }, /* 645 */ + { 84, 12, 3, 0, 0, 84, 0, }, /* 646 */ + { 84, 10, 5, 0, 0, 84, 0, }, /* 647 */ + { 84, 7, 12, 0, 0, 84, 0, }, /* 648 */ + { 84, 21, 12, 0, 0, 84, 0, }, /* 649 */ + { 10, 6, 12, 0, 0, -19, 0, }, /* 650 */ + { 84, 13, 12, 0, 0, 84, 0, }, /* 651 */ + { 39, 6, 12, 0, 0, 39, 0, }, /* 652 */ + { 68, 7, 12, 0, 0, 68, 0, }, /* 653 */ + { 68, 12, 3, 0, 0, 68, 0, }, /* 654 */ + { 68, 10, 5, 0, 0, 68, 0, }, /* 655 */ + { 68, 13, 12, 0, 0, 68, 0, }, /* 656 */ + { 68, 21, 12, 0, 0, 68, 0, }, /* 657 */ + { 92, 7, 12, 0, 0, 92, 0, }, /* 658 */ + { 92, 12, 3, 0, 0, 92, 0, }, /* 659 */ + { 92, 6, 12, 0, 0, 92, 0, }, /* 660 */ + { 92, 21, 12, 0, 0, 92, 0, }, /* 661 */ + { 87, 7, 12, 0, 0, 87, 0, }, /* 662 */ + { 87, 10, 5, 0, 0, 87, 0, }, /* 663 */ + { 87, 12, 3, 0, 0, 87, 0, }, /* 664 */ + { 87, 21, 12, 0, 0, 87, 0, }, /* 665 */ + { 87, 6, 12, 0, 0, 87, 0, }, /* 666 */ + { 34, 5, 12, 0, -928, 34, 0, }, /* 667 */ + { 9, 5, 12, 0, -38864, 9, 0, }, /* 668 */ + { 87, 13, 12, 0, 0, 87, 0, }, /* 669 */ + { 24, 7, 9, 0, 0, 24, 0, }, /* 670 */ + { 24, 7, 10, 0, 0, 24, 0, }, /* 671 */ + { 0, 4, 12, 0, 0, 0, 0, }, /* 672 */ + { 0, 3, 12, 0, 0, 0, 0, }, /* 673 */ + { 26, 25, 12, 0, 0, 26, 0, }, /* 674 */ + { 1, 24, 12, 0, 0, 1, 0, }, /* 675 */ + { 1, 7, 12, 0, 0, -10, 0, }, /* 676 */ + { 1, 26, 12, 0, 0, -10, 0, }, /* 677 */ + { 10, 6, 3, 0, 0, -64, 0, }, /* 678 */ + { 36, 7, 12, 0, 0, 36, 0, }, /* 679 */ + { 10, 21, 12, 0, 0, -22, 0, }, /* 680 */ + { 10, 15, 12, 0, 0, -92, 0, }, /* 681 */ + { 10, 26, 12, 0, 0, -22, 0, }, /* 682 */ + { 20, 14, 12, 0, 0, 20, 0, }, /* 683 */ + { 20, 15, 12, 0, 0, 20, 0, }, /* 684 */ + { 20, 26, 12, 0, 0, 20, 0, }, /* 685 */ + { 71, 7, 12, 0, 0, 71, 0, }, /* 686 */ + { 67, 7, 12, 0, 0, 67, 0, }, /* 687 */ + { 28, 12, 3, 0, 0, -1, 0, }, /* 688 */ + { 10, 15, 12, 0, 0, -1, 0, }, /* 689 */ + { 42, 7, 12, 0, 0, 42, 0, }, /* 690 */ + { 42, 15, 12, 0, 0, 42, 0, }, /* 691 */ + { 19, 7, 12, 0, 0, 19, 0, }, /* 692 */ + { 19, 14, 12, 0, 0, 19, 0, }, /* 693 */ + { 118, 7, 12, 0, 0, 118, 0, }, /* 694 */ + { 118, 12, 3, 0, 0, 118, 0, }, /* 695 */ + { 60, 7, 12, 0, 0, 60, 0, }, /* 696 */ + { 60, 21, 12, 0, 0, 60, 0, }, /* 697 */ + { 43, 7, 12, 0, 0, 43, 0, }, /* 698 */ + { 43, 21, 12, 0, 0, 43, 0, }, /* 699 */ + { 43, 14, 12, 0, 0, 43, 0, }, /* 700 */ + { 14, 9, 12, 0, 40, 14, 0, }, /* 701 */ + { 14, 5, 12, 0, -40, 14, 0, }, /* 702 */ + { 47, 7, 12, 0, 0, 47, 0, }, /* 703 */ + { 45, 7, 12, 0, 0, 45, 0, }, /* 704 */ + { 45, 13, 12, 0, 0, 45, 0, }, /* 705 */ + { 136, 9, 12, 0, 40, 136, 0, }, /* 706 */ + { 136, 5, 12, 0, -40, 136, 0, }, /* 707 */ + { 106, 7, 12, 0, 0, 106, 0, }, /* 708 */ + { 104, 7, 12, 0, 0, 104, 0, }, /* 709 */ + { 104, 21, 12, 0, 0, 104, 0, }, /* 710 */ + { 110, 7, 12, 0, 0, 110, 0, }, /* 711 */ + { 12, 7, 12, 0, 0, 12, 0, }, /* 712 */ + { 81, 7, 12, 0, 0, 81, 0, }, /* 713 */ + { 81, 21, 12, 0, 0, 81, 0, }, /* 714 */ + { 81, 15, 12, 0, 0, 81, 0, }, /* 715 */ + { 120, 7, 12, 0, 0, 120, 0, }, /* 716 */ + { 120, 26, 12, 0, 0, 120, 0, }, /* 717 */ + { 120, 15, 12, 0, 0, 120, 0, }, /* 718 */ + { 116, 7, 12, 0, 0, 116, 0, }, /* 719 */ + { 116, 15, 12, 0, 0, 116, 0, }, /* 720 */ + { 128, 7, 12, 0, 0, 128, 0, }, /* 721 */ + { 128, 15, 12, 0, 0, 128, 0, }, /* 722 */ + { 66, 7, 12, 0, 0, 66, 0, }, /* 723 */ + { 66, 15, 12, 0, 0, 66, 0, }, /* 724 */ + { 66, 21, 12, 0, 0, 66, 0, }, /* 725 */ + { 72, 7, 12, 0, 0, 72, 0, }, /* 726 */ + { 72, 21, 12, 0, 0, 72, 0, }, /* 727 */ + { 98, 7, 12, 0, 0, 98, 0, }, /* 728 */ + { 97, 7, 12, 0, 0, 97, 0, }, /* 729 */ + { 97, 15, 12, 0, 0, 97, 0, }, /* 730 */ + { 31, 7, 12, 0, 0, 31, 0, }, /* 731 */ + { 31, 12, 3, 0, 0, 31, 0, }, /* 732 */ + { 31, 15, 12, 0, 0, 31, 0, }, /* 733 */ + { 31, 21, 12, 0, 0, 31, 0, }, /* 734 */ + { 88, 7, 12, 0, 0, 88, 0, }, /* 735 */ + { 88, 15, 12, 0, 0, 88, 0, }, /* 736 */ + { 88, 21, 12, 0, 0, 88, 0, }, /* 737 */ + { 117, 7, 12, 0, 0, 117, 0, }, /* 738 */ + { 117, 15, 12, 0, 0, 117, 0, }, /* 739 */ + { 112, 7, 12, 0, 0, 112, 0, }, /* 740 */ + { 112, 26, 12, 0, 0, 112, 0, }, /* 741 */ + { 112, 12, 3, 0, 0, 112, 0, }, /* 742 */ + { 112, 15, 12, 0, 0, 112, 0, }, /* 743 */ + { 112, 21, 12, 0, 0, 112, 0, }, /* 744 */ + { 78, 7, 12, 0, 0, 78, 0, }, /* 745 */ + { 78, 21, 12, 0, 0, 78, 0, }, /* 746 */ + { 83, 7, 12, 0, 0, 83, 0, }, /* 747 */ + { 83, 15, 12, 0, 0, 83, 0, }, /* 748 */ + { 82, 7, 12, 0, 0, 82, 0, }, /* 749 */ + { 82, 15, 12, 0, 0, 82, 0, }, /* 750 */ + { 121, 7, 12, 0, 0, 121, 0, }, /* 751 */ + { 121, 21, 12, 0, 0, 121, 0, }, /* 752 */ + { 121, 15, 12, 0, 0, 121, 0, }, /* 753 */ + { 89, 7, 12, 0, 0, 89, 0, }, /* 754 */ + { 130, 9, 12, 0, 64, 130, 0, }, /* 755 */ + { 130, 5, 12, 0, -64, 130, 0, }, /* 756 */ + { 130, 15, 12, 0, 0, 130, 0, }, /* 757 */ + { 144, 7, 12, 0, 0, 144, 0, }, /* 758 */ + { 144, 12, 3, 0, 0, 144, 0, }, /* 759 */ + { 144, 13, 12, 0, 0, 144, 0, }, /* 760 */ + { 1, 15, 12, 0, 0, 1, 0, }, /* 761 */ + { 156, 7, 12, 0, 0, 156, 0, }, /* 762 */ + { 156, 12, 3, 0, 0, 156, 0, }, /* 763 */ + { 156, 17, 12, 0, 0, 156, 0, }, /* 764 */ + { 147, 7, 12, 0, 0, 147, 0, }, /* 765 */ + { 147, 15, 12, 0, 0, 147, 0, }, /* 766 */ + { 148, 7, 12, 0, 0, 148, 0, }, /* 767 */ + { 148, 12, 3, 0, 0, 148, 0, }, /* 768 */ + { 148, 15, 12, 0, 0, 148, 0, }, /* 769 */ + { 148, 21, 12, 0, 0, 148, 0, }, /* 770 */ + { 153, 7, 12, 0, 0, 153, 0, }, /* 771 */ + { 153, 15, 12, 0, 0, 153, 0, }, /* 772 */ + { 149, 7, 12, 0, 0, 149, 0, }, /* 773 */ + { 94, 10, 5, 0, 0, 94, 0, }, /* 774 */ + { 94, 12, 3, 0, 0, 94, 0, }, /* 775 */ + { 94, 7, 12, 0, 0, 94, 0, }, /* 776 */ + { 94, 21, 12, 0, 0, 94, 0, }, /* 777 */ + { 94, 15, 12, 0, 0, 94, 0, }, /* 778 */ + { 94, 13, 12, 0, 0, 94, 0, }, /* 779 */ + { 85, 12, 3, 0, 0, 85, 0, }, /* 780 */ + { 85, 10, 5, 0, 0, 85, 0, }, /* 781 */ + { 85, 7, 12, 0, 0, 85, 0, }, /* 782 */ + { 85, 21, 12, 0, 0, 85, 0, }, /* 783 */ + { 85, 1, 4, 0, 0, 85, 0, }, /* 784 */ + { 101, 7, 12, 0, 0, 101, 0, }, /* 785 */ + { 101, 13, 12, 0, 0, 101, 0, }, /* 786 */ + { 96, 12, 3, 0, 0, 96, 0, }, /* 787 */ + { 96, 7, 12, 0, 0, 96, 0, }, /* 788 */ + { 96, 10, 5, 0, 0, 96, 0, }, /* 789 */ + { 96, 13, 12, 0, 0, 96, 0, }, /* 790 */ + { 96, 21, 12, 0, 0, 96, 0, }, /* 791 */ + { 111, 7, 12, 0, 0, 111, 0, }, /* 792 */ + { 111, 12, 3, 0, 0, 111, 0, }, /* 793 */ + { 111, 21, 12, 0, 0, 111, 0, }, /* 794 */ + { 100, 12, 3, 0, 0, 100, 0, }, /* 795 */ + { 100, 10, 5, 0, 0, 100, 0, }, /* 796 */ + { 100, 7, 12, 0, 0, 100, 0, }, /* 797 */ + { 100, 7, 4, 0, 0, 100, 0, }, /* 798 */ + { 100, 21, 12, 0, 0, 100, 0, }, /* 799 */ + { 100, 13, 12, 0, 0, 100, 0, }, /* 800 */ + { 48, 15, 12, 0, 0, 48, 0, }, /* 801 */ + { 108, 7, 12, 0, 0, 108, 0, }, /* 802 */ + { 108, 10, 5, 0, 0, 108, 0, }, /* 803 */ + { 108, 12, 3, 0, 0, 108, 0, }, /* 804 */ + { 108, 21, 12, 0, 0, 108, 0, }, /* 805 */ + { 129, 7, 12, 0, 0, 129, 0, }, /* 806 */ + { 129, 21, 12, 0, 0, 129, 0, }, /* 807 */ + { 109, 7, 12, 0, 0, 109, 0, }, /* 808 */ + { 109, 12, 3, 0, 0, 109, 0, }, /* 809 */ + { 109, 10, 5, 0, 0, 109, 0, }, /* 810 */ + { 109, 13, 12, 0, 0, 109, 0, }, /* 811 */ + { 107, 12, 3, 0, 0, 107, 0, }, /* 812 */ + { 107, 12, 3, 0, 0, -52, 0, }, /* 813 */ + { 107, 10, 5, 0, 0, 107, 0, }, /* 814 */ + { 107, 10, 5, 0, 0, -52, 0, }, /* 815 */ + { 107, 7, 12, 0, 0, 107, 0, }, /* 816 */ + { 28, 12, 3, 0, 0, -52, 0, }, /* 817 */ + { 107, 10, 3, 0, 0, 107, 0, }, /* 818 */ + { 135, 7, 12, 0, 0, 135, 0, }, /* 819 */ + { 135, 10, 5, 0, 0, 135, 0, }, /* 820 */ + { 135, 12, 3, 0, 0, 135, 0, }, /* 821 */ + { 135, 21, 12, 0, 0, 135, 0, }, /* 822 */ + { 135, 13, 12, 0, 0, 135, 0, }, /* 823 */ + { 124, 7, 12, 0, 0, 124, 0, }, /* 824 */ + { 124, 10, 3, 0, 0, 124, 0, }, /* 825 */ + { 124, 10, 5, 0, 0, 124, 0, }, /* 826 */ + { 124, 12, 3, 0, 0, 124, 0, }, /* 827 */ + { 124, 21, 12, 0, 0, 124, 0, }, /* 828 */ + { 124, 13, 12, 0, 0, 124, 0, }, /* 829 */ + { 123, 7, 12, 0, 0, 123, 0, }, /* 830 */ + { 123, 10, 3, 0, 0, 123, 0, }, /* 831 */ + { 123, 10, 5, 0, 0, 123, 0, }, /* 832 */ + { 123, 12, 3, 0, 0, 123, 0, }, /* 833 */ + { 123, 21, 12, 0, 0, 123, 0, }, /* 834 */ + { 114, 7, 12, 0, 0, 114, 0, }, /* 835 */ + { 114, 10, 5, 0, 0, 114, 0, }, /* 836 */ + { 114, 12, 3, 0, 0, 114, 0, }, /* 837 */ + { 114, 21, 12, 0, 0, 114, 0, }, /* 838 */ + { 114, 13, 12, 0, 0, 114, 0, }, /* 839 */ + { 102, 7, 12, 0, 0, 102, 0, }, /* 840 */ + { 102, 12, 3, 0, 0, 102, 0, }, /* 841 */ + { 102, 10, 5, 0, 0, 102, 0, }, /* 842 */ + { 102, 13, 12, 0, 0, 102, 0, }, /* 843 */ + { 126, 7, 12, 0, 0, 126, 0, }, /* 844 */ + { 126, 12, 3, 0, 0, 126, 0, }, /* 845 */ + { 126, 10, 5, 0, 0, 126, 0, }, /* 846 */ + { 126, 13, 12, 0, 0, 126, 0, }, /* 847 */ + { 126, 15, 12, 0, 0, 126, 0, }, /* 848 */ + { 126, 21, 12, 0, 0, 126, 0, }, /* 849 */ + { 126, 26, 12, 0, 0, 126, 0, }, /* 850 */ + { 142, 7, 12, 0, 0, 142, 0, }, /* 851 */ + { 142, 10, 5, 0, 0, 142, 0, }, /* 852 */ + { 142, 12, 3, 0, 0, 142, 0, }, /* 853 */ + { 142, 21, 12, 0, 0, 142, 0, }, /* 854 */ + { 125, 9, 12, 0, 32, 125, 0, }, /* 855 */ + { 125, 5, 12, 0, -32, 125, 0, }, /* 856 */ + { 125, 13, 12, 0, 0, 125, 0, }, /* 857 */ + { 125, 15, 12, 0, 0, 125, 0, }, /* 858 */ + { 125, 7, 12, 0, 0, 125, 0, }, /* 859 */ + { 154, 7, 12, 0, 0, 154, 0, }, /* 860 */ + { 154, 10, 3, 0, 0, 154, 0, }, /* 861 */ + { 154, 10, 5, 0, 0, 154, 0, }, /* 862 */ + { 154, 12, 3, 0, 0, 154, 0, }, /* 863 */ + { 154, 7, 4, 0, 0, 154, 0, }, /* 864 */ + { 154, 21, 12, 0, 0, 154, 0, }, /* 865 */ + { 154, 13, 12, 0, 0, 154, 0, }, /* 866 */ + { 150, 7, 12, 0, 0, 150, 0, }, /* 867 */ + { 150, 10, 5, 0, 0, 150, 0, }, /* 868 */ + { 150, 12, 3, 0, 0, 150, 0, }, /* 869 */ + { 150, 21, 12, 0, 0, 150, 0, }, /* 870 */ + { 141, 7, 12, 0, 0, 141, 0, }, /* 871 */ + { 141, 12, 3, 0, 0, 141, 0, }, /* 872 */ + { 141, 10, 5, 0, 0, 141, 0, }, /* 873 */ + { 141, 7, 4, 0, 0, 141, 0, }, /* 874 */ + { 141, 21, 12, 0, 0, 141, 0, }, /* 875 */ + { 140, 7, 12, 0, 0, 140, 0, }, /* 876 */ + { 140, 12, 3, 0, 0, 140, 0, }, /* 877 */ + { 140, 10, 5, 0, 0, 140, 0, }, /* 878 */ + { 140, 7, 4, 0, 0, 140, 0, }, /* 879 */ + { 140, 21, 12, 0, 0, 140, 0, }, /* 880 */ + { 122, 7, 12, 0, 0, 122, 0, }, /* 881 */ + { 133, 7, 12, 0, 0, 133, 0, }, /* 882 */ + { 133, 10, 5, 0, 0, 133, 0, }, /* 883 */ + { 133, 12, 3, 0, 0, 133, 0, }, /* 884 */ + { 133, 21, 12, 0, 0, 133, 0, }, /* 885 */ + { 133, 13, 12, 0, 0, 133, 0, }, /* 886 */ + { 133, 15, 12, 0, 0, 133, 0, }, /* 887 */ + { 134, 21, 12, 0, 0, 134, 0, }, /* 888 */ + { 134, 7, 12, 0, 0, 134, 0, }, /* 889 */ + { 134, 12, 3, 0, 0, 134, 0, }, /* 890 */ + { 134, 10, 5, 0, 0, 134, 0, }, /* 891 */ + { 138, 7, 12, 0, 0, 138, 0, }, /* 892 */ + { 138, 12, 3, 0, 0, 138, 0, }, /* 893 */ + { 138, 7, 4, 0, 0, 138, 0, }, /* 894 */ + { 138, 13, 12, 0, 0, 138, 0, }, /* 895 */ + { 143, 7, 12, 0, 0, 143, 0, }, /* 896 */ + { 143, 10, 5, 0, 0, 143, 0, }, /* 897 */ + { 143, 12, 3, 0, 0, 143, 0, }, /* 898 */ + { 143, 13, 12, 0, 0, 143, 0, }, /* 899 */ + { 145, 7, 12, 0, 0, 145, 0, }, /* 900 */ + { 145, 12, 3, 0, 0, 145, 0, }, /* 901 */ + { 145, 10, 5, 0, 0, 145, 0, }, /* 902 */ + { 145, 21, 12, 0, 0, 145, 0, }, /* 903 */ + { 54, 15, 12, 0, 0, 54, 0, }, /* 904 */ + { 54, 21, 12, 0, 0, 54, 0, }, /* 905 */ + { 63, 7, 12, 0, 0, 63, 0, }, /* 906 */ + { 63, 14, 12, 0, 0, 63, 0, }, /* 907 */ + { 63, 21, 12, 0, 0, 63, 0, }, /* 908 */ + { 80, 7, 12, 0, 0, 80, 0, }, /* 909 */ + { 80, 1, 2, 0, 0, 80, 0, }, /* 910 */ + { 127, 7, 12, 0, 0, 127, 0, }, /* 911 */ + { 115, 7, 12, 0, 0, 115, 0, }, /* 912 */ + { 115, 13, 12, 0, 0, 115, 0, }, /* 913 */ + { 115, 21, 12, 0, 0, 115, 0, }, /* 914 */ + { 103, 7, 12, 0, 0, 103, 0, }, /* 915 */ + { 103, 12, 3, 0, 0, 103, 0, }, /* 916 */ + { 103, 21, 12, 0, 0, 103, 0, }, /* 917 */ + { 119, 7, 12, 0, 0, 119, 0, }, /* 918 */ + { 119, 12, 3, 0, 0, 119, 0, }, /* 919 */ + { 119, 21, 12, 0, 0, 119, 0, }, /* 920 */ + { 119, 26, 12, 0, 0, 119, 0, }, /* 921 */ + { 119, 6, 12, 0, 0, 119, 0, }, /* 922 */ + { 119, 13, 12, 0, 0, 119, 0, }, /* 923 */ + { 119, 15, 12, 0, 0, 119, 0, }, /* 924 */ + { 146, 9, 12, 0, 32, 146, 0, }, /* 925 */ + { 146, 5, 12, 0, -32, 146, 0, }, /* 926 */ + { 146, 15, 12, 0, 0, 146, 0, }, /* 927 */ + { 146, 21, 12, 0, 0, 146, 0, }, /* 928 */ + { 99, 7, 12, 0, 0, 99, 0, }, /* 929 */ + { 99, 12, 3, 0, 0, 99, 0, }, /* 930 */ + { 99, 10, 5, 0, 0, 99, 0, }, /* 931 */ + { 99, 6, 12, 0, 0, 99, 0, }, /* 932 */ + { 137, 6, 12, 0, 0, 137, 0, }, /* 933 */ + { 139, 6, 12, 0, 0, 139, 0, }, /* 934 */ + { 155, 12, 3, 0, 0, 155, 0, }, /* 935 */ + { 23, 10, 5, 0, 0, 23, 0, }, /* 936 */ + { 137, 7, 12, 0, 0, 137, 0, }, /* 937 */ + { 155, 7, 12, 0, 0, 155, 0, }, /* 938 */ + { 139, 7, 12, 0, 0, 139, 0, }, /* 939 */ + { 105, 7, 12, 0, 0, 105, 0, }, /* 940 */ + { 105, 26, 12, 0, 0, 105, 0, }, /* 941 */ + { 105, 12, 3, 0, 0, 105, 0, }, /* 942 */ + { 105, 21, 12, 0, 0, 105, 0, }, /* 943 */ + { 10, 1, 2, 0, 0, 105, 0, }, /* 944 */ + { 10, 10, 3, 0, 0, 10, 0, }, /* 945 */ + { 10, 10, 5, 0, 0, 10, 0, }, /* 946 */ + { 20, 12, 3, 0, 0, 20, 0, }, /* 947 */ + { 131, 26, 12, 0, 0, 131, 0, }, /* 948 */ + { 131, 12, 3, 0, 0, 131, 0, }, /* 949 */ + { 131, 21, 12, 0, 0, 131, 0, }, /* 950 */ + { 18, 12, 3, 0, 0, 18, 0, }, /* 951 */ + { 151, 7, 12, 0, 0, 151, 0, }, /* 952 */ + { 151, 12, 3, 0, 0, 151, 0, }, /* 953 */ + { 151, 6, 12, 0, 0, 151, 0, }, /* 954 */ + { 151, 13, 12, 0, 0, 151, 0, }, /* 955 */ + { 151, 26, 12, 0, 0, 151, 0, }, /* 956 */ + { 152, 7, 12, 0, 0, 152, 0, }, /* 957 */ + { 152, 12, 3, 0, 0, 152, 0, }, /* 958 */ + { 152, 13, 12, 0, 0, 152, 0, }, /* 959 */ + { 152, 23, 12, 0, 0, 152, 0, }, /* 960 */ + { 113, 7, 12, 0, 0, 113, 0, }, /* 961 */ + { 113, 15, 12, 0, 0, 113, 0, }, /* 962 */ + { 113, 12, 3, 0, 0, 113, 0, }, /* 963 */ + { 132, 9, 12, 0, 34, 132, 0, }, /* 964 */ + { 132, 5, 12, 0, -34, 132, 0, }, /* 965 */ + { 132, 12, 3, 0, 0, 132, 0, }, /* 966 */ + { 132, 6, 12, 0, 0, 132, 0, }, /* 967 */ + { 132, 13, 12, 0, 0, 132, 0, }, /* 968 */ + { 132, 21, 12, 0, 0, 132, 0, }, /* 969 */ + { 0, 2, 14, 0, 0, 0, 0, }, /* 970 */ + { 10, 26, 11, 0, 0, 10, 0, }, /* 971 */ + { 27, 26, 12, 0, 0, 27, 0, }, /* 972 */ + { 10, 24, 3, 0, 0, 10, 0, }, /* 973 */ + { 10, 1, 3, 0, 0, 10, 0, }, /* 974 */ }; const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ @@ -1185,37 +1204,37 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+F000 */ 126,126, 98, 98,127,128,129,130,131,131,132,133,134,135,136,137, /* U+F800 */ 138,139,140,141,142,143,144,145,146,147,148,142,149,149,150,142, /* U+10000 */ -151,152,153,154,155,156,157,158,159,160,161,142,162,142,163,164, /* U+10800 */ -165,166,167,168,169,170,171,142,172,173,142,174,175,176,177,142, /* U+11000 */ -178,179,142,180,181,182,142,142,183,184,185,186,142,187,142,188, /* U+11800 */ -189,189,189,189,189,189,189,190,191,189,192,142,142,142,142,142, /* U+12000 */ +151,152,153,154,155,156,157,158,159,160,161,142,162,163,164,165, /* U+10800 */ +166,167,168,169,170,171,172,142,173,174,142,175,176,177,178,142, /* U+11000 */ +179,180,181,182,183,184,142,142,185,186,187,188,142,189,142,190, /* U+11800 */ +191,191,191,191,191,191,191,192,193,191,194,142,142,142,142,142, /* U+12000 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+12800 */ -193,193,193,193,193,193,193,193,194,142,142,142,142,142,142,142, /* U+13000 */ +195,195,195,195,195,195,195,195,196,142,142,142,142,142,142,142, /* U+13000 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+13800 */ -142,142,142,142,142,142,142,142,195,195,195,195,196,142,142,142, /* U+14000 */ +142,142,142,142,142,142,142,142,197,197,197,197,198,142,142,142, /* U+14000 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+14800 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+15000 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+15800 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+16000 */ -197,197,197,197,198,199,200,201,142,142,142,142,202,203,204,205, /* U+16800 */ -206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, /* U+17000 */ -206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206, /* U+17800 */ -206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,207, /* U+18000 */ -206,206,206,206,206,208,142,142,142,142,142,142,142,142,142,142, /* U+18800 */ +199,199,199,199,200,201,202,203,142,142,142,142,204,205,206,207, /* U+16800 */ +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, /* U+17000 */ +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208, /* U+17800 */ +208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,209, /* U+18000 */ +208,208,208,208,208,208,210,210,210,211,212,142,142,142,142,142, /* U+18800 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+19000 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+19800 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1A000 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1A800 */ -209,210,211,212,212,213,142,142,142,142,142,142,142,142,142,142, /* U+1B000 */ -142,142,142,142,142,142,142,142,214,215,142,142,142,142,142,142, /* U+1B800 */ +213,214,215,216,216,217,142,142,142,142,142,142,142,142,142,142, /* U+1B000 */ +142,142,142,142,142,142,142,142,218,219,142,142,142,142,142,142, /* U+1B800 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1C000 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+1C800 */ - 71,216,217,218,219,220,221,142,222,223,224,225,226,227,228,229, /* U+1D000 */ -230,230,230,230,231,232,142,142,142,142,142,142,142,142,142,142, /* U+1D800 */ -233,142,234,142,142,235,142,142,142,142,142,142,142,142,142,142, /* U+1E000 */ -236,237,238,142,142,142,142,142,239,240,241,142,242,243,142,142, /* U+1E800 */ -244,245,246,247,248,249,250,251,250,250,252,250,253,254,255,256, /* U+1F000 */ -257,258,259,260,261,262,249,249,249,249,249,249,249,249,249,263, /* U+1F800 */ + 71,220,221,222,223,224,225,142,226,227,228,229,230,231,232,233, /* U+1D000 */ +234,234,234,234,235,236,142,142,142,142,142,142,142,142,142,142, /* U+1D800 */ +237,142,238,142,142,239,142,142,142,142,142,142,142,142,142,142, /* U+1E000 */ +240,241,242,142,142,142,142,142,243,244,245,142,246,247,142,142, /* U+1E800 */ +248,249,250,251,252,253,254,255,254,254,256,254,257,258,259,260, /* U+1F000 */ +261,262,263,264,265,266, 71,267,253,253,253,253,253,253,253,268, /* U+1F800 */ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+20000 */ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+20800 */ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+21000 */ @@ -1236,21 +1255,21 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+28800 */ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+29000 */ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+29800 */ - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,264, 98, 98, /* U+2A000 */ + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,269, 98, 98, /* U+2A000 */ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2A800 */ - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,265, 98, /* U+2B000 */ -266, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2B800 */ + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,270, 98, /* U+2B000 */ +271, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2B800 */ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2C000 */ - 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,267, 98, 98, /* U+2C800 */ + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,272, 98, 98, /* U+2C800 */ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2D000 */ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2D800 */ 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2E000 */ - 98, 98, 98, 98, 98, 98, 98,268,142,142,142,142,142,142,142,142, /* U+2E800 */ + 98, 98, 98, 98, 98, 98, 98,273,142,142,142,142,142,142,142,142, /* U+2E800 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+2F000 */ - 98, 98, 98, 98,269,142,142,142,142,142,142,142,142,142,142,142, /* U+2F800 */ -142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+30000 */ -142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+30800 */ -142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+31000 */ + 98, 98, 98, 98,274,142,142,142,142,142,142,142,142,142,142,142, /* U+2F800 */ + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+30000 */ + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+30800 */ + 98, 98, 98, 98, 98, 98,275,142,142,142,142,142,142,142,142,142, /* U+31000 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+31800 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+32000 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+32800 */ @@ -1600,8 +1619,8 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DE800 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DF000 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+DF800 */ -270,271,272,273,271,271,271,271,271,271,271,271,271,271,271,271, /* U+E0000 */ -271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271, /* U+E0800 */ +276,277,278,279,277,277,277,277,277,277,277,277,277,277,277,277, /* U+E0000 */ +277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277, /* U+E0800 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E1000 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E1800 */ 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142, /* U+E2000 */ @@ -1663,7 +1682,7 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FE000 */ 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FE800 */ 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+FF000 */ -126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,274, /* U+FF800 */ +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,280, /* U+FF800 */ 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+100000 */ 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+100800 */ 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+101000 */ @@ -1695,10 +1714,10 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */ 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10E000 */ 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10E800 */ 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126, /* U+10F000 */ -126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,274, /* U+10F800 */ +126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,280, /* U+10F800 */ }; -const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ +const uint16_t PRIV(ucd_stage2)[] = { /* 71936 bytes, block = 128 */ /* block 0 */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1810,474 +1829,474 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207, /* block 11 */ -207,207,207,207,207,207,207,206,206,208,209,120,120,210,210,211, -120,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, -212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212, -212,212,212,212,212,212,212,212,212,212,212,212,212,212,213,212, -214,212,212,214,212,212,214,212,120,120,120,120,120,120,120,120, -215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215, -215,215,215,215,215,215,215,215,215,215,215,120,120,120,120,215, -215,215,215,214,214,120,120,120,120,120,120,120,120,120,120,120, +207,207,207,207,207,207,207,206,206,205,208,120,120,209,209,210, +120,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211, +211,211,211,211,211,211,211,211,211,211,211,211,211,211,212,211, +213,211,211,213,211,211,213,211,120,120,120,120,120,120,120,120, +214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214, +214,214,214,214,214,214,214,214,214,214,214,120,120,120,120,214, +214,214,214,213,213,120,120,120,120,120,120,120,120,120,120,120, /* block 12 */ -216,216,216,216,216,217,218,218,218,219,219,220,221,219,222,222, -223,223,223,223,223,223,223,223,223,223,223,221,224,120,219,221, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -226,225,225,225,225,225,225,225,225,225,225,227,227,227,227,227, -227,227,227,227,227,227,223,223,223,223,223,223,223,223,223,223, -228,228,228,228,228,228,228,228,228,228,219,219,219,219,225,225, -227,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +215,215,215,215,215,216,217,217,217,218,218,219,220,218,221,221, +222,222,222,222,222,222,222,222,222,222,222,220,223,120,218,220, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +225,224,224,224,224,224,224,224,224,224,224,226,226,226,226,226, +226,226,226,226,226,226,222,222,222,222,222,222,222,222,222,222, +227,227,227,227,227,227,227,227,227,227,218,218,218,218,224,224, +226,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, /* block 13 */ -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,229,225,223,223,223,223,223,223,223,217,222,223, -223,223,223,223,223,230,230,223,223,222,223,223,223,223,225,225, -231,231,231,231,231,231,231,231,231,231,225,225,225,222,222,225, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,228,224,222,222,222,222,222,222,222,216,221,222, +222,222,222,222,222,229,229,222,222,221,222,222,222,222,224,224, +230,230,230,230,230,230,230,230,230,230,224,224,224,221,221,224, /* block 14 */ -232,232,232,232,232,232,232,232,232,232,232,232,232,232,120,233, -234,235,234,234,234,234,234,234,234,234,234,234,234,234,234,234, +231,231,231,231,231,231,231,231,231,231,231,231,231,231,120,232, +233,234,233,233,233,233,233,233,233,233,233,233,233,233,233,233, +233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233, 234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234, -235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, -235,235,235,235,235,235,235,235,235,235,235,120,120,234,234,234, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +234,234,234,234,234,234,234,234,234,234,234,120,120,233,233,233, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, /* block 15 */ -236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, -236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236, -236,236,236,236,236,236,237,237,237,237,237,237,237,237,237,237, -237,236,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -238,238,238,238,238,238,238,238,238,238,239,239,239,239,239,239, -239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239, -239,239,239,239,239,239,239,239,239,239,239,240,240,240,240,240, -240,240,240,240,241,241,242,243,243,243,241,120,120,240,244,244, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235, +235,235,235,235,235,235,236,236,236,236,236,236,236,236,236,236, +236,235,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +237,237,237,237,237,237,237,237,237,237,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238, +238,238,238,238,238,238,238,238,238,238,238,239,239,239,239,239, +239,239,239,239,240,240,241,242,242,242,240,120,120,239,243,243, /* block 16 */ -245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245, -245,245,245,245,245,245,246,246,246,246,247,246,246,246,246,246, -246,246,246,246,247,246,246,246,247,246,246,246,246,246,120,120, -248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,120, -249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249, -249,249,249,249,249,249,249,249,249,250,250,250,120,120,251,120, -234,234,234,234,234,234,234,234,234,234,234,120,120,120,120,120, +244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244, +244,244,244,244,244,244,245,245,245,245,246,245,245,245,245,245, +245,245,245,245,246,245,245,245,246,245,245,245,245,245,120,120, +247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,120, +248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248, +248,248,248,248,248,248,248,248,248,249,249,249,120,120,250,120, +233,233,233,233,233,233,233,233,233,233,233,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 17 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,120,225,225,225,225,225,225,225,225,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -120,120,120,223,223,223,223,223,223,223,223,223,223,223,223,223, -223,223,217,223,223,223,223,223,223,223,223,223,223,223,223,223, -223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,120,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,120,120,120,120,120,120,120,120, +120,120,120,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,216,222,222,222,222,222,222,222,222,222,222,222,222,222, +222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222, /* block 18 */ -252,252,252,253,254,254,254,254,254,254,254,254,254,254,254,254, -254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, -254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254, -254,254,254,254,254,254,254,254,254,254,252,253,252,254,253,253, -253,252,252,252,252,252,252,252,252,253,253,253,253,252,253,253, -254,255,256,113,113,252,252,252,254,254,254,254,254,254,254,254, -254,254,252,252,257,258,259,259,259,259,259,259,259,259,259,259, -260,261,254,254,254,254,254,254,254,254,254,254,254,254,254,254, +251,251,251,252,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253, +253,253,253,253,253,253,253,253,253,253,251,252,251,253,252,252, +252,251,251,251,251,251,251,251,251,252,252,252,252,251,252,252, +253,254,255,113,113,251,251,251,253,253,253,253,253,253,253,253, +253,253,251,251,256,257,258,258,258,258,258,258,258,258,258,258, +259,260,253,253,253,253,253,253,253,253,253,253,253,253,253,253, /* block 19 */ -262,263,264,264,120,262,262,262,262,262,262,262,262,120,120,262, -262,120,120,262,262,262,262,262,262,262,262,262,262,262,262,262, -262,262,262,262,262,262,262,262,262,120,262,262,262,262,262,262, -262,120,262,120,120,120,262,262,262,262,120,120,263,262,265,264, -264,263,263,263,263,120,120,264,264,120,120,264,264,263,262,120, -120,120,120,120,120,120,120,265,120,120,120,120,262,262,120,262, -262,262,263,263,120,120,266,266,266,266,266,266,266,266,266,266, -262,262,267,267,268,268,268,268,268,268,269,267,262,270,263,120, +261,262,263,263,120,261,261,261,261,261,261,261,261,120,120,261, +261,120,120,261,261,261,261,261,261,261,261,261,261,261,261,261, +261,261,261,261,261,261,261,261,261,120,261,261,261,261,261,261, +261,120,261,120,120,120,261,261,261,261,120,120,262,261,264,263, +263,262,262,262,262,120,120,263,263,120,120,263,263,262,261,120, +120,120,120,120,120,120,120,264,120,120,120,120,261,261,120,261, +261,261,262,262,120,120,265,265,265,265,265,265,265,265,265,265, +261,261,266,266,267,267,267,267,267,267,268,266,261,269,262,120, /* block 20 */ -120,271,271,272,120,273,273,273,273,273,273,120,120,120,120,273, -273,120,120,273,273,273,273,273,273,273,273,273,273,273,273,273, -273,273,273,273,273,273,273,273,273,120,273,273,273,273,273,273, -273,120,273,273,120,273,273,120,273,273,120,120,271,120,272,272, -272,271,271,120,120,120,120,271,271,120,120,271,271,271,120,120, -120,271,120,120,120,120,120,120,120,273,273,273,273,120,273,120, -120,120,120,120,120,120,274,274,274,274,274,274,274,274,274,274, -271,271,273,273,273,271,275,120,120,120,120,120,120,120,120,120, +120,270,270,271,120,272,272,272,272,272,272,120,120,120,120,272, +272,120,120,272,272,272,272,272,272,272,272,272,272,272,272,272, +272,272,272,272,272,272,272,272,272,120,272,272,272,272,272,272, +272,120,272,272,120,272,272,120,272,272,120,120,270,120,271,271, +271,270,270,120,120,120,120,270,270,120,120,270,270,270,120,120, +120,270,120,120,120,120,120,120,120,272,272,272,272,120,272,120, +120,120,120,120,120,120,273,273,273,273,273,273,273,273,273,273, +270,270,272,272,272,270,274,120,120,120,120,120,120,120,120,120, /* block 21 */ -120,276,276,277,120,278,278,278,278,278,278,278,278,278,120,278, -278,278,120,278,278,278,278,278,278,278,278,278,278,278,278,278, -278,278,278,278,278,278,278,278,278,120,278,278,278,278,278,278, -278,120,278,278,120,278,278,278,278,278,120,120,276,278,277,277, -277,276,276,276,276,276,120,276,276,277,120,277,277,276,120,120, -278,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -278,278,276,276,120,120,279,279,279,279,279,279,279,279,279,279, -280,281,120,120,120,120,120,120,120,278,276,276,276,276,276,276, +120,275,275,276,120,277,277,277,277,277,277,277,277,277,120,277, +277,277,120,277,277,277,277,277,277,277,277,277,277,277,277,277, +277,277,277,277,277,277,277,277,277,120,277,277,277,277,277,277, +277,120,277,277,120,277,277,277,277,277,120,120,275,277,276,276, +276,275,275,275,275,275,120,275,275,276,120,276,276,275,120,120, +277,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +277,277,275,275,120,120,278,278,278,278,278,278,278,278,278,278, +279,280,120,120,120,120,120,120,120,277,275,275,275,275,275,275, /* block 22 */ -120,282,283,283,120,284,284,284,284,284,284,284,284,120,120,284, -284,120,120,284,284,284,284,284,284,284,284,284,284,284,284,284, -284,284,284,284,284,284,284,284,284,120,284,284,284,284,284,284, -284,120,284,284,120,284,284,284,284,284,120,120,282,284,285,282, -283,282,282,282,282,120,120,283,283,120,120,283,283,282,120,120, -120,120,120,120,120,120,282,285,120,120,120,120,284,284,120,284, -284,284,282,282,120,120,286,286,286,286,286,286,286,286,286,286, -287,284,288,288,288,288,288,288,120,120,120,120,120,120,120,120, +120,281,282,282,120,283,283,283,283,283,283,283,283,120,120,283, +283,120,120,283,283,283,283,283,283,283,283,283,283,283,283,283, +283,283,283,283,283,283,283,283,283,120,283,283,283,283,283,283, +283,120,283,283,120,283,283,283,283,283,120,120,281,283,284,281, +282,281,281,281,281,120,120,282,282,120,120,282,282,281,120,120, +120,120,120,120,120,281,281,284,120,120,120,120,283,283,120,283, +283,283,281,281,120,120,285,285,285,285,285,285,285,285,285,285, +286,283,287,287,287,287,287,287,120,120,120,120,120,120,120,120, /* block 23 */ -120,120,289,290,120,290,290,290,290,290,290,120,120,120,290,290, -290,120,290,290,290,290,120,120,120,290,290,120,290,120,290,290, -120,120,120,290,290,120,120,120,290,290,290,120,120,120,290,290, -290,290,290,290,290,290,290,290,290,290,120,120,120,120,291,292, -289,292,292,120,120,120,292,292,292,120,292,292,292,289,120,120, -290,120,120,120,120,120,120,291,120,120,120,120,120,120,120,120, -120,120,120,120,120,120,293,293,293,293,293,293,293,293,293,293, -294,294,294,295,296,296,296,296,296,297,296,120,120,120,120,120, +120,120,288,289,120,289,289,289,289,289,289,120,120,120,289,289, +289,120,289,289,289,289,120,120,120,289,289,120,289,120,289,289, +120,120,120,289,289,120,120,120,289,289,289,120,120,120,289,289, +289,289,289,289,289,289,289,289,289,289,120,120,120,120,290,291, +288,291,291,120,120,120,291,291,291,120,291,291,291,288,120,120, +289,120,120,120,120,120,120,290,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,292,292,292,292,292,292,292,292,292,292, +293,293,293,294,295,295,295,295,295,296,295,120,120,120,120,120, /* block 24 */ -298,299,299,299,298,300,300,300,300,300,300,300,300,120,300,300, -300,120,300,300,300,300,300,300,300,300,300,300,300,300,300,300, -300,300,300,300,300,300,300,300,300,120,300,300,300,300,300,300, -300,300,300,300,300,300,300,300,300,300,120,120,120,300,298,298, -298,299,299,299,299,120,298,298,298,120,298,298,298,298,120,120, -120,120,120,120,120,298,298,120,300,300,300,120,120,120,120,120, -300,300,298,298,120,120,301,301,301,301,301,301,301,301,301,301, -120,120,120,120,120,120,120,302,303,303,303,303,303,303,303,304, +297,298,298,298,297,299,299,299,299,299,299,299,299,120,299,299, +299,120,299,299,299,299,299,299,299,299,299,299,299,299,299,299, +299,299,299,299,299,299,299,299,299,120,299,299,299,299,299,299, +299,299,299,299,299,299,299,299,299,299,120,120,120,299,297,297, +297,298,298,298,298,120,297,297,297,120,297,297,297,297,120,120, +120,120,120,120,120,297,297,120,299,299,299,120,120,120,120,120, +299,299,297,297,120,120,300,300,300,300,300,300,300,300,300,300, +120,120,120,120,120,120,120,301,302,302,302,302,302,302,302,303, /* block 25 */ -305,306,307,307,308,305,305,305,305,305,305,305,305,120,305,305, -305,120,305,305,305,305,305,305,305,305,305,305,305,305,305,305, -305,305,305,305,305,305,305,305,305,120,305,305,305,305,305,305, -305,305,305,305,120,305,305,305,305,305,120,120,306,305,307,306, -307,307,309,307,307,120,306,307,307,120,307,307,306,306,120,120, -120,120,120,120,120,309,309,120,120,120,120,120,120,120,305,120, -305,305,306,306,120,120,310,310,310,310,310,310,310,310,310,310, -120,305,305,120,120,120,120,120,120,120,120,120,120,120,120,120, +304,305,306,306,307,304,304,304,304,304,304,304,304,120,304,304, +304,120,304,304,304,304,304,304,304,304,304,304,304,304,304,304, +304,304,304,304,304,304,304,304,304,120,304,304,304,304,304,304, +304,304,304,304,120,304,304,304,304,304,120,120,305,304,306,305, +306,306,308,306,306,120,305,306,306,120,306,306,305,305,120,120, +120,120,120,120,120,308,308,120,120,120,120,120,120,120,304,120, +304,304,305,305,120,120,309,309,309,309,309,309,309,309,309,309, +120,304,304,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 26 */ -311,311,312,312,120,313,313,313,313,313,313,313,313,120,313,313, -313,120,313,313,313,313,313,313,313,313,313,313,313,313,313,313, -313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313, -313,313,313,313,313,313,313,313,313,313,313,311,311,313,314,312, -312,311,311,311,311,120,312,312,312,120,312,312,312,311,315,316, -120,120,120,120,313,313,313,314,317,317,317,317,317,317,317,313, -313,313,311,311,120,120,318,318,318,318,318,318,318,318,318,318, -317,317,317,317,317,317,317,317,317,316,313,313,313,313,313,313, +310,310,311,311,312,312,312,312,312,312,312,312,312,120,312,312, +312,120,312,312,312,312,312,312,312,312,312,312,312,312,312,312, +312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312, +312,312,312,312,312,312,312,312,312,312,312,310,310,312,313,311, +311,310,310,310,310,120,311,311,311,120,311,311,311,310,314,315, +120,120,120,120,312,312,312,313,316,316,316,316,316,316,316,312, +312,312,310,310,120,120,317,317,317,317,317,317,317,317,317,317, +316,316,316,316,316,316,316,316,316,315,312,312,312,312,312,312, /* block 27 */ -120,120,319,319,120,320,320,320,320,320,320,320,320,320,320,320, +120,318,319,319,120,320,320,320,320,320,320,320,320,320,320,320, 320,320,320,320,320,320,320,120,120,120,320,320,320,320,320,320, 320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320, 320,320,120,320,320,320,320,320,320,320,320,320,120,320,120,120, -320,320,320,320,320,320,320,120,120,120,321,120,120,120,120,322, -319,319,321,321,321,120,321,120,319,319,319,319,319,319,319,322, -120,120,120,120,120,120,323,323,323,323,323,323,323,323,323,323, -120,120,319,319,324,120,120,120,120,120,120,120,120,120,120,120, +320,320,320,320,320,320,320,120,120,120,318,120,120,120,120,321, +319,319,318,318,318,120,318,120,319,319,319,319,319,319,319,321, +120,120,120,120,120,120,322,322,322,322,322,322,322,322,322,322, +120,120,319,319,323,120,120,120,120,120,120,120,120,120,120,120, /* block 28 */ -120,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325, -325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325, -325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325, -325,326,325,327,326,326,326,326,326,326,326,120,120,120,120, 6, -325,325,325,325,325,325,328,326,326,326,326,326,326,326,326,329, -330,330,330,330,330,330,330,330,330,330,329,329,120,120,120,120, +120,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324, +324,325,324,326,325,325,325,325,325,325,325,120,120,120,120, 6, +324,324,324,324,324,324,327,325,325,325,325,325,325,325,325,328, +329,329,329,329,329,329,329,329,329,329,328,328,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 29 */ -120,331,331,120,331,120,331,331,331,331,331,120,331,331,331,331, -331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331, -331,331,331,331,120,331,120,331,331,331,331,331,331,331,331,331, -331,332,331,333,332,332,332,332,332,332,332,332,332,331,120,120, -331,331,331,331,331,120,334,120,332,332,332,332,332,332,120,120, -335,335,335,335,335,335,335,335,335,335,120,120,331,331,331,331, +120,330,330,120,330,120,330,330,330,330,330,120,330,330,330,330, +330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330, +330,330,330,330,120,330,120,330,330,330,330,330,330,330,330,330, +330,331,330,332,331,331,331,331,331,331,331,331,331,330,120,120, +330,330,330,330,330,120,333,120,331,331,331,331,331,331,120,120, +334,334,334,334,334,334,334,334,334,334,120,120,330,330,330,330, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 30 */ -336,337,337,337,338,338,338,338,338,338,338,338,338,338,338,338, -338,338,338,337,338,337,337,337,339,339,337,337,337,337,337,337, -340,340,340,340,340,340,340,340,340,340,341,341,341,341,341,341, -341,341,341,341,337,339,337,339,337,339,342,343,342,343,344,344, -336,336,336,336,336,336,336,336,120,336,336,336,336,336,336,336, -336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336, -336,336,336,336,336,336,336,336,336,336,336,336,336,120,120,120, -120,339,339,339,339,339,339,339,339,339,339,339,339,339,339,344, +335,336,336,336,337,337,337,337,337,337,337,337,337,337,337,337, +337,337,337,336,337,336,336,336,338,338,336,336,336,336,336,336, +339,339,339,339,339,339,339,339,339,339,340,340,340,340,340,340, +340,340,340,340,336,338,336,338,336,338,341,342,341,342,343,343, +335,335,335,335,335,335,335,335,120,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335, +335,335,335,335,335,335,335,335,335,335,335,335,335,120,120,120, +120,338,338,338,338,338,338,338,338,338,338,338,338,338,338,343, /* block 31 */ -339,339,339,339,339,338,339,339,336,336,336,336,336,339,339,339, -339,339,339,339,339,339,339,339,120,339,339,339,339,339,339,339, -339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339, -339,339,339,339,339,339,339,339,339,339,339,339,339,120,337,337, -337,337,337,337,337,337,339,337,337,337,337,337,337,120,337,337, -338,338,338,338,338, 20, 20, 20, 20,338,338,120,120,120,120,120, +338,338,338,338,338,337,338,338,335,335,335,335,335,338,338,338, +338,338,338,338,338,338,338,338,120,338,338,338,338,338,338,338, +338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338, +338,338,338,338,338,338,338,338,338,338,338,338,338,120,336,336, +336,336,336,336,336,336,338,336,336,336,336,336,336,120,336,336, +337,337,337,337,337, 20, 20, 20, 20,337,337,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 32 */ -345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, -345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, -345,345,345,345,345,345,345,345,345,345,345,346,346,347,347,347, -347,348,347,347,347,347,347,347,346,347,347,348,348,347,347,345, -349,349,349,349,349,349,349,349,349,349,350,350,350,350,350,350, -345,345,345,345,345,345,348,348,347,347,345,345,345,345,347,347, -347,345,346,346,346,345,345,346,346,346,346,346,346,346,345,345, -345,347,347,347,347,345,345,345,345,345,345,345,345,345,345,345, +344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344, +344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344, +344,344,344,344,344,344,344,344,344,344,344,345,345,346,346,346, +346,347,346,346,346,346,346,346,345,346,346,347,347,346,346,344, +348,348,348,348,348,348,348,348,348,348,349,349,349,349,349,349, +344,344,344,344,344,344,347,347,346,346,344,344,344,344,346,346, +346,344,345,345,345,344,344,345,345,345,345,345,345,345,344,344, +344,346,346,346,346,344,344,344,344,344,344,344,344,344,344,344, /* block 33 */ -345,345,347,346,348,347,347,346,346,346,346,346,346,347,345,346, -351,351,351,351,351,351,351,351,351,351,346,346,346,347,352,352, +344,344,346,345,347,346,346,345,345,345,345,345,345,346,344,345, +350,350,350,350,350,350,350,350,350,350,345,345,345,346,351,351, +352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352, +352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352, +352,352,352,352,352,352,120,352,120,120,120,120,120,352,120,120, 353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, 353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353, -353,353,353,353,353,353,120,353,120,120,120,120,120,353,120,120, -354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354, -354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354, -354,354,354,354,354,354,354,354,354,354,354,355,356,354,354,354, +353,353,353,353,353,353,353,353,353,353,353,354,355,353,353,353, /* block 34 */ +356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, +356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, +356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, +356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, +356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, +356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, 357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, 357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, + +/* block 35 */ 357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, 357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, -357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, -357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, +357,357,357,357,357,357,357,357,358,358,358,358,358,358,358,358, 358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, 358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, - -/* block 35 */ 358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, 358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, -358,358,358,358,358,358,358,358,359,359,359,359,359,359,359,359, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, + +/* block 36 */ 359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, 359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, 359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, 359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,120,359,359,359,359,120,120, +359,359,359,359,359,359,359,120,359,120,359,359,359,359,120,120, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, 359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, - -/* block 36 */ -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,120,360,360,360,360,120,120, -360,360,360,360,360,360,360,120,360,120,360,360,360,360,120,120, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, /* block 37 */ -360,360,360,360,360,360,360,360,360,120,360,360,360,360,120,120, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,120,360,360,360,360,120,120,360,360,360,360,360,360,360,120, -360,120,360,360,360,360,120,120,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, +359,359,359,359,359,359,359,359,359,120,359,359,359,359,120,120, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,120,359,359,359,359,120,120,359,359,359,359,359,359,359,120, +359,120,359,359,359,359,120,120,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, /* block 38 */ -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,120,360,360,360,360,120,120,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,360,360,360,360,120,120,361,361,361, -362,362,362,362,362,362,362,362,362,363,363,363,363,363,363,363, -363,363,363,363,363,363,363,363,363,363,363,363,363,120,120,120, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,120,359,359,359,359,120,120,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,359,359,359,359,120,120,360,360,360, +361,361,361,361,361,361,361,361,361,362,362,362,362,362,362,362, +362,362,362,362,362,362,362,362,362,362,362,362,362,120,120,120, /* block 39 */ -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -364,364,364,364,364,364,364,364,364,364,120,120,120,120,120,120, -365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, -365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, -365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, -365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, -365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365, -366,366,366,366,366,366,120,120,367,367,367,367,367,367,120,120, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +363,363,363,363,363,363,363,363,363,363,120,120,120,120,120,120, +364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, +364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, +364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, +364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, +364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364, +365,365,365,365,365,365,120,120,366,366,366,366,366,366,120,120, /* block 40 */ -368,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +367,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, /* block 41 */ -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, /* block 42 */ -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,370,371,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,369,370,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, /* block 43 */ -372,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373, -373,373,373,373,373,373,373,373,373,373,373,374,375,120,120,120, -376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376, -376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376, -376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376, -376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376, -376,376,376,376,376,376,376,376,376,376,376, 5, 5, 5,377,377, -377,376,376,376,376,376,376,376,376,120,120,120,120,120,120,120, +371,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372, +372,372,372,372,372,372,372,372,372,372,372,373,374,120,120,120, +375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375, +375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375, +375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375, +375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375, +375,375,375,375,375,375,375,375,375,375,375, 5, 5, 5,376,376, +376,375,375,375,375,375,375,375,375,120,120,120,120,120,120,120, /* block 44 */ -378,378,378,378,378,378,378,378,378,378,378,378,378,120,378,378, -378,378,379,379,379,120,120,120,120,120,120,120,120,120,120,120, -380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380, -380,380,381,381,381,382,382,120,120,120,120,120,120,120,120,120, -383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383, -383,383,384,384,120,120,120,120,120,120,120,120,120,120,120,120, -385,385,385,385,385,385,385,385,385,385,385,385,385,120,385,385, -385,120,386,386,120,120,120,120,120,120,120,120,120,120,120,120, +377,377,377,377,377,377,377,377,377,377,377,377,377,120,377,377, +377,377,378,378,378,120,120,120,120,120,120,120,120,120,120,120, +379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379, +379,379,380,380,380,381,381,120,120,120,120,120,120,120,120,120, +382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382, +382,382,383,383,120,120,120,120,120,120,120,120,120,120,120,120, +384,384,384,384,384,384,384,384,384,384,384,384,384,120,384,384, +384,120,385,385,120,120,120,120,120,120,120,120,120,120,120,120, /* block 45 */ -387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387, -387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387, -387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387, -387,387,387,387,388,388,389,388,388,388,388,388,388,388,389,389, -389,389,389,389,389,389,388,389,389,388,388,388,388,388,388,388, -388,388,388,388,390,390,390,391,390,390,390,392,387,388,120,120, +386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386, +386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386, +386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386, +386,386,386,386,387,387,388,387,387,387,387,387,387,387,388,388, +388,388,388,388,388,388,387,388,388,387,387,387,387,387,387,387, +387,387,387,387,389,389,389,390,389,389,389,391,386,387,120,120, +392,392,392,392,392,392,392,392,392,392,120,120,120,120,120,120, 393,393,393,393,393,393,393,393,393,393,120,120,120,120,120,120, -394,394,394,394,394,394,394,394,394,394,120,120,120,120,120,120, /* block 46 */ -395,395,396,396,395,396,397,395,395,395,395,398,398,398,399,120, -400,400,400,400,400,400,400,400,400,400,120,120,120,120,120,120, -401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, -401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, -401,401,401,402,401,401,401,401,401,401,401,401,401,401,401,401, -401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, -401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, -401,401,401,401,401,401,401,401,401,120,120,120,120,120,120,120, +394,394,395,395,394,395,396,394,394,394,394,397,397,397,398,120, +399,399,399,399,399,399,399,399,399,399,120,120,120,120,120,120, +400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400, +400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400, +400,400,400,401,400,400,400,400,400,400,400,400,400,400,400,400, +400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400, +400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400, +400,400,400,400,400,400,400,400,400,120,120,120,120,120,120,120, /* block 47 */ -401,401,401,401,401,398,398,401,401,401,401,401,401,401,401,401, -401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401, -401,401,401,401,401,401,401,401,401,398,401,120,120,120,120,120, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369, -369,369,369,369,369,369,120,120,120,120,120,120,120,120,120,120, +400,400,400,400,400,397,397,400,400,400,400,400,400,400,400,400, +400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400, +400,400,400,400,400,400,400,400,400,397,400,120,120,120,120,120, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368, +368,368,368,368,368,368,120,120,120,120,120,120,120,120,120,120, /* block 48 */ -403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403, -403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,120, -404,404,404,405,405,405,405,404,404,405,405,405,120,120,120,120, -405,405,404,405,405,405,405,405,405,404,404,404,120,120,120,120, -406,120,120,120,407,407,408,408,408,408,408,408,408,408,408,408, -409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, -409,409,409,409,409,409,409,409,409,409,409,409,409,409,120,120, -409,409,409,409,409,120,120,120,120,120,120,120,120,120,120,120, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402, +402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,120, +403,403,403,404,404,404,404,403,403,404,404,404,120,120,120,120, +404,404,403,404,404,404,404,404,404,403,403,403,120,120,120,120, +405,120,120,120,406,406,407,407,407,407,407,407,407,407,407,407, +408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408, +408,408,408,408,408,408,408,408,408,408,408,408,408,408,120,120, +408,408,408,408,408,120,120,120,120,120,120,120,120,120,120,120, /* block 49 */ -410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, -410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, -410,410,410,410,410,410,410,410,410,410,410,410,120,120,120,120, -410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410, -410,410,410,410,410,410,410,410,410,410,120,120,120,120,120,120, -411,411,411,411,411,411,411,411,411,411,412,120,120,120,413,413, -414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, -414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, +409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, +409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, +409,409,409,409,409,409,409,409,409,409,409,409,120,120,120,120, +409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409, +409,409,409,409,409,409,409,409,409,409,120,120,120,120,120,120, +410,410,410,410,410,410,410,410,410,410,411,120,120,120,412,412, +413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, +413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413, /* block 50 */ -415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415, -415,415,415,415,415,415,415,416,416,417,417,416,120,120,418,418, -419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, -419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, -419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419, -419,419,419,419,419,420,421,420,421,421,421,421,421,421,421,120, -421,422,421,422,422,421,421,421,421,421,421,421,421,420,420,420, -420,420,420,421,421,421,421,421,421,421,421,421,421,120,120,421, +414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414, +414,414,414,414,414,414,414,415,415,416,416,415,120,120,417,417, +418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, +418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, +418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418, +418,418,418,418,418,419,420,419,420,420,420,420,420,420,420,120, +420,421,420,421,421,420,420,420,420,420,420,420,420,419,419,419, +419,419,419,420,420,420,420,420,420,420,420,420,420,120,120,420, /* block 51 */ -423,423,423,423,423,423,423,423,423,423,120,120,120,120,120,120, -423,423,423,423,423,423,423,423,423,423,120,120,120,120,120,120, -424,424,424,424,424,424,424,425,424,424,424,424,424,424,120,120, -113,113,113,113,113,113,113,113,113,113,113,113,113,113,426,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +422,422,422,422,422,422,422,422,422,422,120,120,120,120,120,120, +422,422,422,422,422,422,422,422,422,422,120,120,120,120,120,120, +423,423,423,423,423,423,423,424,423,423,423,423,423,423,120,120, +113,113,113,113,113,113,113,113,113,113,113,113,113,113,425,113, +113,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 52 */ -427,427,427,427,428,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429, -429,429,429,429,427,430,427,427,427,427,427,428,427,428,428,428, -428,428,427,428,428,429,429,429,429,429,429,429,120,120,120,120, -431,431,431,431,431,431,431,431,431,431,432,432,432,432,432,432, -432,433,433,433,433,433,433,433,433,433,433,427,427,427,427,427, -427,427,427,427,433,433,433,433,433,433,433,433,433,120,120,120, +426,426,426,426,427,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428, +428,428,428,428,426,429,426,426,426,426,426,427,426,427,427,427, +427,427,426,427,427,428,428,428,428,428,428,428,120,120,120,120, +430,430,430,430,430,430,430,430,430,430,431,431,431,431,431,431, +431,432,432,432,432,432,432,432,432,432,432,426,426,426,426,426, +426,426,426,426,432,432,432,432,432,432,432,432,432,120,120,120, /* block 53 */ -434,434,435,436,436,436,436,436,436,436,436,436,436,436,436,436, -436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436, -436,435,434,434,434,434,435,435,434,434,435,434,434,434,436,436, -437,437,437,437,437,437,437,437,437,437,436,436,436,436,436,436, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438, -438,438,438,438,438,438,439,440,439,439,440,440,440,439,440,439, -439,439,440,440,120,120,120,120,120,120,120,120,441,441,441,441, +433,433,434,435,435,435,435,435,435,435,435,435,435,435,435,435, +435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435, +435,434,433,433,433,433,434,434,433,433,434,433,433,433,435,435, +436,436,436,436,436,436,436,436,436,436,435,435,435,435,435,435, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437, +437,437,437,437,437,437,438,439,438,438,439,439,439,438,439,438, +438,438,439,439,120,120,120,120,120,120,120,120,440,440,440,440, /* block 54 */ -442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, -442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442, -442,442,442,442,443,443,443,443,443,443,443,443,444,444,444,444, -444,444,444,444,443,443,444,444,120,120,120,445,445,445,445,445, -446,446,446,446,446,446,446,446,446,446,120,120,120,442,442,442, -447,447,447,447,447,447,447,447,447,447,448,448,448,448,448,448, -448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448, -448,448,448,448,448,448,448,448,449,449,449,449,449,449,450,450, +441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, +441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441, +441,441,441,441,442,442,442,442,442,442,442,442,443,443,443,443, +443,443,443,443,442,442,443,443,120,120,120,444,444,444,444,444, +445,445,445,445,445,445,445,445,445,445,120,120,120,441,441,441, +446,446,446,446,446,446,446,446,446,446,447,447,447,447,447,447, +447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447, +447,447,447,447,447,447,447,447,448,448,448,448,448,448,449,449, /* block 55 */ -451,452,453,454,455,456,457,458,459,120,120,120,120,120,120,120, -460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460, -460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460, -460,460,460,460,460,460,460,460,460,460,460,120,120,460,460,460, -461,461,461,461,461,461,461,461,120,120,120,120,120,120,120,120, -462,463,462,464,463,465,465,466,465,466,467,463,466,466,463,463, -466,468,463,463,463,463,463,463,463,469,470,471,471,465,471,471, -471,471,472,473,474,470,470,475,476,476,477,120,120,120,120,120, +450,451,452,453,454,455,456,457,458,120,120,120,120,120,120,120, +459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459, +459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459, +459,459,459,459,459,459,459,459,459,459,459,120,120,459,459,459, +460,460,460,460,460,460,460,460,120,120,120,120,120,120,120,120, +461,462,461,463,462,464,464,465,464,465,466,462,465,465,462,462, +465,467,462,462,462,462,462,462,462,468,469,470,470,464,470,470, +470,470,471,472,473,469,469,474,475,475,476,120,120,120,120,120, /* block 56 */ 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35,128,128,128,128,128,478,110,110,110,110, + 35, 35, 35, 35, 35, 35,128,128,128,128,128,477,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,121,121,121, 121,121,110,110,110,110,121,121,121,121,121, 35, 35, 35, 35, 35, - 35, 35, 35, 35, 35, 35, 35, 35,479,480, 35, 35, 35,481, 35, 35, + 35, 35, 35, 35, 35, 35, 35, 35,478,479, 35, 35, 35,480, 35, 35, /* block 57 */ - 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,482, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,481, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110, 110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,121, 114,114,113,113,113,113,113,113,113,113,113,113,113,113,113,113, 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, -113,113,113,113,113,113,113,113,113,113,120,113,113,113,113,113, +113,113,113,113,113,113,113,113,482,113,120,113,113,113,113,113, /* block 58 */ 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, @@ -2335,8 +2354,8 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -113,113,113,113,113,113,113,113,113,113,113,113,113,426,426,426, -426,113,426,426,426,113,113,113,113,113,113,113,113,113,113,113, +113,113,113,113,113,113,113,113,113,113,113,113,113,425,425,425, +425,113,425,425,425,113,113,113,113,113,113,113,113,113,113,113, 512,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 64 */ @@ -2511,7 +2530,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ /* block 81 */ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20,120,120, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20,120, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, @@ -2550,12 +2569,12 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 550,120,120,120,120,120,120,120,120,120,120,120,120,120,120,551, /* block 85 */ -360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360, -360,360,360,360,360,360,360,120,120,120,120,120,120,120,120,120, -360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,120, -360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,120, -360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,120, -360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,120, +359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, +359,359,359,359,359,359,359,120,120,120,120,120,120,120,120,120, +359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,120, +359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,120, +359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,120, +359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,120, 552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, 552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552, @@ -2565,7 +2584,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 23, 27, 7, 8, 7, 8, 7, 8, 7, 8, 5, 5, 5, 5, 5,111, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 5, 5, 5, 5, 10, 5, 7,553, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, + 20, 20, 5,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, @@ -2633,7 +2652,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,120, 572,572,582,582,582,582,572,572,572,572,572,572,572,572,572,572, 580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, -580,580,580,580,580,580,580,580,580,580,580,120,120,120,120,120, +580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580, 572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572, 572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572, 572,572,572,572,120,120,120,120,120,120,120,120,120,120,120,120, @@ -2693,7 +2712,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,120,120,120,120,120,120,120,120,120,120, +586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, @@ -2707,7 +2726,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +586,586,586,586,586,586,586,586,586,586,586,586,586,120,120,120, /* block 101 */ 587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587, @@ -2757,11 +2776,11 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 192,193,192,193,192,193,192,193,192,193,597,598,192,193,192,193, 192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193, 192,193,192,193,192,193,192,193,192,193,192,193,192,193,599,198, -200,200,200,600,552,552,552,552,552,552,552,552,552,552,600,479, +200,200,200,600,552,552,552,552,552,552,552,552,552,552,600,478, /* block 106 */ 192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193, -192,193,192,193,192,193,192,193,192,193,192,193,479,479,552,552, +192,193,192,193,192,193,192,193,192,193,192,193,478,478,552,552, 601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, 601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, 601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, @@ -2770,196 +2789,186 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 603,603,604,604,604,604,604,604,120,120,120,120,120,120,120,120, /* block 107 */ - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +605,605,605,605,605,605,605,605, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,111,111,111,111,111,111,111,111,111, 15, 15, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 35, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, -110, 35, 35, 35, 35, 35, 35, 35, 35, 32, 33, 32, 33,605, 32, 33, +110, 35, 35, 35, 35, 35, 35, 35, 35, 32, 33, 32, 33,606, 32, 33, /* block 108 */ - 32, 33, 32, 33, 32, 33, 32, 33,111, 15, 15, 32, 33,606, 35, 22, - 32, 33, 32, 33,607, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, - 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,608,609,610,611,608, 35, -612,613,614,615, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, -120,120, 32, 33,616,617,618,120,120,120,120,120,120,120,120,120, + 32, 33, 32, 33, 32, 33, 32, 33,111, 15, 15, 32, 33,607, 35, 22, + 32, 33, 32, 33,608, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, + 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,609,610,611,612,609, 35, +613,614,615,616, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, +120,120, 32, 33,617,618,619, 32, 33, 32, 33,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -120,120,120,120,120,120,120, 22,110,110, 35, 22, 22, 22, 22, 22, +120,120,120,120,120, 32, 33, 22,110,110, 35, 22, 22, 22, 22, 22, /* block 109 */ -619,619,620,619,619,619,620,619,619,619,619,620,619,619,619,619, -619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619, -619,619,619,621,621,620,620,621,622,622,622,622,120,120,120,120, -623,623,623,624,624,624,625,625,626,625,120,120,120,120,120,120, -627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627, -627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627, -627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627, -627,627,627,627,628,628,628,628,120,120,120,120,120,120,120,120, +620,620,621,620,620,620,621,620,620,620,620,621,620,620,620,620, +620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620, +620,620,620,622,622,621,621,622,623,623,623,623,621,120,120,120, +624,624,624,625,625,625,626,626,627,626,120,120,120,120,120,120, +628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628, +628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628, +628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628, +628,628,628,628,629,629,629,629,120,120,120,120,120,120,120,120, /* block 110 */ -629,629,630,630,630,630,630,630,630,630,630,630,630,630,630,630, -630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630, -630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630, -630,630,630,630,629,629,629,629,629,629,629,629,629,629,629,629, -629,629,629,629,631,631,120,120,120,120,120,120,120,120,632,632, -633,633,633,633,633,633,633,633,633,633,120,120,120,120,120,120, -252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252, -252,634,254,635,254,254,254,254,260,260,260,254,260,254,254,252, +630,630,631,631,631,631,631,631,631,631,631,631,631,631,631,631, +631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, +631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631, +631,631,631,631,630,630,630,630,630,630,630,630,630,630,630,630, +630,630,630,630,632,632,120,120,120,120,120,120,120,120,633,633, +634,634,634,634,634,634,634,634,634,634,120,120,120,120,120,120, +251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251, +251,635,253,636,253,253,253,253,259,259,259,253,259,253,253,251, /* block 111 */ -636,636,636,636,636,636,636,636,636,636,637,637,637,637,637,637, -637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637, -637,637,637,637,637,637,638,638,638,638,638,638,638,638,639,640, -641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641, -641,641,641,641,641,641,641,642,642,642,642,642,642,642,642,642, -642,642,643,643,120,120,120,120,120,120,120,120,120,120,120,644, -357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, -357,357,357,357,357,357,357,357,357,357,357,357,357,120,120,120, +637,637,637,637,637,637,637,637,637,637,638,638,638,638,638,638, +638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638, +638,638,638,638,638,638,639,639,639,639,639,639,639,639,640,641, +642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642, +642,642,642,642,642,642,642,643,643,643,643,643,643,643,643,643, +643,643,644,644,120,120,120,120,120,120,120,120,120,120,120,645, +356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356, +356,356,356,356,356,356,356,356,356,356,356,356,356,120,120,120, /* block 112 */ -645,645,645,646,647,647,647,647,647,647,647,647,647,647,647,647, -647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647, -647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647, -647,647,647,645,646,646,645,645,645,645,646,646,645,645,646,646, -646,648,648,648,648,648,648,648,648,648,648,648,648,648,120,649, -650,650,650,650,650,650,650,650,650,650,120,120,120,120,648,648, -345,345,345,345,345,347,651,345,345,345,345,345,345,345,345,345, -351,351,351,351,351,351,351,351,351,351,345,345,345,345,345,120, +646,646,646,647,648,648,648,648,648,648,648,648,648,648,648,648, +648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648, +648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648, +648,648,648,646,647,647,646,646,646,646,647,647,646,646,647,647, +647,649,649,649,649,649,649,649,649,649,649,649,649,649,120,650, +651,651,651,651,651,651,651,651,651,651,120,120,120,120,649,649, +344,344,344,344,344,346,652,344,344,344,344,344,344,344,344,344, +350,350,350,350,350,350,350,350,350,350,344,344,344,344,344,120, /* block 113 */ -652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652, -652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652, -652,652,652,652,652,652,652,652,652,653,653,653,653,653,653,654, -654,653,653,654,654,653,653,120,120,120,120,120,120,120,120,120, -652,652,652,653,652,652,652,652,652,652,652,652,653,654,120,120, -655,655,655,655,655,655,655,655,655,655,120,120,656,656,656,656, -345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345, -651,345,345,345,345,345,345,352,352,352,345,346,347,346,345,345, +653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653, +653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653, +653,653,653,653,653,653,653,653,653,654,654,654,654,654,654,655, +655,654,654,655,655,654,654,120,120,120,120,120,120,120,120,120, +653,653,653,654,653,653,653,653,653,653,653,653,654,655,120,120, +656,656,656,656,656,656,656,656,656,656,120,120,657,657,657,657, +344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344, +652,344,344,344,344,344,344,351,351,351,344,345,346,345,344,344, /* block 114 */ -657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657, -657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657, -657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657, -658,657,658,658,658,657,657,658,658,657,657,657,657,657,658,658, -657,658,657,120,120,120,120,120,120,120,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,657,657,659,660,660, -661,661,661,661,661,661,661,661,661,661,661,662,663,663,662,662, -664,664,661,665,665,662,663,120,120,120,120,120,120,120,120,120, +658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658, +658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658, +658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658, +659,658,659,659,659,658,658,659,659,658,658,658,658,658,659,659, +658,659,658,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,658,658,660,661,661, +662,662,662,662,662,662,662,662,662,662,662,663,664,664,663,663, +665,665,662,666,666,663,664,120,120,120,120,120,120,120,120,120, /* block 115 */ -120,360,360,360,360,360,360,120,120,360,360,360,360,360,360,120, -120,360,360,360,360,360,360,120,120,120,120,120,120,120,120,120, -360,360,360,360,360,360,360,120,360,360,360,360,360,360,360,120, +120,359,359,359,359,359,359,120,120,359,359,359,359,359,359,120, +120,359,359,359,359,359,359,120,120,120,120,120,120,120,120,120, +359,359,359,359,359,359,359,120,359,359,359,359,359,359,359,120, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, - 35, 35, 35,666, 35, 35, 35, 35, 35, 35, 35, 15,110,110,110,110, - 35, 35, 35, 35, 35,128, 35, 35,120,120,120,120,120,120,120,120, -667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, + 35, 35, 35,667, 35, 35, 35, 35, 35, 35, 35, 15,110,110,110,110, + 35, 35, 35, 35, 35,128, 35, 35, 35,110, 15, 15,120,120,120,120, +668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, /* block 116 */ -667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, -667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, -667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, -667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667, -661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661, -661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661, -661,661,661,662,662,663,662,662,663,662,662,664,662,663,120,120, -668,668,668,668,668,668,668,668,668,668,120,120,120,120,120,120, +668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, +668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, +668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, +668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668, +662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662, +662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662, +662,662,662,663,663,664,663,663,664,663,663,665,663,664,120,120, +669,669,669,669,669,669,669,669,669,669,120,120,120,120,120,120, /* block 117 */ -669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, +670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, /* block 118 */ -670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670, +671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671, /* block 119 */ -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, /* block 120 */ -670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670, +671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671, /* block 121 */ -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, /* block 122 */ -670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670, - -/* block 123 */ -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,669,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,669,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, - -/* block 124 */ -670,670,670,670,670,670,670,670,669,670,670,670,670,670,670,670, -670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670, -670,670,670,670,120,120,120,120,120,120,120,120,120,120,120,120, -358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, -358,358,358,358,358,358,358,120,120,120,120,359,359,359,359,359, -359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, -359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359, -359,359,359,359,359,359,359,359,359,359,359,359,120,120,120,120, - -/* block 125 */ +671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671, 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671, 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671, 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671, + +/* block 123 */ 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +670,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,671,671,671,671,670,671,671,671, 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671, 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,670,671,671,671,671,671,671,671,671,671,671,671, 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, + +/* block 124 */ +671,671,671,671,671,671,671,671,670,671,671,671,671,671,671,671, 671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671, +671,671,671,671,120,120,120,120,120,120,120,120,120,120,120,120, +357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357, +357,357,357,357,357,357,357,120,120,120,120,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358, +358,358,358,358,358,358,358,358,358,358,358,358,120,120,120,120, -/* block 126 */ +/* block 125 */ 672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, 672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, 672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, @@ -2969,6 +2978,16 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, 672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, +/* block 126 */ +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, + /* block 127 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, @@ -2991,53 +3010,53 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ /* block 129 */ 35, 35, 35, 35, 35, 35, 35,120,120,120,120,120,120,120,120,120, -120,120,120,206,206,206,206,206,120,120,120,120,120,215,212,215, -215,215,215,215,215,215,215,215,215,673,215,215,215,215,215,215, -215,215,215,215,215,215,215,120,215,215,215,215,215,120,215,120, -215,215,120,215,215,120,215,215,215,215,215,215,215,215,215,215, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +120,120,120,206,206,206,206,206,120,120,120,120,120,214,211,214, +214,214,214,214,214,214,214,214,214,674,214,214,214,214,214,214, +214,214,214,214,214,214,214,120,214,214,214,214,214,120,214,120, +214,214,120,214,214,120,214,214,214,214,214,214,214,214,214,214, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, /* block 130 */ -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,674,674,674,674,674,674,674,674,674,674,674,674,674,674, -674,674,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -120,120,120,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,675,675,675,675,675,675,675,675,675,675,675,675,675,675, +675,675,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, /* block 131 */ -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, /* block 132 */ -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225, 8, 7, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224, 8, 7, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, /* block 133 */ -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -120,120,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,120,120,120,120,120,120,120,120, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +120,120,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -225,225,675,225,225,225,225,225,225,225,225,225,220,676,120,120, +224,224,676,224,224,224,224,224,224,224,224,224,219,677,120,120, /* block 134 */ 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, @@ -3047,17 +3066,17 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 8, 7, 8, 7, 8,556,556, 7, 8, 5, 5, 5, 5, 16, 16, 16, 5, 5, 5,120, 5, 5, 5, 5, 10, 7, 8, 7, 8, 7, 8, 5, 5, 5, 9, 10, 9, 9, 9,120, 5, 6, 5, 5,120,120,120,120, -225,225,225,225,225,120,225,225,225,225,225,225,225,225,225,225, +224,224,224,224,224,120,224,224,224,224,224,224,224,224,224,224, /* block 135 */ -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,120,120, 24, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,120,120, 24, /* block 136 */ 120, 5, 5, 5, 6, 5, 5, 5, 7, 8, 5, 9, 5, 10, 5, 5, @@ -3071,7 +3090,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ /* block 137 */ 578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578, -578,578,578,578,578,578,578,578,578,578,578,578,578,578,677,677, +578,578,578,578,578,578,578,578,578,578,578,578,578,578,678,678, 581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581, 581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,120, 120,120,581,581,581,581,581,581,120,120,581,581,581,581,581,581, @@ -3080,39 +3099,39 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 511,511,511,511,511,511,511,511,511, 24, 24, 24, 20, 20,120,120, /* block 138 */ -678,678,678,678,678,678,678,678,678,678,678,678,120,678,678,678, -678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, -678,678,678,678,678,678,678,120,678,678,678,678,678,678,678,678, -678,678,678,678,678,678,678,678,678,678,678,120,678,678,120,678, -678,678,678,678,678,678,678,678,678,678,678,678,678,678,120,120, -678,678,678,678,678,678,678,678,678,678,678,678,678,678,120,120, +679,679,679,679,679,679,679,679,679,679,679,679,120,679,679,679, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, +679,679,679,679,679,679,679,120,679,679,679,679,679,679,679,679, +679,679,679,679,679,679,679,679,679,679,679,120,679,679,120,679, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,120,120, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 139 */ -678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, -678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, -678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, -678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, -678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, -678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, -678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678, -678,678,678,678,678,678,678,678,678,678,678,120,120,120,120,120, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, +679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679, +679,679,679,679,679,679,679,679,679,679,679,120,120,120,120,120, /* block 140 */ -679,679,679,120,120,120,120,680,680,680,680,680,680,680,680,680, -680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, -680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680, -680,680,680,680,120,120,120,681,681,681,681,681,681,681,681,681, -682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, -682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, -682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682, -682,682,682,682,682,683,683,683,683,684,684,684,684,684,684,684, +680,680,680,120,120,120,120,681,681,681,681,681,681,681,681,681, +681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, +681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681, +681,681,681,681,120,120,120,682,682,682,682,682,682,682,682,682, +683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, +683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, +683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683, +683,683,683,683,683,684,684,684,684,685,685,685,685,685,685,685, /* block 141 */ -684,684,684,684,684,684,684,684,684,684,683,683,684,684,684,120, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120, -684,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +685,685,685,685,685,685,685,685,685,685,684,684,685,685,685,120, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120, +685,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, @@ -3130,159 +3149,159 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 143 */ -685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, -685,685,685,685,685,685,685,685,685,685,685,685,685,120,120,120, -686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, 686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, -686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686, -686,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -687,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688, -688,688,688,688,688,688,688,688,688,688,688,688,120,120,120,120, +686,686,686,686,686,686,686,686,686,686,686,686,686,120,120,120, +687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687, +687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687, +687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687, +687,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +688,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, +689,689,689,689,689,689,689,689,689,689,689,689,120,120,120,120, /* block 144 */ -689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, -689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689, -690,690,690,690,120,120,120,120,120,120,120,120,120,689,689,689, -691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691, -691,692,691,691,691,691,691,691,691,691,692,120,120,120,120,120, -693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693, -693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693, -693,693,693,693,693,693,694,694,694,694,694,120,120,120,120,120, +690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690, +690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690, +691,691,691,691,120,120,120,120,120,120,120,120,120,690,690,690, +692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692, +692,693,692,692,692,692,692,692,692,692,693,120,120,120,120,120, +694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694, +694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694, +694,694,694,694,694,694,695,695,695,695,695,120,120,120,120,120, /* block 145 */ -695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695, -695,695,695,695,695,695,695,695,695,695,695,695,695,695,120,696, -697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697, -697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697, -697,697,697,697,120,120,120,120,697,697,697,697,697,697,697,697, -698,699,699,699,699,699,120,120,120,120,120,120,120,120,120,120, +696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696, +696,696,696,696,696,696,696,696,696,696,696,696,696,696,120,697, +698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698, +698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698, +698,698,698,698,120,120,120,120,698,698,698,698,698,698,698,698, +699,700,700,700,700,700,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 146 */ -700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700, -700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700, -700,700,700,700,700,700,700,700,701,701,701,701,701,701,701,701, 701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701, 701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701, +701,701,701,701,701,701,701,701,702,702,702,702,702,702,702,702, 702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702, 702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702, -702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702, +703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703, +703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703, +703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703, /* block 147 */ -703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703, -703,703,703,703,703,703,703,703,703,703,703,703,703,703,120,120, -704,704,704,704,704,704,704,704,704,704,120,120,120,120,120,120, -705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, -705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705, -705,705,705,705,120,120,120,120,706,706,706,706,706,706,706,706, +704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704, +704,704,704,704,704,704,704,704,704,704,704,704,704,704,120,120, +705,705,705,705,705,705,705,705,705,705,120,120,120,120,120,120, +706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706, 706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706, -706,706,706,706,706,706,706,706,706,706,706,706,120,120,120,120, +706,706,706,706,120,120,120,120,707,707,707,707,707,707,707,707, +707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707, +707,707,707,707,707,707,707,707,707,707,707,707,120,120,120,120, /* block 148 */ -707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707, -707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707, -707,707,707,707,707,707,707,707,120,120,120,120,120,120,120,120, -708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, 708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708, -708,708,708,708,120,120,120,120,120,120,120,120,120,120,120,709, +708,708,708,708,708,708,708,708,120,120,120,120,120,120,120,120, +709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, +709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, +709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709, +709,709,709,709,120,120,120,120,120,120,120,120,120,120,120,710, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 149 */ -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, /* block 150 */ -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, -710,710,710,710,710,710,710,120,120,120,120,120,120,120,120,120, -710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710, -710,710,710,710,710,710,120,120,120,120,120,120,120,120,120,120, -710,710,710,710,710,710,710,710,120,120,120,120,120,120,120,120, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, +711,711,711,711,711,711,711,120,120,120,120,120,120,120,120,120, +711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, +711,711,711,711,711,711,120,120,120,120,120,120,120,120,120,120, +711,711,711,711,711,711,711,711,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 151 */ -711,711,711,711,711,711,120,120,711,120,711,711,711,711,711,711, -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, -711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711, -711,711,711,711,711,711,120,711,711,120,120,120,711,120,120,711, +712,712,712,712,712,712,120,120,712,120,712,712,712,712,712,712, +712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, 712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712, -712,712,712,712,712,712,120,713,714,714,714,714,714,714,714,714, -715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715, -715,715,715,715,715,715,715,716,716,717,717,717,717,717,717,717, +712,712,712,712,712,712,120,712,712,120,120,120,712,120,120,712, +713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713, +713,713,713,713,713,713,120,714,715,715,715,715,715,715,715,715, +716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716, +716,716,716,716,716,716,716,717,717,718,718,718,718,718,718,718, /* block 152 */ -718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718, -718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,120, -120,120,120,120,120,120,120,719,719,719,719,719,719,719,719,719, +719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719, +719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,120, +120,120,120,120,120,120,120,720,720,720,720,720,720,720,720,720, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720, -720,720,720,120,720,720,120,120,120,120,120,721,721,721,721,721, +721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721, +721,721,721,120,721,721,120,120,120,120,120,722,722,722,722,722, /* block 153 */ -722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722, -722,722,722,722,722,722,723,723,723,723,723,723,120,120,120,724, -725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725, -725,725,725,725,725,725,725,725,725,725,120,120,120,120,120,726, +723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723, +723,723,723,723,723,723,724,724,724,724,724,724,120,120,120,725, +726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726, +726,726,726,726,726,726,726,726,726,726,120,120,120,120,120,727, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 154 */ -727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727, -727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727, 728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728, -728,728,728,728,728,728,728,728,120,120,120,120,729,729,728,728, -729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729, -120,120,729,729,729,729,729,729,729,729,729,729,729,729,729,729, -729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729, +728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728, 729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729, +729,729,729,729,729,729,729,729,120,120,120,120,730,730,729,729, +730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, +120,120,730,730,730,730,730,730,730,730,730,730,730,730,730,730, +730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, +730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, /* block 155 */ -730,731,731,731,120,731,731,120,120,120,120,120,731,731,731,731, -730,730,730,730,120,730,730,730,120,730,730,730,730,730,730,730, -730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730, -730,730,730,730,730,730,120,120,731,731,731,120,120,120,120,731, -732,732,732,732,732,732,732,732,732,120,120,120,120,120,120,120, +731,732,732,732,120,732,732,120,120,120,120,120,732,732,732,732, +731,731,731,731,120,731,731,731,120,731,731,731,731,731,731,731, +731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731, +731,731,731,731,731,731,120,120,732,732,732,120,120,120,120,732, 733,733,733,733,733,733,733,733,733,120,120,120,120,120,120,120, -734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734, -734,734,734,734,734,734,734,734,734,734,734,734,734,735,735,736, +734,734,734,734,734,734,734,734,734,120,120,120,120,120,120,120, +735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735, +735,735,735,735,735,735,735,735,735,735,735,735,735,736,736,737, /* block 156 */ -737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737, -737,737,737,737,737,737,737,737,737,737,737,737,737,738,738,738, +738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738, +738,738,738,738,738,738,738,738,738,738,738,738,738,739,739,739, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -739,739,739,739,739,739,739,739,740,739,739,739,739,739,739,739, -739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739, -739,739,739,739,739,741,741,120,120,120,120,742,742,742,742,742, -743,743,743,743,743,743,743,120,120,120,120,120,120,120,120,120, +740,740,740,740,740,740,740,740,741,740,740,740,740,740,740,740, +740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740, +740,740,740,740,740,742,742,120,120,120,120,743,743,743,743,743, +744,744,744,744,744,744,744,120,120,120,120,120,120,120,120,120, /* block 157 */ -744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744, -744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744, -744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744, -744,744,744,744,744,744,120,120,120,745,745,745,745,745,745,745, -746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746, -746,746,746,746,746,746,120,120,747,747,747,747,747,747,747,747, -748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748, -748,748,748,120,120,120,120,120,749,749,749,749,749,749,749,749, +745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745, +745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745, +745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745, +745,745,745,745,745,745,120,120,120,746,746,746,746,746,746,746, +747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747, +747,747,747,747,747,747,120,120,748,748,748,748,748,748,748,748, +749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749, +749,749,749,120,120,120,120,120,750,750,750,750,750,750,750,750, /* block 158 */ -750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750, -750,750,120,120,120,120,120,120,120,751,751,751,751,120,120,120, -120,120,120,120,120,120,120,120,120,752,752,752,752,752,752,752, +751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751, +751,751,120,120,120,120,120,120,120,752,752,752,752,120,120,120, +120,120,120,120,120,120,120,120,120,753,753,753,753,753,753,753, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, @@ -3290,30 +3309,30 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 159 */ -753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753, -753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753, -753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753, -753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753, -753,753,753,753,753,753,753,753,753,120,120,120,120,120,120,120, +754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754, +754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754, +754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754, +754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754, +754,754,754,754,754,754,754,754,754,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 160 */ -754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754, -754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754, -754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754, -754,754,754,120,120,120,120,120,120,120,120,120,120,120,120,120, 755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755, 755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755, 755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755, -755,755,755,120,120,120,120,120,120,120,756,756,756,756,756,756, +755,755,755,120,120,120,120,120,120,120,120,120,120,120,120,120, +756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756, +756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756, +756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756, +756,756,756,120,120,120,120,120,120,120,757,757,757,757,757,757, /* block 161 */ -757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757, -757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757, -757,757,757,757,758,758,758,758,120,120,120,120,120,120,120,120, -759,759,759,759,759,759,759,759,759,759,120,120,120,120,120,120, +758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758, +758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758, +758,758,758,758,759,759,759,759,120,120,120,120,120,120,120,120, +760,760,760,760,760,760,760,760,760,760,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, @@ -3326,350 +3345,370 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760, -760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,120, +761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761, +761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,120, /* block 163 */ -761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761, -761,761,761,761,761,761,761,761,761,761,761,761,761,762,762,762, -762,762,762,762,762,762,762,761,120,120,120,120,120,120,120,120, -763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763, -763,763,763,763,763,763,764,764,764,764,764,764,764,764,764,764, -764,765,765,765,765,766,766,766,766,766,120,120,120,120,120,120, +762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762, +762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762, +762,762,762,762,762,762,762,762,762,762,120,763,763,764,120,120, +762,762,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 164 */ +765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765, +765,765,765,765,765,765,765,765,765,765,765,765,765,766,766,766, +766,766,766,766,766,766,766,765,120,120,120,120,120,120,120,120, +767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767, +767,767,767,767,767,767,768,768,768,768,768,768,768,768,768,768, +768,769,769,769,769,770,770,770,770,770,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, + +/* block 165 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771, +771,771,771,771,771,772,772,772,772,772,772,772,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767, -767,767,767,767,767,767,767,120,120,120,120,120,120,120,120,120, - -/* block 165 */ -768,769,768,770,770,770,770,770,770,770,770,770,770,770,770,770, -770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770, -770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770, -770,770,770,770,770,770,770,770,769,769,769,769,769,769,769,769, -769,769,769,769,769,769,769,771,771,771,771,771,771,771,120,120, -120,120,772,772,772,772,772,772,772,772,772,772,772,772,772,772, -772,772,772,772,772,772,773,773,773,773,773,773,773,773,773,773, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,769, +773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773, +773,773,773,773,773,773,773,120,120,120,120,120,120,120,120,120, /* block 166 */ -774,774,775,776,776,776,776,776,776,776,776,776,776,776,776,776, +774,775,774,776,776,776,776,776,776,776,776,776,776,776,776,776, 776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, 776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776, -775,775,775,774,774,774,774,775,775,774,774,777,777,778,777,777, -777,777,120,120,120,120,120,120,120,120,120,120,120,778,120,120, -779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779, -779,779,779,779,779,779,779,779,779,120,120,120,120,120,120,120, -780,780,780,780,780,780,780,780,780,780,120,120,120,120,120,120, +776,776,776,776,776,776,776,776,775,775,775,775,775,775,775,775, +775,775,775,775,775,775,775,777,777,777,777,777,777,777,120,120, +120,120,778,778,778,778,778,778,778,778,778,778,778,778,778,778, +778,778,778,778,778,778,779,779,779,779,779,779,779,779,779,779, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,775, /* block 167 */ -781,781,781,782,782,782,782,782,782,782,782,782,782,782,782,782, +780,780,781,782,782,782,782,782,782,782,782,782,782,782,782,782, 782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, -782,782,782,782,782,782,782,781,781,781,781,781,783,781,781,781, -781,781,781,781,781,120,784,784,784,784,784,784,784,784,784,784, -785,785,785,785,782,783,783,120,120,120,120,120,120,120,120,120, -786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786, -786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786, -786,786,786,787,788,788,786,120,120,120,120,120,120,120,120,120, +782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782, +781,781,781,780,780,780,780,781,781,780,780,783,783,784,783,783, +783,783,120,120,120,120,120,120,120,120,120,120,120,784,120,120, +785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785, +785,785,785,785,785,785,785,785,785,120,120,120,120,120,120,120, +786,786,786,786,786,786,786,786,786,786,120,120,120,120,120,120, /* block 168 */ -789,789,790,791,791,791,791,791,791,791,791,791,791,791,791,791, -791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791, -791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791, -791,791,791,790,790,790,789,789,789,789,789,789,789,789,789,790, -790,791,792,792,791,793,793,793,793,789,789,789,789,793,120,120, -794,794,794,794,794,794,794,794,794,794,791,793,791,793,793,793, -120,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795, -795,795,795,795,795,120,120,120,120,120,120,120,120,120,120,120, +787,787,787,788,788,788,788,788,788,788,788,788,788,788,788,788, +788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788, +788,788,788,788,788,788,788,787,787,787,787,787,789,787,787,787, +787,787,787,787,787,120,790,790,790,790,790,790,790,790,790,790, +791,791,791,791,788,789,789,788,120,120,120,120,120,120,120,120, +792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792, +792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792, +792,792,792,793,794,794,792,120,120,120,120,120,120,120,120,120, /* block 169 */ -796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796, -796,796,120,796,796,796,796,796,796,796,796,796,796,796,796,796, -796,796,796,796,796,796,796,796,796,796,796,796,797,797,797,798, -798,798,797,797,798,797,798,798,799,799,799,799,799,799,798,120, +795,795,796,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797, +797,797,797,796,796,796,795,795,795,795,795,795,795,795,795,796, +796,797,798,798,797,799,799,799,799,795,795,795,795,799,796,795, +800,800,800,800,800,800,800,800,800,800,797,799,797,799,799,799, +120,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801, +801,801,801,801,801,120,120,120,120,120,120,120,120,120,120,120, + +/* block 170 */ +802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802, +802,802,120,802,802,802,802,802,802,802,802,802,802,802,802,802, +802,802,802,802,802,802,802,802,802,802,802,802,803,803,803,804, +804,804,803,803,804,803,804,804,805,805,805,805,805,805,804,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 170 */ -800,800,800,800,800,800,800,120,800,120,800,800,800,800,120,800, -800,800,800,800,800,800,800,800,800,800,800,800,800,800,120,800, -800,800,800,800,800,800,800,800,800,801,120,120,120,120,120,120, -802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802, -802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802, -802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,803, -804,804,804,803,803,803,803,803,803,803,803,120,120,120,120,120, -805,805,805,805,805,805,805,805,805,805,120,120,120,120,120,120, - /* block 171 */ -806,807,808,809,120,810,810,810,810,810,810,810,810,120,120,810, -810,120,120,810,810,810,810,810,810,810,810,810,810,810,810,810, -810,810,810,810,810,810,810,810,810,120,810,810,810,810,810,810, -810,120,810,810,120,810,810,810,810,810,120,811,807,810,812,808, -806,808,808,808,808,120,120,808,808,120,120,808,808,808,120,120, -810,120,120,120,120,120,120,812,120,120,120,120,120,810,810,810, -810,810,808,808,120,120,806,806,806,806,806,806,806,120,120,120, -806,806,806,806,806,120,120,120,120,120,120,120,120,120,120,120, +806,806,806,806,806,806,806,120,806,120,806,806,806,806,120,806, +806,806,806,806,806,806,806,806,806,806,806,806,806,806,120,806, +806,806,806,806,806,806,806,806,806,807,120,120,120,120,120,120, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808, +808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,809, +810,810,810,809,809,809,809,809,809,809,809,120,120,120,120,120, +811,811,811,811,811,811,811,811,811,811,120,120,120,120,120,120, /* block 172 */ -813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813, -813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813, -813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813, -813,813,813,813,813,814,814,814,815,815,815,815,815,815,815,815, -814,814,815,815,815,814,815,813,813,813,813,816,816,816,816,816, -817,817,817,817,817,817,817,817,817,817,120,816,120,816,815,813, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +812,813,814,815,120,816,816,816,816,816,816,816,816,120,120,816, +816,120,120,816,816,816,816,816,816,816,816,816,816,816,816,816, +816,816,816,816,816,816,816,816,816,120,816,816,816,816,816,816, +816,120,816,816,120,816,816,816,816,816,120,817,813,816,818,814, +812,814,814,814,814,120,120,814,814,120,120,814,814,814,120,120, +816,120,120,120,120,120,120,818,120,120,120,120,120,816,816,816, +816,816,814,814,120,120,812,812,812,812,812,812,812,120,120,120, +812,812,812,812,812,120,120,120,120,120,120,120,120,120,120,120, /* block 173 */ -818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818, -818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818, -818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818, -819,820,820,821,821,821,821,821,821,820,821,820,820,819,820,821, -821,820,821,821,818,818,822,818,120,120,120,120,120,120,120,120, -823,823,823,823,823,823,823,823,823,823,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819, +819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819, +819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819, +819,819,819,819,819,820,820,820,821,821,821,821,821,821,821,821, +820,820,821,821,821,820,821,819,819,819,819,822,822,822,822,822, +823,823,823,823,823,823,823,823,823,823,822,822,120,822,821,819, +819,819,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 174 */ 824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824, 824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824, -824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,825, -826,826,827,827,827,827,120,120,826,826,826,826,827,827,826,827, -827,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828, -828,828,828,828,828,828,828,828,824,824,824,824,827,827,120,120, +824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824, +825,826,826,827,827,827,827,827,827,826,827,826,826,825,826,827, +827,826,827,827,824,824,828,824,120,120,120,120,120,120,120,120, +829,829,829,829,829,829,829,829,829,829,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 175 */ -829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829, -829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829, -829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829, -830,830,830,831,831,831,831,831,831,831,831,830,830,831,830,831, -831,832,832,832,829,120,120,120,120,120,120,120,120,120,120,120, -833,833,833,833,833,833,833,833,833,833,120,120,120,120,120,120, -395,395,395,395,395,395,395,395,395,395,395,395,395,120,120,120, +830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830, +830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830, +830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,831, +832,832,833,833,833,833,120,120,832,832,832,832,833,833,832,833, +833,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834, +834,834,834,834,834,834,834,834,830,830,830,830,833,833,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 176 */ -834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834, -834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834, -834,834,834,834,834,834,834,834,834,834,834,835,836,835,836,836, -835,835,835,835,835,835,836,835,834,120,120,120,120,120,120,120, -837,837,837,837,837,837,837,837,837,837,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835, +835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835, +835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835, +836,836,836,837,837,837,837,837,837,837,837,836,836,837,836,837, +837,838,838,838,835,120,120,120,120,120,120,120,120,120,120,120, +839,839,839,839,839,839,839,839,839,839,120,120,120,120,120,120, +394,394,394,394,394,394,394,394,394,394,394,394,394,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 177 */ -838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838, -838,838,838,838,838,838,838,838,838,838,838,120,120,839,839,839, -840,840,839,839,839,839,840,839,839,839,839,839,120,120,120,120, -841,841,841,841,841,841,841,841,841,841,842,842,843,843,843,844, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840, +840,840,840,840,840,840,840,840,840,840,840,841,842,841,842,842, +841,841,841,841,841,841,842,841,840,120,120,120,120,120,120,120, +843,843,843,843,843,843,843,843,843,843,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 178 */ -845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845, -845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845, -845,845,845,845,845,845,845,845,845,845,845,845,846,846,846,847, -847,847,847,847,847,847,847,847,846,847,847,848,120,120,120,120, +844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844, +844,844,844,844,844,844,844,844,844,844,844,120,120,845,845,845, +846,846,845,845,845,845,846,845,845,845,845,845,120,120,120,120, +847,847,847,847,847,847,847,847,847,847,848,848,849,849,849,850, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 179 */ +851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851, +851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851, +851,851,851,851,851,851,851,851,851,851,851,851,852,852,852,853, +853,853,853,853,853,853,853,853,852,853,853,854,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849, -849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849, -850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850, -850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850, -851,851,851,851,851,851,851,851,851,851,852,852,852,852,852,852, -852,852,852,120,120,120,120,120,120,120,120,120,120,120,120,853, /* block 180 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -854,854,854,854,854,854,854,854,120,120,854,854,854,854,854,854, -854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854, -854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854, -854,855,855,855,856,856,856,856,120,120,856,856,855,855,855,855, -856,854,857,854,855,120,120,120,120,120,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855, +855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855, +856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856, +856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856, +857,857,857,857,857,857,857,857,857,857,858,858,858,858,858,858, +858,858,858,120,120,120,120,120,120,120,120,120,120,120,120,859, /* block 181 */ -858,859,859,859,859,859,859,859,859,859,859,858,858,858,858,858, -858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858, -858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858, -858,858,858,859,859,859,859,859,859,860,861,859,859,859,859,862, -862,862,862,862,862,862,862,859,120,120,120,120,120,120,120,120, -863,864,864,864,864,864,864,865,865,864,864,864,863,863,863,863, -863,863,863,863,863,863,863,863,863,863,863,863,863,863,863,863, -863,863,863,863,863,863,863,863,863,863,863,863,863,863,863,863, +860,860,860,860,860,860,860,120,120,860,120,120,860,860,860,860, +860,860,860,860,120,860,860,120,860,860,860,860,860,860,860,860, +860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860, +861,862,862,862,862,862,120,862,862,120,120,863,863,862,863,864, +862,864,862,863,865,865,865,120,120,120,120,120,120,120,120,120, +866,866,866,866,866,866,866,866,866,866,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 182 */ -863,863,863,863,866,866,866,866,866,866,864,864,864,864,864,864, -864,864,864,864,864,864,864,865,864,864,867,867,867,863,867,867, -867,867,867,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -868,868,868,868,868,868,868,868,868,868,868,868,868,868,868,868, -868,868,868,868,868,868,868,868,868,868,868,868,868,868,868,868, -868,868,868,868,868,868,868,868,868,868,868,868,868,868,868,868, -868,868,868,868,868,868,868,868,868,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +867,867,867,867,867,867,867,867,120,120,867,867,867,867,867,867, +867,867,867,867,867,867,867,867,867,867,867,867,867,867,867,867, +867,867,867,867,867,867,867,867,867,867,867,867,867,867,867,867, +867,868,868,868,869,869,869,869,120,120,869,869,868,868,868,868, +869,867,870,867,868,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 183 */ -869,869,869,869,869,869,869,869,869,120,869,869,869,869,869,869, -869,869,869,869,869,869,869,869,869,869,869,869,869,869,869,869, -869,869,869,869,869,869,869,869,869,869,869,869,869,869,869,870, -871,871,871,871,871,871,871,120,871,871,871,871,871,871,870,871, -869,872,872,872,872,872,120,120,120,120,120,120,120,120,120,120, -873,873,873,873,873,873,873,873,873,873,874,874,874,874,874,874, -874,874,874,874,874,874,874,874,874,874,874,874,874,120,120,120, -875,875,876,876,876,876,876,876,876,876,876,876,876,876,876,876, +871,872,872,872,872,872,872,872,872,872,872,871,871,871,871,871, +871,871,871,871,871,871,871,871,871,871,871,871,871,871,871,871, +871,871,871,871,871,871,871,871,871,871,871,871,871,871,871,871, +871,871,871,872,872,872,872,872,872,873,874,872,872,872,872,875, +875,875,875,875,875,875,875,872,120,120,120,120,120,120,120,120, +876,877,877,877,877,877,877,878,878,877,877,877,876,876,876,876, +876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876, +876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876, /* block 184 */ -876,876,876,876,876,876,876,876,876,876,876,876,876,876,876,876, -120,120,877,877,877,877,877,877,877,877,877,877,877,877,877,877, -877,877,877,877,877,877,877,877,120,878,877,877,877,877,877,877, -877,878,877,877,878,877,877,120,120,120,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +876,876,876,876,879,879,879,879,879,879,877,877,877,877,877,877, +877,877,877,877,877,877,877,878,877,877,880,880,880,876,880,880, +880,880,880,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,881, +881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,881, +881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,881, +881,881,881,881,881,881,881,881,881,120,120,120,120,120,120,120, /* block 185 */ -879,879,879,879,879,879,879,120,879,879,120,879,879,879,879,879, -879,879,879,879,879,879,879,879,879,879,879,879,879,879,879,879, -879,879,879,879,879,879,879,879,879,879,879,879,879,879,879,879, -879,880,880,880,880,880,880,120,120,120,880,120,880,880,120,880, -880,880,880,880,880,880,881,880,120,120,120,120,120,120,120,120, -882,882,882,882,882,882,882,882,882,882,120,120,120,120,120,120, -883,883,883,883,883,883,120,883,883,120,883,883,883,883,883,883, -883,883,883,883,883,883,883,883,883,883,883,883,883,883,883,883, +882,882,882,882,882,882,882,882,882,120,882,882,882,882,882,882, +882,882,882,882,882,882,882,882,882,882,882,882,882,882,882,882, +882,882,882,882,882,882,882,882,882,882,882,882,882,882,882,883, +884,884,884,884,884,884,884,120,884,884,884,884,884,884,883,884, +882,885,885,885,885,885,120,120,120,120,120,120,120,120,120,120, +886,886,886,886,886,886,886,886,886,886,887,887,887,887,887,887, +887,887,887,887,887,887,887,887,887,887,887,887,887,120,120,120, +888,888,889,889,889,889,889,889,889,889,889,889,889,889,889,889, /* block 186 */ -883,883,883,883,883,883,883,883,883,883,884,884,884,884,884,120, -885,885,120,884,884,885,884,885,883,120,120,120,120,120,120,120, -886,886,886,886,886,886,886,886,886,886,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +889,889,889,889,889,889,889,889,889,889,889,889,889,889,889,889, +120,120,890,890,890,890,890,890,890,890,890,890,890,890,890,890, +890,890,890,890,890,890,890,890,120,891,890,890,890,890,890,890, +890,891,890,890,891,890,890,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 187 */ +892,892,892,892,892,892,892,120,892,892,120,892,892,892,892,892, +892,892,892,892,892,892,892,892,892,892,892,892,892,892,892,892, +892,892,892,892,892,892,892,892,892,892,892,892,892,892,892,892, +892,893,893,893,893,893,893,120,120,120,893,120,893,893,120,893, +893,893,893,893,893,893,894,893,120,120,120,120,120,120,120,120, +895,895,895,895,895,895,895,895,895,895,120,120,120,120,120,120, +896,896,896,896,896,896,120,896,896,120,896,896,896,896,896,896, +896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, + +/* block 188 */ +896,896,896,896,896,896,896,896,896,896,897,897,897,897,897,120, +898,898,120,897,897,898,897,898,896,120,120,120,120,120,120,120, +899,899,899,899,899,899,899,899,899,899,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -887,887,887,887,887,887,887,887,887,887,887,887,887,887,887,887, -887,887,887,888,888,889,889,890,890,120,120,120,120,120,120,120, -/* block 188 */ -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +/* block 189 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891, -294,294,891,294,891,296,296,296,296,296,296,296,296,297,297,297, -297,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296, -296,296,120,120,120,120,120,120,120,120,120,120,120,120,120,892, - -/* block 189 */ -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, - -/* block 190 */ -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,893,893,893,893,893,893,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +900,900,900,900,900,900,900,900,900,900,900,900,900,900,900,900, +900,900,900,901,901,902,902,903,903,120,120,120,120,120,120,120, + +/* block 190 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +590,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +904,904,904,904,904,904,904,904,904,904,904,904,904,904,904,904, +293,293,904,293,904,295,295,295,295,295,295,295,295,296,296,296, +296,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295, +295,295,120,120,120,120,120,120,120,120,120,120,120,120,120,905, /* block 191 */ -894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894, -894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894, -894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894, -894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894, -894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894, -894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,894, -894,894,894,894,894,894,894,894,894,894,894,894,894,894,894,120, -895,895,895,895,895,120,120,120,120,120,120,120,120,120,120,120, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, /* block 192 */ -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,893,893,893,893,893,893,893,893,893,893,893,893, -893,893,893,893,120,120,120,120,120,120,120,120,120,120,120,120, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,906,906,906,906,906,906,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 193 */ -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, +907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907, +907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907, +907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907, +907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907, +907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907, +907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907, +907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,120, +908,908,908,908,908,120,120,120,120,120,120,120,120,120,120,120, /* block 194 */ -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896, -896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,120, -897,897,897,897,897,897,897,897,897,120,120,120,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,906,906,906,906,906,906,906,906,906,906,906,906, +906,906,906,906,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 195 */ -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, +909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, +909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, +909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, +909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, +909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, +909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, +909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, +909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, /* block 196 */ -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, -898,898,898,898,898,898,898,898,898,898,898,898,898,898,898,898, -898,898,898,898,898,898,898,120,120,120,120,120,120,120,120,120, +909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, +909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,909, +909,909,909,909,909,909,909,909,909,909,909,909,909,909,909,120, +910,910,910,910,910,910,910,910,910,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 197 */ +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, + +/* block 198 */ +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911, +911,911,911,911,911,911,911,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, + +/* block 199 */ 601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, 601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, 601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, @@ -3679,38 +3718,38 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, 601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, -/* block 198 */ +/* block 200 */ 601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, 601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, 601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601, 601,601,601,601,601,601,601,601,601,120,120,120,120,120,120,120, -899,899,899,899,899,899,899,899,899,899,899,899,899,899,899,899, -899,899,899,899,899,899,899,899,899,899,899,899,899,899,899,120, -900,900,900,900,900,900,900,900,900,900,120,120,120,120,901,901, +912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912, +912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,120, +913,913,913,913,913,913,913,913,913,913,120,120,120,120,914,914, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 199 */ +/* block 201 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -902,902,902,902,902,902,902,902,902,902,902,902,902,902,902,902, -902,902,902,902,902,902,902,902,902,902,902,902,902,902,120,120, -903,903,903,903,903,904,120,120,120,120,120,120,120,120,120,120, +915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915, +915,915,915,915,915,915,915,915,915,915,915,915,915,915,120,120, +916,916,916,916,916,917,120,120,120,120,120,120,120,120,120,120, -/* block 200 */ -905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905, -905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905, -905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905, -906,906,906,906,906,906,906,907,907,907,907,907,908,908,908,908, -909,909,909,909,907,908,120,120,120,120,120,120,120,120,120,120, -910,910,910,910,910,910,910,910,910,910,120,911,911,911,911,911, -911,911,120,905,905,905,905,905,905,905,905,905,905,905,905,905, -905,905,905,905,905,905,905,905,120,120,120,120,120,905,905,905, +/* block 202 */ +918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, +918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, +918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, +919,919,919,919,919,919,919,920,920,920,920,920,921,921,921,921, +922,922,922,922,920,921,120,120,120,120,120,120,120,120,120,120, +923,923,923,923,923,923,923,923,923,923,120,924,924,924,924,924, +924,924,120,918,918,918,918,918,918,918,918,918,918,918,918,918, +918,918,918,918,918,918,918,918,120,120,120,120,120,918,918,918, -/* block 201 */ -905,905,905,905,905,905,905,905,905,905,905,905,905,905,905,905, +/* block 203 */ +918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, @@ -3719,19 +3758,19 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 202 */ +/* block 204 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912, -912,912,912,912,912,912,912,912,912,912,912,912,912,912,912,912, -913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,913, -913,913,913,913,913,913,913,913,913,913,913,913,913,913,913,913, +925,925,925,925,925,925,925,925,925,925,925,925,925,925,925,925, +925,925,925,925,925,925,925,925,925,925,925,925,925,925,925,925, +926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926, +926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926, -/* block 203 */ -914,914,914,914,914,914,914,914,914,914,914,914,914,914,914,914, -914,914,914,914,914,914,914,915,915,915,915,120,120,120,120,120, +/* block 205 */ +927,927,927,927,927,927,927,927,927,927,927,927,927,927,927,927, +927,927,927,927,927,927,927,928,928,928,928,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, @@ -3739,57 +3778,77 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 204 */ -916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,916, -916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,916, -916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,916, -916,916,916,916,916,916,916,916,916,916,916,916,916,916,916,916, -916,916,916,916,916,916,916,916,916,916,916,120,120,120,120,917, -916,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, -918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, -918,918,918,918,918,918,918,918,918,918,918,918,918,918,918,918, +/* block 206 */ +929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, +929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, +929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, +929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929, +929,929,929,929,929,929,929,929,929,929,929,120,120,120,120,930, +929,931,931,931,931,931,931,931,931,931,931,931,931,931,931,931, +931,931,931,931,931,931,931,931,931,931,931,931,931,931,931,931, +931,931,931,931,931,931,931,931,931,931,931,931,931,931,931,931, -/* block 205 */ -918,918,918,918,918,918,918,918,120,120,120,120,120,120,120,917, -917,917,917,919,919,919,919,919,919,919,919,919,919,919,919,919, -120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +/* block 207 */ +931,931,931,931,931,931,931,931,120,120,120,120,120,120,120,930, +930,930,930,932,932,932,932,932,932,932,932,932,932,932,932,932, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -920,921, 5,111,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, - -/* block 206 */ -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, - -/* block 207 */ -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,120,120,120,120,120,120,120,120, +933,934, 5,111,935,120,120,120,120,120,120,120,120,120,120,120, +936,936,120,120,120,120,120,120,120,120,120,120,120,120,120,120, /* block 208 */ -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922, -922,922,922,120,120,120,120,120,120,120,120,120,120,120,120,120, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, /* block 209 */ +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937, +937,937,937,937,937,937,937,937,120,120,120,120,120,120,120,120, + +/* block 210 */ +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, + +/* block 211 */ +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938, +938,938,938,938,938,938,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, + +/* block 212 */ +937,937,937,937,937,937,937,937,937,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, + +/* block 213 */ 578,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, 573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, 573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, @@ -3799,7 +3858,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, 573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, -/* block 210 */ +/* block 214 */ 573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, 573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, 573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, @@ -3809,7 +3868,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, 573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, -/* block 211 */ +/* block 215 */ 573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573, 573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, @@ -3817,49 +3876,49 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 573,573,573,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,578,578,578,578,120,120,120,120,120,120,120,120, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, -/* block 212 */ -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, +/* block 216 */ +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, -/* block 213 */ -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,923,923,923,923, -923,923,923,923,923,923,923,923,923,923,923,923,120,120,120,120, +/* block 217 */ +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,939,939,939,939, +939,939,939,939,939,939,939,939,939,939,939,939,120,120,120,120, -/* block 214 */ -924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924, -924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924, -924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924, -924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924, -924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924, -924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924, -924,924,924,924,924,924,924,924,924,924,924,120,120,120,120,120, -924,924,924,924,924,924,924,924,924,924,924,924,924,120,120,120, +/* block 218 */ +940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940, +940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940, +940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940, +940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940, +940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940, +940,940,940,940,940,940,940,940,940,940,940,940,940,940,940,940, +940,940,940,940,940,940,940,940,940,940,940,120,120,120,120,120, +940,940,940,940,940,940,940,940,940,940,940,940,940,120,120,120, -/* block 215 */ -924,924,924,924,924,924,924,924,924,120,120,120,120,120,120,120, -924,924,924,924,924,924,924,924,924,924,120,120,925,926,926,927, -928,928,928,928,120,120,120,120,120,120,120,120,120,120,120,120, +/* block 219 */ +940,940,940,940,940,940,940,940,940,120,120,120,120,120,120,120, +940,940,940,940,940,940,940,940,940,940,120,120,941,942,942,943, +944,944,944,944,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 216 */ +/* block 220 */ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, @@ -3869,17 +3928,17 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,120,120,120, -/* block 217 */ +/* block 221 */ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20,929,930,113,113,113, 20, 20, 20,930,929,929, -929,929,929, 24, 24, 24, 24, 24, 24, 24, 24,113,113,113,113,113, + 20, 20, 20, 20, 20,945,946,113,113,113, 20, 20, 20,946,945,945, +945,945,945, 24, 24, 24, 24, 24, 24, 24, 24,113,113,113,113,113, -/* block 218 */ +/* block 222 */ 113,113,113, 20, 20,113,113,113,113,113,113,113, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,113,113,113,113, 20, 20, @@ -3889,17 +3948,17 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 219 */ -684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, -684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, -684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, -684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684, -684,684,931,931,931,684,120,120,120,120,120,120,120,120,120,120, +/* block 223 */ +685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, +685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, +685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, +685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685, +685,685,947,947,947,685,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 220 */ +/* block 224 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, @@ -3909,7 +3968,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 221 */ +/* block 225 */ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, @@ -3919,7 +3978,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582, 582,582, 25, 25, 25, 25, 25, 25, 25,120,120,120,120,120,120,120, -/* block 222 */ +/* block 226 */ 513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, 513,513,513,513,513,513,513,513,513,513,514,514,514,514,514,514, 514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, @@ -3929,7 +3988,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 514,514,514,514,514,514,514,514,513,513,513,513,513,513,513,513, 513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, -/* block 223 */ +/* block 227 */ 513,513,514,514,514,514,514,514,514,514,514,514,514,514,514,514, 514,514,514,514,514,514,514,514,514,514,514,514,513,120,513,513, 120,120,513,120,120,513,513,120,120,513,513,513,513,120,513,513, @@ -3939,7 +3998,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 513,513,513,513,513,513,513,513,513,513,514,514,514,514,514,514, 514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, -/* block 224 */ +/* block 228 */ 514,514,514,514,513,513,120,513,513,513,513,120,120,513,513,513, 513,513,513,513,513,120,513,513,513,513,513,513,513,120,514,514, 514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, @@ -3949,7 +4008,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 514,514,514,514,514,514,514,514,514,514,514,514,513,513,513,513, 513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, -/* block 225 */ +/* block 229 */ 513,513,513,513,513,513,514,514,514,514,514,514,514,514,514,514, 514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, 513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, @@ -3959,7 +4018,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 513,513,513,513,513,513,513,513,513,513,513,513,513,513,514,514, 514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, -/* block 226 */ +/* block 230 */ 514,514,514,514,514,514,514,514,513,513,513,513,513,513,513,513, 513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, 513,513,514,514,514,514,514,514,514,514,514,514,514,514,514,514, @@ -3969,7 +4028,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, 513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, -/* block 227 */ +/* block 231 */ 513,513,513,513,513,513,513,513,513,513,514,514,514,514,514,514, 514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, 514,514,514,514,514,514,120,120,513,513,513,513,513,513,513,513, @@ -3979,7 +4038,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 514,514,513,513,513,513,513,513,513,513,513,513,513,513,513,513, 513,513,513,513,513,513,513,513,513,513,513, 9,514,514,514,514, -/* block 228 */ +/* block 232 */ 514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, 514,514,514,514,514, 9,514,514,514,514,514,514,513,513,513,513, 513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, @@ -3989,7 +4048,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, 9, 514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514, -/* block 229 */ +/* block 233 */ 514,514,514,514,514,514,514,514,514, 9,514,514,514,514,514,514, 513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513, 513,513,513,513,513,513,513,513,513, 9,514,514,514,514,514,514, @@ -3999,97 +4058,97 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -/* block 230 */ -932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932, -932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932, -932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932, -932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932, -932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932, -932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932, -932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932, -932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932, +/* block 234 */ +948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948, +948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948, +948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948, +948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948, +948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948, +948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948, +948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948, +948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948, -/* block 231 */ -933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933, -933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933, -933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933, -933,933,933,933,933,933,933,932,932,932,932,933,933,933,933,933, -933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933, -933,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933, -933,933,933,933,933,933,933,933,933,933,933,933,933,932,932,932, -932,932,932,932,932,933,932,932,932,932,932,932,932,932,932,932, +/* block 235 */ +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,948,948,948,948,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, +949,949,949,949,949,949,949,949,949,949,949,949,949,948,948,948, +948,948,948,948,948,949,948,948,948,948,948,948,948,948,948,948, -/* block 232 */ -932,932,932,932,933,932,932,934,934,934,934,934,120,120,120,120, -120,120,120,120,120,120,120,120,120,120,120,933,933,933,933,933, -120,933,933,933,933,933,933,933,933,933,933,933,933,933,933,933, +/* block 236 */ +948,948,948,948,949,948,948,950,950,950,950,950,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,949,949,949,949,949, +120,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 233 */ -935,935,935,935,935,935,935,120,935,935,935,935,935,935,935,935, -935,935,935,935,935,935,935,935,935,120,120,935,935,935,935,935, -935,935,120,935,935,120,935,935,935,935,935,120,120,120,120,120, +/* block 237 */ +951,951,951,951,951,951,951,120,951,951,951,951,951,951,951,951, +951,951,951,951,951,951,951,951,951,120,120,951,951,951,951,951, +951,951,120,951,951,120,951,951,951,951,951,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 234 */ -936,936,936,936,936,936,936,936,936,936,936,936,936,936,936,936, -936,936,936,936,936,936,936,936,936,936,936,936,936,936,936,936, -936,936,936,936,936,936,936,936,936,936,936,936,936,120,120,120, -937,937,937,937,937,937,937,938,938,938,938,938,938,938,120,120, -939,939,939,939,939,939,939,939,939,939,120,120,120,120,936,940, +/* block 238 */ +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952, +952,952,952,952,952,952,952,952,952,952,952,952,952,120,120,120, +953,953,953,953,953,953,953,954,954,954,954,954,954,954,120,120, +955,955,955,955,955,955,955,955,955,955,120,120,120,120,952,956, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 235 */ +/* block 239 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -941,941,941,941,941,941,941,941,941,941,941,941,941,941,941,941, -941,941,941,941,941,941,941,941,941,941,941,941,941,941,941,941, -941,941,941,941,941,941,941,941,941,941,941,941,942,942,942,942, -943,943,943,943,943,943,943,943,943,943,120,120,120,120,120,944, +957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957, +957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957, +957,957,957,957,957,957,957,957,957,957,957,957,958,958,958,958, +959,959,959,959,959,959,959,959,959,959,120,120,120,120,120,960, -/* block 236 */ -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, +/* block 240 */ +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, -/* block 237 */ -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, -945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945, -945,945,945,945,945,120,120,946,946,946,946,946,946,946,946,946, -947,947,947,947,947,947,947,120,120,120,120,120,120,120,120,120, +/* block 241 */ +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, +961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961, +961,961,961,961,961,120,120,962,962,962,962,962,962,962,962,962, +963,963,963,963,963,963,963,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 238 */ -948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948, -948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948, -948,948,949,949,949,949,949,949,949,949,949,949,949,949,949,949, -949,949,949,949,949,949,949,949,949,949,949,949,949,949,949,949, -949,949,949,949,950,950,950,950,950,950,950,951,120,120,120,120, -952,952,952,952,952,952,952,952,952,952,120,120,120,120,953,953, +/* block 242 */ +964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,964, +964,964,964,964,964,964,964,964,964,964,964,964,964,964,964,964, +964,964,965,965,965,965,965,965,965,965,965,965,965,965,965,965, +965,965,965,965,965,965,965,965,965,965,965,965,965,965,965,965, +965,965,965,965,966,966,966,966,966,966,966,967,120,120,120,120, +968,968,968,968,968,968,968,968,968,968,120,120,120,120,969,969, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 239 */ +/* block 243 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, @@ -4099,7 +4158,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -/* block 240 */ +/* block 244 */ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 25, 25, 25, @@ -4109,7 +4168,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 241 */ +/* block 245 */ 120, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 25, @@ -4119,87 +4178,87 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 242 */ -225,225,225,225,120,225,225,225,225,225,225,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225, -120,225,225,120,225,120,120,225,120,225,225,225,225,225,225,225, -225,225,225,120,225,225,225,225,120,225,120,225,120,120,120,120, -120,120,225,120,120,120,120,225,120,225,120,225,120,225,225,225, -120,225,225,120,225,120,120,225,120,225,120,225,120,225,120,225, -120,225,225,120,225,120,120,225,225,225,225,120,225,225,225,225, -225,225,225,120,225,225,225,225,120,225,225,225,225,120,225,120, +/* block 246 */ +224,224,224,224,120,224,224,224,224,224,224,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224, +120,224,224,120,224,120,120,224,120,224,224,224,224,224,224,224, +224,224,224,120,224,224,224,224,120,224,120,224,120,120,120,120, +120,120,224,120,120,120,120,224,120,224,120,224,120,224,224,224, +120,224,224,120,224,120,120,224,120,224,120,224,120,224,120,224, +120,224,224,120,224,120,120,224,224,224,224,120,224,224,224,224, +224,224,224,120,224,224,224,224,120,224,224,224,224,120,224,120, -/* block 243 */ -225,225,225,225,225,225,225,225,225,225,120,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,120,120,120,120, -120,225,225,225,120,225,225,225,225,225,120,225,225,225,225,225, -225,225,225,225,225,225,225,225,225,225,225,225,120,120,120,120, +/* block 247 */ +224,224,224,224,224,224,224,224,224,224,120,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,120,120,120,120, +120,224,224,224,120,224,224,224,224,224,120,224,224,224,224,224, +224,224,224,224,224,224,224,224,224,224,224,224,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -218,218,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +217,217,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 244 */ +/* block 248 */ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954,954,954, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970,970,970, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, -/* block 245 */ +/* block 249 */ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954,954,954, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954, -954, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, -954, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, -954, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21,970,970,970,970,970,970,970,970,970,970,970,970, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970, +970, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, +970, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, +970, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954, + 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970,970,970, -/* block 246 */ - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,954,954,954, +/* block 250 */ + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 21, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,954,954,954, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, -/* block 247 */ +/* block 251 */ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,955,955,955,955,955,955,955,955,955,955, -955,955,955,955,955,955,955,955,955,955,955,955,955,955,955,955, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,971,971,971,971,971,971,971,971,971,971, +971,971,971,971,971,971,971,971,971,971,971,971,971,971,971,971, -/* block 248 */ -956, 21, 21,954,954,954,954,954,954,954,954,954,954,954,954,954, +/* block 252 */ +972, 21, 21,970,970,970,970,970,970,970,970,970,970,970,970,970, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, - 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20,954,954,954,954, - 20, 20, 20, 20, 20, 20, 20, 20, 20,954,954,954,954,954,954,954, -584,584,954,954,954,954,954,954,954,954,954,954,954,954,954,954, - 21, 21, 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, + 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20,970,970,970,970, + 20, 20, 20, 20, 20, 20, 20, 20, 20,970,970,970,970,970,970,970, +584,584,970,970,970,970,970,970,970,970,970,970,970,970,970,970, + 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, -/* block 249 */ -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, +/* block 253 */ +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, -/* block 250 */ +/* block 254 */ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, @@ -4209,7 +4268,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, -/* block 251 */ +/* block 255 */ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, @@ -4217,9 +4276,9 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,957,957,957,957,957, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,973,973,973,973,973, -/* block 252 */ +/* block 256 */ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, @@ -4229,7 +4288,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, -/* block 253 */ +/* block 257 */ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, @@ -4239,17 +4298,17 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -/* block 254 */ +/* block 258 */ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954,954, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954,954,954,954, + 21, 21, 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970,970, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970,970, -/* block 255 */ +/* block 259 */ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, @@ -4257,99 +4316,109 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20,954,954,954,954,954,954,954,954,954,954,954,954, + 20, 20, 20, 20,970,970,970,970,970,970,970,970,970,970,970,970, -/* block 256 */ +/* block 260 */ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 21, 21, 21, 21,954,954,954,954,954,954,954, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, + 20, 20, 20, 20, 20, 21, 21, 21, 21,970,970,970,970,970,970,970, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, -/* block 257 */ - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,954,954,954,954, +/* block 261 */ + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,970,970,970,970, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20,954,954,954,954,954,954,954,954, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,954,954,954,954,954,954, + 20, 20, 20, 20, 20, 20, 20, 20,970,970,970,970,970,970,970,970, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,970,970,970,970,970,970, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -/* block 258 */ - 20, 20, 20, 20, 20, 20, 20, 20,954,954,954,954,954,954,954,954, +/* block 262 */ + 20, 20, 20, 20, 20, 20, 20, 20,970,970,970,970,970,970,970,970, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,970,970, + 21, 21,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, -/* block 259 */ - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,954, 21, 21, 21, +/* block 263 */ + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21,954, 21, 21, 21, 21,954,954,954, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21,970, 21, 21, 21, 21, 21, 21, -/* block 260 */ +/* block 264 */ + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21,954,954, 21, 21, 21, 21, 21, 21,954,954,954, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, -/* block 261 */ +/* block 265 */ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954,954,954, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,954,954, - 21, 21, 21, 21,954,954,954,954, 21, 21, 21,954,954,954,954,954, + 21, 21, 21, 21,970,970,970,970,970,970,970,970,970,970,970,970, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970, + 21, 21, 21, 21, 21,970,970,970, 21, 21, 21,970,970,970,970,970, -/* block 262 */ - 21, 21, 21,954,954,954,954,954,954,954,954,954,954,954,954,954, - 21, 21, 21, 21, 21, 21,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, +/* block 266 */ + 21, 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970,970, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970, + 21, 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970,970, + 21, 21, 21,970,970,970,970,970,970,970,970,970,970,970,970,970, + 21, 21, 21, 21, 21, 21, 21,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, -/* block 263 */ -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,954,954, -954,954,954,954,954,954,954,954,954,954,954,954,954,954,120,120, +/* block 267 */ + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20,120, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,120,120,120,120,120,120, -/* block 264 */ +/* block 268 */ +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,970,970, +970,970,970,970,970,970,970,970,970,970,970,970,970,970,120,120, + +/* block 269 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -586,586,586,586,586,586,586,120,120,120,120,120,120,120,120,120, +586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 265 */ +/* block 270 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, @@ -4359,7 +4428,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -/* block 266 */ +/* block 271 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,120, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, @@ -4369,7 +4438,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -/* block 267 */ +/* block 272 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,120,120,120,120,120,120,120,120,120,120,120,120,120,120, @@ -4379,7 +4448,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, -/* block 268 */ +/* block 273 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, @@ -4389,7 +4458,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 586,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 269 */ +/* block 274 */ 586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, 586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, @@ -4399,17 +4468,27 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, 120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, -/* block 270 */ +/* block 275 */ +586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, +586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, +586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, +586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586, +586,586,586,586,586,586,586,586,586,586,586,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, +120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120, + +/* block 276 */ 511, 24,511,511,511,511,511,511,511,511,511,511,511,511,511,511, 511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, -958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958, -958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958, -958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958, -958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958, -958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958, -958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958, - -/* block 271 */ +974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974, +974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974, +974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974, +974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974, +974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974, +974,974,974,974,974,974,974,974,974,974,974,974,974,974,974,974, + +/* block 277 */ 511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, 511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, 511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, @@ -4419,7 +4498,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, 511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, -/* block 272 */ +/* block 278 */ 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, @@ -4429,7 +4508,7 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, -/* block 273 */ +/* block 279 */ 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, @@ -4439,15 +4518,15 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 70400 bytes, block = 128 */ 113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113, 511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511, -/* block 274 */ -672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, -672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, -672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, -672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, -672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, -672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, -672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672, -672,672,672,672,672,672,672,672,672,672,672,672,672,672,120,120, +/* block 280 */ +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673, +673,673,673,673,673,673,673,673,673,673,673,673,673,673,120,120, }; diff --git a/thirdparty/pcre2/src/pcre2_ucp.h b/thirdparty/pcre2/src/pcre2_ucp.h index 84b22fb064..9538062c71 100644 --- a/thirdparty/pcre2/src/pcre2_ucp.h +++ b/thirdparty/pcre2/src/pcre2_ucp.h @@ -286,7 +286,12 @@ enum { ucp_Elymaic, ucp_Nandinagari, ucp_Nyiakeng_Puachue_Hmong, - ucp_Wancho + ucp_Wancho, + /* New for Unicode 13.0.0 */ + ucp_Chorasmian, + ucp_Dives_Akuru, + ucp_Khitan_Small_Script, + ucp_Yezidi }; #endif /* PCRE2_UCP_H_IDEMPOTENT_GUARD */ diff --git a/thirdparty/pcre2/src/pcre2_valid_utf.c b/thirdparty/pcre2/src/pcre2_valid_utf.c index 96e8bff993..e47ea78f16 100644 --- a/thirdparty/pcre2/src/pcre2_valid_utf.c +++ b/thirdparty/pcre2/src/pcre2_valid_utf.c @@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language. Written by Philip Hazel Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016-2017 University of Cambridge + New API code Copyright (c) 2016-2020 University of Cambridge ----------------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without @@ -347,7 +347,7 @@ for (p = string; length > 0; p++) length--; if ((*p & 0xfc00) != 0xdc00) { - *erroroffset = p - string; + *erroroffset = p - string - 1; return PCRE2_ERROR_UTF16_ERR2; } } diff --git a/thirdparty/pcre2/src/sljit/sljitConfig.h b/thirdparty/pcre2/src/sljit/sljitConfig.h index d54b5e6f54..1c821d287d 100644 --- a/thirdparty/pcre2/src/sljit/sljitConfig.h +++ b/thirdparty/pcre2/src/sljit/sljitConfig.h @@ -24,15 +24,19 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _SLJIT_CONFIG_H_ -#define _SLJIT_CONFIG_H_ +#ifndef SLJIT_CONFIG_H_ +#define SLJIT_CONFIG_H_ -/* --------------------------------------------------------------------- */ -/* Custom defines */ -/* --------------------------------------------------------------------- */ +#ifdef __cplusplus +extern "C" { +#endif -/* Put your custom defines here. This empty section will never change - which helps maintaining patches (with diff / patch utilities). */ +/* + This file contains the basic configuration options for the SLJIT compiler + and their default values. These options can be overridden in the + sljitConfigPre.h header file when SLJIT_HAVE_CONFIG_PRE is set to a + non-zero value. +*/ /* --------------------------------------------------------------------- */ /* Architecture */ @@ -50,7 +54,7 @@ /* #define SLJIT_CONFIG_MIPS_32 1 */ /* #define SLJIT_CONFIG_MIPS_64 1 */ /* #define SLJIT_CONFIG_SPARC_32 1 */ -/* #define SLJIT_CONFIG_TILEGX 1 */ +/* #define SLJIT_CONFIG_S390X 1 */ /* #define SLJIT_CONFIG_AUTO 1 */ /* #define SLJIT_CONFIG_UNSUPPORTED 1 */ @@ -59,18 +63,19 @@ /* Utilities */ /* --------------------------------------------------------------------- */ -/* Useful for thread-safe compiling of global functions. */ -#ifndef SLJIT_UTIL_GLOBAL_LOCK -/* Enabled by default */ -#define SLJIT_UTIL_GLOBAL_LOCK 1 -#endif - -/* Implements a stack like data structure (by using mmap / VirtualAlloc). */ +/* Implements a stack like data structure (by using mmap / VirtualAlloc */ +/* or a custom allocator). */ #ifndef SLJIT_UTIL_STACK /* Enabled by default */ #define SLJIT_UTIL_STACK 1 #endif +/* Uses user provided allocator to allocate the stack (see SLJIT_UTIL_STACK) */ +#ifndef SLJIT_UTIL_SIMPLE_STACK_ALLOCATION +/* Disabled by default */ +#define SLJIT_UTIL_SIMPLE_STACK_ALLOCATION 0 +#endif + /* Single threaded application. Does not require any locks. */ #ifndef SLJIT_SINGLE_THREADED /* Disabled by default. */ @@ -97,15 +102,31 @@ /* When SLJIT_PROT_EXECUTABLE_ALLOCATOR is enabled SLJIT uses an allocator which does not set writable and executable - permission flags at the same time. The trade-of is increased - memory consumption and disabled dynamic code modifications. */ + permission flags at the same time. + Instead, it creates a shared memory segment (usually backed by a file) + and maps it twice, with different permissions, depending on the use + case. + The trade-off is increased use of virtual memory, incompatibility with + fork(), and some possible additional security risks by the use of + publicly accessible files for the generated code. */ #ifndef SLJIT_PROT_EXECUTABLE_ALLOCATOR /* Disabled by default. */ #define SLJIT_PROT_EXECUTABLE_ALLOCATOR 0 #endif +/* When SLJIT_WX_EXECUTABLE_ALLOCATOR is enabled SLJIT uses an + allocator which does not set writable and executable permission + flags at the same time. + Instead, it creates a new independent map on each invocation and + switches permissions at the underlying pages as needed. + The trade-off is increased memory use and degraded performance. */ +#ifndef SLJIT_WX_EXECUTABLE_ALLOCATOR +/* Disabled by default. */ +#define SLJIT_WX_EXECUTABLE_ALLOCATOR 0 #endif +#endif /* !SLJIT_EXECUTABLE_ALLOCATOR */ + /* Force cdecl calling convention even if a better calling convention (e.g. fastcall) is supported by the C compiler. If this option is disabled (this is the default), functions @@ -144,4 +165,8 @@ /* For further configurations, see the beginning of sljitConfigInternal.h */ +#ifdef __cplusplus +} /* extern "C" */ #endif + +#endif /* SLJIT_CONFIG_H_ */ diff --git a/thirdparty/pcre2/src/sljit/sljitConfigInternal.h b/thirdparty/pcre2/src/sljit/sljitConfigInternal.h index acba9da4be..eb1132db30 100644 --- a/thirdparty/pcre2/src/sljit/sljitConfigInternal.h +++ b/thirdparty/pcre2/src/sljit/sljitConfigInternal.h @@ -24,8 +24,22 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _SLJIT_CONFIG_INTERNAL_H_ -#define _SLJIT_CONFIG_INTERNAL_H_ +#ifndef SLJIT_CONFIG_INTERNAL_H_ +#define SLJIT_CONFIG_INTERNAL_H_ + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_DEBUG && SLJIT_DEBUG && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE))) +#include <stdio.h> +#endif + +#if (defined SLJIT_DEBUG && SLJIT_DEBUG \ + && (!defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) || !defined(SLJIT_HALT_PROCESS))) +#include <stdlib.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* SLJIT defines the following architecture dependent types and macros: @@ -67,30 +81,13 @@ Other macros: 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 (compiler independent helper) + SLJIT_W(number) : defining 64 bit constants on 64 bit architectures (platform independent helper) */ /*****************/ /* Sanity check. */ /*****************/ -#if !((defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ - || (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ - || (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \ - || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ - || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ - || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ - || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ - || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ - || (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ - || (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ - || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ - || (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \ - || (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \ - || (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)) -#error "An architecture must be selected" -#endif - #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ + (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \ @@ -99,15 +96,36 @@ + (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ + (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ + (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ - + (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) \ + (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ + (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ + (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ + + (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ + (defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) \ + (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) >= 2 #error "Multiple architectures are selected" #endif +#if !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) \ + && !(defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) \ + && !(defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) \ + && !(defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) \ + && !(defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ + && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ + && !(defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ + && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ + && !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \ + && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ + && !(defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ + && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) \ + && !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) \ + && !(defined SLJIT_CONFIG_AUTO && SLJIT_CONFIG_AUTO) +#if defined SLJIT_CONFIG_AUTO && !SLJIT_CONFIG_AUTO +#error "An architecture must be selected" +#else /* SLJIT_CONFIG_AUTO */ +#define SLJIT_CONFIG_AUTO 1 +#endif /* !SLJIT_CONFIG_AUTO */ +#endif /* !SLJIT_CONFIG */ + /********************************************************/ /* Automatic CPU detection (requires compiler support). */ /********************************************************/ @@ -140,8 +158,6 @@ #define SLJIT_CONFIG_MIPS_64 1 #elif defined(__sparc__) || defined(__sparc) #define SLJIT_CONFIG_SPARC_32 1 -#elif defined(__tilegx__) -#define SLJIT_CONFIG_TILEGX 1 #else /* Unsupported architecture */ #define SLJIT_CONFIG_UNSUPPORTED 1 @@ -191,6 +207,22 @@ #define SLJIT_CONFIG_SPARC 1 #endif +/***********************************************************/ +/* Intel Control-flow Enforcement Technology (CET) spport. */ +/***********************************************************/ + +#ifdef SLJIT_CONFIG_X86 + +#if defined(__CET__) && !(defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) +#define SLJIT_CONFIG_X86_CET 1 +#endif + +#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined(__GNUC__) +#include <x86intrin.h> +#endif + +#endif /* SLJIT_CONFIG_X86 */ + /**********************************/ /* External function definitions. */ /**********************************/ @@ -265,6 +297,7 @@ /* Type of public API functions. */ /*********************************/ +#ifndef SLJIT_API_FUNC_ATTRIBUTE #if (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) /* Static ABI functions. For all-in-one programs. */ @@ -278,6 +311,7 @@ #else #define SLJIT_API_FUNC_ATTRIBUTE #endif /* (defined SLJIT_CONFIG_STATIC && SLJIT_CONFIG_STATIC) */ +#endif /* defined SLJIT_API_FUNC_ATTRIBUTE */ /****************************/ /* Instruction cache flush. */ @@ -287,7 +321,7 @@ #if __has_builtin(__builtin___clear_cache) #define SLJIT_CACHE_FLUSH(from, to) \ - __builtin___clear_cache((char*)from, (char*)to) + __builtin___clear_cache((char*)(from), (char*)(to)) #endif /* __has_builtin(__builtin___clear_cache) */ #endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */ @@ -318,7 +352,7 @@ #elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) #define SLJIT_CACHE_FLUSH(from, to) \ - __builtin___clear_cache((char*)from, (char*)to) + __builtin___clear_cache((char*)(from), (char*)(to)) #elif defined __ANDROID__ @@ -377,7 +411,7 @@ typedef long int sljit_sw; && !(defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ && !(defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ && !(defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) \ - && !(defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) + && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) #define SLJIT_32BIT_ARCHITECTURE 1 #define SLJIT_WORD_SHIFT 2 typedef unsigned int sljit_uw; @@ -419,10 +453,14 @@ typedef double sljit_f64; #if (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) #define SLJIT_W(w) (w##l) #elif (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE) +#ifdef _WIN64 #define SLJIT_W(w) (w##ll) -#else +#else /* !windows */ +#define SLJIT_W(w) (w##l) +#endif /* windows */ +#else /* 32 bit */ #define SLJIT_W(w) (w) -#endif +#endif /* unknown */ #endif /* !SLJIT_W */ @@ -451,7 +489,27 @@ typedef double sljit_f64; #define SLJIT_BIG_ENDIAN 1 #endif -#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) +#ifndef SLJIT_MIPS_REV + +/* Auto detecting mips revision. */ +#if (defined __mips_isa_rev) && (__mips_isa_rev >= 6) +#define SLJIT_MIPS_REV 6 +#elif (defined __mips_isa_rev && __mips_isa_rev >= 1) \ + || (defined __clang__ && defined _MIPS_ARCH_OCTEON) \ + || (defined __clang__ && defined _MIPS_ARCH_P5600) +/* clang either forgets to define (clang-7) __mips_isa_rev at all + * or sets it to zero (clang-8,-9) for -march=octeon (MIPS64 R2+) + * and -march=p5600 (MIPS32 R5). + * It also sets the __mips macro to 64 or 32 for -mipsN when N <= 5 + * (should be set to N exactly) so we cannot rely on this too. + */ +#define SLJIT_MIPS_REV 1 +#endif + +#endif /* !SLJIT_MIPS_REV */ + +#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ + || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) #define SLJIT_BIG_ENDIAN 1 @@ -478,7 +536,8 @@ typedef double sljit_f64; || (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) \ || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \ || (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32) \ - || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + || (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) \ + || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) #define SLJIT_UNALIGNED 1 #endif @@ -496,17 +555,19 @@ typedef double sljit_f64; #ifndef SLJIT_FUNC -#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) +#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) \ + || !(defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) -/* Force cdecl. */ #define SLJIT_FUNC -#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) - -#if defined(__GNUC__) && !defined(__APPLE__) +#elif defined(__GNUC__) && !defined(__APPLE__) +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) #define SLJIT_FUNC __attribute__ ((fastcall)) #define SLJIT_X86_32_FASTCALL 1 +#else +#define SLJIT_FUNC +#endif /* gcc >= 3.4 */ #elif defined(_MSC_VER) @@ -520,16 +581,10 @@ typedef double sljit_f64; #else /* Unknown compiler. */ -/* The cdecl attribute is the default. */ -#define SLJIT_FUNC - -#endif - -#else /* Non x86-32 architectures. */ - +/* The cdecl calling convention is usually the x86 default. */ #define SLJIT_FUNC -#endif /* SLJIT_CONFIG_X86_32 */ +#endif /* SLJIT_USE_CDECL_CALLING_CONVENTION */ #endif /* !SLJIT_FUNC */ @@ -560,8 +615,16 @@ determine the next executed instruction after return. */ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size); SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr); SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); -#define SLJIT_MALLOC_EXEC(size) sljit_malloc_exec(size) -#define SLJIT_FREE_EXEC(ptr) sljit_free_exec(ptr) +#define SLJIT_BUILTIN_MALLOC_EXEC(size, exec_allocator_data) sljit_malloc_exec(size) +#define SLJIT_BUILTIN_FREE_EXEC(ptr, exec_allocator_data) sljit_free_exec(ptr) + +#ifndef SLJIT_MALLOC_EXEC +#define SLJIT_MALLOC_EXEC(size, exec_allocator_data) SLJIT_BUILTIN_MALLOC_EXEC((size), (exec_allocator_data)) +#endif /* SLJIT_MALLOC_EXEC */ + +#ifndef SLJIT_FREE_EXEC +#define SLJIT_FREE_EXEC(ptr, exec_allocator_data) SLJIT_BUILTIN_FREE_EXEC((ptr), (exec_allocator_data)) +#endif /* SLJIT_FREE_EXEC */ #if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); @@ -570,7 +633,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_EXEC_OFFSET(ptr) 0 #endif -#endif +#endif /* SLJIT_EXECUTABLE_ALLOCATOR */ /**********************************************/ /* Registers and locals offset determination. */ @@ -646,11 +709,32 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #define SLJIT_LOCALS_OFFSET_BASE ((16 + 1 + 6 + 2 + 1) * sizeof(sljit_sw)) #endif -#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) +#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) -#define SLJIT_NUMBER_OF_REGISTERS 10 -#define SLJIT_NUMBER_OF_SAVED_REGISTERS 5 -#define SLJIT_LOCALS_OFFSET_BASE 0 +/* + * https://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html#STACKFRAME + * + * 160 + * .. FR6 + * .. FR4 + * .. FR2 + * 128 FR0 + * 120 R15 (used for SP) + * 112 R14 + * 104 R13 + * 96 R12 + * .. + * 48 R6 + * .. + * 16 R2 + * 8 RESERVED + * 0 SP + */ +#define SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE 160 + +#define SLJIT_NUMBER_OF_REGISTERS 12 +#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8 +#define SLJIT_LOCALS_OFFSET_BASE SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE #elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) @@ -679,24 +763,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); /* Debug and verbose related macros. */ /*************************************/ -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) -#include <stdio.h> -#endif - #if (defined SLJIT_DEBUG && SLJIT_DEBUG) #if !defined(SLJIT_ASSERT) || !defined(SLJIT_UNREACHABLE) /* SLJIT_HALT_PROCESS must halt the process. */ #ifndef SLJIT_HALT_PROCESS -#include <stdlib.h> - #define SLJIT_HALT_PROCESS() \ abort(); #endif /* !SLJIT_HALT_PROCESS */ -#include <stdio.h> - #endif /* !SLJIT_ASSERT || !SLJIT_UNREACHABLE */ /* Feel free to redefine these two macros. */ @@ -742,4 +818,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr); #endif /* !SLJIT_COMPILE_ASSERT */ +#ifdef __cplusplus +} /* extern "C" */ #endif + +#endif /* SLJIT_CONFIG_INTERNAL_H_ */ diff --git a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c index 92ddb94914..61a32f23e9 100644 --- a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c +++ b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c @@ -72,9 +72,8 @@ alloc_chunk / free_chunk : * allocate executable system memory chunks * the size is always divisible by CHUNK_SIZE - allocator_grab_lock / allocator_release_lock : - * make the allocator thread safe - * can be empty if the OS (or the application) does not support threading + SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK : + * provided as part of sljitUtils * only the allocator requires this lock, sljit is fully thread safe as it only uses local variables */ @@ -95,6 +94,7 @@ static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) #else #ifdef __APPLE__ +#ifdef MAP_ANON /* Configures TARGET_OS_OSX when appropriate */ #include <TargetConditionals.h> @@ -104,17 +104,23 @@ static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) #ifdef MAP_JIT +/* + On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a + version where it's OK to have more than one JIT block. + On non-macOS systems, returns MAP_JIT if it is defined. +*/ static SLJIT_INLINE int get_map_jit_flag() { #if TARGET_OS_OSX - /* On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a version - of macOS where it's OK to have more than one JIT block. On non-macOS systems, returns - MAP_JIT if it is defined. */ + sljit_sw page_size = get_page_alignment() + 1; + void *ptr; static int map_jit_flag = -1; - /* The following code is thread safe because multiple initialization - sets map_jit_flag to the same value and the code has no side-effects. - Changing the kernel version witout system restart is (very) unlikely. */ + /* + The following code is thread safe because multiple initialization + sets map_jit_flag to the same value and the code has no side-effects. + Changing the kernel version witout system restart is (very) unlikely. + */ if (map_jit_flag == -1) { struct utsname name; @@ -123,13 +129,14 @@ static SLJIT_INLINE int get_map_jit_flag() /* Kernel version for 10.14.0 (Mojave) */ if (atoi(name.release) >= 18) { - /* Only use MAP_JIT if a hardened runtime is used, because MAP_JIT is incompatible with fork(). */ - void *ptr = mmap(NULL, getpagesize(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + /* Only use MAP_JIT if a hardened runtime is used */ + + ptr = mmap(NULL, page_size, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0); if (ptr == MAP_FAILED) { map_jit_flag = MAP_JIT; } else { - munmap(ptr, getpagesize()); + munmap(ptr, page_size); } } } @@ -141,7 +148,7 @@ static SLJIT_INLINE int get_map_jit_flag() } #endif /* MAP_JIT */ - +#endif /* MAP_ANON */ #endif /* __APPLE__ */ static SLJIT_INLINE void* alloc_chunk(sljit_uw size) @@ -159,10 +166,9 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size) retval = mmap(NULL, size, prot, flags, -1, 0); #else /* !MAP_ANON */ - if (dev_zero < 0) { - if (open_dev_zero()) - return NULL; - } + if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero())) + return NULL; + retval = mmap(NULL, size, prot, MAP_PRIVATE, dev_zero, 0); #endif /* MAP_ANON */ @@ -246,7 +252,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) struct free_block *free_block; sljit_uw chunk_size; - allocator_grab_lock(); + SLJIT_ALLOCATOR_LOCK(); if (size < (64 - sizeof(struct block_header))) size = (64 - sizeof(struct block_header)); size = ALIGN_SIZE(size); @@ -270,7 +276,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) } allocated_size += size; header->size = size; - allocator_release_lock(); + SLJIT_ALLOCATOR_UNLOCK(); return MEM_START(header); } free_block = free_block->next; @@ -279,7 +285,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) chunk_size = (size + sizeof(struct block_header) + CHUNK_SIZE - 1) & CHUNK_MASK; header = (struct block_header*)alloc_chunk(chunk_size); if (!header) { - allocator_release_lock(); + SLJIT_ALLOCATOR_UNLOCK(); return NULL; } @@ -306,7 +312,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) } next_header->size = 1; next_header->prev_size = chunk_size; - allocator_release_lock(); + SLJIT_ALLOCATOR_UNLOCK(); return MEM_START(header); } @@ -315,7 +321,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) struct block_header *header; struct free_block* free_block; - allocator_grab_lock(); + SLJIT_ALLOCATOR_LOCK(); header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header)); allocated_size -= header->size; @@ -352,7 +358,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) } } - allocator_release_lock(); + SLJIT_ALLOCATOR_UNLOCK(); } SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) @@ -360,7 +366,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) struct free_block* free_block; struct free_block* next_free_block; - allocator_grab_lock(); + SLJIT_ALLOCATOR_LOCK(); free_block = free_blocks; while (free_block) { @@ -375,5 +381,5 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) } SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks)); - allocator_release_lock(); + SLJIT_ALLOCATOR_UNLOCK(); } diff --git a/thirdparty/pcre2/src/sljit/sljitLir.c b/thirdparty/pcre2/src/sljit/sljitLir.c index 9bab0c3ec6..d817c90b3a 100644 --- a/thirdparty/pcre2/src/sljit/sljitLir.c +++ b/thirdparty/pcre2/src/sljit/sljitLir.c @@ -28,7 +28,6 @@ #ifdef _WIN32 -/* For SLJIT_CACHE_FLUSH, which can expand to FlushInstructionCache. */ #include <windows.h> #endif /* _WIN32 */ @@ -223,14 +222,6 @@ # define FCSR_FCC 33 #endif -#if (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) -# define IS_JAL 0x04 -# define IS_COND 0x08 - -# define PATCH_B 0x10 -# define PATCH_J 0x20 -#endif - #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) # define IS_MOVABLE 0x04 # define IS_COND 0x08 @@ -274,6 +265,8 @@ #if (defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) #include "sljitProtExecAllocator.c" +#elif (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR) +#include "sljitWXExecAllocator.c" #else #include "sljitExecAllocator.c" #endif @@ -286,6 +279,10 @@ #define SLJIT_ADD_EXEC_OFFSET(ptr, exec_offset) ((sljit_u8 *)(ptr)) #endif +#ifndef SLJIT_UPDATE_WX_FLAGS +#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) +#endif + /* Argument checking features. */ #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) @@ -366,7 +363,7 @@ static sljit_s32 compiler_initialized = 0; static void init_compiler(void); #endif -SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data) +SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data, void *exec_allocator_data) { struct sljit_compiler *compiler = (struct sljit_compiler*)SLJIT_MALLOC(sizeof(struct sljit_compiler), allocator_data); if (!compiler) @@ -393,6 +390,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo compiler->error = SLJIT_SUCCESS; compiler->allocator_data = allocator_data; + compiler->exec_allocator_data = exec_allocator_data; compiler->buf = (struct sljit_memory_fragment*)SLJIT_MALLOC(BUF_SIZE, allocator_data); compiler->abuf = (struct sljit_memory_fragment*)SLJIT_MALLOC(ABUF_SIZE, allocator_data); @@ -485,22 +483,28 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compi } #if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) -SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data) { + SLJIT_UNUSED_ARG(exec_allocator_data); + /* Remove thumb mode flag. */ - SLJIT_FREE_EXEC((void*)((sljit_uw)code & ~0x1)); + SLJIT_FREE_EXEC((void*)((sljit_uw)code & ~0x1), exec_allocator_data); } #elif (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) -SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data) { + SLJIT_UNUSED_ARG(exec_allocator_data); + /* Resolve indirection. */ code = (void*)(*(sljit_uw*)code); - SLJIT_FREE_EXEC(code); + SLJIT_FREE_EXEC(code, exec_allocator_data); } #else -SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data) { - SLJIT_FREE_EXEC(code); + SLJIT_UNUSED_ARG(exec_allocator_data); + + SLJIT_FREE_EXEC(code, exec_allocator_data); } #endif @@ -627,7 +631,10 @@ static SLJIT_INLINE sljit_s32 get_arg_count(sljit_s32 arg_types) return arg_count; } -#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) + +/* Only used in RISC architectures where the instruction size is constant */ +#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ + && !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) static SLJIT_INLINE sljit_uw compute_next_addr(struct sljit_label *label, struct sljit_jump *jump, struct sljit_const *const_, struct sljit_put_label *put_label) @@ -649,7 +656,7 @@ static SLJIT_INLINE sljit_uw compute_next_addr(struct sljit_label *label, struct return result; } -#endif /* !SLJIT_CONFIG_X86 */ +#endif /* !SLJIT_CONFIG_X86 && !SLJIT_CONFIG_S390X */ static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler, sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, @@ -926,7 +933,8 @@ static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, s static const char* op0_names[] = { (char*)"breakpoint", (char*)"nop", (char*)"lmul.uw", (char*)"lmul.sw", - (char*)"divmod.u", (char*)"divmod.s", (char*)"div.u", (char*)"div.s" + (char*)"divmod.u", (char*)"divmod.s", (char*)"div.u", (char*)"div.s", + (char*)"endbr", (char*)"skip_frames_before_return" }; static const char* op1_names[] = { @@ -943,6 +951,12 @@ static const char* op2_names[] = { (char*)"shl", (char*)"lshr", (char*)"ashr", }; +static const char* op_src_names[] = { + (char*)"fast_return", (char*)"skip_frames_before_fast_return", + (char*)"prefetch_l1", (char*)"prefetch_l2", + (char*)"prefetch_l3", (char*)"prefetch_once", +}; + static const char* fop1_names[] = { (char*)"mov", (char*)"conv", (char*)"conv", (char*)"conv", (char*)"conv", (char*)"conv", (char*)"cmp", (char*)"neg", @@ -1152,37 +1166,21 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_c CHECK_RETURN_OK; } -static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) -{ -#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) - FUNCTION_CHECK_SRC(src, srcw); - CHECK_ARGUMENT(src != SLJIT_IMM); - compiler->last_flags = 0; -#endif -#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) - if (SLJIT_UNLIKELY(!!compiler->verbose)) { - fprintf(compiler->verbose, " fast_return "); - sljit_verbose_param(compiler, src, srcw); - fprintf(compiler->verbose, "\n"); - } -#endif - CHECK_RETURN_OK; -} - static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW) - || ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW)); - CHECK_ARGUMENT(op < SLJIT_LMUL_UW || compiler->scratches >= 2); - if (op >= SLJIT_LMUL_UW) + || ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW) + || (op >= SLJIT_ENDBR && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN)); + CHECK_ARGUMENT(GET_OPCODE(op) < SLJIT_LMUL_UW || GET_OPCODE(op) >= SLJIT_ENDBR || compiler->scratches >= 2); + if ((GET_OPCODE(op) >= SLJIT_LMUL_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN) compiler->last_flags = 0; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) if (SLJIT_UNLIKELY(!!compiler->verbose)) { fprintf(compiler->verbose, " %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]); - if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW) { + if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) { fprintf(compiler->verbose, (op & SLJIT_I32_OP) ? "32" : "w"); } fprintf(compiler->verbose, "\n"); @@ -1224,7 +1222,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler break; } - FUNCTION_CHECK_DST(dst, dstw, 1); + FUNCTION_CHECK_DST(dst, dstw, HAS_FLAGS(op)); FUNCTION_CHECK_SRC(src, srcw); if (GET_OPCODE(op) >= SLJIT_NOT) { @@ -1304,7 +1302,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler break; } - FUNCTION_CHECK_DST(dst, dstw, 1); + FUNCTION_CHECK_DST(dst, dstw, HAS_FLAGS(op)); FUNCTION_CHECK_SRC(src1, src1w); FUNCTION_CHECK_SRC(src2, src2w); compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z)); @@ -1325,6 +1323,33 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler CHECK_RETURN_OK; } +static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(op >= SLJIT_FAST_RETURN && op <= SLJIT_PREFETCH_ONCE); + FUNCTION_CHECK_SRC(src, srcw); + + if (op == SLJIT_FAST_RETURN || op == SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN) + { + CHECK_ARGUMENT(src != SLJIT_IMM); + compiler->last_flags = 0; + } + else if (op >= SLJIT_PREFETCH_L1 && op <= SLJIT_PREFETCH_ONCE) + { + CHECK_ARGUMENT(src & SLJIT_MEM); + } +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " %s ", op_src_names[op - SLJIT_OP_SRC_BASE]); + sljit_verbose_param(compiler, src, srcw); + fprintf(compiler->verbose, "\n"); + } +#endif + CHECK_RETURN_OK; +} + static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_register_index(sljit_s32 reg) { SLJIT_UNUSED_ARG(reg); @@ -1360,6 +1385,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_co #elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2) 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 CHECK_ARGUMENT(size == 4 && (((sljit_sw)instruction) & 0x3) == 0); #endif @@ -2016,7 +2043,7 @@ static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *comp #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \ || (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \ - || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1)) + || ((defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) && !(defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6)) static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 dst_reg, @@ -2093,8 +2120,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *com # include "sljitNativeMIPS_common.c" #elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) # include "sljitNativeSPARC_common.c" -#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) -# include "sljitNativeTILEGX_64.c" +#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) +# include "sljitNativeS390X.c" #endif #if !(defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) @@ -2125,7 +2152,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler #endif if (SLJIT_UNLIKELY((src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM))) { - /* Immediate is prefered as second argument by most architectures. */ + /* Immediate is preferred as second argument by most architectures. */ switch (condition) { case SLJIT_LESS: condition = SLJIT_GREATER; @@ -2274,9 +2301,10 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) return "unsupported"; } -SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data) +SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data, void *exec_allocator_data) { SLJIT_UNUSED_ARG(allocator_data); + SLJIT_UNUSED_ARG(exec_allocator_data); SLJIT_UNREACHABLE(); return NULL; } @@ -2324,9 +2352,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) return 0; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code) +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data) { SLJIT_UNUSED_ARG(code); + SLJIT_UNUSED_ARG(exec_allocator_data); SLJIT_UNREACHABLE(); } @@ -2381,15 +2410,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * return SLJIT_ERR_UNSUPPORTED; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) -{ - SLJIT_UNUSED_ARG(compiler); - SLJIT_UNUSED_ARG(src); - SLJIT_UNUSED_ARG(srcw); - SLJIT_UNREACHABLE(); - return SLJIT_ERR_UNSUPPORTED; -} - SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { SLJIT_UNUSED_ARG(compiler); @@ -2429,6 +2449,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return SLJIT_ERR_UNSUPPORTED; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(op); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + SLJIT_UNREACHABLE(); + return SLJIT_ERR_UNSUPPORTED; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { SLJIT_UNREACHABLE(); @@ -2549,6 +2580,13 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw SLJIT_UNREACHABLE(); } +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_label, struct sljit_label *label) +{ + SLJIT_UNUSED_ARG(put_label); + SLJIT_UNUSED_ARG(label); + SLJIT_UNREACHABLE(); +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) { SLJIT_UNUSED_ARG(compiler); diff --git a/thirdparty/pcre2/src/sljit/sljitLir.h b/thirdparty/pcre2/src/sljit/sljitLir.h index 836d25cf71..93d2804675 100644 --- a/thirdparty/pcre2/src/sljit/sljitLir.h +++ b/thirdparty/pcre2/src/sljit/sljitLir.h @@ -24,8 +24,8 @@ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _SLJIT_LIR_H_ -#define _SLJIT_LIR_H_ +#ifndef SLJIT_LIR_H_ +#define SLJIT_LIR_H_ /* ------------------------------------------------------------------------ @@ -70,9 +70,11 @@ - pass --smc-check=all argument to valgrind, since JIT is a "self-modifying code" */ -#if !(defined SLJIT_NO_DEFAULT_CONFIG && SLJIT_NO_DEFAULT_CONFIG) +#if (defined SLJIT_HAVE_CONFIG_PRE && SLJIT_HAVE_CONFIG_PRE) +#include "sljitConfigPre.h" +#endif /* SLJIT_HAVE_CONFIG_PRE */ + #include "sljitConfig.h" -#endif /* The following header file defines useful macros for fine tuning sljit based code generators. They are listed in the beginning @@ -80,6 +82,14 @@ of sljitConfigInternal.h */ #include "sljitConfigInternal.h" +#if (defined SLJIT_HAVE_CONFIG_POST && SLJIT_HAVE_CONFIG_POST) +#include "sljitConfigPost.h" +#endif /* SLJIT_HAVE_CONFIG_POST */ + +#ifdef __cplusplus +extern "C" { +#endif + /* --------------------------------------------------------------------- */ /* Error codes */ /* --------------------------------------------------------------------- */ @@ -154,10 +164,10 @@ of sljitConfigInternal.h */ */ /* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1 - or sljit_emit_op2 operations the result is discarded. If no status - flags are set, no instructions are emitted for these operations. Data - prefetch is a special exception, see SLJIT_MOV operation. Other SLJIT - operations do not support SLJIT_UNUSED as a destination operand. */ + or sljit_emit_op2 operations the result is discarded. Some status + flags must be set when the destination is SLJIT_UNUSED, because the + operation would have no effect otherwise. Other SLJIT operations do + not support SLJIT_UNUSED as a destination operand. */ #define SLJIT_UNUSED 0 /* Scratch registers. */ @@ -381,6 +391,7 @@ struct sljit_compiler { struct sljit_put_label *last_put_label; void *allocator_data; + void *exec_allocator_data; struct sljit_memory_fragment *buf; struct sljit_memory_fragment *abuf; @@ -447,9 +458,9 @@ struct sljit_compiler { sljit_sw cache_argw; #endif -#if (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) - sljit_s32 cache_arg; - sljit_sw cache_argw; +#if (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X) + /* Need to allocate register save area to make calls. */ + sljit_s32 have_save_area; #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -481,10 +492,12 @@ struct sljit_compiler { custom memory managers. This pointer is passed to SLJIT_MALLOC and SLJIT_FREE macros. Most allocators (including the default one) ignores this value, and it is recommended to pass NULL - as a dummy value for allocator_data. + as a dummy value for allocator_data. The exec_allocator_data + has the same purpose but this one is passed to SLJIT_MALLOC_EXEC / + SLJIT_MALLOC_FREE functions. Returns NULL if failed. */ -SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data); +SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allocator_data, void *exec_allocator_data); /* Frees everything except the compiled machine code. */ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compiler); @@ -531,7 +544,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil /* Free executable code. */ -SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code); +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data); /* When the protected executable allocator is used the JIT code is mapped @@ -567,10 +580,14 @@ static SLJIT_INLINE sljit_uw sljit_get_generated_code_size(struct sljit_compiler #define SLJIT_HAS_FPU 0 /* [Limitation] Some registers are virtual registers. */ #define SLJIT_HAS_VIRTUAL_REGISTERS 1 +/* [Emulated] Has zero register (setting a memory location to zero is efficient). */ +#define SLJIT_HAS_ZERO_REGISTER 2 /* [Emulated] Count leading zero is supported. */ -#define SLJIT_HAS_CLZ 2 +#define SLJIT_HAS_CLZ 3 /* [Emulated] Conditional move is supported. */ -#define SLJIT_HAS_CMOV 3 +#define SLJIT_HAS_CMOV 4 +/* [Emulated] Conditional move is supported. */ +#define SLJIT_HAS_PREFETCH 5 #if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) /* [Not emulated] SSE2 support is available on x86. */ @@ -658,10 +675,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp sljit_s32 src, sljit_sw srcw); /* Generating entry and exit points for fast call functions (see SLJIT_FAST_CALL). - Both sljit_emit_fast_enter and sljit_emit_fast_return functions preserve the + Both sljit_emit_fast_enter and SLJIT_FAST_RETURN operations preserve the values of all registers and stack frame. The return address is stored in the dst argument of sljit_emit_fast_enter, and this return address can be passed - to sljit_emit_fast_return to continue the execution after the fast call. + to SLJIT_FAST_RETURN to continue the execution after the fast call. Fast calls are cheap operations (usually only a single call instruction is emitted) but they do not preserve any registers. However the callee function @@ -669,16 +686,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp efficiently exploited by various optimizations. Registers can be saved manually by the callee function if needed. - Although returning to different address by sljit_emit_fast_return is possible, + Although returning to different address by SLJIT_FAST_RETURN is possible, this address usually cannot be predicted by the return address predictor of - modern CPUs which may reduce performance. Furthermore using sljit_emit_ijump - to return is also inefficient since return address prediction is usually - triggered by a specific form of ijump. + modern CPUs which may reduce performance. Furthermore certain security + enhancement technologies such as Intel Control-flow Enforcement Technology + (CET) may disallow returning to a different address. Flags: - (does not modify flags). */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw); -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw); /* Source and destination operands for arithmetical instructions @@ -692,7 +708,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler */ /* - IMPORATNT NOTE: memory access MUST be naturally aligned except + IMPORTANT NOTE: memory access MUST be naturally aligned unless SLJIT_UNALIGNED macro is defined and its value is 1. length | alignment @@ -734,6 +750,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler mips: [reg+imm], -65536 <= imm <= 65535 sparc: [reg+imm], -4096 <= imm <= 4095 [reg+reg] is supported + s390x: [reg+imm], -2^19 <= imm < 2^19 + [reg+reg] is supported + Write-back is not supported */ /* Macros for specifying operand types. */ @@ -887,6 +906,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler the behaviour is undefined. */ #define SLJIT_DIV_SW (SLJIT_OP0_BASE + 7) #define SLJIT_DIV_S32 (SLJIT_DIV_SW | SLJIT_I32_OP) +/* Flags: - (does not modify flags) + ENDBR32 instruction for x86-32 and ENDBR64 instruction for x86-64 + when Intel Control-flow Enforcement Technology (CET) is enabled. + No instruction for other architectures. */ +#define SLJIT_ENDBR (SLJIT_OP0_BASE + 8) +/* Flags: - (may destroy flags) + Skip stack frames before return. */ +#define SLJIT_SKIP_FRAMES_BEFORE_RETURN (SLJIT_OP0_BASE + 9) SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op); @@ -904,15 +931,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile U32 - unsigned int (32 bit) data transfer S32 - signed int (32 bit) data transfer P - pointer (sljit_p) data transfer - - If the destination of a MOV instruction is SLJIT_UNUSED and the source - operand is a memory address the compiler emits a prefetch instruction - if this instruction is supported by the current CPU. Higher data sizes - bring the data closer to the core: a MOV with word size loads the data - into a higher level cache than a byte size. Otherwise the type does not - affect the prefetch instruction. Furthermore a prefetch instruction - never fails, so it can be used to prefetch a data from an address and - check whether that address is NULL afterwards. */ /* Flags: - (does not modify flags) */ @@ -1017,8 +1035,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w); +/* Starting index of opcodes for sljit_emit_op2. */ +#define SLJIT_OP_SRC_BASE 128 + +/* Note: src cannot be an immedate value + Flags: - (does not modify flags) */ +#define SLJIT_FAST_RETURN (SLJIT_OP_SRC_BASE + 0) +/* Skip stack frames before fast return. + Note: src cannot be an immedate value + Flags: may destroy flags. */ +#define SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN (SLJIT_OP_SRC_BASE + 1) +/* Prefetch value into the level 1 data cache + Note: if the target CPU does not support data prefetch, + no instructions are emitted. + Note: this instruction never fails, even if the memory address is invalid. + Flags: - (does not modify flags) */ +#define SLJIT_PREFETCH_L1 (SLJIT_OP_SRC_BASE + 2) +/* Prefetch value into the level 2 data cache + Note: same as SLJIT_PREFETCH_L1 if the target CPU + does not support this instruction form. + Note: this instruction never fails, even if the memory address is invalid. + Flags: - (does not modify flags) */ +#define SLJIT_PREFETCH_L2 (SLJIT_OP_SRC_BASE + 3) +/* Prefetch value into the level 3 data cache + Note: same as SLJIT_PREFETCH_L2 if the target CPU + does not support this instruction form. + Note: this instruction never fails, even if the memory address is invalid. + Flags: - (does not modify flags) */ +#define SLJIT_PREFETCH_L3 (SLJIT_OP_SRC_BASE + 4) +/* Prefetch a value which is only used once (and can be discarded afterwards) + Note: same as SLJIT_PREFETCH_L1 if the target CPU + does not support this instruction form. + Note: this instruction never fails, even if the memory address is invalid. + Flags: - (does not modify flags) */ +#define SLJIT_PREFETCH_ONCE (SLJIT_OP_SRC_BASE + 5) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw); + /* Starting index of opcodes for sljit_emit_fop1. */ -#define SLJIT_FOP1_BASE 128 +#define SLJIT_FOP1_BASE 160 /* Flags: - (does not modify flags) */ #define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0) @@ -1057,7 +1113,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil sljit_s32 src, sljit_sw srcw); /* Starting index of opcodes for sljit_emit_fop2. */ -#define SLJIT_FOP2_BASE 160 +#define SLJIT_FOP2_BASE 192 /* Flags: - (does not modify flags) */ #define SLJIT_ADD_F64 (SLJIT_FOP2_BASE + 0) @@ -1161,7 +1217,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi /* Unconditional jump types. */ #define SLJIT_JUMP 24 - /* Fast calling method. See sljit_emit_fast_enter / sljit_emit_fast_return. */ + /* Fast calling method. See sljit_emit_fast_enter / SLJIT_FAST_RETURN. */ #define SLJIT_FAST_CALL 25 /* Called function must be declared with the SLJIT_FUNC attribute. */ #define SLJIT_CALL 26 @@ -1361,12 +1417,6 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void); /* Portable helper function to get an offset of a member. */ #define SLJIT_OFFSETOF(base, member) ((sljit_sw)(&((base*)0x10)->member) - 0x10) -#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) -/* This global lock is useful to compile common functions. */ -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void); -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void); -#endif - #if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) /* The sljit_stack structure and its manipulation functions provides @@ -1490,4 +1540,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags); -#endif /* _SLJIT_LIR_H_ */ +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SLJIT_LIR_H_ */ diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c index 71f7bcdadb..ae8479f031 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c @@ -467,18 +467,28 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw execut sljit_s32 bl = (mov_pc & 0x0000f000) != RD(TMP_PC); sljit_sw diff = (sljit_sw)(((sljit_sw)new_addr - (sljit_sw)(inst + 2) - executable_offset) >> 2); + SLJIT_UNUSED_ARG(executable_offset); + if (diff <= 0x7fffff && diff >= -0x800000) { /* Turn to branch. */ if (!bl) { + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0); + } inst[0] = (mov_pc & COND_MASK) | (B - CONDITIONAL) | (diff & 0xffffff); if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1); inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } } else { + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0); + } inst[0] = (mov_pc & COND_MASK) | (BL - CONDITIONAL) | (diff & 0xffffff); inst[1] = NOP; if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1); inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } @@ -491,28 +501,52 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw execut ptr = inst + 1; if (*inst != mov_pc) { + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + (!bl ? 1 : 2), 0); + } inst[0] = mov_pc; if (!bl) { if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1); inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } } else { inst[1] = BLX | RM(TMP_REG1); if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1); inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } } } + + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0); + } + *ptr = new_addr; + + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1); + } } #else sljit_uw *inst = (sljit_uw*)jump_ptr; + + SLJIT_UNUSED_ARG(executable_offset); + SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT); + + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0); + } + inst[0] = MOVW | (inst[0] & 0xf000) | ((new_addr << 4) & 0xf0000) | (new_addr & 0xfff); inst[1] = MOVT | (inst[1] & 0xf000) | ((new_addr >> 12) & 0xf0000) | ((new_addr >> 16) & 0xfff); + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1); inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } @@ -529,10 +563,18 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_off sljit_uw ldr_literal = ptr[1]; sljit_uw src2; + SLJIT_UNUSED_ARG(executable_offset); + src2 = get_imm(new_constant); if (src2) { + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0); + } + *inst = 0xe3a00000 | (ldr_literal & 0xf000) | src2; + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1); inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } @@ -541,8 +583,14 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_off src2 = get_imm(~new_constant); if (src2) { + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0); + } + *inst = 0xe3e00000 | (ldr_literal & 0xf000) | src2; + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1); inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } @@ -555,19 +603,44 @@ static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_off ptr = inst + 1; if (*inst != ldr_literal) { + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 0); + } + *inst = ldr_literal; + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 1, 1); inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 1); } } + + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0); + } + *ptr = new_constant; + + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1); + } #else sljit_uw *inst = (sljit_uw*)addr; + + SLJIT_UNUSED_ARG(executable_offset); + SLJIT_ASSERT((inst[0] & 0xfff00000) == MOVW && (inst[1] & 0xfff00000) == MOVT); + + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0); + } + inst[0] = MOVW | (inst[0] & 0xf000) | ((new_constant << 4) & 0xf0000) | (new_constant & 0xfff); inst[1] = MOVT | (inst[1] & 0xf000) | ((new_constant >> 12) & 0xf0000) | ((new_constant >> 16) & 0xfff); + if (flush_cache) { + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1); inst = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } @@ -612,7 +685,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil #else size = compiler->size; #endif - code = (sljit_uw*)SLJIT_MALLOC_EXEC(size * sizeof(sljit_uw)); + code = (sljit_uw*)SLJIT_MALLOC_EXEC(size * sizeof(sljit_uw), compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; @@ -653,7 +726,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil } else { if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) { - SLJIT_FREE_EXEC(code); + SLJIT_FREE_EXEC(code, compiler->exec_allocator_data); compiler->error = SLJIT_ERR_ALLOC_FAILED; return NULL; } @@ -666,6 +739,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); label->size = code_ptr - code; label = label->next; + + next_addr = compute_next_addr(label, jump, const_, put_label); } } } @@ -754,7 +829,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil cpool_current_index = 0; while (buf_ptr < buf_end) { if (SLJIT_UNLIKELY(resolve_const_pool_index(compiler, &first_patch, cpool_current_index, cpool_start_address, buf_ptr))) { - SLJIT_FREE_EXEC(code); + SLJIT_FREE_EXEC(code, compiler->exec_allocator_data); compiler->error = SLJIT_ERR_ALLOC_FAILED; return NULL; } @@ -854,6 +929,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil code_ptr = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); SLJIT_CACHE_FLUSH(code, code_ptr); + SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1); return code; } @@ -870,6 +946,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + case SLJIT_HAS_PREFETCH: +#endif return 1; default: @@ -1676,6 +1755,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); } return SLJIT_SUCCESS; + case SLJIT_ENDBR: + case SLJIT_SKIP_FRAMES_BEFORE_RETURN: + return SLJIT_SUCCESS; } return SLJIT_SUCCESS; @@ -1690,14 +1772,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); - if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { -#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) - if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) - return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1); -#endif - return SLJIT_SUCCESS; - } - switch (GET_OPCODE(op)) { case SLJIT_MOV: case SLJIT_MOV_U32: @@ -1779,6 +1853,40 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); + ADJUST_LOCAL_OFFSET(src, srcw); + + switch (op) { + case SLJIT_FAST_RETURN: + SLJIT_ASSERT(reg_map[TMP_REG2] == 14); + + if (FAST_IS_REG(src)) + FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src))); + else + FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1)); + + return push_inst(compiler, BX | RM(TMP_REG2)); + case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: + return SLJIT_SUCCESS; + case SLJIT_PREFETCH_L1: + case SLJIT_PREFETCH_L2: + case SLJIT_PREFETCH_L3: + case SLJIT_PREFETCH_ONCE: +#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7) + SLJIT_ASSERT(src & SLJIT_MEM); + return emit_op_mem(compiler, PRELOAD | LOAD_DATA, TMP_PC, src, srcw, TMP_REG1); +#else /* !SLJIT_CONFIG_ARM_V7 */ + return SLJIT_SUCCESS; +#endif /* SLJIT_CONFIG_ARM_V7 */ + } + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -2041,22 +2149,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * return emit_op_mem(compiler, WORD_SIZE, TMP_REG2, dst, dstw, TMP_REG1); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); - - SLJIT_ASSERT(reg_map[TMP_REG2] == 14); - - if (FAST_IS_REG(src)) - FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG2) | RM(src))); - else - FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG2, src, srcw, TMP_REG1)); - - return push_inst(compiler, BX | RM(TMP_REG2)); -} - /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ @@ -2615,11 +2707,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile } else { if (is_type1_transfer) { - if (memw > 4095 && memw < -4095) + if (memw > 4095 || memw < -4095) return SLJIT_ERR_UNSUPPORTED; } else { - if (memw > 255 && memw < -255) + if (memw > 255 || memw < -255) return SLJIT_ERR_UNSUPPORTED; } } diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c index e15b3451e8..52267e7df7 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c @@ -151,16 +151,6 @@ static SLJIT_INLINE sljit_s32 emit_imm64_const(struct sljit_compiler *compiler, return push_inst(compiler, MOVK | RD(dst) | ((imm >> 48) << 5) | (3 << 21)); } -static SLJIT_INLINE void modify_imm64_const(sljit_ins* inst, sljit_uw new_imm) -{ - sljit_s32 dst = inst[0] & 0x1f; - SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ && (inst[1] & 0xffe00000) == (MOVK | (1 << 21))); - inst[0] = MOVZ | dst | ((new_imm & 0xffff) << 5); - inst[1] = MOVK | dst | (((new_imm >> 16) & 0xffff) << 5) | (1 << 21); - inst[2] = MOVK | dst | (((new_imm >> 32) & 0xffff) << 5) | (2 << 21); - inst[3] = MOVK | dst | ((new_imm >> 48) << 5) | (3 << 21); -} - static SLJIT_INLINE sljit_sw detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset) { sljit_sw diff; @@ -253,7 +243,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); - code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); + code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; @@ -380,6 +370,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); SLJIT_CACHE_FLUSH(code, code_ptr); + SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1); return code; } @@ -396,6 +387,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: + case SLJIT_HAS_PREFETCH: return 1; default: @@ -1154,6 +1146,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile case SLJIT_DIV_UW: case SLJIT_DIV_SW: return push_inst(compiler, ((op == SLJIT_DIV_UW ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)); + case SLJIT_ENDBR: + case SLJIT_SKIP_FRAMES_BEFORE_RETURN: + return SLJIT_SUCCESS; } return SLJIT_SUCCESS; @@ -1171,23 +1166,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); - if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { - if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) { - SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4); - - if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8) - dst = 5; - else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16) - dst = 3; - else - dst = 1; - - /* Signed word sized load is the prefetch instruction. */ - return emit_op_mem(compiler, WORD_SIZE | SIGNED, dst, src, srcw, TMP_REG1); - } - return SLJIT_SUCCESS; - } - dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; op = GET_OPCODE(op); @@ -1327,6 +1305,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); + ADJUST_LOCAL_OFFSET(src, srcw); + + switch (op) { + case SLJIT_FAST_RETURN: + if (FAST_IS_REG(src)) + FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src))); + else + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1)); + + return push_inst(compiler, RET | RN(TMP_LR)); + case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: + return SLJIT_SUCCESS; + case SLJIT_PREFETCH_L1: + case SLJIT_PREFETCH_L2: + case SLJIT_PREFETCH_L3: + case SLJIT_PREFETCH_ONCE: + SLJIT_ASSERT(reg_map[1] == 0 && reg_map[3] == 2 && reg_map[5] == 4); + + /* The reg_map[op] should provide the appropriate constant. */ + if (op == SLJIT_PREFETCH_L1) + op = 1; + else if (op == SLJIT_PREFETCH_L2) + op = 3; + else if (op == SLJIT_PREFETCH_L3) + op = 5; + else + op = 2; + + /* Signed word sized load is the prefetch instruction. */ + return emit_op_mem(compiler, WORD_SIZE | SIGNED, op, src, srcw, TMP_REG1); + } + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -1578,20 +1596,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_LR, dst, dstw, TMP_REG1); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); - - if (FAST_IS_REG(src)) - FAIL_IF(push_inst(compiler, ORR | RD(TMP_LR) | RN(TMP_ZERO) | RM(src))); - else - FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_LR, src, srcw, TMP_REG1)); - - return push_inst(compiler, RET | RN(TMP_LR)); -} - /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ @@ -1865,7 +1869,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -256)) + if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256)) return SLJIT_ERR_UNSUPPORTED; if (type & SLJIT_MEM_SUPP) @@ -1915,7 +1919,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil CHECK_ERROR(); CHECK(check_sljit_emit_fmem(compiler, type, freg, mem, memw)); - if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -256)) + if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -256)) return SLJIT_ERR_UNSUPPORTED; if (type & SLJIT_MEM_SUPP) @@ -2021,15 +2025,24 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct slj 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; - modify_imm64_const(inst, new_target); + sljit_s32 dst; + SLJIT_UNUSED_ARG(executable_offset); + + SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0); + + dst = inst[0] & 0x1f; + SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ && (inst[1] & 0xffe00000) == (MOVK | (1 << 21))); + inst[0] = MOVZ | dst | ((new_target & 0xffff) << 5); + inst[1] = MOVK | dst | (((new_target >> 16) & 0xffff) << 5) | (1 << 21); + inst[2] = MOVK | dst | (((new_target >> 32) & 0xffff) << 5) | (2 << 21); + inst[3] = MOVK | dst | ((new_target >> 48) << 5) | (3 << 21); + + SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 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_ins* inst = (sljit_ins*)addr; - modify_imm64_const(inst, new_constant); - inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); - SLJIT_CACHE_FLUSH(inst, inst + 4); + sljit_set_jump_addr(addr, new_constant, executable_offset); } diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c index cdfe4a4d24..4624882f42 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c @@ -377,7 +377,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); - code = (sljit_u16*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_u16)); + code = (sljit_u16*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_u16), compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; @@ -463,6 +463,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil 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); + /* Set thumb mode flag. */ return (void*)((sljit_uw)code | 0x1); } @@ -480,6 +482,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: + case SLJIT_HAS_PREFETCH: return 1; default: @@ -607,7 +610,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s Although some clever things could be done here, "NOT IMM" does not worth the efforts. */ break; case SLJIT_ADD: - nimm = -imm; + nimm = -(sljit_sw)imm; if (IS_2_LO_REGS(reg, dst)) { if (imm <= 0x7) return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); @@ -629,7 +632,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s nimm = get_imm(imm); if (nimm != INVALID_IMM) return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); - nimm = get_imm(-imm); + nimm = get_imm(-(sljit_sw)imm); if (nimm != INVALID_IMM) return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); break; @@ -654,11 +657,11 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s nimm = get_imm(imm); if (nimm != INVALID_IMM) return push_inst32(compiler, CMPI_W | RN4(reg) | nimm); - nimm = get_imm(-imm); + nimm = get_imm(-(sljit_sw)imm); if (nimm != INVALID_IMM) return push_inst32(compiler, CMNI_W | RN4(reg) | nimm); } - nimm = -imm; + nimm = -(sljit_sw)imm; if (IS_2_LO_REGS(reg, dst)) { if (imm <= 0x7) return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg)); @@ -680,7 +683,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s nimm = get_imm(imm); if (nimm != INVALID_IMM) return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); - nimm = get_imm(-imm); + nimm = get_imm(-(sljit_sw)imm); if (nimm != INVALID_IMM) return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm); break; @@ -1328,6 +1331,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile } return SLJIT_SUCCESS; #endif /* __ARM_FEATURE_IDIV || __ARM_ARCH_EXT_IDIV__ */ + case SLJIT_ENDBR: + case SLJIT_SKIP_FRAMES_BEFORE_RETURN: + return SLJIT_SUCCESS; } return SLJIT_SUCCESS; @@ -1345,13 +1351,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); - if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { - /* Since TMP_PC has index 15, IS_2_LO_REGS and IS_3_LO_REGS checks always fail. */ - if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) - return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1); - return SLJIT_SUCCESS; - } - dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1; op = GET_OPCODE(op); @@ -1475,6 +1474,35 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG2); } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); + ADJUST_LOCAL_OFFSET(src, srcw); + + switch (op) { + case SLJIT_FAST_RETURN: + SLJIT_ASSERT(reg_map[TMP_REG2] == 14); + + if (FAST_IS_REG(src)) + FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src))); + else + FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2)); + + return push_inst16(compiler, BX | RN3(TMP_REG2)); + case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: + return SLJIT_SUCCESS; + case SLJIT_PREFETCH_L1: + case SLJIT_PREFETCH_L2: + case SLJIT_PREFETCH_L3: + case SLJIT_PREFETCH_ONCE: + return emit_op_mem(compiler, PRELOAD, TMP_PC, src, srcw, TMP_REG1); + } + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -1728,22 +1756,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * return emit_op_mem(compiler, WORD_SIZE | STORE, TMP_REG2, dst, dstw, TMP_REG1); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); - - SLJIT_ASSERT(reg_map[TMP_REG2] == 14); - - if (FAST_IS_REG(src)) - FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG2, src))); - else - FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG2, src, srcw, TMP_REG2)); - - return push_inst16(compiler, BX | RN3(TMP_REG2)); -} - /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ @@ -2264,7 +2276,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile CHECK_ERROR(); CHECK(check_sljit_emit_mem(compiler, type, reg, mem, memw)); - if ((mem & OFFS_REG_MASK) || (memw > 255 && memw < -255)) + if ((mem & OFFS_REG_MASK) || (memw > 255 || memw < -255)) return SLJIT_ERR_UNSUPPORTED; if (type & SLJIT_MEM_SUPP) @@ -2356,15 +2368,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct slj SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { sljit_u16 *inst = (sljit_u16*)addr; + SLJIT_UNUSED_ARG(executable_offset); + + SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0); modify_imm32_const(inst, new_target); + SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1); inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); 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_u16 *inst = (sljit_u16*)addr; - modify_imm32_const(inst, new_constant); - inst = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); - SLJIT_CACHE_FLUSH(inst, inst + 4); + sljit_set_jump_addr(addr, new_constant, executable_offset); } diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c index 16dec052fe..f887ee1311 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c @@ -86,12 +86,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S8) { -#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst)); -#else +#else /* SLJIT_MIPS_REV < 1 */ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst))); return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst)); -#endif +#endif /* SLJIT_MIPS_REV >= 1 */ } return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst)); } @@ -105,12 +105,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { if (op == SLJIT_MOV_S16) { -#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst)); -#else +#else /* SLJIT_MIPS_REV < 1 */ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst))); return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst)); -#endif +#endif /* SLJIT_MIPS_REV >= 1 */ } return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst)); } @@ -129,12 +129,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); -#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, CLZ | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (!(flags & UNUSED_DEST)) FAIL_IF(push_inst(compiler, CLZ | S(src2) | T(dst) | D(dst), DR(dst))); -#else +#else /* SLJIT_MIPS_REV < 1 */ if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { FAIL_IF(push_inst(compiler, SRL | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); @@ -149,7 +149,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl FAIL_IF(push_inst(compiler, ADDIU | S(dst) | T(dst) | IMM(1), DR(dst))); FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, SLL | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); -#endif +#endif /* SLJIT_MIPS_REV >= 1 */ return SLJIT_SUCCESS; case SLJIT_ADD: @@ -368,21 +368,22 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl SLJIT_ASSERT(!(flags & SRC2_IMM)); if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) { -#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) || (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); -#else /* !SLJIT_MIPS_R1 && !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 1 */ FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); return push_inst(compiler, MFLO | D(dst), DR(dst)); -#endif /* SLJIT_MIPS_R1 || SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 1 */ } -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) + +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) FAIL_IF(push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst))); FAIL_IF(push_inst(compiler, MUH | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); -#else /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ FAIL_IF(push_inst(compiler, MULT | S(src1) | T(src2), MOVABLE_INS)); FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ FAIL_IF(push_inst(compiler, SRA | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); return push_inst(compiler, SUBU | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); @@ -424,23 +425,20 @@ 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_UNUSED_ARG(executable_offset); + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0); SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI); inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff); + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { - sljit_ins *inst = (sljit_ins *)addr; - - SLJIT_ASSERT((inst[0] & 0xffe00000) == LUI && (inst[1] & 0xfc000000) == ORI); - inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff); - inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff); - inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); - SLJIT_CACHE_FLUSH(inst, inst + 2); + sljit_set_jump_addr(addr, new_constant, executable_offset); } static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr) diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c index a6a2bcc0c9..5ab9b7d06b 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c @@ -220,12 +220,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl case SLJIT_CLZ: SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); -#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) if (op & SLJIT_SET_Z) FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | TA(EQUAL_FLAG) | DA(EQUAL_FLAG), EQUAL_FLAG)); if (!(flags & UNUSED_DEST)) FAIL_IF(push_inst(compiler, SELECT_OP(DCLZ, CLZ) | S(src2) | T(dst) | D(dst), DR(dst))); -#else +#else /* SLJIT_MIPS_REV < 1 */ if (SLJIT_UNLIKELY(flags & UNUSED_DEST)) { FAIL_IF(push_inst(compiler, SELECT_OP(DSRL32, SRL) | T(src2) | DA(EQUAL_FLAG) | SH_IMM(31), EQUAL_FLAG)); return push_inst(compiler, XORI | SA(EQUAL_FLAG) | TA(EQUAL_FLAG) | IMM(1), EQUAL_FLAG); @@ -240,7 +240,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst))); FAIL_IF(push_inst(compiler, BGEZ | S(TMP_REG1) | IMM(-2), UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, SELECT_OP(DSLL, SLL) | T(TMP_REG1) | D(TMP_REG1) | SH_IMM(1), UNMOVABLE_INS)); -#endif +#endif /* SLJIT_MIPS_REV >= 1 */ return SLJIT_SUCCESS; case SLJIT_ADD: @@ -459,26 +459,27 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl SLJIT_ASSERT(!(flags & SRC2_IMM)); if (GET_FLAG_TYPE(op) != SLJIT_MUL_OVERFLOW) { -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst)); -#elif (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) if (op & SLJIT_I32_OP) return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst)); FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS)); return push_inst(compiler, MFLO | D(dst), DR(dst)); -#else /* !SLJIT_MIPS_R6 && !SLJIT_MIPS_R1 */ +#else /* SLJIT_MIPS_REV < 1 */ FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); return push_inst(compiler, MFLO | D(dst), DR(dst)); -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ } -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) + +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) FAIL_IF(push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst))); FAIL_IF(push_inst(compiler, SELECT_OP(DMUH, MUH) | S(src1) | T(src2) | DA(EQUAL_FLAG), EQUAL_FLAG)); -#else /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ FAIL_IF(push_inst(compiler, SELECT_OP(DMULT, MULT) | S(src1) | T(src2), MOVABLE_INS)); FAIL_IF(push_inst(compiler, MFHI | DA(EQUAL_FLAG), EQUAL_FLAG)); FAIL_IF(push_inst(compiler, MFLO | D(dst), DR(dst))); -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ FAIL_IF(push_inst(compiler, SELECT_OP(DSRA32, SRA) | T(dst) | DA(OTHER_FLAG) | SH_IMM(31), OTHER_FLAG)); return push_inst(compiler, SELECT_OP(DSUBU, SUBU) | SA(EQUAL_FLAG) | TA(OTHER_FLAG) | DA(OTHER_FLAG), OTHER_FLAG); @@ -524,25 +525,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_UNUSED_ARG(executable_offset); + SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 0); inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff); inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff); inst[5] = (inst[5] & 0xffff0000) | (new_target & 0xffff); + SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 6); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { - sljit_ins *inst = (sljit_ins *)addr; - - inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff); - inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff); - inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff); - inst[5] = (inst[5] & 0xffff0000) | (new_constant & 0xffff); - inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); - SLJIT_CACHE_FLUSH(inst, inst + 6); + sljit_set_jump_addr(addr, new_constant, executable_offset); } static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr) diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c index 7d1d087496..ecf4dac4c8 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c @@ -25,15 +25,16 @@ */ /* Latest MIPS architecture. */ -/* Automatically detect SLJIT_MIPS_R1 */ -#if (defined __mips_isa_rev) && (__mips_isa_rev >= 6) -#define SLJIT_MIPS_R6 1 +#ifndef __mips_hard_float +/* Disable automatic detection, covers both -msoft-float and -mno-float */ +#undef SLJIT_IS_FPU_AVAILABLE +#define SLJIT_IS_FPU_AVAILABLE 0 #endif SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) { -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) return "MIPS32-R6" SLJIT_CPUINFO; @@ -41,7 +42,7 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) return "MIPS64-R6" SLJIT_CPUINFO; #endif /* SLJIT_CONFIG_MIPS_32 */ -#elif (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) return "MIPS32-R1" SLJIT_CPUINFO; @@ -49,9 +50,9 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) return "MIPS64-R1" SLJIT_CPUINFO; #endif /* SLJIT_CONFIG_MIPS_32 */ -#else /* SLJIT_MIPS_R1 */ +#else /* SLJIT_MIPS_REV < 1 */ return "MIPS III" SLJIT_CPUINFO; -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ } /* Length of an instruction word @@ -117,11 +118,11 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define FR(dr) (freg_map[dr]) #define HI(opcode) ((opcode) << 26) #define LO(opcode) (opcode) -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) /* CMP.cond.fmt */ /* S = (20 << 21) D = (21 << 21) */ #define CMP_FMT_S (20 << 21) -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ /* S = (16 << 21) D = (17 << 21) */ #define FMT_S (16 << 21) #define FMT_D (17 << 21) @@ -134,13 +135,13 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define ANDI (HI(12)) #define B (HI(4)) #define BAL (HI(1) | (17 << 16)) -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #define BC1EQZ (HI(17) | (9 << 21) | FT(TMP_FREG3)) #define BC1NEZ (HI(17) | (13 << 21) | FT(TMP_FREG3)) -#else /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ #define BC1F (HI(17) | (8 << 21)) #define BC1T (HI(17) | (8 << 21) | (1 << 16)) -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ #define BEQ (HI(4)) #define BGEZ (HI(1) | (1 << 16)) #define BGTZ (HI(7)) @@ -149,23 +150,23 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define BNE (HI(5)) #define BREAK (HI(0) | LO(13)) #define CFC1 (HI(17) | (2 << 21)) -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #define C_UEQ_S (HI(17) | CMP_FMT_S | LO(3)) #define C_ULE_S (HI(17) | CMP_FMT_S | LO(7)) #define C_ULT_S (HI(17) | CMP_FMT_S | LO(5)) #define C_UN_S (HI(17) | CMP_FMT_S | LO(1)) #define C_FD (FD(TMP_FREG3)) -#else /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ #define C_UEQ_S (HI(17) | FMT_S | LO(51)) #define C_ULE_S (HI(17) | FMT_S | LO(55)) #define C_ULT_S (HI(17) | FMT_S | LO(53)) #define C_UN_S (HI(17) | FMT_S | LO(49)) #define C_FD (0) -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ #define CVT_S_S (HI(17) | FMT_S | LO(32)) #define DADDIU (HI(25)) #define DADDU (HI(0) | LO(45)) -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #define DDIV (HI(0) | (2 << 6) | LO(30)) #define DDIVU (HI(0) | (2 << 6) | LO(31)) #define DMOD (HI(0) | (3 << 6) | LO(30)) @@ -176,14 +177,14 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define DMUHU (HI(0) | (3 << 6) | LO(29)) #define DMUL (HI(0) | (2 << 6) | LO(28)) #define DMULU (HI(0) | (2 << 6) | LO(29)) -#else /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ #define DDIV (HI(0) | LO(30)) #define DDIVU (HI(0) | LO(31)) #define DIV (HI(0) | LO(26)) #define DIVU (HI(0) | LO(27)) #define DMULT (HI(0) | LO(28)) #define DMULTU (HI(0) | LO(29)) -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ #define DIV_S (HI(17) | FMT_S | LO(3)) #define DSLL (HI(0) | LO(56)) #define DSLL32 (HI(0) | LO(60)) @@ -198,33 +199,33 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define J (HI(2)) #define JAL (HI(3)) #define JALR (HI(0) | LO(9)) -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #define JR (HI(0) | LO(9)) -#else /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ #define JR (HI(0) | LO(8)) -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ #define LD (HI(55)) #define LUI (HI(15)) #define LW (HI(35)) #define MFC1 (HI(17)) -#if !(defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) -#define MFHI (HI(0) | LO(16)) -#define MFLO (HI(0) | LO(18)) -#else /* SLJIT_MIPS_R6 */ +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #define MOD (HI(0) | (3 << 6) | LO(26)) #define MODU (HI(0) | (3 << 6) | LO(27)) -#endif /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ +#define MFHI (HI(0) | LO(16)) +#define MFLO (HI(0) | LO(18)) +#endif /* SLJIT_MIPS_REV >= 6 */ #define MOV_S (HI(17) | FMT_S | LO(6)) #define MTC1 (HI(17) | (4 << 21)) -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #define MUH (HI(0) | (3 << 6) | LO(24)) #define MUHU (HI(0) | (3 << 6) | LO(25)) #define MUL (HI(0) | (2 << 6) | LO(24)) #define MULU (HI(0) | (2 << 6) | LO(25)) -#else /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ #define MULT (HI(0) | LO(24)) #define MULTU (HI(0) | LO(25)) -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ #define MUL_S (HI(17) | FMT_S | LO(2)) #define NEG_S (HI(17) | FMT_S | LO(7)) #define NOP (HI(0) | LO(0)) @@ -251,23 +252,23 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { #define XOR (HI(0) | LO(38)) #define XORI (HI(14)) -#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) || (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) #define CLZ (HI(28) | LO(32)) -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #define DCLZ (LO(18)) -#else /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ #define DCLZ (HI(28) | LO(36)) #define MOVF (HI(0) | (0 << 16) | LO(1)) #define MOVN (HI(0) | LO(11)) #define MOVT (HI(0) | (1 << 16) | LO(1)) #define MOVZ (HI(0) | LO(10)) #define MUL (HI(28) | LO(2)) -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ #define PREF (HI(51)) #define PREFX (HI(19) | LO(15)) #define SEB (HI(31) | (16 << 6) | LO(32)) #define SEH (HI(31) | (24 << 6) | LO(32)) -#endif +#endif /* SLJIT_MIPS_REV >= 1 */ #if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) #define ADDU_W ADDU @@ -289,9 +290,9 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = { Useful for reordering instructions in the delay slot. */ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit_s32 delay_slot) { + sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS || delay_slot == ((ins >> 11) & 0x1f) || delay_slot == ((ins >> 16) & 0x1f)); - sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins)); FAIL_IF(!ptr); *ptr = ins; compiler->size++; @@ -303,10 +304,10 @@ static SLJIT_INLINE sljit_ins invert_branch(sljit_s32 flags) { if (flags & IS_BIT26_COND) return (1 << 26); -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) if (flags & IS_BIT23_COND) return (1 << 23); -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ return (1 << 16); } @@ -519,7 +520,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); - code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); + code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; @@ -666,6 +667,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil /* GCC workaround for invalid code generation with -O2. */ sljit_cache_flush(code, code_ptr); #endif + SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1); return code; } @@ -678,17 +680,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) #ifdef SLJIT_IS_FPU_AVAILABLE return SLJIT_IS_FPU_AVAILABLE; #elif defined(__GNUC__) - asm ("cfc1 %0, $0" : "=r"(fir)); + __asm__ ("cfc1 %0, $0" : "=r"(fir)); return (fir >> 22) & 0x1; #else #error "FIR check is not implemented for this architecture" #endif + case SLJIT_HAS_ZERO_REGISTER: + return 1; -#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) case SLJIT_HAS_CLZ: case SLJIT_HAS_CMOV: + case SLJIT_HAS_PREFETCH: return 1; -#endif +#endif /* SLJIT_MIPS_REV >= 1 */ default: return fir; @@ -1230,7 +1235,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile return push_inst(compiler, NOP, UNMOVABLE_INS); case SLJIT_LMUL_UW: case SLJIT_LMUL_SW: -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULU : DMUL) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3))); FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMUHU : DMUH) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG1), DR(TMP_REG1))); @@ -1240,7 +1245,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile #endif /* SLJIT_CONFIG_MIPS_64 */ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0))); return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1)); -#else /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) FAIL_IF(push_inst(compiler, (op == SLJIT_LMUL_UW ? DMULTU : DMULT) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); #else /* !SLJIT_CONFIG_MIPS_64 */ @@ -1248,13 +1253,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile #endif /* SLJIT_CONFIG_MIPS_64 */ FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ case SLJIT_DIVMOD_UW: case SLJIT_DIVMOD_SW: case SLJIT_DIV_UW: case SLJIT_DIV_SW: SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments); -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (int_op) { FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1) | D(TMP_REG3), DR(TMP_REG3))); @@ -1270,11 +1275,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile #endif /* SLJIT_CONFIG_MIPS_64 */ FAIL_IF(push_inst(compiler, ADDU_W | S(TMP_REG3) | TA(0) | D(SLJIT_R0), DR(SLJIT_R0))); return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_R1), DR(SLJIT_R1)); -#else /* !SLJIT_MIPS_R6 */ -#if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +#else /* SLJIT_MIPS_REV < 6 */ +#if !(defined SLJIT_MIPS_REV) FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); -#endif /* !SLJIT_MIPS_R1 */ +#endif /* !SLJIT_MIPS_REV */ #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (int_op) FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_DIV_UW ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); @@ -1285,13 +1290,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile #endif /* SLJIT_CONFIG_MIPS_64 */ FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); return (op >= SLJIT_DIV_UW) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ + case SLJIT_ENDBR: + case SLJIT_SKIP_FRAMES_BEFORE_RETURN: + return SLJIT_SUCCESS; } return SLJIT_SUCCESS; } -#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { @@ -1312,7 +1320,7 @@ static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, return push_inst(compiler, PREFX | S(src & REG_MASK) | T(OFFS_REG(src)), MOVABLE_INS); } -#endif +#endif /* SLJIT_MIPS_REV >= 1 */ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, @@ -1329,14 +1337,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); - if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { -#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) - if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) - return emit_prefetch(compiler, src, srcw); -#endif - return SLJIT_SUCCESS; - } - #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT) flags |= INT_DATA | SIGNED_DATA; @@ -1463,6 +1463,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile #endif } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); + ADJUST_LOCAL_OFFSET(src, srcw); + + switch (op) { + case SLJIT_FAST_RETURN: + if (FAST_IS_REG(src)) + FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG)); + else + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw)); + + FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS)); + return push_inst(compiler, NOP, UNMOVABLE_INS); + case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: + return SLJIT_SUCCESS; + case SLJIT_PREFETCH_L1: + case SLJIT_PREFETCH_L2: + case SLJIT_PREFETCH_L3: + case SLJIT_PREFETCH_ONCE: +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1) + return emit_prefetch(compiler, src, srcw); +#else /* SLJIT_MIPS_REV < 1 */ + return SLJIT_SUCCESS; +#endif /* SLJIT_MIPS_REV >= 1 */ + } + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -1732,25 +1764,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * ADJUST_LOCAL_OFFSET(dst, dstw); if (FAST_IS_REG(dst)) - return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), DR(dst)); + return push_inst(compiler, ADDU_W | SA(RETURN_ADDR_REG) | TA(0) | D(dst), UNMOVABLE_INS); /* Memory. */ - return emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); - - if (FAST_IS_REG(src)) - FAIL_IF(push_inst(compiler, ADDU_W | S(src) | TA(0) | DA(RETURN_ADDR_REG), RETURN_ADDR_REG)); - else - FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG, src, srcw)); - - FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS)); - return push_inst(compiler, NOP, UNMOVABLE_INS); + FAIL_IF(emit_op_mem(compiler, WORD_DATA, RETURN_ADDR_REG, dst, dstw)); + compiler->delay_slot = UNMOVABLE_INS; + return SLJIT_SUCCESS; } /* --------------------------------------------------------------------- */ @@ -1790,7 +1809,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi flags = IS_BIT26_COND; \ delay_check = src; -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) #define BR_T() \ inst = BC1NEZ; \ @@ -1801,7 +1820,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi flags = IS_BIT23_COND; \ delay_check = FCSR_FCC; -#else /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ #define BR_T() \ inst = BC1T | JUMP_LENGTH; \ @@ -1812,7 +1831,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi flags = IS_BIT16_COND; \ delay_check = FCSR_FCC; -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) { @@ -2123,11 +2142,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co case SLJIT_GREATER_EQUAL_F64: case SLJIT_UNORDERED_F64: case SLJIT_ORDERED_F64: -#if (defined SLJIT_MIPS_R6 && SLJIT_MIPS_R6) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6) FAIL_IF(push_inst(compiler, MFC1 | TA(dst_ar) | FS(TMP_FREG3), dst_ar)); -#else /* !SLJIT_MIPS_R6 */ +#else /* SLJIT_MIPS_REV < 6 */ FAIL_IF(push_inst(compiler, CFC1 | TA(dst_ar) | DA(FCSR_REG), dst_ar)); -#endif /* SLJIT_MIPS_R6 */ +#endif /* SLJIT_MIPS_REV >= 6 */ FAIL_IF(push_inst(compiler, SRL | TA(dst_ar) | DA(dst_ar) | SH_IMM(23), dst_ar)); FAIL_IF(push_inst(compiler, ANDI | SA(dst_ar) | TA(dst_ar) | IMM(1), dst_ar)); src_ar = dst_ar; @@ -2167,14 +2186,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil sljit_s32 dst_reg, sljit_s32 src, sljit_sw srcw) { -#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) sljit_ins ins; -#endif +#endif /* SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6 */ CHECK_ERROR(); CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); -#if (defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) +#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1 && SLJIT_MIPS_REV < 6) if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) @@ -2231,9 +2250,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil return push_inst(compiler, ins | S(src) | D(dst_reg), DR(dst_reg)); -#else +#else /* SLJIT_MIPS_REV < 1 || SLJIT_MIPS_REV >= 6 */ return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw); -#endif +#endif /* SLJIT_MIPS_REV >= 1 */ } SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c index 3ce741153f..7d9ec5338f 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c @@ -258,21 +258,18 @@ 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_UNUSED_ARG(executable_offset); + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0); SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI); inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 16) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | (new_target & 0xffff); + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 1); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 2); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { - sljit_ins *inst = (sljit_ins *)addr; - - SLJIT_ASSERT((inst[0] & 0xfc1f0000) == ADDIS && (inst[1] & 0xfc000000) == ORI); - inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 16) & 0xffff); - inst[1] = (inst[1] & 0xffff0000) | (new_constant & 0xffff); - inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); - SLJIT_CACHE_FLUSH(inst, inst + 2); + sljit_set_jump_addr(addr, new_constant, executable_offset); } diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c index 3b73021cc8..92147d2a5d 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c +++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c @@ -477,23 +477,19 @@ 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_UNUSED_ARG(executable_offset); + SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0); inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff); inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff); inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff); inst[4] = (inst[4] & 0xffff0000) | (new_target & 0xffff); + SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1); inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); SLJIT_CACHE_FLUSH(inst, inst + 5); } SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset) { - sljit_ins *inst = (sljit_ins*)addr; - - inst[0] = (inst[0] & 0xffff0000) | ((new_constant >> 48) & 0xffff); - inst[1] = (inst[1] & 0xffff0000) | ((new_constant >> 32) & 0xffff); - inst[3] = (inst[3] & 0xffff0000) | ((new_constant >> 16) & 0xffff); - inst[4] = (inst[4] & 0xffff0000) | (new_constant & 0xffff); - inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); - SLJIT_CACHE_FLUSH(inst, inst + 5); + sljit_set_jump_addr(addr, new_constant, executable_offset); } diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c index e827514315..d84562ce09 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c +++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c @@ -404,7 +404,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil compiler->size += (sizeof(struct sljit_function_context) / sizeof(sljit_ins)); #endif #endif - code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); + code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; @@ -607,6 +607,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); SLJIT_CACHE_FLUSH(code, code_ptr); + SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1); #if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) return code_ptr; @@ -626,7 +627,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) return 1; #endif + /* A saved register is set to a zero value. */ + case SLJIT_HAS_ZERO_REGISTER: case SLJIT_HAS_CLZ: + case SLJIT_HAS_PREFETCH: return 1; default: @@ -1158,6 +1162,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile #else return push_inst(compiler, (op == SLJIT_DIV_UW ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); #endif + case SLJIT_ENDBR: + case SLJIT_SKIP_FRAMES_BEFORE_RETURN: + return SLJIT_SUCCESS; } return SLJIT_SUCCESS; @@ -1203,13 +1210,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); - if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { - if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) - return emit_prefetch(compiler, src, srcw); - - return SLJIT_SUCCESS; - } - op = GET_OPCODE(op); if ((src & SLJIT_IMM) && srcw == 0) src = TMP_ZERO; @@ -1536,6 +1536,35 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); + ADJUST_LOCAL_OFFSET(src, srcw); + + switch (op) { + case SLJIT_FAST_RETURN: + if (FAST_IS_REG(src)) + FAIL_IF(push_inst(compiler, MTLR | S(src))); + else { + FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); + FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2))); + } + + return push_inst(compiler, BLR); + case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: + return SLJIT_SUCCESS; + case SLJIT_PREFETCH_L1: + case SLJIT_PREFETCH_L2: + case SLJIT_PREFETCH_L3: + case SLJIT_PREFETCH_ONCE: + return emit_prefetch(compiler, src, srcw); + } + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -1854,22 +1883,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0); } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); - - if (FAST_IS_REG(src)) - FAIL_IF(push_inst(compiler, MTLR | S(src))); - else { - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); - FAIL_IF(push_inst(compiler, MTLR | S(TMP_REG2))); - } - - return push_inst(compiler, BLR); -} - /* --------------------------------------------------------------------- */ /* Conditional instructions */ /* --------------------------------------------------------------------- */ diff --git a/thirdparty/pcre2/src/sljit/sljitNativeS390X.c b/thirdparty/pcre2/src/sljit/sljitNativeS390X.c new file mode 100644 index 0000000000..a8b65112d4 --- /dev/null +++ b/thirdparty/pcre2/src/sljit/sljitNativeS390X.c @@ -0,0 +1,2812 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/auxv.h> + +#ifdef __ARCH__ +#define ENABLE_STATIC_FACILITY_DETECTION 1 +#else +#define ENABLE_STATIC_FACILITY_DETECTION 0 +#endif +#define ENABLE_DYNAMIC_FACILITY_DETECTION 1 + +SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void) +{ + return "s390x" SLJIT_CPUINFO; +} + +/* Instructions. */ +typedef sljit_uw sljit_ins; + +/* Instruction tags (most significant halfword). */ +const sljit_ins sljit_ins_const = (sljit_ins)1 << 48; + +static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = { + 14, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 0, 1 +}; + +/* there are also a[2-15] available, but they are slower to access and + * their use is limited as mundaym explained: + * https://github.com/zherczeg/sljit/pull/91#discussion_r486895689 + */ + +/* General Purpose Registers [0-15]. */ +typedef sljit_uw sljit_gpr; + +/* + * WARNING + * the following code is non standard and should be improved for + * consistency, but doesn't use SLJIT_NUMBER_OF_REGISTERS based + * registers because r0 and r1 are the ABI recommended volatiles. + * there is a gpr() function that maps sljit to physical register numbers + * that should be used instead of the usual index into reg_map[] and + * will be retired ASAP (TODO: carenas) + */ + +const sljit_gpr r0 = 0; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 2]: 0 in address calculations; reserved */ +const sljit_gpr r1 = 1; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 3]: reserved */ +const sljit_gpr r2 = 2; /* reg_map[1]: 1st argument */ +const sljit_gpr r3 = 3; /* reg_map[2]: 2nd argument */ +const sljit_gpr r4 = 4; /* reg_map[3]: 3rd argument */ +const sljit_gpr r5 = 5; /* reg_map[4]: 4th argument */ +const sljit_gpr r6 = 6; /* reg_map[5]: 5th argument; 1st saved register */ +const sljit_gpr r7 = 7; /* reg_map[6] */ +const sljit_gpr r8 = 8; /* reg_map[7] */ +const sljit_gpr r9 = 9; /* reg_map[8] */ +const sljit_gpr r10 = 10; /* reg_map[9] */ +const sljit_gpr r11 = 11; /* reg_map[10] */ +const sljit_gpr r12 = 12; /* reg_map[11]: GOT */ +const sljit_gpr r13 = 13; /* reg_map[12]: Literal Pool pointer */ +const sljit_gpr r14 = 14; /* reg_map[0]: return address and flag register */ +const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stack pointer */ + +/* WARNING: r12 and r13 shouldn't be used as per ABI recommendation */ +/* TODO(carenas): r12 might conflict in PIC code, reserve? */ +/* TODO(carenas): r13 is usually pointed to "pool" per ABI, using a tmp + * like we do know might be faster though, reserve? + */ + +/* TODO(carenas): should be named TMP_REG[1-2] for consistency */ +#define tmp0 r0 +#define tmp1 r1 + +/* TODO(carenas): flags should move to a different register so that + * link register doesn't need to change + */ + +/* Link registers. The normal link register is r14, but since + we use that for flags we need to use r0 instead to do fast + calls so that flags are preserved. */ +const sljit_gpr link_r = 14; /* r14 */ +const sljit_gpr fast_link_r = 0; /* r0 */ + +/* Flag register layout: + + 0 32 33 34 36 64 + +---------------+---+---+-------+-------+ + | ZERO | 0 | 0 | C C |///////| + +---------------+---+---+-------+-------+ +*/ +const sljit_gpr flag_r = 14; /* r14 */ + +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) +{ + SLJIT_ASSERT(r != SLJIT_UNUSED); + SLJIT_ASSERT(r < (sljit_s32)(sizeof(reg_map) / sizeof(reg_map[0]))); + return reg_map[r]; +} + +/* Size of instruction in bytes. Tags must already be cleared. */ +static SLJIT_INLINE sljit_uw sizeof_ins(sljit_ins ins) +{ + /* keep faulting instructions */ + if (ins == 0) + return 2; + + if ((ins & 0x00000000ffffL) == ins) + return 2; + if ((ins & 0x0000ffffffffL) == ins) + return 4; + if ((ins & 0xffffffffffffL) == ins) + return 6; + + SLJIT_UNREACHABLE(); + return (sljit_uw)-1; +} + +static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) +{ + sljit_ins *ibuf = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins)); + FAIL_IF(!ibuf); + *ibuf = ins; + compiler->size++; + return SLJIT_SUCCESS; +} + +static sljit_s32 encode_inst(void **ptr, sljit_ins ins) +{ + sljit_u16 *ibuf = (sljit_u16 *)*ptr; + sljit_uw size = sizeof_ins(ins); + + SLJIT_ASSERT((size & 6) == size); + switch (size) { + case 6: + *ibuf++ = (sljit_u16)(ins >> 32); + /* fallthrough */ + case 4: + *ibuf++ = (sljit_u16)(ins >> 16); + /* fallthrough */ + case 2: + *ibuf++ = (sljit_u16)(ins); + } + *ptr = (void*)ibuf; + return SLJIT_SUCCESS; +} + +/* Map the given type to a 4-bit condition code mask. */ +static SLJIT_INLINE sljit_u8 get_cc(sljit_s32 type) { + const sljit_u8 eq = 1 << 3; /* equal {,to zero} */ + const sljit_u8 lt = 1 << 2; /* less than {,zero} */ + const sljit_u8 gt = 1 << 1; /* greater than {,zero} */ + const sljit_u8 ov = 1 << 0; /* {overflow,NaN} */ + + switch (type) { + case SLJIT_EQUAL: + case SLJIT_EQUAL_F64: + return eq; + + case SLJIT_NOT_EQUAL: + case SLJIT_NOT_EQUAL_F64: + return ~eq; + + case SLJIT_LESS: + case SLJIT_SIG_LESS: + case SLJIT_LESS_F64: + return lt; + + case SLJIT_LESS_EQUAL: + case SLJIT_SIG_LESS_EQUAL: + case SLJIT_LESS_EQUAL_F64: + return (lt | eq); + + case SLJIT_GREATER: + case SLJIT_SIG_GREATER: + case SLJIT_GREATER_F64: + return gt; + + case SLJIT_GREATER_EQUAL: + case SLJIT_SIG_GREATER_EQUAL: + case SLJIT_GREATER_EQUAL_F64: + return (gt | eq); + + case SLJIT_OVERFLOW: + case SLJIT_MUL_OVERFLOW: + case SLJIT_UNORDERED_F64: + return ov; + + case SLJIT_NOT_OVERFLOW: + case SLJIT_MUL_NOT_OVERFLOW: + case SLJIT_ORDERED_F64: + return ~ov; + } + + SLJIT_UNREACHABLE(); + return (sljit_u8)-1; +} + +/* Facility to bit index mappings. + Note: some facilities share the same bit index. */ +typedef sljit_uw facility_bit; +#define STORE_FACILITY_LIST_EXTENDED_FACILITY 7 +#define FAST_LONG_DISPLACEMENT_FACILITY 19 +#define EXTENDED_IMMEDIATE_FACILITY 21 +#define GENERAL_INSTRUCTION_EXTENSION_FACILITY 34 +#define DISTINCT_OPERAND_FACILITY 45 +#define HIGH_WORD_FACILITY 45 +#define POPULATION_COUNT_FACILITY 45 +#define LOAD_STORE_ON_CONDITION_1_FACILITY 45 +#define MISCELLANEOUS_INSTRUCTION_EXTENSIONS_1_FACILITY 49 +#define LOAD_STORE_ON_CONDITION_2_FACILITY 53 +#define MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY 58 +#define VECTOR_FACILITY 129 +#define VECTOR_ENHANCEMENTS_1_FACILITY 135 + +/* Report whether a facility is known to be present due to the compiler + settings. This function should always be compiled to a constant + value given a constant argument. */ +static SLJIT_INLINE int have_facility_static(facility_bit x) +{ +#if ENABLE_STATIC_FACILITY_DETECTION + switch (x) { + case FAST_LONG_DISPLACEMENT_FACILITY: + return (__ARCH__ >= 6 /* z990 */); + case EXTENDED_IMMEDIATE_FACILITY: + case STORE_FACILITY_LIST_EXTENDED_FACILITY: + return (__ARCH__ >= 7 /* z9-109 */); + case GENERAL_INSTRUCTION_EXTENSION_FACILITY: + return (__ARCH__ >= 8 /* z10 */); + case DISTINCT_OPERAND_FACILITY: + return (__ARCH__ >= 9 /* z196 */); + case MISCELLANEOUS_INSTRUCTION_EXTENSIONS_1_FACILITY: + return (__ARCH__ >= 10 /* zEC12 */); + case LOAD_STORE_ON_CONDITION_2_FACILITY: + case VECTOR_FACILITY: + return (__ARCH__ >= 11 /* z13 */); + case MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY: + case VECTOR_ENHANCEMENTS_1_FACILITY: + return (__ARCH__ >= 12 /* z14 */); + default: + SLJIT_UNREACHABLE(); + } +#endif + return 0; +} + +static SLJIT_INLINE unsigned long get_hwcap() +{ + static unsigned long hwcap = 0; + if (SLJIT_UNLIKELY(!hwcap)) { + hwcap = getauxval(AT_HWCAP); + SLJIT_ASSERT(hwcap != 0); + } + return hwcap; +} + +static SLJIT_INLINE int have_stfle() +{ + if (have_facility_static(STORE_FACILITY_LIST_EXTENDED_FACILITY)) + return 1; + + return (get_hwcap() & HWCAP_S390_STFLE); +} + +/* Report whether the given facility is available. This function always + performs a runtime check. */ +static int have_facility_dynamic(facility_bit x) +{ +#if ENABLE_DYNAMIC_FACILITY_DETECTION + static struct { + sljit_uw bits[4]; + } cpu_features; + size_t size = sizeof(cpu_features); + const sljit_uw word_index = x >> 6; + const sljit_uw bit_index = ((1UL << 63) >> (x & 63)); + + SLJIT_ASSERT(x < size * 8); + if (SLJIT_UNLIKELY(!have_stfle())) + return 0; + + if (SLJIT_UNLIKELY(cpu_features.bits[0] == 0)) { + __asm__ __volatile__ ( + "lgr %%r0, %0;" + "stfle 0(%1);" + /* outputs */: + /* inputs */: "d" ((size / 8) - 1), "a" (&cpu_features) + /* clobbers */: "r0", "cc", "memory" + ); + SLJIT_ASSERT(cpu_features.bits[0] != 0); + } + return (cpu_features.bits[word_index] & bit_index) != 0; +#else + return 0; +#endif +} + +#define HAVE_FACILITY(name, bit) \ +static SLJIT_INLINE int name() \ +{ \ + static int have = -1; \ + /* Static check first. May allow the function to be optimized away. */ \ + if (have_facility_static(bit)) \ + have = 1; \ + else if (SLJIT_UNLIKELY(have < 0)) \ + have = have_facility_dynamic(bit) ? 1 : 0; \ +\ + return have; \ +} + +HAVE_FACILITY(have_eimm, EXTENDED_IMMEDIATE_FACILITY) +HAVE_FACILITY(have_ldisp, FAST_LONG_DISPLACEMENT_FACILITY) +HAVE_FACILITY(have_genext, GENERAL_INSTRUCTION_EXTENSION_FACILITY) +HAVE_FACILITY(have_lscond1, LOAD_STORE_ON_CONDITION_1_FACILITY) +HAVE_FACILITY(have_lscond2, LOAD_STORE_ON_CONDITION_2_FACILITY) +HAVE_FACILITY(have_misc2, MISCELLANEOUS_INSTRUCTION_EXTENSIONS_2_FACILITY) +#undef HAVE_FACILITY + +#define is_u12(d) (0 <= (d) && (d) <= 0x00000fffL) +#define is_u32(d) (0 <= (d) && (d) <= 0xffffffffL) + +#define CHECK_SIGNED(v, bitlen) \ + ((v) == (((v) << (sizeof(v) * 8 - bitlen)) >> (sizeof(v) * 8 - bitlen))) + +#define is_s16(d) CHECK_SIGNED((d), 16) +#define is_s20(d) CHECK_SIGNED((d), 20) +#define is_s32(d) CHECK_SIGNED((d), 32) + +static SLJIT_INLINE sljit_uw disp_s20(sljit_s32 d) +{ + sljit_uw dh = (d >> 12) & 0xff; + sljit_uw dl = (d << 8) & 0xfff00; + + SLJIT_ASSERT(is_s20(d)); + return dh | dl; +} + +/* TODO(carenas): variadic macro is not strictly needed */ +#define SLJIT_S390X_INSTRUCTION(op, ...) \ +static SLJIT_INLINE sljit_ins op(__VA_ARGS__) + +/* RR form instructions. */ +#define SLJIT_S390X_RR(name, pattern) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src) \ +{ \ + return (pattern) | ((dst & 0xf) << 4) | (src & 0xf); \ +} + +/* ADD */ +SLJIT_S390X_RR(ar, 0x1a00) + +/* ADD LOGICAL */ +SLJIT_S390X_RR(alr, 0x1e00) + +/* AND */ +SLJIT_S390X_RR(nr, 0x1400) + +/* BRANCH AND SAVE */ +SLJIT_S390X_RR(basr, 0x0d00) + +/* BRANCH ON CONDITION */ +SLJIT_S390X_RR(bcr, 0x0700) /* TODO(mundaym): type for mask? */ + +/* COMPARE */ +SLJIT_S390X_RR(cr, 0x1900) + +/* COMPARE LOGICAL */ +SLJIT_S390X_RR(clr, 0x1500) + +/* DIVIDE */ +SLJIT_S390X_RR(dr, 0x1d00) + +/* EXCLUSIVE OR */ +SLJIT_S390X_RR(xr, 0x1700) + +/* LOAD */ +SLJIT_S390X_RR(lr, 0x1800) + +/* LOAD COMPLEMENT */ +SLJIT_S390X_RR(lcr, 0x1300) + +/* OR */ +SLJIT_S390X_RR(or, 0x1600) + +/* SUBTRACT */ +SLJIT_S390X_RR(sr, 0x1b00) + +/* SUBTRACT LOGICAL */ +SLJIT_S390X_RR(slr, 0x1f00) + +#undef SLJIT_S390X_RR + +/* RRE form instructions */ +#define SLJIT_S390X_RRE(name, pattern) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src) \ +{ \ + return (pattern) | ((dst & 0xf) << 4) | (src & 0xf); \ +} + +/* ADD */ +SLJIT_S390X_RRE(agr, 0xb9080000) + +/* ADD LOGICAL */ +SLJIT_S390X_RRE(algr, 0xb90a0000) + +/* ADD LOGICAL WITH CARRY */ +SLJIT_S390X_RRE(alcr, 0xb9980000) +SLJIT_S390X_RRE(alcgr, 0xb9880000) + +/* AND */ +SLJIT_S390X_RRE(ngr, 0xb9800000) + +/* COMPARE */ +SLJIT_S390X_RRE(cgr, 0xb9200000) + +/* COMPARE LOGICAL */ +SLJIT_S390X_RRE(clgr, 0xb9210000) + +/* DIVIDE LOGICAL */ +SLJIT_S390X_RRE(dlr, 0xb9970000) +SLJIT_S390X_RRE(dlgr, 0xb9870000) + +/* DIVIDE SINGLE */ +SLJIT_S390X_RRE(dsgr, 0xb90d0000) + +/* EXCLUSIVE OR */ +SLJIT_S390X_RRE(xgr, 0xb9820000) + +/* LOAD */ +SLJIT_S390X_RRE(lgr, 0xb9040000) +SLJIT_S390X_RRE(lgfr, 0xb9140000) + +/* LOAD BYTE */ +SLJIT_S390X_RRE(lbr, 0xb9260000) +SLJIT_S390X_RRE(lgbr, 0xb9060000) + +/* LOAD COMPLEMENT */ +SLJIT_S390X_RRE(lcgr, 0xb9030000) + +/* LOAD HALFWORD */ +SLJIT_S390X_RRE(lhr, 0xb9270000) +SLJIT_S390X_RRE(lghr, 0xb9070000) + +/* LOAD LOGICAL */ +SLJIT_S390X_RRE(llgfr, 0xb9160000) + +/* LOAD LOGICAL CHARACTER */ +SLJIT_S390X_RRE(llcr, 0xb9940000) +SLJIT_S390X_RRE(llgcr, 0xb9840000) + +/* LOAD LOGICAL HALFWORD */ +SLJIT_S390X_RRE(llhr, 0xb9950000) +SLJIT_S390X_RRE(llghr, 0xb9850000) + +/* MULTIPLY LOGICAL */ +SLJIT_S390X_RRE(mlgr, 0xb9860000) + +/* MULTIPLY SINGLE */ +SLJIT_S390X_RRE(msr, 0xb2520000) +SLJIT_S390X_RRE(msgr, 0xb90c0000) +SLJIT_S390X_RRE(msgfr, 0xb91c0000) + +/* OR */ +SLJIT_S390X_RRE(ogr, 0xb9810000) + +/* SUBTRACT */ +SLJIT_S390X_RRE(sgr, 0xb9090000) + +/* SUBTRACT LOGICAL */ +SLJIT_S390X_RRE(slgr, 0xb90b0000) + +/* SUBTRACT LOGICAL WITH BORROW */ +SLJIT_S390X_RRE(slbr, 0xb9990000) +SLJIT_S390X_RRE(slbgr, 0xb9890000) + +#undef SLJIT_S390X_RRE + +/* RI-a form instructions */ +#define SLJIT_S390X_RIA(name, pattern, imm_type) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, imm_type imm) \ +{ \ + return (pattern) | ((reg & 0xf) << 20) | (imm & 0xffff); \ +} + +/* ADD HALFWORD IMMEDIATE */ +SLJIT_S390X_RIA(ahi, 0xa70a0000, sljit_s16) +SLJIT_S390X_RIA(aghi, 0xa70b0000, sljit_s16) + +/* COMPARE HALFWORD IMMEDIATE */ +SLJIT_S390X_RIA(chi, 0xa70e0000, sljit_s16) +SLJIT_S390X_RIA(cghi, 0xa70f0000, sljit_s16) + +/* LOAD HALFWORD IMMEDIATE */ +SLJIT_S390X_RIA(lhi, 0xa7080000, sljit_s16) +SLJIT_S390X_RIA(lghi, 0xa7090000, sljit_s16) + +/* LOAD LOGICAL IMMEDIATE */ +SLJIT_S390X_RIA(llihh, 0xa50c0000, sljit_u16) +SLJIT_S390X_RIA(llihl, 0xa50d0000, sljit_u16) +SLJIT_S390X_RIA(llilh, 0xa50e0000, sljit_u16) +SLJIT_S390X_RIA(llill, 0xa50f0000, sljit_u16) + +/* MULTIPLY HALFWORD IMMEDIATE */ +SLJIT_S390X_RIA(mhi, 0xa70c0000, sljit_s16) +SLJIT_S390X_RIA(mghi, 0xa70d0000, sljit_s16) + +/* OR IMMEDIATE */ +SLJIT_S390X_RIA(oilh, 0xa50a0000, sljit_u16) + +/* TEST UNDER MASK */ +SLJIT_S390X_RIA(tmlh, 0xa7000000, sljit_u16) + +#undef SLJIT_S390X_RIA + +/* RIL-a form instructions (requires extended immediate facility) */ +#define SLJIT_S390X_RILA(name, pattern, imm_type) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, imm_type imm) \ +{ \ + SLJIT_ASSERT(have_eimm()); \ + return (pattern) | ((sljit_ins)(reg & 0xf) << 36) | (imm & 0xffffffff); \ +} + +/* ADD IMMEDIATE */ +SLJIT_S390X_RILA(afi, 0xc20900000000, sljit_s32) +SLJIT_S390X_RILA(agfi, 0xc20800000000, sljit_s32) + +/* ADD IMMEDIATE HIGH */ +SLJIT_S390X_RILA(aih, 0xcc0800000000, sljit_s32) /* TODO(mundaym): high-word facility? */ + +/* ADD LOGICAL IMMEDIATE */ +SLJIT_S390X_RILA(alfi, 0xc20b00000000, sljit_u32) +SLJIT_S390X_RILA(algfi, 0xc20a00000000, sljit_u32) + +/* AND IMMEDIATE */ +SLJIT_S390X_RILA(nihf, 0xc00a00000000, sljit_u32) +SLJIT_S390X_RILA(nilf, 0xc00b00000000, sljit_u32) + +/* COMPARE IMMEDIATE */ +SLJIT_S390X_RILA(cfi, 0xc20d00000000, sljit_s32) +SLJIT_S390X_RILA(cgfi, 0xc20c00000000, sljit_s32) + +/* COMPARE IMMEDIATE HIGH */ +SLJIT_S390X_RILA(cih, 0xcc0d00000000, sljit_s32) /* TODO(mundaym): high-word facility? */ + +/* COMPARE LOGICAL IMMEDIATE */ +SLJIT_S390X_RILA(clfi, 0xc20f00000000, sljit_u32) +SLJIT_S390X_RILA(clgfi, 0xc20e00000000, sljit_u32) + +/* EXCLUSIVE OR IMMEDIATE */ +SLJIT_S390X_RILA(xilf, 0xc00700000000, sljit_u32) + +/* INSERT IMMEDIATE */ +SLJIT_S390X_RILA(iihf, 0xc00800000000, sljit_u32) +SLJIT_S390X_RILA(iilf, 0xc00900000000, sljit_u32) + +/* LOAD IMMEDIATE */ +SLJIT_S390X_RILA(lgfi, 0xc00100000000, sljit_s32) + +/* LOAD LOGICAL IMMEDIATE */ +SLJIT_S390X_RILA(llihf, 0xc00e00000000, sljit_u32) +SLJIT_S390X_RILA(llilf, 0xc00f00000000, sljit_u32) + +/* OR IMMEDIATE */ +SLJIT_S390X_RILA(oilf, 0xc00d00000000, sljit_u32) + +#undef SLJIT_S390X_RILA + +/* RX-a form instructions */ +#define SLJIT_S390X_RXA(name, pattern) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr r, sljit_u16 d, sljit_gpr x, sljit_gpr b) \ +{ \ + sljit_ins ri, xi, bi, di; \ +\ + SLJIT_ASSERT((d & 0xfff) == d); \ + ri = (sljit_ins)(r & 0xf) << 20; \ + xi = (sljit_ins)(x & 0xf) << 16; \ + bi = (sljit_ins)(b & 0xf) << 12; \ + di = (sljit_ins)(d & 0xfff); \ +\ + return (pattern) | ri | xi | bi | di; \ +} + +/* ADD */ +SLJIT_S390X_RXA(a, 0x5a000000) + +/* ADD LOGICAL */ +SLJIT_S390X_RXA(al, 0x5e000000) + +/* AND */ +SLJIT_S390X_RXA(n, 0x54000000) + +/* EXCLUSIVE OR */ +SLJIT_S390X_RXA(x, 0x57000000) + +/* LOAD */ +SLJIT_S390X_RXA(l, 0x58000000) + +/* LOAD ADDRESS */ +SLJIT_S390X_RXA(la, 0x41000000) + +/* LOAD HALFWORD */ +SLJIT_S390X_RXA(lh, 0x48000000) + +/* MULTIPLY SINGLE */ +SLJIT_S390X_RXA(ms, 0x71000000) + +/* OR */ +SLJIT_S390X_RXA(o, 0x56000000) + +/* STORE */ +SLJIT_S390X_RXA(st, 0x50000000) + +/* STORE CHARACTER */ +SLJIT_S390X_RXA(stc, 0x42000000) + +/* STORE HALFWORD */ +SLJIT_S390X_RXA(sth, 0x40000000) + +/* SUBTRACT */ +SLJIT_S390X_RXA(s, 0x5b000000) + +/* SUBTRACT LOGICAL */ +SLJIT_S390X_RXA(sl, 0x5f000000) + +#undef SLJIT_S390X_RXA + +/* RXY-a instructions */ +#define SLJIT_S390X_RXYA(name, pattern, cond) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b) \ +{ \ + sljit_ins ri, xi, bi, di; \ +\ + SLJIT_ASSERT(cond); \ + ri = (sljit_ins)(r & 0xf) << 36; \ + xi = (sljit_ins)(x & 0xf) << 32; \ + bi = (sljit_ins)(b & 0xf) << 28; \ + di = (sljit_ins)disp_s20(d) << 8; \ +\ + return (pattern) | ri | xi | bi | di; \ +} + +/* ADD */ +SLJIT_S390X_RXYA(ay, 0xe3000000005a, have_ldisp()) +SLJIT_S390X_RXYA(ag, 0xe30000000008, 1) + +/* ADD LOGICAL */ +SLJIT_S390X_RXYA(aly, 0xe3000000005e, have_ldisp()) +SLJIT_S390X_RXYA(alg, 0xe3000000000a, 1) + +/* ADD LOGICAL WITH CARRY */ +SLJIT_S390X_RXYA(alc, 0xe30000000098, 1) +SLJIT_S390X_RXYA(alcg, 0xe30000000088, 1) + +/* AND */ +SLJIT_S390X_RXYA(ny, 0xe30000000054, have_ldisp()) +SLJIT_S390X_RXYA(ng, 0xe30000000080, 1) + +/* EXCLUSIVE OR */ +SLJIT_S390X_RXYA(xy, 0xe30000000057, have_ldisp()) +SLJIT_S390X_RXYA(xg, 0xe30000000082, 1) + +/* LOAD */ +SLJIT_S390X_RXYA(ly, 0xe30000000058, have_ldisp()) +SLJIT_S390X_RXYA(lg, 0xe30000000004, 1) +SLJIT_S390X_RXYA(lgf, 0xe30000000014, 1) + +/* LOAD BYTE */ +SLJIT_S390X_RXYA(lb, 0xe30000000076, have_ldisp()) +SLJIT_S390X_RXYA(lgb, 0xe30000000077, have_ldisp()) + +/* LOAD HALFWORD */ +SLJIT_S390X_RXYA(lhy, 0xe30000000078, have_ldisp()) +SLJIT_S390X_RXYA(lgh, 0xe30000000015, 1) + +/* LOAD LOGICAL */ +SLJIT_S390X_RXYA(llgf, 0xe30000000016, 1) + +/* LOAD LOGICAL CHARACTER */ +SLJIT_S390X_RXYA(llc, 0xe30000000094, have_eimm()) +SLJIT_S390X_RXYA(llgc, 0xe30000000090, 1) + +/* LOAD LOGICAL HALFWORD */ +SLJIT_S390X_RXYA(llh, 0xe30000000095, have_eimm()) +SLJIT_S390X_RXYA(llgh, 0xe30000000091, 1) + +/* MULTIPLY SINGLE */ +SLJIT_S390X_RXYA(msy, 0xe30000000051, have_ldisp()) +SLJIT_S390X_RXYA(msg, 0xe3000000000c, 1) + +/* OR */ +SLJIT_S390X_RXYA(oy, 0xe30000000056, have_ldisp()) +SLJIT_S390X_RXYA(og, 0xe30000000081, 1) + +/* STORE */ +SLJIT_S390X_RXYA(sty, 0xe30000000050, have_ldisp()) +SLJIT_S390X_RXYA(stg, 0xe30000000024, 1) + +/* STORE CHARACTER */ +SLJIT_S390X_RXYA(stcy, 0xe30000000072, have_ldisp()) + +/* STORE HALFWORD */ +SLJIT_S390X_RXYA(sthy, 0xe30000000070, have_ldisp()) + +/* SUBTRACT */ +SLJIT_S390X_RXYA(sy, 0xe3000000005b, have_ldisp()) +SLJIT_S390X_RXYA(sg, 0xe30000000009, 1) + +/* SUBTRACT LOGICAL */ +SLJIT_S390X_RXYA(sly, 0xe3000000005f, have_ldisp()) +SLJIT_S390X_RXYA(slg, 0xe3000000000b, 1) + +/* SUBTRACT LOGICAL WITH BORROW */ +SLJIT_S390X_RXYA(slb, 0xe30000000099, 1) +SLJIT_S390X_RXYA(slbg, 0xe30000000089, 1) + +#undef SLJIT_S390X_RXYA + +/* RS-a instructions */ +#define SLJIT_S390X_RSA(name, pattern) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, sljit_sw d, sljit_gpr b) \ +{ \ + sljit_ins r1 = (sljit_ins)(reg & 0xf) << 20; \ + sljit_ins b2 = (sljit_ins)(b & 0xf) << 12; \ + sljit_ins d2 = (sljit_ins)(d & 0xfff); \ + return (pattern) | r1 | b2 | d2; \ +} + +/* SHIFT LEFT SINGLE LOGICAL */ +SLJIT_S390X_RSA(sll, 0x89000000) + +/* SHIFT RIGHT SINGLE */ +SLJIT_S390X_RSA(sra, 0x8a000000) + +/* SHIFT RIGHT SINGLE LOGICAL */ +SLJIT_S390X_RSA(srl, 0x88000000) + +#undef SLJIT_S390X_RSA + +/* RSY-a instructions */ +#define SLJIT_S390X_RSYA(name, pattern, cond) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_sw d, sljit_gpr b) \ +{ \ + sljit_ins r1, r3, b2, d2; \ +\ + SLJIT_ASSERT(cond); \ + r1 = (sljit_ins)(dst & 0xf) << 36; \ + r3 = (sljit_ins)(src & 0xf) << 32; \ + b2 = (sljit_ins)(b & 0xf) << 28; \ + d2 = (sljit_ins)disp_s20(d) << 8; \ +\ + return (pattern) | r1 | r3 | b2 | d2; \ +} + +/* LOAD MULTIPLE */ +SLJIT_S390X_RSYA(lmg, 0xeb0000000004, 1) + +/* SHIFT LEFT LOGICAL */ +SLJIT_S390X_RSYA(sllg, 0xeb000000000d, 1) + +/* SHIFT RIGHT SINGLE */ +SLJIT_S390X_RSYA(srag, 0xeb000000000a, 1) + +/* SHIFT RIGHT SINGLE LOGICAL */ +SLJIT_S390X_RSYA(srlg, 0xeb000000000c, 1) + +/* STORE MULTIPLE */ +SLJIT_S390X_RSYA(stmg, 0xeb0000000024, 1) + +#undef SLJIT_S390X_RSYA + +/* RIE-f instructions (require general-instructions-extension facility) */ +#define SLJIT_S390X_RIEF(name, pattern) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_u8 start, sljit_u8 end, sljit_u8 rot) \ +{ \ + sljit_ins r1, r2, i3, i4, i5; \ +\ + SLJIT_ASSERT(have_genext()); \ + r1 = (sljit_ins)(dst & 0xf) << 36; \ + r2 = (sljit_ins)(src & 0xf) << 32; \ + i3 = (sljit_ins)start << 24; \ + i4 = (sljit_ins)end << 16; \ + i5 = (sljit_ins)rot << 8; \ +\ + return (pattern) | r1 | r2 | i3 | i4 | i5; \ +} + +/* ROTATE THEN AND SELECTED BITS */ +/* SLJIT_S390X_RIEF(rnsbg, 0xec0000000054) */ + +/* ROTATE THEN EXCLUSIVE OR SELECTED BITS */ +/* SLJIT_S390X_RIEF(rxsbg, 0xec0000000057) */ + +/* ROTATE THEN OR SELECTED BITS */ +SLJIT_S390X_RIEF(rosbg, 0xec0000000056) + +/* ROTATE THEN INSERT SELECTED BITS */ +/* SLJIT_S390X_RIEF(risbg, 0xec0000000055) */ +/* SLJIT_S390X_RIEF(risbgn, 0xec0000000059) */ + +/* ROTATE THEN INSERT SELECTED BITS HIGH */ +SLJIT_S390X_RIEF(risbhg, 0xec000000005d) + +/* ROTATE THEN INSERT SELECTED BITS LOW */ +/* SLJIT_S390X_RIEF(risblg, 0xec0000000051) */ + +#undef SLJIT_S390X_RIEF + +/* RRF-a instructions */ +#define SLJIT_S390X_RRFA(name, pattern, cond) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src1, sljit_gpr src2) \ +{ \ + sljit_ins r1, r2, r3; \ +\ + SLJIT_ASSERT(cond); \ + r1 = (sljit_ins)(dst & 0xf) << 4; \ + r2 = (sljit_ins)(src1 & 0xf); \ + r3 = (sljit_ins)(src2 & 0xf) << 12; \ +\ + return (pattern) | r3 | r1 | r2; \ +} + +/* MULTIPLY */ +SLJIT_S390X_RRFA(msrkc, 0xb9fd0000, have_misc2()) +SLJIT_S390X_RRFA(msgrkc, 0xb9ed0000, have_misc2()) + +#undef SLJIT_S390X_RRFA + +/* RRF-c instructions (require load/store-on-condition 1 facility) */ +#define SLJIT_S390X_RRFC(name, pattern) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_uw mask) \ +{ \ + sljit_ins r1, r2, m3; \ +\ + SLJIT_ASSERT(have_lscond1()); \ + r1 = (sljit_ins)(dst & 0xf) << 4; \ + r2 = (sljit_ins)(src & 0xf); \ + m3 = (sljit_ins)(mask & 0xf) << 12; \ +\ + return (pattern) | m3 | r1 | r2; \ +} + +/* LOAD HALFWORD IMMEDIATE ON CONDITION */ +SLJIT_S390X_RRFC(locr, 0xb9f20000) +SLJIT_S390X_RRFC(locgr, 0xb9e20000) + +#undef SLJIT_S390X_RRFC + +/* RIE-g instructions (require load/store-on-condition 2 facility) */ +#define SLJIT_S390X_RIEG(name, pattern) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, sljit_sw imm, sljit_uw mask) \ +{ \ + sljit_ins r1, m3, i2; \ +\ + SLJIT_ASSERT(have_lscond2()); \ + r1 = (sljit_ins)(reg & 0xf) << 36; \ + m3 = (sljit_ins)(mask & 0xf) << 32; \ + i2 = (sljit_ins)(imm & 0xffffL) << 16; \ +\ + return (pattern) | r1 | m3 | i2; \ +} + +/* LOAD HALFWORD IMMEDIATE ON CONDITION */ +SLJIT_S390X_RIEG(lochi, 0xec0000000042) +SLJIT_S390X_RIEG(locghi, 0xec0000000046) + +#undef SLJIT_S390X_RIEG + +#define SLJIT_S390X_RILB(name, pattern, cond) \ +SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, sljit_sw ri) \ +{ \ + sljit_ins r1, ri2; \ +\ + SLJIT_ASSERT(cond); \ + r1 = (sljit_ins)(reg & 0xf) << 36; \ + ri2 = (sljit_ins)(ri & 0xffffffff); \ +\ + return (pattern) | r1 | ri2; \ +} + +/* BRANCH RELATIVE AND SAVE LONG */ +SLJIT_S390X_RILB(brasl, 0xc00500000000, 1) + +/* LOAD ADDRESS RELATIVE LONG */ +SLJIT_S390X_RILB(larl, 0xc00000000000, 1) + +/* LOAD RELATIVE LONG */ +SLJIT_S390X_RILB(lgrl, 0xc40800000000, have_genext()) + +#undef SLJIT_S390X_RILB + +SLJIT_S390X_INSTRUCTION(br, sljit_gpr target) +{ + return 0x07f0 | target; +} + +SLJIT_S390X_INSTRUCTION(brcl, sljit_uw mask, sljit_sw target) +{ + sljit_ins m1 = (sljit_ins)(mask & 0xf) << 36; + sljit_ins ri2 = (sljit_ins)target & 0xffffffff; + return 0xc00400000000L | m1 | ri2; +} + +SLJIT_S390X_INSTRUCTION(flogr, sljit_gpr dst, sljit_gpr src) +{ + sljit_ins r1 = ((sljit_ins)dst & 0xf) << 8; + sljit_ins r2 = ((sljit_ins)src & 0xf); + SLJIT_ASSERT(have_eimm()); + return 0xb9830000 | r1 | r2; +} + +/* INSERT PROGRAM MASK */ +SLJIT_S390X_INSTRUCTION(ipm, sljit_gpr dst) +{ + return 0xb2220000 | ((sljit_ins)(dst & 0xf) << 4); +} + +/* ROTATE THEN INSERT SELECTED BITS HIGH (ZERO) */ +SLJIT_S390X_INSTRUCTION(risbhgz, sljit_gpr dst, sljit_gpr src, sljit_u8 start, sljit_u8 end, sljit_u8 rot) +{ + return risbhg(dst, src, start, 0x8 | end, rot); +} + +#undef SLJIT_S390X_INSTRUCTION + +/* load condition code as needed to match type */ +static sljit_s32 push_load_cc(struct sljit_compiler *compiler, sljit_s32 type) +{ + type &= ~SLJIT_I32_OP; + switch (type) { + case SLJIT_ZERO: + case SLJIT_NOT_ZERO: + return push_inst(compiler, cih(flag_r, 0)); + break; + default: + return push_inst(compiler, tmlh(flag_r, 0x3000)); + break; + } + return SLJIT_SUCCESS; +} + +static sljit_s32 push_store_zero_flag(struct sljit_compiler *compiler, sljit_s32 op, sljit_gpr source) +{ + /* insert low 32-bits into high 32-bits of flag register */ + FAIL_IF(push_inst(compiler, risbhgz(flag_r, source, 0, 31, 32))); + if (!(op & SLJIT_I32_OP)) { + /* OR high 32-bits with high 32-bits of flag register */ + return push_inst(compiler, rosbg(flag_r, source, 0, 31, 0)); + } + return SLJIT_SUCCESS; +} + +/* load 64-bit immediate into register without clobbering flags */ +static sljit_s32 push_load_imm_inst(struct sljit_compiler *compiler, sljit_gpr target, sljit_sw v) +{ + /* 4 byte instructions */ + if (is_s16(v)) + return push_inst(compiler, lghi(target, (sljit_s16)v)); + + if ((sljit_uw)v == (v & 0x000000000000ffffU)) + return push_inst(compiler, llill(target, (sljit_u16)v)); + + if ((sljit_uw)v == (v & 0x00000000ffff0000U)) + return push_inst(compiler, llilh(target, (sljit_u16)(v >> 16))); + + if ((sljit_uw)v == (v & 0x0000ffff00000000U)) + return push_inst(compiler, llihl(target, (sljit_u16)(v >> 32))); + + if ((sljit_uw)v == (v & 0xffff000000000000U)) + return push_inst(compiler, llihh(target, (sljit_u16)(v >> 48))); + + /* 6 byte instructions (requires extended immediate facility) */ + if (have_eimm()) { + if (is_s32(v)) + return push_inst(compiler, lgfi(target, (sljit_s32)v)); + + if ((sljit_uw)v == (v & 0x00000000ffffffffU)) + return push_inst(compiler, llilf(target, (sljit_u32)v)); + + if ((sljit_uw)v == (v & 0xffffffff00000000U)) + return push_inst(compiler, llihf(target, (sljit_u32)(v >> 32))); + + FAIL_IF(push_inst(compiler, llilf(target, (sljit_u32)v))); + return push_inst(compiler, iihf(target, (sljit_u32)(v >> 32))); + } + /* TODO(mundaym): instruction sequences that don't use extended immediates */ + abort(); +} + +struct addr { + sljit_gpr base; + sljit_gpr index; + sljit_sw offset; +}; + +/* transform memory operand into D(X,B) form with a signed 20-bit offset */ +static sljit_s32 make_addr_bxy(struct sljit_compiler *compiler, + struct addr *addr, sljit_s32 mem, sljit_sw off, + sljit_gpr tmp /* clobbered, must not be r0 */) +{ + sljit_gpr base = r0; + sljit_gpr index = r0; + + SLJIT_ASSERT(tmp != r0); + if (mem & REG_MASK) + base = gpr(mem & REG_MASK); + + if (mem & OFFS_REG_MASK) { + index = gpr(OFFS_REG(mem)); + if (off != 0) { + /* shift and put the result into tmp */ + SLJIT_ASSERT(0 <= off && off < 64); + FAIL_IF(push_inst(compiler, sllg(tmp, index, off, 0))); + index = tmp; + off = 0; /* clear offset */ + } + } + else if (!is_s20(off)) { + FAIL_IF(push_load_imm_inst(compiler, tmp, off)); + index = tmp; + off = 0; /* clear offset */ + } + addr->base = base; + addr->index = index; + addr->offset = off; + return SLJIT_SUCCESS; +} + +/* transform memory operand into D(X,B) form with an unsigned 12-bit offset */ +static sljit_s32 make_addr_bx(struct sljit_compiler *compiler, + struct addr *addr, sljit_s32 mem, sljit_sw off, + sljit_gpr tmp /* clobbered, must not be r0 */) +{ + sljit_gpr base = r0; + sljit_gpr index = r0; + + SLJIT_ASSERT(tmp != r0); + if (mem & REG_MASK) + base = gpr(mem & REG_MASK); + + if (mem & OFFS_REG_MASK) { + index = gpr(OFFS_REG(mem)); + if (off != 0) { + /* shift and put the result into tmp */ + SLJIT_ASSERT(0 <= off && off < 64); + FAIL_IF(push_inst(compiler, sllg(tmp, index, off, 0))); + index = tmp; + off = 0; /* clear offset */ + } + } + else if (!is_u12(off)) { + FAIL_IF(push_load_imm_inst(compiler, tmp, off)); + index = tmp; + off = 0; /* clear offset */ + } + addr->base = base; + addr->index = index; + addr->offset = off; + return SLJIT_SUCCESS; +} + +#define EVAL(op, r, addr) op(r, addr.offset, addr.index, addr.base) +#define WHEN(cond, r, i1, i2, addr) \ + (cond) ? EVAL(i1, r, addr) : EVAL(i2, r, addr) + +static sljit_s32 load_word(struct sljit_compiler *compiler, sljit_gpr dst, + sljit_s32 src, sljit_sw srcw, + sljit_gpr tmp /* clobbered */, sljit_s32 is_32bit) +{ + struct addr addr; + sljit_ins ins; + + SLJIT_ASSERT(src & SLJIT_MEM); + if (have_ldisp() || !is_32bit) + FAIL_IF(make_addr_bxy(compiler, &addr, src, srcw, tmp)); + else + FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp)); + + if (is_32bit) + ins = WHEN(is_u12(addr.offset), dst, l, ly, addr); + else + ins = lg(dst, addr.offset, addr.index, addr.base); + + return push_inst(compiler, ins); +} + +static sljit_s32 store_word(struct sljit_compiler *compiler, sljit_gpr src, + sljit_s32 dst, sljit_sw dstw, + sljit_gpr tmp /* clobbered */, sljit_s32 is_32bit) +{ + struct addr addr; + sljit_ins ins; + + SLJIT_ASSERT(dst & SLJIT_MEM); + if (have_ldisp() || !is_32bit) + FAIL_IF(make_addr_bxy(compiler, &addr, dst, dstw, tmp)); + else + FAIL_IF(make_addr_bx(compiler, &addr, dst, dstw, tmp)); + + if (is_32bit) + ins = WHEN(is_u12(addr.offset), src, st, sty, addr); + else + ins = stg(src, addr.offset, addr.index, addr.base); + + return push_inst(compiler, ins); +} + +#undef WHEN + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + struct sljit_jump *jump; + struct sljit_s390x_const *const_; + struct sljit_put_label *put_label; + sljit_sw executable_offset; + sljit_uw ins_size = 0; /* instructions */ + sljit_uw pool_size = 0; /* literal pool */ + sljit_uw pad_size; + sljit_uw i, j = 0; + struct sljit_memory_fragment *buf; + void *code, *code_ptr; + sljit_uw *pool, *pool_ptr; + + sljit_uw source; + sljit_sw offset; /* TODO(carenas): only need 32 bit */ + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_generate_code(compiler)); + reverse_buf(compiler); + + /* branch handling */ + label = compiler->labels; + jump = compiler->jumps; + put_label = compiler->put_labels; + + /* TODO(carenas): compiler->executable_size could be calculated + * before to avoid the following loop (except for + * pool_size) + */ + /* calculate the size of the code */ + for (buf = compiler->buf; buf != NULL; buf = buf->next) { + sljit_uw len = buf->used_size / sizeof(sljit_ins); + sljit_ins *ibuf = (sljit_ins *)buf->memory; + for (i = 0; i < len; ++i, ++j) { + sljit_ins ins = ibuf[i]; + + /* TODO(carenas): instruction tag vs size/addr == j + * using instruction tags for const is creative + * but unlike all other architectures, and is not + * done consistently for all other objects. + * This might need reviewing later. + */ + if (ins & sljit_ins_const) { + pool_size += sizeof(*pool); + ins &= ~sljit_ins_const; + } + if (label && label->size == j) { + label->size = ins_size; + label = label->next; + } + if (jump && jump->addr == j) { + if ((jump->flags & SLJIT_REWRITABLE_JUMP) || (jump->flags & 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); + ins_size += 2; + } + jump = jump->next; + } + if (put_label && put_label->addr == j) { + pool_size += sizeof(*pool); + put_label = put_label->next; + } + ins_size += sizeof_ins(ins); + } + } + + /* emit trailing label */ + if (label && label->size == j) { + label->size = ins_size; + label = label->next; + } + + SLJIT_ASSERT(!label); + SLJIT_ASSERT(!jump); + SLJIT_ASSERT(!put_label); + + /* 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; + SLJIT_ASSERT(pad_size < 8UL); + + /* allocate target buffer */ + code = SLJIT_MALLOC_EXEC(ins_size + pad_size + pool_size, + compiler->exec_allocator_data); + PTR_FAIL_WITH_EXEC_IF(code); + code_ptr = code; + executable_offset = SLJIT_EXEC_OFFSET(code); + + /* TODO(carenas): pool is optional, and the ABI recommends it to + * be created before the function code, instead of + * globally; if generated code is too big could + * need offsets bigger than 32bit words and asser() + */ + pool = (sljit_uw *)((sljit_uw)code + ins_size + pad_size); + pool_ptr = pool; + const_ = (struct sljit_s390x_const *)compiler->consts; + + /* update label addresses */ + label = compiler->labels; + while (label) { + label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET( + (sljit_uw)code_ptr + label->size, executable_offset); + label = label->next; + } + + /* reset jumps */ + jump = compiler->jumps; + put_label = compiler->put_labels; + + /* emit the code */ + j = 0; + for (buf = compiler->buf; buf != NULL; buf = buf->next) { + sljit_uw len = buf->used_size / sizeof(sljit_ins); + sljit_ins *ibuf = (sljit_ins *)buf->memory; + for (i = 0; i < len; ++i, ++j) { + sljit_ins ins = ibuf[i]; + if (ins & sljit_ins_const) { + /* clear the const tag */ + ins &= ~sljit_ins_const; + + /* update instruction with relative address of constant */ + source = (sljit_uw)code_ptr; + offset = (sljit_uw)pool_ptr - source; + SLJIT_ASSERT(!(offset & 1)); + offset >>= 1; /* halfword (not byte) offset */ + SLJIT_ASSERT(is_s32(offset)); + ins |= (sljit_ins)offset & 0xffffffff; + + /* update address */ + const_->const_.addr = (sljit_uw)pool_ptr; + + /* store initial value into pool and update pool address */ + *(pool_ptr++) = const_->init_value; + + /* move to next constant */ + const_ = (struct sljit_s390x_const *)const_->const_.next; + } + if (jump && jump->addr == j) { + sljit_sw target = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; + if ((jump->flags & SLJIT_REWRITABLE_JUMP) || (jump->flags & JUMP_ADDR)) { + jump->addr = (sljit_uw)pool_ptr; + + /* load address into tmp1 */ + source = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + offset = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source; + SLJIT_ASSERT(!(offset & 1)); + offset >>= 1; + SLJIT_ASSERT(is_s32(offset)); + encode_inst(&code_ptr, + lgrl(tmp1, offset & 0xffffffff)); + + /* store jump target into pool and update pool address */ + *(pool_ptr++) = target; + + /* branch to tmp1 */ + sljit_ins op = (ins >> 32) & 0xf; + sljit_ins arg = (ins >> 36) & 0xf; + switch (op) { + case 4: /* brcl -> bcr */ + ins = bcr(arg, tmp1); + break; + case 5: /* brasl -> basr */ + ins = basr(arg, tmp1); + break; + default: + abort(); + } + } + else { + jump->addr = (sljit_uw)code_ptr + 2; + source = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + offset = target - source; + + /* offset must be halfword aligned */ + SLJIT_ASSERT(!(offset & 1)); + offset >>= 1; + SLJIT_ASSERT(is_s32(offset)); /* TODO(mundaym): handle arbitrary offsets */ + + /* patch jump target */ + ins |= (sljit_ins)offset & 0xffffffff; + } + jump = jump->next; + } + if (put_label && put_label->addr == j) { + source = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + + SLJIT_ASSERT(put_label->label); + put_label->addr = (sljit_uw)code_ptr; + + /* store target into pool */ + *pool_ptr = put_label->label->addr; + offset = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source; + pool_ptr++; + + SLJIT_ASSERT(!(offset & 1)); + offset >>= 1; + SLJIT_ASSERT(is_s32(offset)); + ins |= (sljit_ins)offset & 0xffffffff; + + put_label = put_label->next; + } + encode_inst(&code_ptr, ins); + } + } + SLJIT_ASSERT((sljit_u8 *)code + ins_size == code_ptr); + SLJIT_ASSERT((sljit_u8 *)pool + pool_size == (sljit_u8 *)pool_ptr); + + compiler->error = SLJIT_ERR_COMPILED; + compiler->executable_offset = executable_offset; + compiler->executable_size = ins_size; + code = SLJIT_ADD_EXEC_OFFSET(code, executable_offset); + code_ptr = SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); + SLJIT_CACHE_FLUSH(code, code_ptr); + SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1); + return code; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) +{ + /* TODO(mundaym): implement all */ + switch (feature_type) { + case SLJIT_HAS_CLZ: + return have_eimm() ? 1 : 0; /* FLOGR instruction */ + case SLJIT_HAS_CMOV: + return have_lscond1() ? 1 : 0; + case SLJIT_HAS_FPU: + return 0; + } + return 0; +} + +/* --------------------------------------------------------------------- */ +/* Entry, exit */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) +{ + sljit_s32 args = get_arg_count(arg_types); + sljit_sw frame_size; + + CHECK_ERROR(); + CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + + /* saved registers go in callee allocated save area */ + compiler->local_size = (local_size + 0xf) & ~0xf; + frame_size = compiler->local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE; + + FAIL_IF(push_inst(compiler, stmg(r6, r15, r6 * sizeof(sljit_sw), r15))); /* save registers TODO(MGM): optimize */ + if (frame_size != 0) { + if (is_s16(-frame_size)) + FAIL_IF(push_inst(compiler, aghi(r15, -((sljit_s16)frame_size)))); + else if (is_s32(-frame_size)) + FAIL_IF(push_inst(compiler, agfi(r15, -((sljit_s32)frame_size)))); + else { + FAIL_IF(push_load_imm_inst(compiler, tmp1, -frame_size)); + FAIL_IF(push_inst(compiler, la(r15, 0, tmp1, r15))); + } + } + + if (args >= 1) + FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S0), gpr(SLJIT_R0)))); + if (args >= 2) + FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S1), gpr(SLJIT_R1)))); + if (args >= 3) + FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S2), gpr(SLJIT_R2)))); + SLJIT_ASSERT(args < 4); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, + sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, + sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) +{ + CHECK_ERROR(); + CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); + set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + + /* TODO(mundaym): stack space for saved floating point registers */ + compiler->local_size = (local_size + 0xf) & ~0xf; + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) +{ + sljit_sw size; + sljit_gpr end; + + CHECK_ERROR(); + CHECK(check_sljit_emit_return(compiler, op, src, srcw)); + + FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); + + size = compiler->local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + (r6 * sizeof(sljit_sw)); + if (!is_s20(size)) { + FAIL_IF(push_load_imm_inst(compiler, tmp1, compiler->local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE)); + FAIL_IF(push_inst(compiler, la(r15, 0, tmp1, r15))); + size = r6 * sizeof(sljit_sw); + end = r14; /* r15 has been restored already */ + } + else + end = r15; + + FAIL_IF(push_inst(compiler, lmg(r6, end, size, r15))); /* restore registers TODO(MGM): optimize */ + FAIL_IF(push_inst(compiler, br(r14))); /* return */ + + return SLJIT_SUCCESS; +} + +/* --------------------------------------------------------------------- */ +/* Operators */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) +{ + sljit_gpr arg0 = gpr(SLJIT_R0); + sljit_gpr arg1 = gpr(SLJIT_R1); + + CHECK_ERROR(); + CHECK(check_sljit_emit_op0(compiler, op)); + + op = GET_OPCODE(op) | (op & SLJIT_I32_OP); + switch (op) { + case SLJIT_BREAKPOINT: + /* TODO(mundaym): insert real breakpoint? */ + case SLJIT_NOP: + return push_inst(compiler, 0x0700 /* 2-byte nop */); + case SLJIT_LMUL_UW: + FAIL_IF(push_inst(compiler, mlgr(arg0, arg0))); + break; + case SLJIT_LMUL_SW: + /* signed multiplication from: */ + /* Hacker's Delight, Second Edition: Chapter 8-3. */ + FAIL_IF(push_inst(compiler, srag(tmp0, arg0, 63, 0))); + FAIL_IF(push_inst(compiler, srag(tmp1, arg1, 63, 0))); + FAIL_IF(push_inst(compiler, ngr(tmp0, arg1))); + FAIL_IF(push_inst(compiler, ngr(tmp1, arg0))); + + /* unsigned multiplication */ + FAIL_IF(push_inst(compiler, mlgr(arg0, arg0))); + + FAIL_IF(push_inst(compiler, sgr(arg0, tmp0))); + FAIL_IF(push_inst(compiler, sgr(arg0, tmp1))); + break; + case SLJIT_DIV_U32: + case SLJIT_DIVMOD_U32: + FAIL_IF(push_inst(compiler, lhi(tmp0, 0))); + FAIL_IF(push_inst(compiler, lr(tmp1, arg0))); + FAIL_IF(push_inst(compiler, dlr(tmp0, arg1))); + FAIL_IF(push_inst(compiler, lr(arg0, tmp1))); /* quotient */ + if (op == SLJIT_DIVMOD_U32) + return push_inst(compiler, lr(arg1, tmp0)); /* remainder */ + + return SLJIT_SUCCESS; + case SLJIT_DIV_S32: + case SLJIT_DIVMOD_S32: + FAIL_IF(push_inst(compiler, lhi(tmp0, 0))); + FAIL_IF(push_inst(compiler, lr(tmp1, arg0))); + FAIL_IF(push_inst(compiler, dr(tmp0, arg1))); + FAIL_IF(push_inst(compiler, lr(arg0, tmp1))); /* quotient */ + if (op == SLJIT_DIVMOD_S32) + return push_inst(compiler, lr(arg1, tmp0)); /* remainder */ + + return SLJIT_SUCCESS; + case SLJIT_DIV_UW: + case SLJIT_DIVMOD_UW: + FAIL_IF(push_inst(compiler, lghi(tmp0, 0))); + FAIL_IF(push_inst(compiler, lgr(tmp1, arg0))); + FAIL_IF(push_inst(compiler, dlgr(tmp0, arg1))); + FAIL_IF(push_inst(compiler, lgr(arg0, tmp1))); /* quotient */ + if (op == SLJIT_DIVMOD_UW) + return push_inst(compiler, lgr(arg1, tmp0)); /* remainder */ + + return SLJIT_SUCCESS; + case SLJIT_DIV_SW: + case SLJIT_DIVMOD_SW: + FAIL_IF(push_inst(compiler, lgr(tmp1, arg0))); + FAIL_IF(push_inst(compiler, dsgr(tmp0, arg1))); + FAIL_IF(push_inst(compiler, lgr(arg0, tmp1))); /* quotient */ + if (op == SLJIT_DIVMOD_SW) + return push_inst(compiler, lgr(arg1, tmp0)); /* remainder */ + + return SLJIT_SUCCESS; + case SLJIT_ENDBR: + return SLJIT_SUCCESS; + case SLJIT_SKIP_FRAMES_BEFORE_RETURN: + return SLJIT_SUCCESS; + default: + SLJIT_UNREACHABLE(); + } + /* swap result registers */ + FAIL_IF(push_inst(compiler, lgr(tmp0, arg0))); + FAIL_IF(push_inst(compiler, lgr(arg0, arg1))); + return push_inst(compiler, lgr(arg1, tmp0)); +} + +/* LEVAL will be defined later with different parameters as needed */ +#define WHEN2(cond, i1, i2) (cond) ? LEVAL(i1) : LEVAL(i2) + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + sljit_ins ins; + struct addr mem; + sljit_gpr dst_r; + sljit_gpr src_r; + sljit_s32 opcode = GET_OPCODE(op); + + CHECK_ERROR(); + CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src, srcw); + + if ((dst == SLJIT_UNUSED) && !HAS_FLAGS(op)) { + /* TODO(carenas): implement prefetch? */ + return SLJIT_SUCCESS; + } + if (opcode >= SLJIT_MOV && opcode <= SLJIT_MOV_P) { + /* LOAD REGISTER */ + if (FAST_IS_REG(dst) && FAST_IS_REG(src)) { + dst_r = gpr(dst); + src_r = gpr(src); + switch (opcode | (op & SLJIT_I32_OP)) { + /* 32-bit */ + case SLJIT_MOV32_U8: + ins = llcr(dst_r, src_r); + break; + case SLJIT_MOV32_S8: + ins = lbr(dst_r, src_r); + break; + case SLJIT_MOV32_U16: + ins = llhr(dst_r, src_r); + break; + case SLJIT_MOV32_S16: + ins = lhr(dst_r, src_r); + break; + case SLJIT_MOV32: + ins = lr(dst_r, src_r); + break; + /* 64-bit */ + case SLJIT_MOV_U8: + ins = llgcr(dst_r, src_r); + break; + case SLJIT_MOV_S8: + ins = lgbr(dst_r, src_r); + break; + case SLJIT_MOV_U16: + ins = llghr(dst_r, src_r); + break; + case SLJIT_MOV_S16: + ins = lghr(dst_r, src_r); + break; + case SLJIT_MOV_U32: + ins = llgfr(dst_r, src_r); + break; + case SLJIT_MOV_S32: + ins = lgfr(dst_r, src_r); + break; + case SLJIT_MOV: + case SLJIT_MOV_P: + ins = lgr(dst_r, src_r); + break; + default: + ins = 0; + SLJIT_UNREACHABLE(); + } + FAIL_IF(push_inst(compiler, ins)); + if (HAS_FLAGS(op)) { + /* only handle zero flag */ + SLJIT_ASSERT(!(op & VARIABLE_FLAG_MASK)); + return push_store_zero_flag(compiler, op, dst_r); + } + return SLJIT_SUCCESS; + } + /* LOAD IMMEDIATE */ + if (FAST_IS_REG(dst) && (src & SLJIT_IMM)) { + switch (opcode) { + case SLJIT_MOV_U8: + srcw = (sljit_sw)((sljit_u8)(srcw)); + break; + case SLJIT_MOV_S8: + srcw = (sljit_sw)((sljit_s8)(srcw)); + break; + case SLJIT_MOV_U16: + srcw = (sljit_sw)((sljit_u16)(srcw)); + break; + case SLJIT_MOV_S16: + srcw = (sljit_sw)((sljit_s16)(srcw)); + break; + case SLJIT_MOV_U32: + srcw = (sljit_sw)((sljit_u32)(srcw)); + break; + case SLJIT_MOV_S32: + srcw = (sljit_sw)((sljit_s32)(srcw)); + break; + } + return push_load_imm_inst(compiler, gpr(dst), srcw); + } + /* LOAD */ + /* TODO(carenas): avoid reg being defined later */ + #define LEVAL(i) EVAL(i, reg, mem) + if (FAST_IS_REG(dst) && (src & SLJIT_MEM)) { + sljit_gpr reg = gpr(dst); + + FAIL_IF(make_addr_bxy(compiler, &mem, src, srcw, tmp1)); + /* TODO(carenas): convert all calls below to LEVAL */ + switch (opcode | (op & SLJIT_I32_OP)) { + case SLJIT_MOV32_U8: + ins = llc(reg, mem.offset, mem.index, mem.base); + break; + case SLJIT_MOV32_S8: + ins = lb(reg, mem.offset, mem.index, mem.base); + break; + case SLJIT_MOV32_U16: + ins = llh(reg, mem.offset, mem.index, mem.base); + break; + case SLJIT_MOV32_S16: + ins = WHEN2(is_u12(mem.offset), lh, lhy); + break; + case SLJIT_MOV32: + ins = WHEN2(is_u12(mem.offset), l, ly); + break; + case SLJIT_MOV_U8: + ins = LEVAL(llgc); + break; + case SLJIT_MOV_S8: + ins = lgb(reg, mem.offset, mem.index, mem.base); + break; + case SLJIT_MOV_U16: + ins = LEVAL(llgh); + break; + case SLJIT_MOV_S16: + ins = lgh(reg, mem.offset, mem.index, mem.base); + break; + case SLJIT_MOV_U32: + ins = LEVAL(llgf); + break; + case SLJIT_MOV_S32: + ins = lgf(reg, mem.offset, mem.index, mem.base); + break; + case SLJIT_MOV_P: + case SLJIT_MOV: + ins = lg(reg, mem.offset, mem.index, mem.base); + break; + default: + SLJIT_UNREACHABLE(); + } + FAIL_IF(push_inst(compiler, ins)); + if (HAS_FLAGS(op)) { + /* only handle zero flag */ + SLJIT_ASSERT(!(op & VARIABLE_FLAG_MASK)); + return push_store_zero_flag(compiler, op, reg); + } + return SLJIT_SUCCESS; + } + /* STORE and STORE IMMEDIATE */ + if ((dst & SLJIT_MEM) + && (FAST_IS_REG(src) || (src & SLJIT_IMM))) { + sljit_gpr reg = FAST_IS_REG(src) ? gpr(src) : tmp0; + if (src & SLJIT_IMM) { + /* TODO(mundaym): MOVE IMMEDIATE? */ + FAIL_IF(push_load_imm_inst(compiler, reg, srcw)); + } + struct addr mem; + FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1)); + switch (opcode) { + case SLJIT_MOV_U8: + case SLJIT_MOV_S8: + return push_inst(compiler, + WHEN2(is_u12(mem.offset), stc, stcy)); + case SLJIT_MOV_U16: + case SLJIT_MOV_S16: + return push_inst(compiler, + WHEN2(is_u12(mem.offset), sth, sthy)); + case SLJIT_MOV_U32: + case SLJIT_MOV_S32: + return push_inst(compiler, + WHEN2(is_u12(mem.offset), st, sty)); + case SLJIT_MOV_P: + case SLJIT_MOV: + FAIL_IF(push_inst(compiler, LEVAL(stg))); + if (HAS_FLAGS(op)) { + /* only handle zero flag */ + SLJIT_ASSERT(!(op & VARIABLE_FLAG_MASK)); + return push_store_zero_flag(compiler, op, reg); + } + return SLJIT_SUCCESS; + default: + SLJIT_UNREACHABLE(); + } + } + #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: + case SLJIT_MOV_S8: + FAIL_IF(push_inst(compiler, + EVAL(llgc, tmp0, mem))); + FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1)); + return push_inst(compiler, + EVAL(stcy, tmp0, mem)); + case SLJIT_MOV_U16: + case SLJIT_MOV_S16: + FAIL_IF(push_inst(compiler, + EVAL(llgh, tmp0, mem))); + FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1)); + return push_inst(compiler, + EVAL(sthy, tmp0, mem)); + case SLJIT_MOV_U32: + case SLJIT_MOV_S32: + FAIL_IF(push_inst(compiler, + EVAL(ly, tmp0, mem))); + FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1)); + return push_inst(compiler, + EVAL(sty, tmp0, mem)); + case SLJIT_MOV_P: + case SLJIT_MOV: + FAIL_IF(push_inst(compiler, + EVAL(lg, tmp0, mem))); + FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1)); + FAIL_IF(push_inst(compiler, + EVAL(stg, tmp0, mem))); + if (HAS_FLAGS(op)) { + /* only handle zero flag */ + SLJIT_ASSERT(!(op & VARIABLE_FLAG_MASK)); + return push_store_zero_flag(compiler, op, tmp0); + } + return SLJIT_SUCCESS; + default: + SLJIT_UNREACHABLE(); + } + } + SLJIT_UNREACHABLE(); + } + + SLJIT_ASSERT((src & SLJIT_IMM) == 0); /* no immediates */ + + dst_r = SLOW_IS_REG(dst) ? gpr(REG_MASK & dst) : tmp0; + src_r = FAST_IS_REG(src) ? gpr(REG_MASK & src) : tmp0; + if (src & SLJIT_MEM) + FAIL_IF(load_word(compiler, src_r, src, srcw, tmp1, src & SLJIT_I32_OP)); + + /* TODO(mundaym): optimize loads and stores */ + switch (opcode | (op & SLJIT_I32_OP)) { + case SLJIT_NOT: + /* emulate ~x with x^-1 */ + FAIL_IF(push_load_imm_inst(compiler, tmp1, -1)); + if (src_r != dst_r) + FAIL_IF(push_inst(compiler, lgr(dst_r, src_r))); + + FAIL_IF(push_inst(compiler, xgr(dst_r, tmp1))); + break; + case SLJIT_NOT32: + /* emulate ~x with x^-1 */ + if (have_eimm()) + FAIL_IF(push_inst(compiler, xilf(dst_r, -1))); + else { + FAIL_IF(push_load_imm_inst(compiler, tmp1, -1)); + if (src_r != dst_r) + FAIL_IF(push_inst(compiler, lr(dst_r, src_r))); + + FAIL_IF(push_inst(compiler, xr(dst_r, tmp1))); + } + break; + case SLJIT_NEG: + FAIL_IF(push_inst(compiler, lcgr(dst_r, src_r))); + break; + case SLJIT_NEG32: + FAIL_IF(push_inst(compiler, lcr(dst_r, src_r))); + break; + case SLJIT_CLZ: + if (have_eimm()) { + FAIL_IF(push_inst(compiler, flogr(tmp0, src_r))); /* clobbers tmp1 */ + if (dst_r != tmp0) + FAIL_IF(push_inst(compiler, lgr(dst_r, tmp0))); + } else { + abort(); /* TODO(mundaym): no eimm (?) */ + } + break; + case SLJIT_CLZ32: + if (have_eimm()) { + FAIL_IF(push_inst(compiler, sllg(tmp1, src_r, 32, 0))); + FAIL_IF(push_inst(compiler, iilf(tmp1, 0xffffffff))); + FAIL_IF(push_inst(compiler, flogr(tmp0, tmp1))); /* clobbers tmp1 */ + if (dst_r != tmp0) + FAIL_IF(push_inst(compiler, lr(dst_r, tmp0))); + } else { + abort(); /* TODO(mundaym): no eimm (?) */ + } + break; + default: + SLJIT_UNREACHABLE(); + } + + /* write condition code to emulated flag register */ + if (op & VARIABLE_FLAG_MASK) + FAIL_IF(push_inst(compiler, ipm(flag_r))); + + /* write zero flag to emulated flag register */ + if (op & SLJIT_SET_Z) + FAIL_IF(push_store_zero_flag(compiler, op, dst_r)); + + /* TODO(carenas): doesn't need FAIL_IF */ + if ((dst != SLJIT_UNUSED) && (dst & SLJIT_MEM)) + FAIL_IF(store_word(compiler, dst_r, dst, dstw, tmp1, op & SLJIT_I32_OP)); + + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE int is_commutative(sljit_s32 op) +{ + switch (GET_OPCODE(op)) { + case SLJIT_ADD: + case SLJIT_ADDC: + case SLJIT_MUL: + case SLJIT_AND: + case SLJIT_OR: + case SLJIT_XOR: + return 1; + } + return 0; +} + +static SLJIT_INLINE int is_shift(sljit_s32 op) { + sljit_s32 v = GET_OPCODE(op); + return (v == SLJIT_SHL || v == SLJIT_ASHR || v == SLJIT_LSHR) ? 1 : 0; +} + +static SLJIT_INLINE int sets_signed_flag(sljit_s32 op) +{ + switch (GET_FLAG_TYPE(op)) { + case SLJIT_OVERFLOW: + case SLJIT_NOT_OVERFLOW: + case SLJIT_SIG_LESS: + case SLJIT_SIG_LESS_EQUAL: + case SLJIT_SIG_GREATER: + case SLJIT_SIG_GREATER_EQUAL: + return 1; + } + return 0; +} + +/* Report whether we have an instruction for: + op dst src imm + where dst and src are separate registers. */ +static int have_op_3_imm(sljit_s32 op, sljit_sw imm) { + return 0; /* TODO(mundaym): implement */ +} + +/* Report whether we have an instruction for: + op reg imm + where reg is both a source and the destination. */ +static int have_op_2_imm(sljit_s32 op, sljit_sw imm) { + switch (GET_OPCODE(op) | (op & SLJIT_I32_OP)) { + case SLJIT_ADD32: + case SLJIT_ADD: + if (!HAS_FLAGS(op) || sets_signed_flag(op)) + return have_eimm() ? is_s32(imm) : is_s16(imm); + + return have_eimm() && is_u32(imm); + case SLJIT_MUL32: + case SLJIT_MUL: + /* TODO(mundaym): general extension check */ + /* for ms{,g}fi */ + if (op & VARIABLE_FLAG_MASK) + return 0; + + return have_genext() && is_s16(imm); + case SLJIT_OR32: + case SLJIT_XOR32: + case SLJIT_AND32: + /* only use if have extended immediate facility */ + /* this ensures flags are set correctly */ + return have_eimm(); + case SLJIT_AND: + case SLJIT_OR: + case SLJIT_XOR: + /* TODO(mundaym): make this more flexible */ + /* avoid using immediate variations, flags */ + /* won't be set correctly */ + return 0; + case SLJIT_ADDC32: + case SLJIT_ADDC: + /* no ADD LOGICAL WITH CARRY IMMEDIATE */ + return 0; + case SLJIT_SUB: + case SLJIT_SUB32: + case SLJIT_SUBC: + case SLJIT_SUBC32: + /* no SUBTRACT IMMEDIATE */ + /* TODO(mundaym): SUBTRACT LOGICAL IMMEDIATE */ + return 0; + } + return 0; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(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(); + CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); + ADJUST_LOCAL_OFFSET(dst, dstw); + ADJUST_LOCAL_OFFSET(src1, src1w); + ADJUST_LOCAL_OFFSET(src2, src2w); + + if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) + return SLJIT_SUCCESS; + + sljit_gpr dst_r = SLOW_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0; + + if (is_commutative(op)) { + #define SWAP_ARGS \ + do { \ + sljit_s32 t = src1; \ + sljit_sw tw = src1w; \ + src1 = src2; \ + src1w = src2w; \ + src2 = t; \ + src2w = tw; \ + } while(0); + + /* prefer immediate in src2 */ + if (src1 & SLJIT_IMM) { + SWAP_ARGS + } + + /* prefer to have src1 use same register as dst */ + if (FAST_IS_REG(src2) && gpr(src2 & REG_MASK) == dst_r) { + SWAP_ARGS + } + + /* prefer memory argument in src2 */ + if (FAST_IS_REG(src2) && (src1 & SLJIT_MEM)) { + SWAP_ARGS + } + #undef SWAP_ARGS + } + + /* src1 must be in a register */ + sljit_gpr src1_r = FAST_IS_REG(src1) ? gpr(src1 & REG_MASK) : tmp0; + if (src1 & SLJIT_IMM) + FAIL_IF(push_load_imm_inst(compiler, src1_r, src1w)); + + if (src1 & SLJIT_MEM) + FAIL_IF(load_word(compiler, src1_r, src1, src1w, tmp1, op & SLJIT_I32_OP)); + + /* emit comparison before subtract */ + if (GET_OPCODE(op) == SLJIT_SUB && (op & VARIABLE_FLAG_MASK)) { + sljit_sw cmp = 0; + switch (GET_FLAG_TYPE(op)) { + case SLJIT_LESS: + case SLJIT_LESS_EQUAL: + case SLJIT_GREATER: + case SLJIT_GREATER_EQUAL: + cmp = 1; /* unsigned */ + break; + case SLJIT_EQUAL: + case SLJIT_SIG_LESS: + case SLJIT_SIG_LESS_EQUAL: + case SLJIT_SIG_GREATER: + case SLJIT_SIG_GREATER_EQUAL: + cmp = -1; /* signed */ + break; + } + if (cmp) { + /* clear flags - no need to generate now */ + op &= ~VARIABLE_FLAG_MASK; + sljit_gpr src2_r = FAST_IS_REG(src2) ? gpr(src2 & REG_MASK) : tmp1; + if (src2 & SLJIT_IMM) { + #define LEVAL(i) i(src1_r, src2w) + if (cmp > 0 && is_u32(src2w)) { + /* unsigned */ + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, clfi, clgfi))); + } + else if (cmp < 0 && is_s16(src2w)) { + /* signed */ + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, chi, cghi))); + } + else if (cmp < 0 && is_s32(src2w)) { + /* signed */ + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, cfi, cgfi))); + } + #undef LEVAL + #define LEVAL(i) i(src1_r, src2_r) + else { + FAIL_IF(push_load_imm_inst(compiler, src2_r, src2w)); + if (cmp > 0) { + /* unsigned */ + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, clr, clgr))); + } + if (cmp < 0) { + /* signed */ + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, cr, cgr))); + } + } + } + else { + if (src2 & SLJIT_MEM) { + /* TODO(mundaym): comparisons with memory */ + /* load src2 into register */ + FAIL_IF(load_word(compiler, src2_r, src2, src2w, tmp1, op & SLJIT_I32_OP)); + } + if (cmp > 0) { + /* unsigned */ + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, clr, clgr))); + } + if (cmp < 0) { + /* signed */ + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, cr, cgr))); + } + #undef LEVAL + } + FAIL_IF(push_inst(compiler, ipm(flag_r))); + } + } + + if (!HAS_FLAGS(op) && dst == SLJIT_UNUSED) + return SLJIT_SUCCESS; + + /* need to specify signed or logical operation */ + int signed_flags = sets_signed_flag(op); + + if (is_shift(op)) { + /* handle shifts first, they have more constraints than other operations */ + sljit_sw d = 0; + sljit_gpr b = FAST_IS_REG(src2) ? gpr(src2 & REG_MASK) : r0; + if (src2 & SLJIT_IMM) + d = src2w & ((op & SLJIT_I32_OP) ? 31 : 63); + + if (src2 & SLJIT_MEM) { + /* shift amount (b) cannot be in r0 (i.e. tmp0) */ + FAIL_IF(load_word(compiler, tmp1, src2, src2w, tmp1, op & SLJIT_I32_OP)); + b = tmp1; + } + /* src1 and dst share the same register in the base 32-bit ISA */ + /* TODO(mundaym): not needed when distinct-operand facility is available */ + int workaround_alias = op & SLJIT_I32_OP && src1_r != dst_r; + if (workaround_alias) { + /* put src1 into tmp0 so we can overwrite it */ + FAIL_IF(push_inst(compiler, lr(tmp0, src1_r))); + src1_r = tmp0; + } + switch (GET_OPCODE(op) | (op & SLJIT_I32_OP)) { + case SLJIT_SHL: + FAIL_IF(push_inst(compiler, sllg(dst_r, src1_r, d, b))); + break; + case SLJIT_SHL32: + FAIL_IF(push_inst(compiler, sll(src1_r, d, b))); + break; + case SLJIT_LSHR: + FAIL_IF(push_inst(compiler, srlg(dst_r, src1_r, d, b))); + break; + case SLJIT_LSHR32: + FAIL_IF(push_inst(compiler, srl(src1_r, d, b))); + break; + case SLJIT_ASHR: + FAIL_IF(push_inst(compiler, srag(dst_r, src1_r, d, b))); + break; + case SLJIT_ASHR32: + FAIL_IF(push_inst(compiler, sra(src1_r, d, b))); + break; + default: + SLJIT_UNREACHABLE(); + } + if (workaround_alias && dst_r != src1_r) + FAIL_IF(push_inst(compiler, lr(dst_r, src1_r))); + + } + else if ((GET_OPCODE(op) == SLJIT_MUL) && HAS_FLAGS(op)) { + /* multiply instructions do not generally set flags so we need to manually */ + /* detect overflow conditions */ + /* TODO(mundaym): 64-bit overflow */ + SLJIT_ASSERT(GET_FLAG_TYPE(op) == SLJIT_MUL_OVERFLOW || + GET_FLAG_TYPE(op) == SLJIT_MUL_NOT_OVERFLOW); + sljit_gpr src2_r = FAST_IS_REG(src2) ? gpr(src2 & REG_MASK) : tmp1; + if (src2 & SLJIT_IMM) { + /* load src2 into register */ + FAIL_IF(push_load_imm_inst(compiler, src2_r, src2w)); + } + if (src2 & SLJIT_MEM) { + /* load src2 into register */ + FAIL_IF(load_word(compiler, src2_r, src2, src2w, tmp1, op & SLJIT_I32_OP)); + } + if (have_misc2()) { + #define LEVAL(i) i(dst_r, src1_r, src2_r) + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, msrkc, msgrkc))); + #undef LEVAL + } + else if (op & SLJIT_I32_OP) { + op &= ~VARIABLE_FLAG_MASK; + FAIL_IF(push_inst(compiler, lgfr(tmp0, src1_r))); + FAIL_IF(push_inst(compiler, msgfr(tmp0, src2_r))); + if (dst_r != tmp0) { + FAIL_IF(push_inst(compiler, lr(dst_r, tmp0))); + } + FAIL_IF(push_inst(compiler, aih(tmp0, 1))); + FAIL_IF(push_inst(compiler, nihf(tmp0, ~1U))); + FAIL_IF(push_inst(compiler, ipm(flag_r))); + FAIL_IF(push_inst(compiler, oilh(flag_r, 0x2000))); + } + else + return SLJIT_ERR_UNSUPPORTED; + + } + else if ((GET_OPCODE(op) == SLJIT_SUB) && (op & SLJIT_SET_Z) && !signed_flags) { + /* subtract logical instructions do not set the right flags unfortunately */ + /* instead, negate src2 and issue an add logical */ + /* TODO(mundaym): distinct operand facility where needed */ + if (src1_r != dst_r && src1_r != tmp0) { + #define LEVAL(i) i(tmp0, src1_r) + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, lr, lgr))); + src1_r = tmp0; + #undef LEVAL + } + sljit_gpr src2_r = FAST_IS_REG(src2) ? gpr(src2 & REG_MASK) : tmp1; + if (src2 & SLJIT_IMM) { + /* load src2 into register */ + FAIL_IF(push_load_imm_inst(compiler, src2_r, src2w)); + } + if (src2 & SLJIT_MEM) { + /* load src2 into register */ + FAIL_IF(load_word(compiler, src2_r, src2, src2w, tmp1, op & SLJIT_I32_OP)); + } + if (op & SLJIT_I32_OP) { + FAIL_IF(push_inst(compiler, lcr(tmp1, src2_r))); + FAIL_IF(push_inst(compiler, alr(src1_r, tmp1))); + if (src1_r != dst_r) + FAIL_IF(push_inst(compiler, lr(dst_r, src1_r))); + } + else { + FAIL_IF(push_inst(compiler, lcgr(tmp1, src2_r))); + FAIL_IF(push_inst(compiler, algr(src1_r, tmp1))); + if (src1_r != dst_r) + FAIL_IF(push_inst(compiler, lgr(dst_r, src1_r))); + } + } + else if ((src2 & SLJIT_IMM) && (src1_r == dst_r) && have_op_2_imm(op, src2w)) { + switch (GET_OPCODE(op) | (op & SLJIT_I32_OP)) { + #define LEVAL(i) i(dst_r, src2w) + case SLJIT_ADD: + if (!HAS_FLAGS(op) || signed_flags) { + FAIL_IF(push_inst(compiler, + WHEN2(is_s16(src2w), aghi, agfi))); + } + else + FAIL_IF(push_inst(compiler, LEVAL(algfi))); + + break; + case SLJIT_ADD32: + if (!HAS_FLAGS(op) || signed_flags) + FAIL_IF(push_inst(compiler, + WHEN2(is_s16(src2w), ahi, afi))); + else + FAIL_IF(push_inst(compiler, LEVAL(alfi))); + + break; + #undef LEVAL /* TODO(carenas): move down and refactor? */ + case SLJIT_MUL: + FAIL_IF(push_inst(compiler, mhi(dst_r, src2w))); + break; + case SLJIT_MUL32: + FAIL_IF(push_inst(compiler, mghi(dst_r, src2w))); + break; + case SLJIT_OR32: + FAIL_IF(push_inst(compiler, oilf(dst_r, src2w))); + break; + case SLJIT_XOR32: + FAIL_IF(push_inst(compiler, xilf(dst_r, src2w))); + break; + case SLJIT_AND32: + FAIL_IF(push_inst(compiler, nilf(dst_r, src2w))); + break; + default: + SLJIT_UNREACHABLE(); + } + } + else if ((src2 & SLJIT_IMM) && have_op_3_imm(op, src2w)) { + abort(); /* TODO(mundaym): implement */ + } + else if ((src2 & SLJIT_MEM) && (dst_r == src1_r)) { + /* most 32-bit instructions can only handle 12-bit immediate offsets */ + int need_u12 = !have_ldisp() && + (op & SLJIT_I32_OP) && + (GET_OPCODE(op) != SLJIT_ADDC) && + (GET_OPCODE(op) != SLJIT_SUBC); + struct addr mem; + if (need_u12) + FAIL_IF(make_addr_bx(compiler, &mem, src2, src2w, tmp1)); + else + FAIL_IF(make_addr_bxy(compiler, &mem, src2, src2w, tmp1)); + + int can_u12 = is_u12(mem.offset) ? 1 : 0; + sljit_ins ins = 0; + switch (GET_OPCODE(op) | (op & SLJIT_I32_OP)) { + /* 64-bit ops */ + #define LEVAL(i) EVAL(i, dst_r, mem) + case SLJIT_ADD: + ins = WHEN2(signed_flags, ag, alg); + break; + case SLJIT_SUB: + ins = WHEN2(signed_flags, sg, slg); + break; + case SLJIT_ADDC: + ins = LEVAL(alcg); + break; + case SLJIT_SUBC: + ins = LEVAL(slbg); + break; + case SLJIT_MUL: + ins = LEVAL(msg); + break; + case SLJIT_OR: + ins = LEVAL(og); + break; + case SLJIT_XOR: + ins = LEVAL(xg); + break; + case SLJIT_AND: + ins = LEVAL(ng); + break; + /* 32-bit ops */ + case SLJIT_ADD32: + if (signed_flags) + ins = WHEN2(can_u12, a, ay); + else + ins = WHEN2(can_u12, al, aly); + break; + case SLJIT_SUB32: + if (signed_flags) + ins = WHEN2(can_u12, s, sy); + else + ins = WHEN2(can_u12, sl, sly); + break; + case SLJIT_ADDC32: + ins = LEVAL(alc); + break; + case SLJIT_SUBC32: + ins = LEVAL(slb); + break; + case SLJIT_MUL32: + ins = WHEN2(can_u12, ms, msy); + break; + case SLJIT_OR32: + ins = WHEN2(can_u12, o, oy); + break; + case SLJIT_XOR32: + ins = WHEN2(can_u12, x, xy); + break; + case SLJIT_AND32: + ins = WHEN2(can_u12, n, ny); + break; + #undef LEVAL + default: + SLJIT_UNREACHABLE(); + } + FAIL_IF(push_inst(compiler, ins)); + } + else { + sljit_gpr src2_r = FAST_IS_REG(src2) ? gpr(src2 & REG_MASK) : tmp1; + if (src2 & SLJIT_IMM) { + /* load src2 into register */ + FAIL_IF(push_load_imm_inst(compiler, src2_r, src2w)); + } + if (src2 & SLJIT_MEM) { + /* load src2 into register */ + FAIL_IF(load_word(compiler, src2_r, src2, src2w, tmp1, op & SLJIT_I32_OP)); + } + /* TODO(mundaym): distinct operand facility where needed */ + #define LEVAL(i) i(tmp0, src1_r) + if (src1_r != dst_r && src1_r != tmp0) { + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, lr, lgr))); + src1_r = tmp0; + } + #undef LEVAL + sljit_ins ins = 0; + switch (GET_OPCODE(op) | (op & SLJIT_I32_OP)) { + #define LEVAL(i) i(src1_r, src2_r) + /* 64-bit ops */ + case SLJIT_ADD: + ins = WHEN2(signed_flags, agr, algr); + break; + case SLJIT_SUB: + ins = WHEN2(signed_flags, sgr, slgr); + break; + case SLJIT_ADDC: + ins = LEVAL(alcgr); + break; + case SLJIT_SUBC: + ins = LEVAL(slbgr); + break; + case SLJIT_MUL: + ins = LEVAL(msgr); + break; + case SLJIT_AND: + ins = LEVAL(ngr); + break; + case SLJIT_OR: + ins = LEVAL(ogr); + break; + case SLJIT_XOR: + ins = LEVAL(xgr); + break; + /* 32-bit ops */ + case SLJIT_ADD32: + ins = WHEN2(signed_flags, ar, alr); + break; + case SLJIT_SUB32: + ins = WHEN2(signed_flags, sr, slr); + break; + case SLJIT_ADDC32: + ins = LEVAL(alcr); + break; + case SLJIT_SUBC32: + ins = LEVAL(slbr); + break; + case SLJIT_MUL32: + ins = LEVAL(msr); + break; + case SLJIT_AND32: + ins = LEVAL(nr); + break; + case SLJIT_OR32: + ins = LEVAL(or); + break; + case SLJIT_XOR32: + ins = LEVAL(xr); + break; + #undef LEVAL + default: + SLJIT_UNREACHABLE(); + } + FAIL_IF(push_inst(compiler, ins)); + #define LEVAL(i) i(dst_r, src1_r) + if (src1_r != dst_r) + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, lr, lgr))); + #undef LEVAL + } + + /* write condition code to emulated flag register */ + if (op & VARIABLE_FLAG_MASK) + FAIL_IF(push_inst(compiler, ipm(flag_r))); + + /* write zero flag to emulated flag register */ + if (op & SLJIT_SET_Z) + FAIL_IF(push_store_zero_flag(compiler, op, dst_r)); + + /* finally write the result to memory if required */ + if (dst & SLJIT_MEM) { + SLJIT_ASSERT(dst_r != tmp1); + /* TODO(carenas): s/FAIL_IF/ return */ + FAIL_IF(store_word(compiler, dst_r, dst, dstw, tmp1, op & SLJIT_I32_OP)); + } + + 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) +{ + sljit_gpr src_r; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); + ADJUST_LOCAL_OFFSET(src, srcw); + + 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, tmp1, 0)); + + return push_inst(compiler, br(src_r)); + case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: + /* TODO(carenas): implement? */ + return SLJIT_SUCCESS; + case SLJIT_PREFETCH_L1: + case SLJIT_PREFETCH_L2: + case SLJIT_PREFETCH_L3: + case SLJIT_PREFETCH_ONCE: + /* TODO(carenas): implement */ + return SLJIT_SUCCESS; + default: + /* TODO(carenas): probably should not success by default */ + return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) +{ + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); + return gpr(reg); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg) +{ + CHECK_REG_INDEX(check_sljit_get_float_register_index(reg)); + abort(); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, sljit_s32 size) +{ + sljit_ins ins = 0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); + + memcpy((sljit_u8 *)&ins + sizeof(ins) - size, instruction, size); + return push_inst(compiler, ins); +} + +/* --------------------------------------------------------------------- */ +/* Floating point operators */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + abort(); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(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(); + abort(); +} + +/* --------------------------------------------------------------------- */ +/* Other instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + if (FAST_IS_REG(dst)) + return push_inst(compiler, lgr(gpr(dst), fast_link_r)); + + /* memory */ + return store_word(compiler, fast_link_r, dst, dstw, tmp1, 0); +} + +/* --------------------------------------------------------------------- */ +/* Conditional instructions */ +/* --------------------------------------------------------------------- */ + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compiler *compiler) +{ + struct sljit_label *label; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_label(compiler)); + + if (compiler->last_label && compiler->last_label->size == compiler->size) + return compiler->last_label; + + label = (struct sljit_label*)ensure_abuf(compiler, sizeof(struct sljit_label)); + PTR_FAIL_IF(!label); + set_label(label, compiler); + return label; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) +{ + sljit_u8 mask = ((type & 0xff) < SLJIT_JUMP) ? get_cc(type & 0xff) : 0xf; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_jump(compiler, type)); + + /* reload condition code */ + if (mask != 0xf) + PTR_FAIL_IF(push_load_cc(compiler, type & 0xff)); + + /* record jump */ + struct sljit_jump *jump = (struct sljit_jump *) + ensure_abuf(compiler, sizeof(struct sljit_jump)); + PTR_FAIL_IF(!jump); + set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); + jump->addr = compiler->size; + + /* emit jump instruction */ + type &= 0xff; + if (type >= SLJIT_FAST_CALL) + PTR_FAIL_IF(push_inst(compiler, brasl(type == SLJIT_FAST_CALL ? fast_link_r : link_r, 0))); + else + PTR_FAIL_IF(push_inst(compiler, brcl(mask, 0))); + + return jump; +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types) +{ + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_jump(compiler, type); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) +{ + sljit_gpr src_r = FAST_IS_REG(src) ? gpr(src) : tmp1; + + CHECK_ERROR(); + CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); + ADJUST_LOCAL_OFFSET(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) + FAIL_IF(load_word(compiler, src_r, src, srcw, tmp1, 0 /* 64-bit */)); + + /* emit jump instruction */ + if (type >= SLJIT_FAST_CALL) + return push_inst(compiler, basr(type == SLJIT_FAST_CALL ? fast_link_r : link_r, src_r)); + + return push_inst(compiler, br(src_r)); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 arg_types, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw)); + +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \ + || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + compiler->skip_checks = 1; +#endif + + return sljit_emit_ijump(compiler, type, src, srcw); +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 dst, sljit_sw dstw, + sljit_s32 type) +{ + sljit_u8 mask = get_cc(type & 0xff); + + CHECK_ERROR(); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type)); + + sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0; + sljit_gpr loc_r = tmp1; + switch (GET_OPCODE(op)) { + case SLJIT_AND: + case SLJIT_OR: + case SLJIT_XOR: + /* dst is also source operand */ + if (dst & SLJIT_MEM) + FAIL_IF(load_word(compiler, dst_r, dst, dstw, tmp1, op & SLJIT_I32_OP)); + + break; + case SLJIT_MOV: + case (SLJIT_MOV32 & ~SLJIT_I32_OP): + /* can write straight into destination */ + loc_r = dst_r; + break; + default: + SLJIT_UNREACHABLE(); + } + + if (mask != 0xf) + FAIL_IF(push_load_cc(compiler, type & 0xff)); + + /* TODO(mundaym): fold into cmov helper function? */ + #define LEVAL(i) i(loc_r, 1, mask) + if (have_lscond2()) { + FAIL_IF(push_load_imm_inst(compiler, loc_r, 0)); + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, lochi, locghi))); + } else { + /* TODO(mundaym): no load/store-on-condition 2 facility (ipm? branch-and-set?) */ + abort(); + } + #undef LEVAL + + /* apply bitwise op and set condition codes */ + switch (GET_OPCODE(op)) { + #define LEVAL(i) i(dst_r, loc_r) + case SLJIT_AND: + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, nr, ngr))); + break; + case SLJIT_OR: + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, or, ogr))); + break; + case SLJIT_XOR: + FAIL_IF(push_inst(compiler, + WHEN2(op & SLJIT_I32_OP, xr, xgr))); + break; + #undef LEVAL + } + + /* set zero flag if needed */ + if (op & SLJIT_SET_Z) + FAIL_IF(push_store_zero_flag(compiler, op, dst_r)); + + /* store result to memory if required */ + /* TODO(carenas): s/FAIL_IF/ return */ + if (dst & SLJIT_MEM) + FAIL_IF(store_word(compiler, dst_r, dst, dstw, tmp1, op & SLJIT_I32_OP)); + + return SLJIT_SUCCESS; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compiler, sljit_s32 type, + sljit_s32 dst_reg, + sljit_s32 src, sljit_sw srcw) +{ + sljit_u8 mask = get_cc(type & 0xff); + sljit_gpr dst_r = gpr(dst_reg & ~SLJIT_I32_OP); + sljit_gpr src_r = FAST_IS_REG(src) ? gpr(src) : tmp0; + + CHECK_ERROR(); + CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw)); + + if (mask != 0xf) + FAIL_IF(push_load_cc(compiler, type & 0xff)); + + if (src & SLJIT_IMM) { + /* TODO(mundaym): fast path with lscond2 */ + FAIL_IF(push_load_imm_inst(compiler, src_r, srcw)); + } + + #define LEVAL(i) i(dst_r, src_r, mask) + if (have_lscond1()) + return push_inst(compiler, + WHEN2(dst_reg & SLJIT_I32_OP, locr, locgr)); + + #undef LEVAL + + /* TODO(mundaym): implement */ + return SLJIT_ERR_UNSUPPORTED; +} + +/* --------------------------------------------------------------------- */ +/* 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) +{ + struct sljit_s390x_const *const_; + sljit_gpr dst_r; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); + + const_ = (struct sljit_s390x_const*)ensure_abuf(compiler, + sizeof(struct sljit_s390x_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, sljit_ins_const | lgrl(dst_r, 0))); + else { + PTR_FAIL_IF(push_inst(compiler, sljit_ins_const | larl(tmp1, 0))); + PTR_FAIL_IF(push_inst(compiler, lg(dst_r, 0, r0, tmp1))); + } + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, tmp1, 0 /* always 64-bit */)); + + return (struct sljit_const*)const_; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) +{ + /* Update the constant pool. */ + sljit_uw *ptr = (sljit_uw *)addr; + SLJIT_UNUSED_ARG(executable_offset); + + SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 0); + *ptr = new_target; + SLJIT_UPDATE_WX_FLAGS(ptr, ptr + 1, 1); + 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_set_jump_addr(addr, new_constant, executable_offset); +} + +SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label *sljit_emit_put_label( + struct sljit_compiler *compiler, + sljit_s32 dst, sljit_sw dstw) +{ + struct sljit_put_label *put_label; + sljit_gpr dst_r; + + CHECK_ERROR_PTR(); + CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw)); + ADJUST_LOCAL_OFFSET(dst, dstw); + + put_label = (struct sljit_put_label*)ensure_abuf(compiler, sizeof(struct sljit_put_label)); + PTR_FAIL_IF(!put_label); + set_put_label(put_label, compiler, 0); + + 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))); + } + + if (dst & SLJIT_MEM) + PTR_FAIL_IF(store_word(compiler, dst_r, dst, dstw, tmp1, 0)); + + return put_label; +} + +/* TODO(carenas): EVAL probably should move up or be refactored */ +#undef WHEN2 +#undef EVAL + +#undef tmp1 +#undef tmp0 + +/* TODO(carenas): undef other macros that spill like is_u12? */ diff --git a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c index 8079fad8df..e5167f02ba 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c @@ -266,21 +266,18 @@ 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_UNUSED_ARG(executable_offset); + SLJIT_UPDATE_WX_FLAGS(inst, inst + 2, 0); SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000)); inst[0] = (inst[0] & 0xffc00000) | ((new_target >> 10) & 0x3fffff); inst[1] = (inst[1] & 0xfffffc00) | (new_target & 0x3ff); + 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_ins *inst = (sljit_ins *)addr; - - SLJIT_ASSERT(((inst[0] & 0xc1c00000) == 0x01000000) && ((inst[1] & 0xc1f82000) == 0x80102000)); - inst[0] = (inst[0] & 0xffc00000) | ((new_constant >> 10) & 0x3fffff); - inst[1] = (inst[1] & 0xfffffc00) | (new_constant & 0x3ff); - inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset); - SLJIT_CACHE_FLUSH(inst, inst + 2); + sljit_set_jump_addr(addr, new_constant, executable_offset); } diff --git a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c index bfa4ecede2..544d80d028 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c @@ -311,7 +311,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); - code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); + code = (sljit_ins*)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins), compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; @@ -437,6 +437,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset); SLJIT_CACHE_FLUSH(code, code_ptr); + SLJIT_UPDATE_WX_FLAGS(code, code_ptr, 1); return code; } @@ -451,6 +452,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) return 1; #endif + case SLJIT_HAS_ZERO_REGISTER: + return 1; + #if (defined SLJIT_CONFIG_SPARC_64 && SLJIT_CONFIG_SPARC_64) case SLJIT_HAS_CMOV: return 1; @@ -872,6 +876,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile #else #error "Implementation required" #endif + case SLJIT_ENDBR: + case SLJIT_SKIP_FRAMES_BEFORE_RETURN: + return SLJIT_SUCCESS; } return SLJIT_SUCCESS; @@ -888,9 +895,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); - if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) - return SLJIT_SUCCESS; - op = GET_OPCODE(op); switch (op) { case SLJIT_MOV: @@ -971,6 +975,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); + ADJUST_LOCAL_OFFSET(src, srcw); + + switch (op) { + case SLJIT_FAST_RETURN: + if (FAST_IS_REG(src)) + FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK))); + else + FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw)); + + FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS)); + return push_inst(compiler, NOP, UNMOVABLE_INS); + case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: + case SLJIT_PREFETCH_L1: + case SLJIT_PREFETCH_L2: + case SLJIT_PREFETCH_L3: + case SLJIT_PREFETCH_ONCE: + return SLJIT_SUCCESS; + } + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -1215,25 +1246,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * ADJUST_LOCAL_OFFSET(dst, dstw); if (FAST_IS_REG(dst)) - return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), DR(dst)); + return push_inst(compiler, OR | D(dst) | S1(0) | S2(TMP_LINK), UNMOVABLE_INS); /* Memory. */ - return emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); - - if (FAST_IS_REG(src)) - FAIL_IF(push_inst(compiler, OR | D(TMP_LINK) | S1(0) | S2(src), DR(TMP_LINK))); - else - FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, TMP_LINK, src, srcw)); - - FAIL_IF(push_inst(compiler, JMPL | D(0) | S1(TMP_LINK) | IMM(8), UNMOVABLE_INS)); - return push_inst(compiler, NOP, UNMOVABLE_INS); + FAIL_IF(emit_op_mem(compiler, WORD_DATA, TMP_LINK, dst, dstw)); + compiler->delay_slot = UNMOVABLE_INS; + return SLJIT_SUCCESS; } /* --------------------------------------------------------------------- */ diff --git a/thirdparty/pcre2/src/sljit/sljitNativeTILEGX-encoder.c b/thirdparty/pcre2/src/sljit/sljitNativeTILEGX-encoder.c deleted file mode 100644 index dd82ebae6a..0000000000 --- a/thirdparty/pcre2/src/sljit/sljitNativeTILEGX-encoder.c +++ /dev/null @@ -1,10159 +0,0 @@ -/* - * Stack-less Just-In-Time compiler - * - * Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved. - * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* This code is owned by Tilera Corporation, and distributed as part - of multiple projects. In sljit, the code is under BSD licence. */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#define BFD_RELOC(x) R_##x - -/* Special registers. */ -#define TREG_LR 55 -#define TREG_SN 56 -#define TREG_ZERO 63 - -/* Canonical name of each register. */ -const char *const tilegx_register_names[] = -{ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", - "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", - "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", - "r48", "r49", "r50", "r51", "r52", "tp", "sp", "lr", - "sn", "idn0", "idn1", "udn0", "udn1", "udn2", "udn3", "zero" -}; - -enum -{ - R_NONE = 0, - R_TILEGX_NONE = 0, - R_TILEGX_64 = 1, - R_TILEGX_32 = 2, - R_TILEGX_16 = 3, - R_TILEGX_8 = 4, - R_TILEGX_64_PCREL = 5, - R_TILEGX_32_PCREL = 6, - R_TILEGX_16_PCREL = 7, - R_TILEGX_8_PCREL = 8, - R_TILEGX_HW0 = 9, - R_TILEGX_HW1 = 10, - R_TILEGX_HW2 = 11, - R_TILEGX_HW3 = 12, - R_TILEGX_HW0_LAST = 13, - R_TILEGX_HW1_LAST = 14, - R_TILEGX_HW2_LAST = 15, - R_TILEGX_COPY = 16, - R_TILEGX_GLOB_DAT = 17, - R_TILEGX_JMP_SLOT = 18, - R_TILEGX_RELATIVE = 19, - R_TILEGX_BROFF_X1 = 20, - R_TILEGX_JUMPOFF_X1 = 21, - R_TILEGX_JUMPOFF_X1_PLT = 22, - R_TILEGX_IMM8_X0 = 23, - R_TILEGX_IMM8_Y0 = 24, - R_TILEGX_IMM8_X1 = 25, - R_TILEGX_IMM8_Y1 = 26, - R_TILEGX_DEST_IMM8_X1 = 27, - R_TILEGX_MT_IMM14_X1 = 28, - R_TILEGX_MF_IMM14_X1 = 29, - R_TILEGX_MMSTART_X0 = 30, - R_TILEGX_MMEND_X0 = 31, - R_TILEGX_SHAMT_X0 = 32, - R_TILEGX_SHAMT_X1 = 33, - R_TILEGX_SHAMT_Y0 = 34, - R_TILEGX_SHAMT_Y1 = 35, - R_TILEGX_IMM16_X0_HW0 = 36, - R_TILEGX_IMM16_X1_HW0 = 37, - R_TILEGX_IMM16_X0_HW1 = 38, - R_TILEGX_IMM16_X1_HW1 = 39, - R_TILEGX_IMM16_X0_HW2 = 40, - R_TILEGX_IMM16_X1_HW2 = 41, - R_TILEGX_IMM16_X0_HW3 = 42, - R_TILEGX_IMM16_X1_HW3 = 43, - R_TILEGX_IMM16_X0_HW0_LAST = 44, - R_TILEGX_IMM16_X1_HW0_LAST = 45, - R_TILEGX_IMM16_X0_HW1_LAST = 46, - R_TILEGX_IMM16_X1_HW1_LAST = 47, - R_TILEGX_IMM16_X0_HW2_LAST = 48, - R_TILEGX_IMM16_X1_HW2_LAST = 49, - R_TILEGX_IMM16_X0_HW0_PCREL = 50, - R_TILEGX_IMM16_X1_HW0_PCREL = 51, - R_TILEGX_IMM16_X0_HW1_PCREL = 52, - R_TILEGX_IMM16_X1_HW1_PCREL = 53, - R_TILEGX_IMM16_X0_HW2_PCREL = 54, - R_TILEGX_IMM16_X1_HW2_PCREL = 55, - R_TILEGX_IMM16_X0_HW3_PCREL = 56, - R_TILEGX_IMM16_X1_HW3_PCREL = 57, - R_TILEGX_IMM16_X0_HW0_LAST_PCREL = 58, - R_TILEGX_IMM16_X1_HW0_LAST_PCREL = 59, - R_TILEGX_IMM16_X0_HW1_LAST_PCREL = 60, - R_TILEGX_IMM16_X1_HW1_LAST_PCREL = 61, - R_TILEGX_IMM16_X0_HW2_LAST_PCREL = 62, - R_TILEGX_IMM16_X1_HW2_LAST_PCREL = 63, - R_TILEGX_IMM16_X0_HW0_GOT = 64, - R_TILEGX_IMM16_X1_HW0_GOT = 65, - - R_TILEGX_IMM16_X0_HW0_PLT_PCREL = 66, - R_TILEGX_IMM16_X1_HW0_PLT_PCREL = 67, - R_TILEGX_IMM16_X0_HW1_PLT_PCREL = 68, - R_TILEGX_IMM16_X1_HW1_PLT_PCREL = 69, - R_TILEGX_IMM16_X0_HW2_PLT_PCREL = 70, - R_TILEGX_IMM16_X1_HW2_PLT_PCREL = 71, - - R_TILEGX_IMM16_X0_HW0_LAST_GOT = 72, - R_TILEGX_IMM16_X1_HW0_LAST_GOT = 73, - R_TILEGX_IMM16_X0_HW1_LAST_GOT = 74, - R_TILEGX_IMM16_X1_HW1_LAST_GOT = 75, - R_TILEGX_IMM16_X0_HW0_TLS_GD = 78, - R_TILEGX_IMM16_X1_HW0_TLS_GD = 79, - R_TILEGX_IMM16_X0_HW0_TLS_LE = 80, - R_TILEGX_IMM16_X1_HW0_TLS_LE = 81, - R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE = 82, - R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE = 83, - R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE = 84, - R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE = 85, - R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD = 86, - R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD = 87, - R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD = 88, - R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD = 89, - R_TILEGX_IMM16_X0_HW0_TLS_IE = 92, - R_TILEGX_IMM16_X1_HW0_TLS_IE = 93, - - R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL = 94, - R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL = 95, - R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL = 96, - R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL = 97, - R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL = 98, - R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL = 99, - - R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE = 100, - R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE = 101, - R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE = 102, - R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE = 103, - R_TILEGX_TLS_DTPMOD64 = 106, - R_TILEGX_TLS_DTPOFF64 = 107, - R_TILEGX_TLS_TPOFF64 = 108, - R_TILEGX_TLS_DTPMOD32 = 109, - R_TILEGX_TLS_DTPOFF32 = 110, - R_TILEGX_TLS_TPOFF32 = 111, - R_TILEGX_TLS_GD_CALL = 112, - R_TILEGX_IMM8_X0_TLS_GD_ADD = 113, - R_TILEGX_IMM8_X1_TLS_GD_ADD = 114, - R_TILEGX_IMM8_Y0_TLS_GD_ADD = 115, - R_TILEGX_IMM8_Y1_TLS_GD_ADD = 116, - R_TILEGX_TLS_IE_LOAD = 117, - R_TILEGX_IMM8_X0_TLS_ADD = 118, - R_TILEGX_IMM8_X1_TLS_ADD = 119, - R_TILEGX_IMM8_Y0_TLS_ADD = 120, - R_TILEGX_IMM8_Y1_TLS_ADD = 121, - R_TILEGX_GNU_VTINHERIT = 128, - R_TILEGX_GNU_VTENTRY = 129, - R_TILEGX_IRELATIVE = 130, - R_TILEGX_NUM = 131 -}; - -typedef enum -{ - TILEGX_PIPELINE_X0, - TILEGX_PIPELINE_X1, - TILEGX_PIPELINE_Y0, - TILEGX_PIPELINE_Y1, - TILEGX_PIPELINE_Y2, -} tilegx_pipeline; - -typedef unsigned long long tilegx_bundle_bits; - -/* These are the bits that determine if a bundle is in the X encoding. */ -#define TILEGX_BUNDLE_MODE_MASK ((tilegx_bundle_bits)3 << 62) - -enum -{ - /* Maximum number of instructions in a bundle (2 for X, 3 for Y). */ - TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE = 3, - - /* How many different pipeline encodings are there? X0, X1, Y0, Y1, Y2. */ - TILEGX_NUM_PIPELINE_ENCODINGS = 5, - - /* Log base 2 of TILEGX_BUNDLE_SIZE_IN_BYTES. */ - TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES = 3, - - /* Instructions take this many bytes. */ - TILEGX_BUNDLE_SIZE_IN_BYTES = 1 << TILEGX_LOG2_BUNDLE_SIZE_IN_BYTES, - - /* Log base 2 of TILEGX_BUNDLE_ALIGNMENT_IN_BYTES. */ - TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES = 3, - - /* Bundles should be aligned modulo this number of bytes. */ - TILEGX_BUNDLE_ALIGNMENT_IN_BYTES = - (1 << TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES), - - /* Number of registers (some are magic, such as network I/O). */ - TILEGX_NUM_REGISTERS = 64, -}; - -/* Make a few "tile_" variables to simplify common code between - architectures. */ - -typedef tilegx_bundle_bits tile_bundle_bits; -#define TILE_BUNDLE_SIZE_IN_BYTES TILEGX_BUNDLE_SIZE_IN_BYTES -#define TILE_BUNDLE_ALIGNMENT_IN_BYTES TILEGX_BUNDLE_ALIGNMENT_IN_BYTES -#define TILE_LOG2_BUNDLE_ALIGNMENT_IN_BYTES \ - TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES - -/* 64-bit pattern for a { bpt ; nop } bundle. */ -#define TILEGX_BPT_BUNDLE 0x286a44ae51485000ULL - -typedef enum -{ - TILEGX_OP_TYPE_REGISTER, - TILEGX_OP_TYPE_IMMEDIATE, - TILEGX_OP_TYPE_ADDRESS, - TILEGX_OP_TYPE_SPR -} tilegx_operand_type; - -struct tilegx_operand -{ - /* Is this operand a register, immediate or address? */ - tilegx_operand_type type; - - /* The default relocation type for this operand. */ - signed int default_reloc : 16; - - /* How many bits is this value? (used for range checking) */ - unsigned int num_bits : 5; - - /* Is the value signed? (used for range checking) */ - unsigned int is_signed : 1; - - /* Is this operand a source register? */ - unsigned int is_src_reg : 1; - - /* Is this operand written? (i.e. is it a destination register) */ - unsigned int is_dest_reg : 1; - - /* Is this operand PC-relative? */ - unsigned int is_pc_relative : 1; - - /* By how many bits do we right shift the value before inserting? */ - unsigned int rightshift : 2; - - /* Return the bits for this operand to be ORed into an existing bundle. */ - tilegx_bundle_bits (*insert) (int op); - - /* Extract this operand and return it. */ - unsigned int (*extract) (tilegx_bundle_bits bundle); -}; - -typedef enum -{ - TILEGX_OPC_BPT, - TILEGX_OPC_INFO, - TILEGX_OPC_INFOL, - TILEGX_OPC_LD4S_TLS, - TILEGX_OPC_LD_TLS, - TILEGX_OPC_MOVE, - TILEGX_OPC_MOVEI, - TILEGX_OPC_MOVELI, - TILEGX_OPC_PREFETCH, - TILEGX_OPC_PREFETCH_ADD_L1, - TILEGX_OPC_PREFETCH_ADD_L1_FAULT, - TILEGX_OPC_PREFETCH_ADD_L2, - TILEGX_OPC_PREFETCH_ADD_L2_FAULT, - TILEGX_OPC_PREFETCH_ADD_L3, - TILEGX_OPC_PREFETCH_ADD_L3_FAULT, - TILEGX_OPC_PREFETCH_L1, - TILEGX_OPC_PREFETCH_L1_FAULT, - TILEGX_OPC_PREFETCH_L2, - TILEGX_OPC_PREFETCH_L2_FAULT, - TILEGX_OPC_PREFETCH_L3, - TILEGX_OPC_PREFETCH_L3_FAULT, - TILEGX_OPC_RAISE, - TILEGX_OPC_ADD, - TILEGX_OPC_ADDI, - TILEGX_OPC_ADDLI, - TILEGX_OPC_ADDX, - TILEGX_OPC_ADDXI, - TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXSC, - TILEGX_OPC_AND, - TILEGX_OPC_ANDI, - TILEGX_OPC_BEQZ, - TILEGX_OPC_BEQZT, - TILEGX_OPC_BFEXTS, - TILEGX_OPC_BFEXTU, - TILEGX_OPC_BFINS, - TILEGX_OPC_BGEZ, - TILEGX_OPC_BGEZT, - TILEGX_OPC_BGTZ, - TILEGX_OPC_BGTZT, - TILEGX_OPC_BLBC, - TILEGX_OPC_BLBCT, - TILEGX_OPC_BLBS, - TILEGX_OPC_BLBST, - TILEGX_OPC_BLEZ, - TILEGX_OPC_BLEZT, - TILEGX_OPC_BLTZ, - TILEGX_OPC_BLTZT, - TILEGX_OPC_BNEZ, - TILEGX_OPC_BNEZT, - TILEGX_OPC_CLZ, - TILEGX_OPC_CMOVEQZ, - TILEGX_OPC_CMOVNEZ, - TILEGX_OPC_CMPEQ, - TILEGX_OPC_CMPEQI, - TILEGX_OPC_CMPEXCH, - TILEGX_OPC_CMPEXCH4, - TILEGX_OPC_CMPLES, - TILEGX_OPC_CMPLEU, - TILEGX_OPC_CMPLTS, - TILEGX_OPC_CMPLTSI, - TILEGX_OPC_CMPLTU, - TILEGX_OPC_CMPLTUI, - TILEGX_OPC_CMPNE, - TILEGX_OPC_CMUL, - TILEGX_OPC_CMULA, - TILEGX_OPC_CMULAF, - TILEGX_OPC_CMULF, - TILEGX_OPC_CMULFR, - TILEGX_OPC_CMULH, - TILEGX_OPC_CMULHR, - TILEGX_OPC_CRC32_32, - TILEGX_OPC_CRC32_8, - TILEGX_OPC_CTZ, - TILEGX_OPC_DBLALIGN, - TILEGX_OPC_DBLALIGN2, - TILEGX_OPC_DBLALIGN4, - TILEGX_OPC_DBLALIGN6, - TILEGX_OPC_DRAIN, - TILEGX_OPC_DTLBPR, - TILEGX_OPC_EXCH, - TILEGX_OPC_EXCH4, - TILEGX_OPC_FDOUBLE_ADD_FLAGS, - TILEGX_OPC_FDOUBLE_ADDSUB, - TILEGX_OPC_FDOUBLE_MUL_FLAGS, - TILEGX_OPC_FDOUBLE_PACK1, - TILEGX_OPC_FDOUBLE_PACK2, - TILEGX_OPC_FDOUBLE_SUB_FLAGS, - TILEGX_OPC_FDOUBLE_UNPACK_MAX, - TILEGX_OPC_FDOUBLE_UNPACK_MIN, - TILEGX_OPC_FETCHADD, - TILEGX_OPC_FETCHADD4, - TILEGX_OPC_FETCHADDGEZ, - TILEGX_OPC_FETCHADDGEZ4, - TILEGX_OPC_FETCHAND, - TILEGX_OPC_FETCHAND4, - TILEGX_OPC_FETCHOR, - TILEGX_OPC_FETCHOR4, - TILEGX_OPC_FINV, - TILEGX_OPC_FLUSH, - TILEGX_OPC_FLUSHWB, - TILEGX_OPC_FNOP, - TILEGX_OPC_FSINGLE_ADD1, - TILEGX_OPC_FSINGLE_ADDSUB2, - TILEGX_OPC_FSINGLE_MUL1, - TILEGX_OPC_FSINGLE_MUL2, - TILEGX_OPC_FSINGLE_PACK1, - TILEGX_OPC_FSINGLE_PACK2, - TILEGX_OPC_FSINGLE_SUB1, - TILEGX_OPC_ICOH, - TILEGX_OPC_ILL, - TILEGX_OPC_INV, - TILEGX_OPC_IRET, - TILEGX_OPC_J, - TILEGX_OPC_JAL, - TILEGX_OPC_JALR, - TILEGX_OPC_JALRP, - TILEGX_OPC_JR, - TILEGX_OPC_JRP, - TILEGX_OPC_LD, - TILEGX_OPC_LD1S, - TILEGX_OPC_LD1S_ADD, - TILEGX_OPC_LD1U, - TILEGX_OPC_LD1U_ADD, - TILEGX_OPC_LD2S, - TILEGX_OPC_LD2S_ADD, - TILEGX_OPC_LD2U, - TILEGX_OPC_LD2U_ADD, - TILEGX_OPC_LD4S, - TILEGX_OPC_LD4S_ADD, - TILEGX_OPC_LD4U, - TILEGX_OPC_LD4U_ADD, - TILEGX_OPC_LD_ADD, - TILEGX_OPC_LDNA, - TILEGX_OPC_LDNA_ADD, - TILEGX_OPC_LDNT, - TILEGX_OPC_LDNT1S, - TILEGX_OPC_LDNT1S_ADD, - TILEGX_OPC_LDNT1U, - TILEGX_OPC_LDNT1U_ADD, - TILEGX_OPC_LDNT2S, - TILEGX_OPC_LDNT2S_ADD, - TILEGX_OPC_LDNT2U, - TILEGX_OPC_LDNT2U_ADD, - TILEGX_OPC_LDNT4S, - TILEGX_OPC_LDNT4S_ADD, - TILEGX_OPC_LDNT4U, - TILEGX_OPC_LDNT4U_ADD, - TILEGX_OPC_LDNT_ADD, - TILEGX_OPC_LNK, - TILEGX_OPC_MF, - TILEGX_OPC_MFSPR, - TILEGX_OPC_MM, - TILEGX_OPC_MNZ, - TILEGX_OPC_MTSPR, - TILEGX_OPC_MUL_HS_HS, - TILEGX_OPC_MUL_HS_HU, - TILEGX_OPC_MUL_HS_LS, - TILEGX_OPC_MUL_HS_LU, - TILEGX_OPC_MUL_HU_HU, - TILEGX_OPC_MUL_HU_LS, - TILEGX_OPC_MUL_HU_LU, - TILEGX_OPC_MUL_LS_LS, - TILEGX_OPC_MUL_LS_LU, - TILEGX_OPC_MUL_LU_LU, - TILEGX_OPC_MULA_HS_HS, - TILEGX_OPC_MULA_HS_HU, - TILEGX_OPC_MULA_HS_LS, - TILEGX_OPC_MULA_HS_LU, - TILEGX_OPC_MULA_HU_HU, - TILEGX_OPC_MULA_HU_LS, - TILEGX_OPC_MULA_HU_LU, - TILEGX_OPC_MULA_LS_LS, - TILEGX_OPC_MULA_LS_LU, - TILEGX_OPC_MULA_LU_LU, - TILEGX_OPC_MULAX, - TILEGX_OPC_MULX, - TILEGX_OPC_MZ, - TILEGX_OPC_NAP, - TILEGX_OPC_NOP, - TILEGX_OPC_NOR, - TILEGX_OPC_OR, - TILEGX_OPC_ORI, - TILEGX_OPC_PCNT, - TILEGX_OPC_REVBITS, - TILEGX_OPC_REVBYTES, - TILEGX_OPC_ROTL, - TILEGX_OPC_ROTLI, - TILEGX_OPC_SHL, - TILEGX_OPC_SHL16INSLI, - TILEGX_OPC_SHL1ADD, - TILEGX_OPC_SHL1ADDX, - TILEGX_OPC_SHL2ADD, - TILEGX_OPC_SHL2ADDX, - TILEGX_OPC_SHL3ADD, - TILEGX_OPC_SHL3ADDX, - TILEGX_OPC_SHLI, - TILEGX_OPC_SHLX, - TILEGX_OPC_SHLXI, - TILEGX_OPC_SHRS, - TILEGX_OPC_SHRSI, - TILEGX_OPC_SHRU, - TILEGX_OPC_SHRUI, - TILEGX_OPC_SHRUX, - TILEGX_OPC_SHRUXI, - TILEGX_OPC_SHUFFLEBYTES, - TILEGX_OPC_ST, - TILEGX_OPC_ST1, - TILEGX_OPC_ST1_ADD, - TILEGX_OPC_ST2, - TILEGX_OPC_ST2_ADD, - TILEGX_OPC_ST4, - TILEGX_OPC_ST4_ADD, - TILEGX_OPC_ST_ADD, - TILEGX_OPC_STNT, - TILEGX_OPC_STNT1, - TILEGX_OPC_STNT1_ADD, - TILEGX_OPC_STNT2, - TILEGX_OPC_STNT2_ADD, - TILEGX_OPC_STNT4, - TILEGX_OPC_STNT4_ADD, - TILEGX_OPC_STNT_ADD, - TILEGX_OPC_SUB, - TILEGX_OPC_SUBX, - TILEGX_OPC_SUBXSC, - TILEGX_OPC_SWINT0, - TILEGX_OPC_SWINT1, - TILEGX_OPC_SWINT2, - TILEGX_OPC_SWINT3, - TILEGX_OPC_TBLIDXB0, - TILEGX_OPC_TBLIDXB1, - TILEGX_OPC_TBLIDXB2, - TILEGX_OPC_TBLIDXB3, - TILEGX_OPC_V1ADD, - TILEGX_OPC_V1ADDI, - TILEGX_OPC_V1ADDUC, - TILEGX_OPC_V1ADIFFU, - TILEGX_OPC_V1AVGU, - TILEGX_OPC_V1CMPEQ, - TILEGX_OPC_V1CMPEQI, - TILEGX_OPC_V1CMPLES, - TILEGX_OPC_V1CMPLEU, - TILEGX_OPC_V1CMPLTS, - TILEGX_OPC_V1CMPLTSI, - TILEGX_OPC_V1CMPLTU, - TILEGX_OPC_V1CMPLTUI, - TILEGX_OPC_V1CMPNE, - TILEGX_OPC_V1DDOTPU, - TILEGX_OPC_V1DDOTPUA, - TILEGX_OPC_V1DDOTPUS, - TILEGX_OPC_V1DDOTPUSA, - TILEGX_OPC_V1DOTP, - TILEGX_OPC_V1DOTPA, - TILEGX_OPC_V1DOTPU, - TILEGX_OPC_V1DOTPUA, - TILEGX_OPC_V1DOTPUS, - TILEGX_OPC_V1DOTPUSA, - TILEGX_OPC_V1INT_H, - TILEGX_OPC_V1INT_L, - TILEGX_OPC_V1MAXU, - TILEGX_OPC_V1MAXUI, - TILEGX_OPC_V1MINU, - TILEGX_OPC_V1MINUI, - TILEGX_OPC_V1MNZ, - TILEGX_OPC_V1MULTU, - TILEGX_OPC_V1MULU, - TILEGX_OPC_V1MULUS, - TILEGX_OPC_V1MZ, - TILEGX_OPC_V1SADAU, - TILEGX_OPC_V1SADU, - TILEGX_OPC_V1SHL, - TILEGX_OPC_V1SHLI, - TILEGX_OPC_V1SHRS, - TILEGX_OPC_V1SHRSI, - TILEGX_OPC_V1SHRU, - TILEGX_OPC_V1SHRUI, - TILEGX_OPC_V1SUB, - TILEGX_OPC_V1SUBUC, - TILEGX_OPC_V2ADD, - TILEGX_OPC_V2ADDI, - TILEGX_OPC_V2ADDSC, - TILEGX_OPC_V2ADIFFS, - TILEGX_OPC_V2AVGS, - TILEGX_OPC_V2CMPEQ, - TILEGX_OPC_V2CMPEQI, - TILEGX_OPC_V2CMPLES, - TILEGX_OPC_V2CMPLEU, - TILEGX_OPC_V2CMPLTS, - TILEGX_OPC_V2CMPLTSI, - TILEGX_OPC_V2CMPLTU, - TILEGX_OPC_V2CMPLTUI, - TILEGX_OPC_V2CMPNE, - TILEGX_OPC_V2DOTP, - TILEGX_OPC_V2DOTPA, - TILEGX_OPC_V2INT_H, - TILEGX_OPC_V2INT_L, - TILEGX_OPC_V2MAXS, - TILEGX_OPC_V2MAXSI, - TILEGX_OPC_V2MINS, - TILEGX_OPC_V2MINSI, - TILEGX_OPC_V2MNZ, - TILEGX_OPC_V2MULFSC, - TILEGX_OPC_V2MULS, - TILEGX_OPC_V2MULTS, - TILEGX_OPC_V2MZ, - TILEGX_OPC_V2PACKH, - TILEGX_OPC_V2PACKL, - TILEGX_OPC_V2PACKUC, - TILEGX_OPC_V2SADAS, - TILEGX_OPC_V2SADAU, - TILEGX_OPC_V2SADS, - TILEGX_OPC_V2SADU, - TILEGX_OPC_V2SHL, - TILEGX_OPC_V2SHLI, - TILEGX_OPC_V2SHLSC, - TILEGX_OPC_V2SHRS, - TILEGX_OPC_V2SHRSI, - TILEGX_OPC_V2SHRU, - TILEGX_OPC_V2SHRUI, - TILEGX_OPC_V2SUB, - TILEGX_OPC_V2SUBSC, - TILEGX_OPC_V4ADD, - TILEGX_OPC_V4ADDSC, - TILEGX_OPC_V4INT_H, - TILEGX_OPC_V4INT_L, - TILEGX_OPC_V4PACKSC, - TILEGX_OPC_V4SHL, - TILEGX_OPC_V4SHLSC, - TILEGX_OPC_V4SHRS, - TILEGX_OPC_V4SHRU, - TILEGX_OPC_V4SUB, - TILEGX_OPC_V4SUBSC, - TILEGX_OPC_WH64, - TILEGX_OPC_XOR, - TILEGX_OPC_XORI, - TILEGX_OPC_NONE -} tilegx_mnemonic; - -enum -{ - TILEGX_MAX_OPERANDS = 4 /* bfexts */ -}; - -struct tilegx_opcode -{ - /* The opcode mnemonic, e.g. "add" */ - const char *name; - - /* The enum value for this mnemonic. */ - tilegx_mnemonic mnemonic; - - /* A bit mask of which of the five pipes this instruction - is compatible with: - X0 0x01 - X1 0x02 - Y0 0x04 - Y1 0x08 - Y2 0x10 */ - unsigned char pipes; - - /* How many operands are there? */ - unsigned char num_operands; - - /* Which register does this write implicitly, or TREG_ZERO if none? */ - unsigned char implicitly_written_register; - - /* Can this be bundled with other instructions (almost always true). */ - unsigned char can_bundle; - - /* The description of the operands. Each of these is an - * index into the tilegx_operands[] table. */ - unsigned char operands[TILEGX_NUM_PIPELINE_ENCODINGS][TILEGX_MAX_OPERANDS]; - - /* A mask of which bits have predefined values for each pipeline. - * This is useful for disassembly. */ - tilegx_bundle_bits fixed_bit_masks[TILEGX_NUM_PIPELINE_ENCODINGS]; - - /* For each bit set in fixed_bit_masks, what the value is for this - * instruction. */ - tilegx_bundle_bits fixed_bit_values[TILEGX_NUM_PIPELINE_ENCODINGS]; -}; - -/* Used for non-textual disassembly into structs. */ -struct tilegx_decoded_instruction -{ - const struct tilegx_opcode *opcode; - const struct tilegx_operand *operands[TILEGX_MAX_OPERANDS]; - long long operand_values[TILEGX_MAX_OPERANDS]; -}; - -enum -{ - ADDI_IMM8_OPCODE_X0 = 1, - ADDI_IMM8_OPCODE_X1 = 1, - ADDI_OPCODE_Y0 = 0, - ADDI_OPCODE_Y1 = 1, - ADDLI_OPCODE_X0 = 1, - ADDLI_OPCODE_X1 = 0, - ADDXI_IMM8_OPCODE_X0 = 2, - ADDXI_IMM8_OPCODE_X1 = 2, - ADDXI_OPCODE_Y0 = 1, - ADDXI_OPCODE_Y1 = 2, - ADDXLI_OPCODE_X0 = 2, - ADDXLI_OPCODE_X1 = 1, - ADDXSC_RRR_0_OPCODE_X0 = 1, - ADDXSC_RRR_0_OPCODE_X1 = 1, - ADDX_RRR_0_OPCODE_X0 = 2, - ADDX_RRR_0_OPCODE_X1 = 2, - ADDX_RRR_0_OPCODE_Y0 = 0, - ADDX_SPECIAL_0_OPCODE_Y1 = 0, - ADD_RRR_0_OPCODE_X0 = 3, - ADD_RRR_0_OPCODE_X1 = 3, - ADD_RRR_0_OPCODE_Y0 = 1, - ADD_SPECIAL_0_OPCODE_Y1 = 1, - ANDI_IMM8_OPCODE_X0 = 3, - ANDI_IMM8_OPCODE_X1 = 3, - ANDI_OPCODE_Y0 = 2, - ANDI_OPCODE_Y1 = 3, - AND_RRR_0_OPCODE_X0 = 4, - AND_RRR_0_OPCODE_X1 = 4, - AND_RRR_5_OPCODE_Y0 = 0, - AND_RRR_5_OPCODE_Y1 = 0, - BEQZT_BRANCH_OPCODE_X1 = 16, - BEQZ_BRANCH_OPCODE_X1 = 17, - BFEXTS_BF_OPCODE_X0 = 4, - BFEXTU_BF_OPCODE_X0 = 5, - BFINS_BF_OPCODE_X0 = 6, - BF_OPCODE_X0 = 3, - BGEZT_BRANCH_OPCODE_X1 = 18, - BGEZ_BRANCH_OPCODE_X1 = 19, - BGTZT_BRANCH_OPCODE_X1 = 20, - BGTZ_BRANCH_OPCODE_X1 = 21, - BLBCT_BRANCH_OPCODE_X1 = 22, - BLBC_BRANCH_OPCODE_X1 = 23, - BLBST_BRANCH_OPCODE_X1 = 24, - BLBS_BRANCH_OPCODE_X1 = 25, - BLEZT_BRANCH_OPCODE_X1 = 26, - BLEZ_BRANCH_OPCODE_X1 = 27, - BLTZT_BRANCH_OPCODE_X1 = 28, - BLTZ_BRANCH_OPCODE_X1 = 29, - BNEZT_BRANCH_OPCODE_X1 = 30, - BNEZ_BRANCH_OPCODE_X1 = 31, - BRANCH_OPCODE_X1 = 2, - CMOVEQZ_RRR_0_OPCODE_X0 = 5, - CMOVEQZ_RRR_4_OPCODE_Y0 = 0, - CMOVNEZ_RRR_0_OPCODE_X0 = 6, - CMOVNEZ_RRR_4_OPCODE_Y0 = 1, - CMPEQI_IMM8_OPCODE_X0 = 4, - CMPEQI_IMM8_OPCODE_X1 = 4, - CMPEQI_OPCODE_Y0 = 3, - CMPEQI_OPCODE_Y1 = 4, - CMPEQ_RRR_0_OPCODE_X0 = 7, - CMPEQ_RRR_0_OPCODE_X1 = 5, - CMPEQ_RRR_3_OPCODE_Y0 = 0, - CMPEQ_RRR_3_OPCODE_Y1 = 2, - CMPEXCH4_RRR_0_OPCODE_X1 = 6, - CMPEXCH_RRR_0_OPCODE_X1 = 7, - CMPLES_RRR_0_OPCODE_X0 = 8, - CMPLES_RRR_0_OPCODE_X1 = 8, - CMPLES_RRR_2_OPCODE_Y0 = 0, - CMPLES_RRR_2_OPCODE_Y1 = 0, - CMPLEU_RRR_0_OPCODE_X0 = 9, - CMPLEU_RRR_0_OPCODE_X1 = 9, - CMPLEU_RRR_2_OPCODE_Y0 = 1, - CMPLEU_RRR_2_OPCODE_Y1 = 1, - CMPLTSI_IMM8_OPCODE_X0 = 5, - CMPLTSI_IMM8_OPCODE_X1 = 5, - CMPLTSI_OPCODE_Y0 = 4, - CMPLTSI_OPCODE_Y1 = 5, - CMPLTS_RRR_0_OPCODE_X0 = 10, - CMPLTS_RRR_0_OPCODE_X1 = 10, - CMPLTS_RRR_2_OPCODE_Y0 = 2, - CMPLTS_RRR_2_OPCODE_Y1 = 2, - CMPLTUI_IMM8_OPCODE_X0 = 6, - CMPLTUI_IMM8_OPCODE_X1 = 6, - CMPLTU_RRR_0_OPCODE_X0 = 11, - CMPLTU_RRR_0_OPCODE_X1 = 11, - CMPLTU_RRR_2_OPCODE_Y0 = 3, - CMPLTU_RRR_2_OPCODE_Y1 = 3, - CMPNE_RRR_0_OPCODE_X0 = 12, - CMPNE_RRR_0_OPCODE_X1 = 12, - CMPNE_RRR_3_OPCODE_Y0 = 1, - CMPNE_RRR_3_OPCODE_Y1 = 3, - CMULAF_RRR_0_OPCODE_X0 = 13, - CMULA_RRR_0_OPCODE_X0 = 14, - CMULFR_RRR_0_OPCODE_X0 = 15, - CMULF_RRR_0_OPCODE_X0 = 16, - CMULHR_RRR_0_OPCODE_X0 = 17, - CMULH_RRR_0_OPCODE_X0 = 18, - CMUL_RRR_0_OPCODE_X0 = 19, - CNTLZ_UNARY_OPCODE_X0 = 1, - CNTLZ_UNARY_OPCODE_Y0 = 1, - CNTTZ_UNARY_OPCODE_X0 = 2, - CNTTZ_UNARY_OPCODE_Y0 = 2, - CRC32_32_RRR_0_OPCODE_X0 = 20, - CRC32_8_RRR_0_OPCODE_X0 = 21, - DBLALIGN2_RRR_0_OPCODE_X0 = 22, - DBLALIGN2_RRR_0_OPCODE_X1 = 13, - DBLALIGN4_RRR_0_OPCODE_X0 = 23, - DBLALIGN4_RRR_0_OPCODE_X1 = 14, - DBLALIGN6_RRR_0_OPCODE_X0 = 24, - DBLALIGN6_RRR_0_OPCODE_X1 = 15, - DBLALIGN_RRR_0_OPCODE_X0 = 25, - DRAIN_UNARY_OPCODE_X1 = 1, - DTLBPR_UNARY_OPCODE_X1 = 2, - EXCH4_RRR_0_OPCODE_X1 = 16, - EXCH_RRR_0_OPCODE_X1 = 17, - FDOUBLE_ADDSUB_RRR_0_OPCODE_X0 = 26, - FDOUBLE_ADD_FLAGS_RRR_0_OPCODE_X0 = 27, - FDOUBLE_MUL_FLAGS_RRR_0_OPCODE_X0 = 28, - FDOUBLE_PACK1_RRR_0_OPCODE_X0 = 29, - FDOUBLE_PACK2_RRR_0_OPCODE_X0 = 30, - FDOUBLE_SUB_FLAGS_RRR_0_OPCODE_X0 = 31, - FDOUBLE_UNPACK_MAX_RRR_0_OPCODE_X0 = 32, - FDOUBLE_UNPACK_MIN_RRR_0_OPCODE_X0 = 33, - FETCHADD4_RRR_0_OPCODE_X1 = 18, - FETCHADDGEZ4_RRR_0_OPCODE_X1 = 19, - FETCHADDGEZ_RRR_0_OPCODE_X1 = 20, - FETCHADD_RRR_0_OPCODE_X1 = 21, - FETCHAND4_RRR_0_OPCODE_X1 = 22, - FETCHAND_RRR_0_OPCODE_X1 = 23, - FETCHOR4_RRR_0_OPCODE_X1 = 24, - FETCHOR_RRR_0_OPCODE_X1 = 25, - FINV_UNARY_OPCODE_X1 = 3, - FLUSHWB_UNARY_OPCODE_X1 = 4, - FLUSH_UNARY_OPCODE_X1 = 5, - FNOP_UNARY_OPCODE_X0 = 3, - FNOP_UNARY_OPCODE_X1 = 6, - FNOP_UNARY_OPCODE_Y0 = 3, - FNOP_UNARY_OPCODE_Y1 = 8, - FSINGLE_ADD1_RRR_0_OPCODE_X0 = 34, - FSINGLE_ADDSUB2_RRR_0_OPCODE_X0 = 35, - FSINGLE_MUL1_RRR_0_OPCODE_X0 = 36, - FSINGLE_MUL2_RRR_0_OPCODE_X0 = 37, - FSINGLE_PACK1_UNARY_OPCODE_X0 = 4, - FSINGLE_PACK1_UNARY_OPCODE_Y0 = 4, - FSINGLE_PACK2_RRR_0_OPCODE_X0 = 38, - FSINGLE_SUB1_RRR_0_OPCODE_X0 = 39, - ICOH_UNARY_OPCODE_X1 = 7, - ILL_UNARY_OPCODE_X1 = 8, - ILL_UNARY_OPCODE_Y1 = 9, - IMM8_OPCODE_X0 = 4, - IMM8_OPCODE_X1 = 3, - INV_UNARY_OPCODE_X1 = 9, - IRET_UNARY_OPCODE_X1 = 10, - JALRP_UNARY_OPCODE_X1 = 11, - JALRP_UNARY_OPCODE_Y1 = 10, - JALR_UNARY_OPCODE_X1 = 12, - JALR_UNARY_OPCODE_Y1 = 11, - JAL_JUMP_OPCODE_X1 = 0, - JRP_UNARY_OPCODE_X1 = 13, - JRP_UNARY_OPCODE_Y1 = 12, - JR_UNARY_OPCODE_X1 = 14, - JR_UNARY_OPCODE_Y1 = 13, - JUMP_OPCODE_X1 = 4, - J_JUMP_OPCODE_X1 = 1, - LD1S_ADD_IMM8_OPCODE_X1 = 7, - LD1S_OPCODE_Y2 = 0, - LD1S_UNARY_OPCODE_X1 = 15, - LD1U_ADD_IMM8_OPCODE_X1 = 8, - LD1U_OPCODE_Y2 = 1, - LD1U_UNARY_OPCODE_X1 = 16, - LD2S_ADD_IMM8_OPCODE_X1 = 9, - LD2S_OPCODE_Y2 = 2, - LD2S_UNARY_OPCODE_X1 = 17, - LD2U_ADD_IMM8_OPCODE_X1 = 10, - LD2U_OPCODE_Y2 = 3, - LD2U_UNARY_OPCODE_X1 = 18, - LD4S_ADD_IMM8_OPCODE_X1 = 11, - LD4S_OPCODE_Y2 = 1, - LD4S_UNARY_OPCODE_X1 = 19, - LD4U_ADD_IMM8_OPCODE_X1 = 12, - LD4U_OPCODE_Y2 = 2, - LD4U_UNARY_OPCODE_X1 = 20, - LDNA_UNARY_OPCODE_X1 = 21, - LDNT1S_ADD_IMM8_OPCODE_X1 = 13, - LDNT1S_UNARY_OPCODE_X1 = 22, - LDNT1U_ADD_IMM8_OPCODE_X1 = 14, - LDNT1U_UNARY_OPCODE_X1 = 23, - LDNT2S_ADD_IMM8_OPCODE_X1 = 15, - LDNT2S_UNARY_OPCODE_X1 = 24, - LDNT2U_ADD_IMM8_OPCODE_X1 = 16, - LDNT2U_UNARY_OPCODE_X1 = 25, - LDNT4S_ADD_IMM8_OPCODE_X1 = 17, - LDNT4S_UNARY_OPCODE_X1 = 26, - LDNT4U_ADD_IMM8_OPCODE_X1 = 18, - LDNT4U_UNARY_OPCODE_X1 = 27, - LDNT_ADD_IMM8_OPCODE_X1 = 19, - LDNT_UNARY_OPCODE_X1 = 28, - LD_ADD_IMM8_OPCODE_X1 = 20, - LD_OPCODE_Y2 = 3, - LD_UNARY_OPCODE_X1 = 29, - LNK_UNARY_OPCODE_X1 = 30, - LNK_UNARY_OPCODE_Y1 = 14, - LWNA_ADD_IMM8_OPCODE_X1 = 21, - MFSPR_IMM8_OPCODE_X1 = 22, - MF_UNARY_OPCODE_X1 = 31, - MM_BF_OPCODE_X0 = 7, - MNZ_RRR_0_OPCODE_X0 = 40, - MNZ_RRR_0_OPCODE_X1 = 26, - MNZ_RRR_4_OPCODE_Y0 = 2, - MNZ_RRR_4_OPCODE_Y1 = 2, - MODE_OPCODE_YA2 = 1, - MODE_OPCODE_YB2 = 2, - MODE_OPCODE_YC2 = 3, - MTSPR_IMM8_OPCODE_X1 = 23, - MULAX_RRR_0_OPCODE_X0 = 41, - MULAX_RRR_3_OPCODE_Y0 = 2, - MULA_HS_HS_RRR_0_OPCODE_X0 = 42, - MULA_HS_HS_RRR_9_OPCODE_Y0 = 0, - MULA_HS_HU_RRR_0_OPCODE_X0 = 43, - MULA_HS_LS_RRR_0_OPCODE_X0 = 44, - MULA_HS_LU_RRR_0_OPCODE_X0 = 45, - MULA_HU_HU_RRR_0_OPCODE_X0 = 46, - MULA_HU_HU_RRR_9_OPCODE_Y0 = 1, - MULA_HU_LS_RRR_0_OPCODE_X0 = 47, - MULA_HU_LU_RRR_0_OPCODE_X0 = 48, - MULA_LS_LS_RRR_0_OPCODE_X0 = 49, - MULA_LS_LS_RRR_9_OPCODE_Y0 = 2, - MULA_LS_LU_RRR_0_OPCODE_X0 = 50, - MULA_LU_LU_RRR_0_OPCODE_X0 = 51, - MULA_LU_LU_RRR_9_OPCODE_Y0 = 3, - MULX_RRR_0_OPCODE_X0 = 52, - MULX_RRR_3_OPCODE_Y0 = 3, - MUL_HS_HS_RRR_0_OPCODE_X0 = 53, - MUL_HS_HS_RRR_8_OPCODE_Y0 = 0, - MUL_HS_HU_RRR_0_OPCODE_X0 = 54, - MUL_HS_LS_RRR_0_OPCODE_X0 = 55, - MUL_HS_LU_RRR_0_OPCODE_X0 = 56, - MUL_HU_HU_RRR_0_OPCODE_X0 = 57, - MUL_HU_HU_RRR_8_OPCODE_Y0 = 1, - MUL_HU_LS_RRR_0_OPCODE_X0 = 58, - MUL_HU_LU_RRR_0_OPCODE_X0 = 59, - MUL_LS_LS_RRR_0_OPCODE_X0 = 60, - MUL_LS_LS_RRR_8_OPCODE_Y0 = 2, - MUL_LS_LU_RRR_0_OPCODE_X0 = 61, - MUL_LU_LU_RRR_0_OPCODE_X0 = 62, - MUL_LU_LU_RRR_8_OPCODE_Y0 = 3, - MZ_RRR_0_OPCODE_X0 = 63, - MZ_RRR_0_OPCODE_X1 = 27, - MZ_RRR_4_OPCODE_Y0 = 3, - MZ_RRR_4_OPCODE_Y1 = 3, - NAP_UNARY_OPCODE_X1 = 32, - NOP_UNARY_OPCODE_X0 = 5, - NOP_UNARY_OPCODE_X1 = 33, - NOP_UNARY_OPCODE_Y0 = 5, - NOP_UNARY_OPCODE_Y1 = 15, - NOR_RRR_0_OPCODE_X0 = 64, - NOR_RRR_0_OPCODE_X1 = 28, - NOR_RRR_5_OPCODE_Y0 = 1, - NOR_RRR_5_OPCODE_Y1 = 1, - ORI_IMM8_OPCODE_X0 = 7, - ORI_IMM8_OPCODE_X1 = 24, - OR_RRR_0_OPCODE_X0 = 65, - OR_RRR_0_OPCODE_X1 = 29, - OR_RRR_5_OPCODE_Y0 = 2, - OR_RRR_5_OPCODE_Y1 = 2, - PCNT_UNARY_OPCODE_X0 = 6, - PCNT_UNARY_OPCODE_Y0 = 6, - REVBITS_UNARY_OPCODE_X0 = 7, - REVBITS_UNARY_OPCODE_Y0 = 7, - REVBYTES_UNARY_OPCODE_X0 = 8, - REVBYTES_UNARY_OPCODE_Y0 = 8, - ROTLI_SHIFT_OPCODE_X0 = 1, - ROTLI_SHIFT_OPCODE_X1 = 1, - ROTLI_SHIFT_OPCODE_Y0 = 0, - ROTLI_SHIFT_OPCODE_Y1 = 0, - ROTL_RRR_0_OPCODE_X0 = 66, - ROTL_RRR_0_OPCODE_X1 = 30, - ROTL_RRR_6_OPCODE_Y0 = 0, - ROTL_RRR_6_OPCODE_Y1 = 0, - RRR_0_OPCODE_X0 = 5, - RRR_0_OPCODE_X1 = 5, - RRR_0_OPCODE_Y0 = 5, - RRR_0_OPCODE_Y1 = 6, - RRR_1_OPCODE_Y0 = 6, - RRR_1_OPCODE_Y1 = 7, - RRR_2_OPCODE_Y0 = 7, - RRR_2_OPCODE_Y1 = 8, - RRR_3_OPCODE_Y0 = 8, - RRR_3_OPCODE_Y1 = 9, - RRR_4_OPCODE_Y0 = 9, - RRR_4_OPCODE_Y1 = 10, - RRR_5_OPCODE_Y0 = 10, - RRR_5_OPCODE_Y1 = 11, - RRR_6_OPCODE_Y0 = 11, - RRR_6_OPCODE_Y1 = 12, - RRR_7_OPCODE_Y0 = 12, - RRR_7_OPCODE_Y1 = 13, - RRR_8_OPCODE_Y0 = 13, - RRR_9_OPCODE_Y0 = 14, - SHIFT_OPCODE_X0 = 6, - SHIFT_OPCODE_X1 = 6, - SHIFT_OPCODE_Y0 = 15, - SHIFT_OPCODE_Y1 = 14, - SHL16INSLI_OPCODE_X0 = 7, - SHL16INSLI_OPCODE_X1 = 7, - SHL1ADDX_RRR_0_OPCODE_X0 = 67, - SHL1ADDX_RRR_0_OPCODE_X1 = 31, - SHL1ADDX_RRR_7_OPCODE_Y0 = 1, - SHL1ADDX_RRR_7_OPCODE_Y1 = 1, - SHL1ADD_RRR_0_OPCODE_X0 = 68, - SHL1ADD_RRR_0_OPCODE_X1 = 32, - SHL1ADD_RRR_1_OPCODE_Y0 = 0, - SHL1ADD_RRR_1_OPCODE_Y1 = 0, - SHL2ADDX_RRR_0_OPCODE_X0 = 69, - SHL2ADDX_RRR_0_OPCODE_X1 = 33, - SHL2ADDX_RRR_7_OPCODE_Y0 = 2, - SHL2ADDX_RRR_7_OPCODE_Y1 = 2, - SHL2ADD_RRR_0_OPCODE_X0 = 70, - SHL2ADD_RRR_0_OPCODE_X1 = 34, - SHL2ADD_RRR_1_OPCODE_Y0 = 1, - SHL2ADD_RRR_1_OPCODE_Y1 = 1, - SHL3ADDX_RRR_0_OPCODE_X0 = 71, - SHL3ADDX_RRR_0_OPCODE_X1 = 35, - SHL3ADDX_RRR_7_OPCODE_Y0 = 3, - SHL3ADDX_RRR_7_OPCODE_Y1 = 3, - SHL3ADD_RRR_0_OPCODE_X0 = 72, - SHL3ADD_RRR_0_OPCODE_X1 = 36, - SHL3ADD_RRR_1_OPCODE_Y0 = 2, - SHL3ADD_RRR_1_OPCODE_Y1 = 2, - SHLI_SHIFT_OPCODE_X0 = 2, - SHLI_SHIFT_OPCODE_X1 = 2, - SHLI_SHIFT_OPCODE_Y0 = 1, - SHLI_SHIFT_OPCODE_Y1 = 1, - SHLXI_SHIFT_OPCODE_X0 = 3, - SHLXI_SHIFT_OPCODE_X1 = 3, - SHLX_RRR_0_OPCODE_X0 = 73, - SHLX_RRR_0_OPCODE_X1 = 37, - SHL_RRR_0_OPCODE_X0 = 74, - SHL_RRR_0_OPCODE_X1 = 38, - SHL_RRR_6_OPCODE_Y0 = 1, - SHL_RRR_6_OPCODE_Y1 = 1, - SHRSI_SHIFT_OPCODE_X0 = 4, - SHRSI_SHIFT_OPCODE_X1 = 4, - SHRSI_SHIFT_OPCODE_Y0 = 2, - SHRSI_SHIFT_OPCODE_Y1 = 2, - SHRS_RRR_0_OPCODE_X0 = 75, - SHRS_RRR_0_OPCODE_X1 = 39, - SHRS_RRR_6_OPCODE_Y0 = 2, - SHRS_RRR_6_OPCODE_Y1 = 2, - SHRUI_SHIFT_OPCODE_X0 = 5, - SHRUI_SHIFT_OPCODE_X1 = 5, - SHRUI_SHIFT_OPCODE_Y0 = 3, - SHRUI_SHIFT_OPCODE_Y1 = 3, - SHRUXI_SHIFT_OPCODE_X0 = 6, - SHRUXI_SHIFT_OPCODE_X1 = 6, - SHRUX_RRR_0_OPCODE_X0 = 76, - SHRUX_RRR_0_OPCODE_X1 = 40, - SHRU_RRR_0_OPCODE_X0 = 77, - SHRU_RRR_0_OPCODE_X1 = 41, - SHRU_RRR_6_OPCODE_Y0 = 3, - SHRU_RRR_6_OPCODE_Y1 = 3, - SHUFFLEBYTES_RRR_0_OPCODE_X0 = 78, - ST1_ADD_IMM8_OPCODE_X1 = 25, - ST1_OPCODE_Y2 = 0, - ST1_RRR_0_OPCODE_X1 = 42, - ST2_ADD_IMM8_OPCODE_X1 = 26, - ST2_OPCODE_Y2 = 1, - ST2_RRR_0_OPCODE_X1 = 43, - ST4_ADD_IMM8_OPCODE_X1 = 27, - ST4_OPCODE_Y2 = 2, - ST4_RRR_0_OPCODE_X1 = 44, - STNT1_ADD_IMM8_OPCODE_X1 = 28, - STNT1_RRR_0_OPCODE_X1 = 45, - STNT2_ADD_IMM8_OPCODE_X1 = 29, - STNT2_RRR_0_OPCODE_X1 = 46, - STNT4_ADD_IMM8_OPCODE_X1 = 30, - STNT4_RRR_0_OPCODE_X1 = 47, - STNT_ADD_IMM8_OPCODE_X1 = 31, - STNT_RRR_0_OPCODE_X1 = 48, - ST_ADD_IMM8_OPCODE_X1 = 32, - ST_OPCODE_Y2 = 3, - ST_RRR_0_OPCODE_X1 = 49, - SUBXSC_RRR_0_OPCODE_X0 = 79, - SUBXSC_RRR_0_OPCODE_X1 = 50, - SUBX_RRR_0_OPCODE_X0 = 80, - SUBX_RRR_0_OPCODE_X1 = 51, - SUBX_RRR_0_OPCODE_Y0 = 2, - SUBX_RRR_0_OPCODE_Y1 = 2, - SUB_RRR_0_OPCODE_X0 = 81, - SUB_RRR_0_OPCODE_X1 = 52, - SUB_RRR_0_OPCODE_Y0 = 3, - SUB_RRR_0_OPCODE_Y1 = 3, - SWINT0_UNARY_OPCODE_X1 = 34, - SWINT1_UNARY_OPCODE_X1 = 35, - SWINT2_UNARY_OPCODE_X1 = 36, - SWINT3_UNARY_OPCODE_X1 = 37, - TBLIDXB0_UNARY_OPCODE_X0 = 9, - TBLIDXB0_UNARY_OPCODE_Y0 = 9, - TBLIDXB1_UNARY_OPCODE_X0 = 10, - TBLIDXB1_UNARY_OPCODE_Y0 = 10, - TBLIDXB2_UNARY_OPCODE_X0 = 11, - TBLIDXB2_UNARY_OPCODE_Y0 = 11, - TBLIDXB3_UNARY_OPCODE_X0 = 12, - TBLIDXB3_UNARY_OPCODE_Y0 = 12, - UNARY_RRR_0_OPCODE_X0 = 82, - UNARY_RRR_0_OPCODE_X1 = 53, - UNARY_RRR_1_OPCODE_Y0 = 3, - UNARY_RRR_1_OPCODE_Y1 = 3, - V1ADDI_IMM8_OPCODE_X0 = 8, - V1ADDI_IMM8_OPCODE_X1 = 33, - V1ADDUC_RRR_0_OPCODE_X0 = 83, - V1ADDUC_RRR_0_OPCODE_X1 = 54, - V1ADD_RRR_0_OPCODE_X0 = 84, - V1ADD_RRR_0_OPCODE_X1 = 55, - V1ADIFFU_RRR_0_OPCODE_X0 = 85, - V1AVGU_RRR_0_OPCODE_X0 = 86, - V1CMPEQI_IMM8_OPCODE_X0 = 9, - V1CMPEQI_IMM8_OPCODE_X1 = 34, - V1CMPEQ_RRR_0_OPCODE_X0 = 87, - V1CMPEQ_RRR_0_OPCODE_X1 = 56, - V1CMPLES_RRR_0_OPCODE_X0 = 88, - V1CMPLES_RRR_0_OPCODE_X1 = 57, - V1CMPLEU_RRR_0_OPCODE_X0 = 89, - V1CMPLEU_RRR_0_OPCODE_X1 = 58, - V1CMPLTSI_IMM8_OPCODE_X0 = 10, - V1CMPLTSI_IMM8_OPCODE_X1 = 35, - V1CMPLTS_RRR_0_OPCODE_X0 = 90, - V1CMPLTS_RRR_0_OPCODE_X1 = 59, - V1CMPLTUI_IMM8_OPCODE_X0 = 11, - V1CMPLTUI_IMM8_OPCODE_X1 = 36, - V1CMPLTU_RRR_0_OPCODE_X0 = 91, - V1CMPLTU_RRR_0_OPCODE_X1 = 60, - V1CMPNE_RRR_0_OPCODE_X0 = 92, - V1CMPNE_RRR_0_OPCODE_X1 = 61, - V1DDOTPUA_RRR_0_OPCODE_X0 = 161, - V1DDOTPUSA_RRR_0_OPCODE_X0 = 93, - V1DDOTPUS_RRR_0_OPCODE_X0 = 94, - V1DDOTPU_RRR_0_OPCODE_X0 = 162, - V1DOTPA_RRR_0_OPCODE_X0 = 95, - V1DOTPUA_RRR_0_OPCODE_X0 = 163, - V1DOTPUSA_RRR_0_OPCODE_X0 = 96, - V1DOTPUS_RRR_0_OPCODE_X0 = 97, - V1DOTPU_RRR_0_OPCODE_X0 = 164, - V1DOTP_RRR_0_OPCODE_X0 = 98, - V1INT_H_RRR_0_OPCODE_X0 = 99, - V1INT_H_RRR_0_OPCODE_X1 = 62, - V1INT_L_RRR_0_OPCODE_X0 = 100, - V1INT_L_RRR_0_OPCODE_X1 = 63, - V1MAXUI_IMM8_OPCODE_X0 = 12, - V1MAXUI_IMM8_OPCODE_X1 = 37, - V1MAXU_RRR_0_OPCODE_X0 = 101, - V1MAXU_RRR_0_OPCODE_X1 = 64, - V1MINUI_IMM8_OPCODE_X0 = 13, - V1MINUI_IMM8_OPCODE_X1 = 38, - V1MINU_RRR_0_OPCODE_X0 = 102, - V1MINU_RRR_0_OPCODE_X1 = 65, - V1MNZ_RRR_0_OPCODE_X0 = 103, - V1MNZ_RRR_0_OPCODE_X1 = 66, - V1MULTU_RRR_0_OPCODE_X0 = 104, - V1MULUS_RRR_0_OPCODE_X0 = 105, - V1MULU_RRR_0_OPCODE_X0 = 106, - V1MZ_RRR_0_OPCODE_X0 = 107, - V1MZ_RRR_0_OPCODE_X1 = 67, - V1SADAU_RRR_0_OPCODE_X0 = 108, - V1SADU_RRR_0_OPCODE_X0 = 109, - V1SHLI_SHIFT_OPCODE_X0 = 7, - V1SHLI_SHIFT_OPCODE_X1 = 7, - V1SHL_RRR_0_OPCODE_X0 = 110, - V1SHL_RRR_0_OPCODE_X1 = 68, - V1SHRSI_SHIFT_OPCODE_X0 = 8, - V1SHRSI_SHIFT_OPCODE_X1 = 8, - V1SHRS_RRR_0_OPCODE_X0 = 111, - V1SHRS_RRR_0_OPCODE_X1 = 69, - V1SHRUI_SHIFT_OPCODE_X0 = 9, - V1SHRUI_SHIFT_OPCODE_X1 = 9, - V1SHRU_RRR_0_OPCODE_X0 = 112, - V1SHRU_RRR_0_OPCODE_X1 = 70, - V1SUBUC_RRR_0_OPCODE_X0 = 113, - V1SUBUC_RRR_0_OPCODE_X1 = 71, - V1SUB_RRR_0_OPCODE_X0 = 114, - V1SUB_RRR_0_OPCODE_X1 = 72, - V2ADDI_IMM8_OPCODE_X0 = 14, - V2ADDI_IMM8_OPCODE_X1 = 39, - V2ADDSC_RRR_0_OPCODE_X0 = 115, - V2ADDSC_RRR_0_OPCODE_X1 = 73, - V2ADD_RRR_0_OPCODE_X0 = 116, - V2ADD_RRR_0_OPCODE_X1 = 74, - V2ADIFFS_RRR_0_OPCODE_X0 = 117, - V2AVGS_RRR_0_OPCODE_X0 = 118, - V2CMPEQI_IMM8_OPCODE_X0 = 15, - V2CMPEQI_IMM8_OPCODE_X1 = 40, - V2CMPEQ_RRR_0_OPCODE_X0 = 119, - V2CMPEQ_RRR_0_OPCODE_X1 = 75, - V2CMPLES_RRR_0_OPCODE_X0 = 120, - V2CMPLES_RRR_0_OPCODE_X1 = 76, - V2CMPLEU_RRR_0_OPCODE_X0 = 121, - V2CMPLEU_RRR_0_OPCODE_X1 = 77, - V2CMPLTSI_IMM8_OPCODE_X0 = 16, - V2CMPLTSI_IMM8_OPCODE_X1 = 41, - V2CMPLTS_RRR_0_OPCODE_X0 = 122, - V2CMPLTS_RRR_0_OPCODE_X1 = 78, - V2CMPLTUI_IMM8_OPCODE_X0 = 17, - V2CMPLTUI_IMM8_OPCODE_X1 = 42, - V2CMPLTU_RRR_0_OPCODE_X0 = 123, - V2CMPLTU_RRR_0_OPCODE_X1 = 79, - V2CMPNE_RRR_0_OPCODE_X0 = 124, - V2CMPNE_RRR_0_OPCODE_X1 = 80, - V2DOTPA_RRR_0_OPCODE_X0 = 125, - V2DOTP_RRR_0_OPCODE_X0 = 126, - V2INT_H_RRR_0_OPCODE_X0 = 127, - V2INT_H_RRR_0_OPCODE_X1 = 81, - V2INT_L_RRR_0_OPCODE_X0 = 128, - V2INT_L_RRR_0_OPCODE_X1 = 82, - V2MAXSI_IMM8_OPCODE_X0 = 18, - V2MAXSI_IMM8_OPCODE_X1 = 43, - V2MAXS_RRR_0_OPCODE_X0 = 129, - V2MAXS_RRR_0_OPCODE_X1 = 83, - V2MINSI_IMM8_OPCODE_X0 = 19, - V2MINSI_IMM8_OPCODE_X1 = 44, - V2MINS_RRR_0_OPCODE_X0 = 130, - V2MINS_RRR_0_OPCODE_X1 = 84, - V2MNZ_RRR_0_OPCODE_X0 = 131, - V2MNZ_RRR_0_OPCODE_X1 = 85, - V2MULFSC_RRR_0_OPCODE_X0 = 132, - V2MULS_RRR_0_OPCODE_X0 = 133, - V2MULTS_RRR_0_OPCODE_X0 = 134, - V2MZ_RRR_0_OPCODE_X0 = 135, - V2MZ_RRR_0_OPCODE_X1 = 86, - V2PACKH_RRR_0_OPCODE_X0 = 136, - V2PACKH_RRR_0_OPCODE_X1 = 87, - V2PACKL_RRR_0_OPCODE_X0 = 137, - V2PACKL_RRR_0_OPCODE_X1 = 88, - V2PACKUC_RRR_0_OPCODE_X0 = 138, - V2PACKUC_RRR_0_OPCODE_X1 = 89, - V2SADAS_RRR_0_OPCODE_X0 = 139, - V2SADAU_RRR_0_OPCODE_X0 = 140, - V2SADS_RRR_0_OPCODE_X0 = 141, - V2SADU_RRR_0_OPCODE_X0 = 142, - V2SHLI_SHIFT_OPCODE_X0 = 10, - V2SHLI_SHIFT_OPCODE_X1 = 10, - V2SHLSC_RRR_0_OPCODE_X0 = 143, - V2SHLSC_RRR_0_OPCODE_X1 = 90, - V2SHL_RRR_0_OPCODE_X0 = 144, - V2SHL_RRR_0_OPCODE_X1 = 91, - V2SHRSI_SHIFT_OPCODE_X0 = 11, - V2SHRSI_SHIFT_OPCODE_X1 = 11, - V2SHRS_RRR_0_OPCODE_X0 = 145, - V2SHRS_RRR_0_OPCODE_X1 = 92, - V2SHRUI_SHIFT_OPCODE_X0 = 12, - V2SHRUI_SHIFT_OPCODE_X1 = 12, - V2SHRU_RRR_0_OPCODE_X0 = 146, - V2SHRU_RRR_0_OPCODE_X1 = 93, - V2SUBSC_RRR_0_OPCODE_X0 = 147, - V2SUBSC_RRR_0_OPCODE_X1 = 94, - V2SUB_RRR_0_OPCODE_X0 = 148, - V2SUB_RRR_0_OPCODE_X1 = 95, - V4ADDSC_RRR_0_OPCODE_X0 = 149, - V4ADDSC_RRR_0_OPCODE_X1 = 96, - V4ADD_RRR_0_OPCODE_X0 = 150, - V4ADD_RRR_0_OPCODE_X1 = 97, - V4INT_H_RRR_0_OPCODE_X0 = 151, - V4INT_H_RRR_0_OPCODE_X1 = 98, - V4INT_L_RRR_0_OPCODE_X0 = 152, - V4INT_L_RRR_0_OPCODE_X1 = 99, - V4PACKSC_RRR_0_OPCODE_X0 = 153, - V4PACKSC_RRR_0_OPCODE_X1 = 100, - V4SHLSC_RRR_0_OPCODE_X0 = 154, - V4SHLSC_RRR_0_OPCODE_X1 = 101, - V4SHL_RRR_0_OPCODE_X0 = 155, - V4SHL_RRR_0_OPCODE_X1 = 102, - V4SHRS_RRR_0_OPCODE_X0 = 156, - V4SHRS_RRR_0_OPCODE_X1 = 103, - V4SHRU_RRR_0_OPCODE_X0 = 157, - V4SHRU_RRR_0_OPCODE_X1 = 104, - V4SUBSC_RRR_0_OPCODE_X0 = 158, - V4SUBSC_RRR_0_OPCODE_X1 = 105, - V4SUB_RRR_0_OPCODE_X0 = 159, - V4SUB_RRR_0_OPCODE_X1 = 106, - WH64_UNARY_OPCODE_X1 = 38, - XORI_IMM8_OPCODE_X0 = 20, - XORI_IMM8_OPCODE_X1 = 45, - XOR_RRR_0_OPCODE_X0 = 160, - XOR_RRR_0_OPCODE_X1 = 107, - XOR_RRR_5_OPCODE_Y0 = 3, - XOR_RRR_5_OPCODE_Y1 = 3 -}; - -static __inline unsigned int -get_BFEnd_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x3f); -} - -static __inline unsigned int -get_BFOpcodeExtension_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 24)) & 0xf); -} - -static __inline unsigned int -get_BFStart_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 18)) & 0x3f); -} - -static __inline unsigned int -get_BrOff_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 31)) & 0x0000003f) | - (((unsigned int)(n >> 37)) & 0x0001ffc0); -} - -static __inline unsigned int -get_BrType_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 54)) & 0x1f); -} - -static __inline unsigned int -get_Dest_Imm8_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 31)) & 0x0000003f) | - (((unsigned int)(n >> 43)) & 0x000000c0); -} - -static __inline unsigned int -get_Dest_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 0)) & 0x3f); -} - -static __inline unsigned int -get_Dest_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 31)) & 0x3f); -} - -static __inline unsigned int -get_Dest_Y0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 0)) & 0x3f); -} - -static __inline unsigned int -get_Dest_Y1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 31)) & 0x3f); -} - -static __inline unsigned int -get_Imm16_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0xffff); -} - -static __inline unsigned int -get_Imm16_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0xffff); -} - -static __inline unsigned int -get_Imm8OpcodeExtension_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 20)) & 0xff); -} - -static __inline unsigned int -get_Imm8OpcodeExtension_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 51)) & 0xff); -} - -static __inline unsigned int -get_Imm8_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0xff); -} - -static __inline unsigned int -get_Imm8_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0xff); -} - -static __inline unsigned int -get_Imm8_Y0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0xff); -} - -static __inline unsigned int -get_Imm8_Y1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0xff); -} - -static __inline unsigned int -get_JumpOff_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 31)) & 0x7ffffff); -} - -static __inline unsigned int -get_JumpOpcodeExtension_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 58)) & 0x1); -} - -static __inline unsigned int -get_MF_Imm14_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 37)) & 0x3fff); -} - -static __inline unsigned int -get_MT_Imm14_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 31)) & 0x0000003f) | - (((unsigned int)(n >> 37)) & 0x00003fc0); -} - -static __inline unsigned int -get_Mode(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 62)) & 0x3); -} - -static __inline unsigned int -get_Opcode_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 28)) & 0x7); -} - -static __inline unsigned int -get_Opcode_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 59)) & 0x7); -} - -static __inline unsigned int -get_Opcode_Y0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 27)) & 0xf); -} - -static __inline unsigned int -get_Opcode_Y1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 58)) & 0xf); -} - -static __inline unsigned int -get_Opcode_Y2(tilegx_bundle_bits n) -{ - return (((n >> 26)) & 0x00000001) | - (((unsigned int)(n >> 56)) & 0x00000002); -} - -static __inline unsigned int -get_RRROpcodeExtension_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 18)) & 0x3ff); -} - -static __inline unsigned int -get_RRROpcodeExtension_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 49)) & 0x3ff); -} - -static __inline unsigned int -get_RRROpcodeExtension_Y0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 18)) & 0x3); -} - -static __inline unsigned int -get_RRROpcodeExtension_Y1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 49)) & 0x3); -} - -static __inline unsigned int -get_ShAmt_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x3f); -} - -static __inline unsigned int -get_ShAmt_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0x3f); -} - -static __inline unsigned int -get_ShAmt_Y0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x3f); -} - -static __inline unsigned int -get_ShAmt_Y1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0x3f); -} - -static __inline unsigned int -get_ShiftOpcodeExtension_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 18)) & 0x3ff); -} - -static __inline unsigned int -get_ShiftOpcodeExtension_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 49)) & 0x3ff); -} - -static __inline unsigned int -get_ShiftOpcodeExtension_Y0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 18)) & 0x3); -} - -static __inline unsigned int -get_ShiftOpcodeExtension_Y1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 49)) & 0x3); -} - -static __inline unsigned int -get_SrcA_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 6)) & 0x3f); -} - -static __inline unsigned int -get_SrcA_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 37)) & 0x3f); -} - -static __inline unsigned int -get_SrcA_Y0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 6)) & 0x3f); -} - -static __inline unsigned int -get_SrcA_Y1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 37)) & 0x3f); -} - -static __inline unsigned int -get_SrcA_Y2(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 20)) & 0x3f); -} - -static __inline unsigned int -get_SrcBDest_Y2(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 51)) & 0x3f); -} - -static __inline unsigned int -get_SrcB_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x3f); -} - -static __inline unsigned int -get_SrcB_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0x3f); -} - -static __inline unsigned int -get_SrcB_Y0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x3f); -} - -static __inline unsigned int -get_SrcB_Y1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0x3f); -} - -static __inline unsigned int -get_UnaryOpcodeExtension_X0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x3f); -} - -static __inline unsigned int -get_UnaryOpcodeExtension_X1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0x3f); -} - -static __inline unsigned int -get_UnaryOpcodeExtension_Y0(tilegx_bundle_bits num) -{ - const unsigned int n = (unsigned int)num; - return (((n >> 12)) & 0x3f); -} - -static __inline unsigned int -get_UnaryOpcodeExtension_Y1(tilegx_bundle_bits n) -{ - return (((unsigned int)(n >> 43)) & 0x3f); -} - -static __inline int -sign_extend(int n, int num_bits) -{ - int shift = (int)(sizeof(int) * 8 - num_bits); - return (n << shift) >> shift; -} - -static __inline tilegx_bundle_bits -create_BFEnd_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 12); -} - -static __inline tilegx_bundle_bits -create_BFOpcodeExtension_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0xf) << 24); -} - -static __inline tilegx_bundle_bits -create_BFStart_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 18); -} - -static __inline tilegx_bundle_bits -create_BrOff_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) | - (((tilegx_bundle_bits)(n & 0x0001ffc0)) << 37); -} - -static __inline tilegx_bundle_bits -create_BrType_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x1f)) << 54); -} - -static __inline tilegx_bundle_bits -create_Dest_Imm8_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) | - (((tilegx_bundle_bits)(n & 0x000000c0)) << 43); -} - -static __inline tilegx_bundle_bits -create_Dest_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 0); -} - -static __inline tilegx_bundle_bits -create_Dest_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3f)) << 31); -} - -static __inline tilegx_bundle_bits -create_Dest_Y0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 0); -} - -static __inline tilegx_bundle_bits -create_Dest_Y1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3f)) << 31); -} - -static __inline tilegx_bundle_bits -create_Imm16_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0xffff) << 12); -} - -static __inline tilegx_bundle_bits -create_Imm16_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0xffff)) << 43); -} - -static __inline tilegx_bundle_bits -create_Imm8OpcodeExtension_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0xff) << 20); -} - -static __inline tilegx_bundle_bits -create_Imm8OpcodeExtension_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0xff)) << 51); -} - -static __inline tilegx_bundle_bits -create_Imm8_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0xff) << 12); -} - -static __inline tilegx_bundle_bits -create_Imm8_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0xff)) << 43); -} - -static __inline tilegx_bundle_bits -create_Imm8_Y0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0xff) << 12); -} - -static __inline tilegx_bundle_bits -create_Imm8_Y1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0xff)) << 43); -} - -static __inline tilegx_bundle_bits -create_JumpOff_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x7ffffff)) << 31); -} - -static __inline tilegx_bundle_bits -create_JumpOpcodeExtension_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x1)) << 58); -} - -static __inline tilegx_bundle_bits -create_MF_Imm14_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3fff)) << 37); -} - -static __inline tilegx_bundle_bits -create_MT_Imm14_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x0000003f)) << 31) | - (((tilegx_bundle_bits)(n & 0x00003fc0)) << 37); -} - -static __inline tilegx_bundle_bits -create_Mode(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3)) << 62); -} - -static __inline tilegx_bundle_bits -create_Opcode_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x7) << 28); -} - -static __inline tilegx_bundle_bits -create_Opcode_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x7)) << 59); -} - -static __inline tilegx_bundle_bits -create_Opcode_Y0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0xf) << 27); -} - -static __inline tilegx_bundle_bits -create_Opcode_Y1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0xf)) << 58); -} - -static __inline tilegx_bundle_bits -create_Opcode_Y2(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x00000001) << 26) | - (((tilegx_bundle_bits)(n & 0x00000002)) << 56); -} - -static __inline tilegx_bundle_bits -create_RRROpcodeExtension_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3ff) << 18); -} - -static __inline tilegx_bundle_bits -create_RRROpcodeExtension_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3ff)) << 49); -} - -static __inline tilegx_bundle_bits -create_RRROpcodeExtension_Y0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3) << 18); -} - -static __inline tilegx_bundle_bits -create_RRROpcodeExtension_Y1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3)) << 49); -} - -static __inline tilegx_bundle_bits -create_ShAmt_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 12); -} - -static __inline tilegx_bundle_bits -create_ShAmt_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3f)) << 43); -} - -static __inline tilegx_bundle_bits -create_ShAmt_Y0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 12); -} - -static __inline tilegx_bundle_bits -create_ShAmt_Y1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3f)) << 43); -} - -static __inline tilegx_bundle_bits -create_ShiftOpcodeExtension_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3ff) << 18); -} - -static __inline tilegx_bundle_bits -create_ShiftOpcodeExtension_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3ff)) << 49); -} - -static __inline tilegx_bundle_bits -create_ShiftOpcodeExtension_Y0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3) << 18); -} - -static __inline tilegx_bundle_bits -create_ShiftOpcodeExtension_Y1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3)) << 49); -} - -static __inline tilegx_bundle_bits -create_SrcA_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 6); -} - -static __inline tilegx_bundle_bits -create_SrcA_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3f)) << 37); -} - -static __inline tilegx_bundle_bits -create_SrcA_Y0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 6); -} - -static __inline tilegx_bundle_bits -create_SrcA_Y1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3f)) << 37); -} - -static __inline tilegx_bundle_bits -create_SrcA_Y2(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 20); -} - -static __inline tilegx_bundle_bits -create_SrcBDest_Y2(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3f)) << 51); -} - -static __inline tilegx_bundle_bits -create_SrcB_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 12); -} - -static __inline tilegx_bundle_bits -create_SrcB_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3f)) << 43); -} - -static __inline tilegx_bundle_bits -create_SrcB_Y0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 12); -} - -static __inline tilegx_bundle_bits -create_SrcB_Y1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3f)) << 43); -} - -static __inline tilegx_bundle_bits -create_UnaryOpcodeExtension_X0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 12); -} - -static __inline tilegx_bundle_bits -create_UnaryOpcodeExtension_X1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3f)) << 43); -} - -static __inline tilegx_bundle_bits -create_UnaryOpcodeExtension_Y0(int num) -{ - const unsigned int n = (unsigned int)num; - return ((n & 0x3f) << 12); -} - -static __inline tilegx_bundle_bits -create_UnaryOpcodeExtension_Y1(int num) -{ - const unsigned int n = (unsigned int)num; - return (((tilegx_bundle_bits)(n & 0x3f)) << 43); -} - -const struct tilegx_opcode tilegx_opcodes[336] = -{ - { "bpt", TILEGX_OPC_BPT, 0x2, 0, TREG_ZERO, 0, - { { 0, }, { }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffffffff80000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286a44ae00000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "info", TILEGX_OPC_INFO, 0xf, 1, TREG_ZERO, 1, - { { 0 }, { 1 }, { 2 }, { 3 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00fffULL, - 0xfff807ff80000000ULL, - 0x0000000078000fffULL, - 0x3c0007ff80000000ULL, - 0ULL - }, - { - 0x0000000040300fffULL, - 0x181807ff80000000ULL, - 0x0000000010000fffULL, - 0x0c0007ff80000000ULL, - -1ULL - } -#endif - }, - { "infol", TILEGX_OPC_INFOL, 0x3, 1, TREG_ZERO, 1, - { { 4 }, { 5 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc000000070000fffULL, - 0xf80007ff80000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000070000fffULL, - 0x380007ff80000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ld4s_tls", TILEGX_OPC_LD4S_TLS, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1858000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ld_tls", TILEGX_OPC_LD_TLS, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18a0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "move", TILEGX_OPC_MOVE, 0xf, 2, TREG_ZERO, 1, - { { 8, 9 }, { 6, 7 }, { 10, 11 }, { 12, 13 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0xfffff80000000000ULL, - 0x00000000780ff000ULL, - 0x3c07f80000000000ULL, - 0ULL - }, - { - 0x000000005107f000ULL, - 0x283bf80000000000ULL, - 0x00000000500bf000ULL, - 0x2c05f80000000000ULL, - -1ULL - } -#endif - }, - { "movei", TILEGX_OPC_MOVEI, 0xf, 2, TREG_ZERO, 1, - { { 8, 0 }, { 6, 1 }, { 10, 2 }, { 12, 3 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00fc0ULL, - 0xfff807e000000000ULL, - 0x0000000078000fc0ULL, - 0x3c0007e000000000ULL, - 0ULL - }, - { - 0x0000000040100fc0ULL, - 0x180807e000000000ULL, - 0x0000000000000fc0ULL, - 0x040007e000000000ULL, - -1ULL - } -#endif - }, - { "moveli", TILEGX_OPC_MOVELI, 0x3, 2, TREG_ZERO, 1, - { { 8, 4 }, { 6, 5 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc000000070000fc0ULL, - 0xf80007e000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000010000fc0ULL, - 0x000007e000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "prefetch", TILEGX_OPC_PREFETCH, 0x12, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff81f80000000ULL, - 0ULL, - 0ULL, - 0xc3f8000004000000ULL - }, - { - -1ULL, - 0x286a801f80000000ULL, - -1ULL, - -1ULL, - 0x41f8000004000000ULL - } -#endif - }, - { "prefetch_add_l1", TILEGX_OPC_PREFETCH_ADD_L1, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8001f80000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1840001f80000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "prefetch_add_l1_fault", TILEGX_OPC_PREFETCH_ADD_L1_FAULT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8001f80000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1838001f80000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "prefetch_add_l2", TILEGX_OPC_PREFETCH_ADD_L2, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8001f80000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1850001f80000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "prefetch_add_l2_fault", TILEGX_OPC_PREFETCH_ADD_L2_FAULT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8001f80000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1848001f80000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "prefetch_add_l3", TILEGX_OPC_PREFETCH_ADD_L3, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8001f80000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1860001f80000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "prefetch_add_l3_fault", TILEGX_OPC_PREFETCH_ADD_L3_FAULT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8001f80000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1858001f80000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "prefetch_l1", TILEGX_OPC_PREFETCH_L1, 0x12, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff81f80000000ULL, - 0ULL, - 0ULL, - 0xc3f8000004000000ULL - }, - { - -1ULL, - 0x286a801f80000000ULL, - -1ULL, - -1ULL, - 0x41f8000004000000ULL - } -#endif - }, - { "prefetch_l1_fault", TILEGX_OPC_PREFETCH_L1_FAULT, 0x12, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff81f80000000ULL, - 0ULL, - 0ULL, - 0xc3f8000004000000ULL - }, - { - -1ULL, - 0x286a781f80000000ULL, - -1ULL, - -1ULL, - 0x41f8000000000000ULL - } -#endif - }, - { "prefetch_l2", TILEGX_OPC_PREFETCH_L2, 0x12, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff81f80000000ULL, - 0ULL, - 0ULL, - 0xc3f8000004000000ULL - }, - { - -1ULL, - 0x286a901f80000000ULL, - -1ULL, - -1ULL, - 0x43f8000004000000ULL - } -#endif - }, - { "prefetch_l2_fault", TILEGX_OPC_PREFETCH_L2_FAULT, 0x12, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff81f80000000ULL, - 0ULL, - 0ULL, - 0xc3f8000004000000ULL - }, - { - -1ULL, - 0x286a881f80000000ULL, - -1ULL, - -1ULL, - 0x43f8000000000000ULL - } -#endif - }, - { "prefetch_l3", TILEGX_OPC_PREFETCH_L3, 0x12, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff81f80000000ULL, - 0ULL, - 0ULL, - 0xc3f8000004000000ULL - }, - { - -1ULL, - 0x286aa01f80000000ULL, - -1ULL, - -1ULL, - 0x83f8000000000000ULL - } -#endif - }, - { "prefetch_l3_fault", TILEGX_OPC_PREFETCH_L3_FAULT, 0x12, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff81f80000000ULL, - 0ULL, - 0ULL, - 0xc3f8000004000000ULL - }, - { - -1ULL, - 0x286a981f80000000ULL, - -1ULL, - -1ULL, - 0x81f8000004000000ULL - } -#endif - }, - { "raise", TILEGX_OPC_RAISE, 0x2, 0, TREG_ZERO, 1, - { { 0, }, { }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffffffff80000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286a44ae80000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "add", TILEGX_OPC_ADD, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x00000000500c0000ULL, - 0x2806000000000000ULL, - 0x0000000028040000ULL, - 0x1802000000000000ULL, - -1ULL - } -#endif - }, - { "addi", TILEGX_OPC_ADDI, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0x0000000078000000ULL, - 0x3c00000000000000ULL, - 0ULL - }, - { - 0x0000000040100000ULL, - 0x1808000000000000ULL, - 0ULL, - 0x0400000000000000ULL, - -1ULL - } -#endif - }, - { "addli", TILEGX_OPC_ADDLI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc000000070000000ULL, - 0xf800000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000010000000ULL, - 0ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "addx", TILEGX_OPC_ADDX, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000050080000ULL, - 0x2804000000000000ULL, - 0x0000000028000000ULL, - 0x1800000000000000ULL, - -1ULL - } -#endif - }, - { "addxi", TILEGX_OPC_ADDXI, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0x0000000078000000ULL, - 0x3c00000000000000ULL, - 0ULL - }, - { - 0x0000000040200000ULL, - 0x1810000000000000ULL, - 0x0000000008000000ULL, - 0x0800000000000000ULL, - -1ULL - } -#endif - }, - { "addxli", TILEGX_OPC_ADDXLI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc000000070000000ULL, - 0xf800000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000020000000ULL, - 0x0800000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "addxsc", TILEGX_OPC_ADDXSC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050040000ULL, - 0x2802000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "and", TILEGX_OPC_AND, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000050100000ULL, - 0x2808000000000000ULL, - 0x0000000050000000ULL, - 0x2c00000000000000ULL, - -1ULL - } -#endif - }, - { "andi", TILEGX_OPC_ANDI, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0x0000000078000000ULL, - 0x3c00000000000000ULL, - 0ULL - }, - { - 0x0000000040300000ULL, - 0x1818000000000000ULL, - 0x0000000010000000ULL, - 0x0c00000000000000ULL, - -1ULL - } -#endif - }, - { "beqz", TILEGX_OPC_BEQZ, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1440000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "beqzt", TILEGX_OPC_BEQZT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1400000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "bfexts", TILEGX_OPC_BFEXTS, 0x1, 4, TREG_ZERO, 1, - { { 8, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007f000000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000034000000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "bfextu", TILEGX_OPC_BFEXTU, 0x1, 4, TREG_ZERO, 1, - { { 8, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007f000000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000035000000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "bfins", TILEGX_OPC_BFINS, 0x1, 4, TREG_ZERO, 1, - { { 23, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007f000000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000036000000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "bgez", TILEGX_OPC_BGEZ, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x14c0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "bgezt", TILEGX_OPC_BGEZT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1480000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "bgtz", TILEGX_OPC_BGTZ, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1540000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "bgtzt", TILEGX_OPC_BGTZT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1500000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "blbc", TILEGX_OPC_BLBC, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x15c0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "blbct", TILEGX_OPC_BLBCT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1580000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "blbs", TILEGX_OPC_BLBS, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1640000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "blbst", TILEGX_OPC_BLBST, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1600000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "blez", TILEGX_OPC_BLEZ, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x16c0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "blezt", TILEGX_OPC_BLEZT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1680000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "bltz", TILEGX_OPC_BLTZ, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1740000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "bltzt", TILEGX_OPC_BLTZT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1700000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "bnez", TILEGX_OPC_BNEZ, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x17c0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "bnezt", TILEGX_OPC_BNEZT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 20 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xffc0000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1780000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "clz", TILEGX_OPC_CLZ, 0x5, 2, TREG_ZERO, 1, - { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0ULL, - 0x00000000780ff000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051481000ULL, - -1ULL, - 0x00000000300c1000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmoveqz", TILEGX_OPC_CMOVEQZ, 0x5, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050140000ULL, - -1ULL, - 0x0000000048000000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmovnez", TILEGX_OPC_CMOVNEZ, 0x5, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050180000ULL, - -1ULL, - 0x0000000048040000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmpeq", TILEGX_OPC_CMPEQ, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x00000000501c0000ULL, - 0x280a000000000000ULL, - 0x0000000040000000ULL, - 0x2404000000000000ULL, - -1ULL - } -#endif - }, - { "cmpeqi", TILEGX_OPC_CMPEQI, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0x0000000078000000ULL, - 0x3c00000000000000ULL, - 0ULL - }, - { - 0x0000000040400000ULL, - 0x1820000000000000ULL, - 0x0000000018000000ULL, - 0x1000000000000000ULL, - -1ULL - } -#endif - }, - { "cmpexch", TILEGX_OPC_CMPEXCH, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x280e000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmpexch4", TILEGX_OPC_CMPEXCH4, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x280c000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmples", TILEGX_OPC_CMPLES, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000050200000ULL, - 0x2810000000000000ULL, - 0x0000000038000000ULL, - 0x2000000000000000ULL, - -1ULL - } -#endif - }, - { "cmpleu", TILEGX_OPC_CMPLEU, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000050240000ULL, - 0x2812000000000000ULL, - 0x0000000038040000ULL, - 0x2002000000000000ULL, - -1ULL - } -#endif - }, - { "cmplts", TILEGX_OPC_CMPLTS, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000050280000ULL, - 0x2814000000000000ULL, - 0x0000000038080000ULL, - 0x2004000000000000ULL, - -1ULL - } -#endif - }, - { "cmpltsi", TILEGX_OPC_CMPLTSI, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 10, 11, 2 }, { 12, 13, 3 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0x0000000078000000ULL, - 0x3c00000000000000ULL, - 0ULL - }, - { - 0x0000000040500000ULL, - 0x1828000000000000ULL, - 0x0000000020000000ULL, - 0x1400000000000000ULL, - -1ULL - } -#endif - }, - { "cmpltu", TILEGX_OPC_CMPLTU, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x00000000502c0000ULL, - 0x2816000000000000ULL, - 0x00000000380c0000ULL, - 0x2006000000000000ULL, - -1ULL - } -#endif - }, - { "cmpltui", TILEGX_OPC_CMPLTUI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000040600000ULL, - 0x1830000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmpne", TILEGX_OPC_CMPNE, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000050300000ULL, - 0x2818000000000000ULL, - 0x0000000040040000ULL, - 0x2406000000000000ULL, - -1ULL - } -#endif - }, - { "cmul", TILEGX_OPC_CMUL, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000504c0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmula", TILEGX_OPC_CMULA, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050380000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmulaf", TILEGX_OPC_CMULAF, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050340000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmulf", TILEGX_OPC_CMULF, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050400000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmulfr", TILEGX_OPC_CMULFR, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000503c0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmulh", TILEGX_OPC_CMULH, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050480000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "cmulhr", TILEGX_OPC_CMULHR, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050440000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "crc32_32", TILEGX_OPC_CRC32_32, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050500000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "crc32_8", TILEGX_OPC_CRC32_8, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050540000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ctz", TILEGX_OPC_CTZ, 0x5, 2, TREG_ZERO, 1, - { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0ULL, - 0x00000000780ff000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051482000ULL, - -1ULL, - 0x00000000300c2000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "dblalign", TILEGX_OPC_DBLALIGN, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050640000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "dblalign2", TILEGX_OPC_DBLALIGN2, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050580000ULL, - 0x281a000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "dblalign4", TILEGX_OPC_DBLALIGN4, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000505c0000ULL, - 0x281c000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "dblalign6", TILEGX_OPC_DBLALIGN6, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050600000ULL, - 0x281e000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "drain", TILEGX_OPC_DRAIN, 0x2, 0, TREG_ZERO, 0, - { { 0, }, { }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286a080000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "dtlbpr", TILEGX_OPC_DTLBPR, 0x2, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286a100000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "exch", TILEGX_OPC_EXCH, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x2822000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "exch4", TILEGX_OPC_EXCH4, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x2820000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fdouble_add_flags", TILEGX_OPC_FDOUBLE_ADD_FLAGS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000506c0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fdouble_addsub", TILEGX_OPC_FDOUBLE_ADDSUB, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050680000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fdouble_mul_flags", TILEGX_OPC_FDOUBLE_MUL_FLAGS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050700000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fdouble_pack1", TILEGX_OPC_FDOUBLE_PACK1, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050740000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fdouble_pack2", TILEGX_OPC_FDOUBLE_PACK2, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050780000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fdouble_sub_flags", TILEGX_OPC_FDOUBLE_SUB_FLAGS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000507c0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fdouble_unpack_max", TILEGX_OPC_FDOUBLE_UNPACK_MAX, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050800000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fdouble_unpack_min", TILEGX_OPC_FDOUBLE_UNPACK_MIN, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050840000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fetchadd", TILEGX_OPC_FETCHADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x282a000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fetchadd4", TILEGX_OPC_FETCHADD4, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x2824000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fetchaddgez", TILEGX_OPC_FETCHADDGEZ, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x2828000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fetchaddgez4", TILEGX_OPC_FETCHADDGEZ4, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x2826000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fetchand", TILEGX_OPC_FETCHAND, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x282e000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fetchand4", TILEGX_OPC_FETCHAND4, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x282c000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fetchor", TILEGX_OPC_FETCHOR, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x2832000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fetchor4", TILEGX_OPC_FETCHOR4, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x2830000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "finv", TILEGX_OPC_FINV, 0x2, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286a180000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "flush", TILEGX_OPC_FLUSH, 0x2, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286a280000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "flushwb", TILEGX_OPC_FLUSHWB, 0x2, 0, TREG_ZERO, 1, - { { 0, }, { }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286a200000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fnop", TILEGX_OPC_FNOP, 0xf, 0, TREG_ZERO, 1, - { { }, { }, { }, { }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0xfffff80000000000ULL, - 0x00000000780ff000ULL, - 0x3c07f80000000000ULL, - 0ULL - }, - { - 0x0000000051483000ULL, - 0x286a300000000000ULL, - 0x00000000300c3000ULL, - 0x1c06400000000000ULL, - -1ULL - } -#endif - }, - { "fsingle_add1", TILEGX_OPC_FSINGLE_ADD1, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050880000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fsingle_addsub2", TILEGX_OPC_FSINGLE_ADDSUB2, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000508c0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fsingle_mul1", TILEGX_OPC_FSINGLE_MUL1, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050900000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fsingle_mul2", TILEGX_OPC_FSINGLE_MUL2, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050940000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fsingle_pack1", TILEGX_OPC_FSINGLE_PACK1, 0x5, 2, TREG_ZERO, 1, - { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0ULL, - 0x00000000780ff000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051484000ULL, - -1ULL, - 0x00000000300c4000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fsingle_pack2", TILEGX_OPC_FSINGLE_PACK2, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050980000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "fsingle_sub1", TILEGX_OPC_FSINGLE_SUB1, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000509c0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "icoh", TILEGX_OPC_ICOH, 0x2, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286a380000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ill", TILEGX_OPC_ILL, 0xa, 0, TREG_ZERO, 1, - { { 0, }, { }, { 0, }, { }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0x3c07f80000000000ULL, - 0ULL - }, - { - -1ULL, - 0x286a400000000000ULL, - -1ULL, - 0x1c06480000000000ULL, - -1ULL - } -#endif - }, - { "inv", TILEGX_OPC_INV, 0x2, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286a480000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "iret", TILEGX_OPC_IRET, 0x2, 0, TREG_ZERO, 1, - { { 0, }, { }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286a500000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "j", TILEGX_OPC_J, 0x2, 1, TREG_ZERO, 1, - { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfc00000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x2400000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "jal", TILEGX_OPC_JAL, 0x2, 1, TREG_LR, 1, - { { 0, }, { 25 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfc00000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x2000000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "jalr", TILEGX_OPC_JALR, 0xa, 1, TREG_LR, 1, - { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0x3c07f80000000000ULL, - 0ULL - }, - { - -1ULL, - 0x286a600000000000ULL, - -1ULL, - 0x1c06580000000000ULL, - -1ULL - } -#endif - }, - { "jalrp", TILEGX_OPC_JALRP, 0xa, 1, TREG_LR, 1, - { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0x3c07f80000000000ULL, - 0ULL - }, - { - -1ULL, - 0x286a580000000000ULL, - -1ULL, - 0x1c06500000000000ULL, - -1ULL - } -#endif - }, - { "jr", TILEGX_OPC_JR, 0xa, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0x3c07f80000000000ULL, - 0ULL - }, - { - -1ULL, - 0x286a700000000000ULL, - -1ULL, - 0x1c06680000000000ULL, - -1ULL - } -#endif - }, - { "jrp", TILEGX_OPC_JRP, 0xa, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 13 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0x3c07f80000000000ULL, - 0ULL - }, - { - -1ULL, - 0x286a680000000000ULL, - -1ULL, - 0x1c06600000000000ULL, - -1ULL - } -#endif - }, - { "ld", TILEGX_OPC_LD, 0x12, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0xc200000004000000ULL - }, - { - -1ULL, - 0x286ae80000000000ULL, - -1ULL, - -1ULL, - 0x8200000004000000ULL - } -#endif - }, - { "ld1s", TILEGX_OPC_LD1S, 0x12, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0xc200000004000000ULL - }, - { - -1ULL, - 0x286a780000000000ULL, - -1ULL, - -1ULL, - 0x4000000000000000ULL - } -#endif - }, - { "ld1s_add", TILEGX_OPC_LD1S_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1838000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ld1u", TILEGX_OPC_LD1U, 0x12, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0xc200000004000000ULL - }, - { - -1ULL, - 0x286a800000000000ULL, - -1ULL, - -1ULL, - 0x4000000004000000ULL - } -#endif - }, - { "ld1u_add", TILEGX_OPC_LD1U_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1840000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ld2s", TILEGX_OPC_LD2S, 0x12, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0xc200000004000000ULL - }, - { - -1ULL, - 0x286a880000000000ULL, - -1ULL, - -1ULL, - 0x4200000000000000ULL - } -#endif - }, - { "ld2s_add", TILEGX_OPC_LD2S_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1848000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ld2u", TILEGX_OPC_LD2U, 0x12, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0xc200000004000000ULL - }, - { - -1ULL, - 0x286a900000000000ULL, - -1ULL, - -1ULL, - 0x4200000004000000ULL - } -#endif - }, - { "ld2u_add", TILEGX_OPC_LD2U_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1850000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ld4s", TILEGX_OPC_LD4S, 0x12, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0xc200000004000000ULL - }, - { - -1ULL, - 0x286a980000000000ULL, - -1ULL, - -1ULL, - 0x8000000004000000ULL - } -#endif - }, - { "ld4s_add", TILEGX_OPC_LD4S_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1858000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ld4u", TILEGX_OPC_LD4U, 0x12, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 26, 14 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0xc200000004000000ULL - }, - { - -1ULL, - 0x286aa00000000000ULL, - -1ULL, - -1ULL, - 0x8200000000000000ULL - } -#endif - }, - { "ld4u_add", TILEGX_OPC_LD4U_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1860000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ld_add", TILEGX_OPC_LD_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18a0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldna", TILEGX_OPC_LDNA, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286aa80000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldna_add", TILEGX_OPC_LDNA_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18a8000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt", TILEGX_OPC_LDNT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286ae00000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt1s", TILEGX_OPC_LDNT1S, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286ab00000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt1s_add", TILEGX_OPC_LDNT1S_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1868000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt1u", TILEGX_OPC_LDNT1U, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286ab80000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt1u_add", TILEGX_OPC_LDNT1U_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1870000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt2s", TILEGX_OPC_LDNT2S, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286ac00000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt2s_add", TILEGX_OPC_LDNT2S_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1878000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt2u", TILEGX_OPC_LDNT2U, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286ac80000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt2u_add", TILEGX_OPC_LDNT2U_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1880000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt4s", TILEGX_OPC_LDNT4S, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286ad00000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt4s_add", TILEGX_OPC_LDNT4S_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1888000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt4u", TILEGX_OPC_LDNT4U, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 6, 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286ad80000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt4u_add", TILEGX_OPC_LDNT4U_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1890000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "ldnt_add", TILEGX_OPC_LDNT_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 6, 15, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1898000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "lnk", TILEGX_OPC_LNK, 0xa, 1, TREG_ZERO, 1, - { { 0, }, { 6 }, { 0, }, { 12 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0x3c07f80000000000ULL, - 0ULL - }, - { - -1ULL, - 0x286af00000000000ULL, - -1ULL, - 0x1c06700000000000ULL, - -1ULL - } -#endif - }, - { "mf", TILEGX_OPC_MF, 0x2, 0, TREG_ZERO, 1, - { { 0, }, { }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286af80000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mfspr", TILEGX_OPC_MFSPR, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 6, 27 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18b0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mm", TILEGX_OPC_MM, 0x1, 4, TREG_ZERO, 1, - { { 23, 9, 21, 22 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007f000000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000037000000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mnz", TILEGX_OPC_MNZ, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000050a00000ULL, - 0x2834000000000000ULL, - 0x0000000048080000ULL, - 0x2804000000000000ULL, - -1ULL - } -#endif - }, - { "mtspr", TILEGX_OPC_MTSPR, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 28, 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18b8000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mul_hs_hs", TILEGX_OPC_MUL_HS_HS, 0x5, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050d40000ULL, - -1ULL, - 0x0000000068000000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mul_hs_hu", TILEGX_OPC_MUL_HS_HU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050d80000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mul_hs_ls", TILEGX_OPC_MUL_HS_LS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050dc0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mul_hs_lu", TILEGX_OPC_MUL_HS_LU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050e00000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mul_hu_hu", TILEGX_OPC_MUL_HU_HU, 0x5, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050e40000ULL, - -1ULL, - 0x0000000068040000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mul_hu_ls", TILEGX_OPC_MUL_HU_LS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050e80000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mul_hu_lu", TILEGX_OPC_MUL_HU_LU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050ec0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mul_ls_ls", TILEGX_OPC_MUL_LS_LS, 0x5, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050f00000ULL, - -1ULL, - 0x0000000068080000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mul_ls_lu", TILEGX_OPC_MUL_LS_LU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050f40000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mul_lu_lu", TILEGX_OPC_MUL_LU_LU, 0x5, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050f80000ULL, - -1ULL, - 0x00000000680c0000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mula_hs_hs", TILEGX_OPC_MULA_HS_HS, 0x5, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050a80000ULL, - -1ULL, - 0x0000000070000000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mula_hs_hu", TILEGX_OPC_MULA_HS_HU, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050ac0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mula_hs_ls", TILEGX_OPC_MULA_HS_LS, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050b00000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mula_hs_lu", TILEGX_OPC_MULA_HS_LU, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050b40000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mula_hu_hu", TILEGX_OPC_MULA_HU_HU, 0x5, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050b80000ULL, - -1ULL, - 0x0000000070040000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mula_hu_ls", TILEGX_OPC_MULA_HU_LS, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050bc0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mula_hu_lu", TILEGX_OPC_MULA_HU_LU, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050c00000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mula_ls_ls", TILEGX_OPC_MULA_LS_LS, 0x5, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050c40000ULL, - -1ULL, - 0x0000000070080000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mula_ls_lu", TILEGX_OPC_MULA_LS_LU, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050c80000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mula_lu_lu", TILEGX_OPC_MULA_LU_LU, 0x5, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050cc0000ULL, - -1ULL, - 0x00000000700c0000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mulax", TILEGX_OPC_MULAX, 0x5, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 24, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050a40000ULL, - -1ULL, - 0x0000000040080000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mulx", TILEGX_OPC_MULX, 0x5, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 10, 11, 18 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0x00000000780c0000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000050d00000ULL, - -1ULL, - 0x00000000400c0000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "mz", TILEGX_OPC_MZ, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000050fc0000ULL, - 0x2836000000000000ULL, - 0x00000000480c0000ULL, - 0x2806000000000000ULL, - -1ULL - } -#endif - }, - { "nap", TILEGX_OPC_NAP, 0x2, 0, TREG_ZERO, 0, - { { 0, }, { }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286b000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "nop", TILEGX_OPC_NOP, 0xf, 0, TREG_ZERO, 1, - { { }, { }, { }, { }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0xfffff80000000000ULL, - 0x00000000780ff000ULL, - 0x3c07f80000000000ULL, - 0ULL - }, - { - 0x0000000051485000ULL, - 0x286b080000000000ULL, - 0x00000000300c5000ULL, - 0x1c06780000000000ULL, - -1ULL - } -#endif - }, - { "nor", TILEGX_OPC_NOR, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000051000000ULL, - 0x2838000000000000ULL, - 0x0000000050040000ULL, - 0x2c02000000000000ULL, - -1ULL - } -#endif - }, - { "or", TILEGX_OPC_OR, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000051040000ULL, - 0x283a000000000000ULL, - 0x0000000050080000ULL, - 0x2c04000000000000ULL, - -1ULL - } -#endif - }, - { "ori", TILEGX_OPC_ORI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000040700000ULL, - 0x18c0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "pcnt", TILEGX_OPC_PCNT, 0x5, 2, TREG_ZERO, 1, - { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0ULL, - 0x00000000780ff000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051486000ULL, - -1ULL, - 0x00000000300c6000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "revbits", TILEGX_OPC_REVBITS, 0x5, 2, TREG_ZERO, 1, - { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0ULL, - 0x00000000780ff000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051487000ULL, - -1ULL, - 0x00000000300c7000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "revbytes", TILEGX_OPC_REVBYTES, 0x5, 2, TREG_ZERO, 1, - { { 8, 9 }, { 0, }, { 10, 11 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0ULL, - 0x00000000780ff000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051488000ULL, - -1ULL, - 0x00000000300c8000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "rotl", TILEGX_OPC_ROTL, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000051080000ULL, - 0x283c000000000000ULL, - 0x0000000058000000ULL, - 0x3000000000000000ULL, - -1ULL - } -#endif - }, - { "rotli", TILEGX_OPC_ROTLI, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000060040000ULL, - 0x3002000000000000ULL, - 0x0000000078000000ULL, - 0x3800000000000000ULL, - -1ULL - } -#endif - }, - { "shl", TILEGX_OPC_SHL, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000051280000ULL, - 0x284c000000000000ULL, - 0x0000000058040000ULL, - 0x3002000000000000ULL, - -1ULL - } -#endif - }, - { "shl16insli", TILEGX_OPC_SHL16INSLI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 4 }, { 6, 7, 5 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc000000070000000ULL, - 0xf800000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000070000000ULL, - 0x3800000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "shl1add", TILEGX_OPC_SHL1ADD, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000051100000ULL, - 0x2840000000000000ULL, - 0x0000000030000000ULL, - 0x1c00000000000000ULL, - -1ULL - } -#endif - }, - { "shl1addx", TILEGX_OPC_SHL1ADDX, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x00000000510c0000ULL, - 0x283e000000000000ULL, - 0x0000000060040000ULL, - 0x3402000000000000ULL, - -1ULL - } -#endif - }, - { "shl2add", TILEGX_OPC_SHL2ADD, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000051180000ULL, - 0x2844000000000000ULL, - 0x0000000030040000ULL, - 0x1c02000000000000ULL, - -1ULL - } -#endif - }, - { "shl2addx", TILEGX_OPC_SHL2ADDX, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000051140000ULL, - 0x2842000000000000ULL, - 0x0000000060080000ULL, - 0x3404000000000000ULL, - -1ULL - } -#endif - }, - { "shl3add", TILEGX_OPC_SHL3ADD, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000051200000ULL, - 0x2848000000000000ULL, - 0x0000000030080000ULL, - 0x1c04000000000000ULL, - -1ULL - } -#endif - }, - { "shl3addx", TILEGX_OPC_SHL3ADDX, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x00000000511c0000ULL, - 0x2846000000000000ULL, - 0x00000000600c0000ULL, - 0x3406000000000000ULL, - -1ULL - } -#endif - }, - { "shli", TILEGX_OPC_SHLI, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000060080000ULL, - 0x3004000000000000ULL, - 0x0000000078040000ULL, - 0x3802000000000000ULL, - -1ULL - } -#endif - }, - { "shlx", TILEGX_OPC_SHLX, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051240000ULL, - 0x284a000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "shlxi", TILEGX_OPC_SHLXI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000600c0000ULL, - 0x3006000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "shrs", TILEGX_OPC_SHRS, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x00000000512c0000ULL, - 0x284e000000000000ULL, - 0x0000000058080000ULL, - 0x3004000000000000ULL, - -1ULL - } -#endif - }, - { "shrsi", TILEGX_OPC_SHRSI, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000060100000ULL, - 0x3008000000000000ULL, - 0x0000000078080000ULL, - 0x3804000000000000ULL, - -1ULL - } -#endif - }, - { "shru", TILEGX_OPC_SHRU, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000051340000ULL, - 0x2852000000000000ULL, - 0x00000000580c0000ULL, - 0x3006000000000000ULL, - -1ULL - } -#endif - }, - { "shrui", TILEGX_OPC_SHRUI, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 10, 11, 31 }, { 12, 13, 32 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000060140000ULL, - 0x300a000000000000ULL, - 0x00000000780c0000ULL, - 0x3806000000000000ULL, - -1ULL - } -#endif - }, - { "shrux", TILEGX_OPC_SHRUX, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051300000ULL, - 0x2850000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "shruxi", TILEGX_OPC_SHRUXI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000060180000ULL, - 0x300c000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "shufflebytes", TILEGX_OPC_SHUFFLEBYTES, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051380000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "st", TILEGX_OPC_ST, 0x12, 2, TREG_ZERO, 1, - { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0xc200000004000000ULL - }, - { - -1ULL, - 0x2862000000000000ULL, - -1ULL, - -1ULL, - 0xc200000004000000ULL - } -#endif - }, - { "st1", TILEGX_OPC_ST1, 0x12, 2, TREG_ZERO, 1, - { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0xc200000004000000ULL - }, - { - -1ULL, - 0x2854000000000000ULL, - -1ULL, - -1ULL, - 0xc000000000000000ULL - } -#endif - }, - { "st1_add", TILEGX_OPC_ST1_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18c8000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "st2", TILEGX_OPC_ST2, 0x12, 2, TREG_ZERO, 1, - { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0xc200000004000000ULL - }, - { - -1ULL, - 0x2856000000000000ULL, - -1ULL, - -1ULL, - 0xc000000004000000ULL - } -#endif - }, - { "st2_add", TILEGX_OPC_ST2_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18d0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "st4", TILEGX_OPC_ST4, 0x12, 2, TREG_ZERO, 1, - { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 14, 33 } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0xc200000004000000ULL - }, - { - -1ULL, - 0x2858000000000000ULL, - -1ULL, - -1ULL, - 0xc200000000000000ULL - } -#endif - }, - { "st4_add", TILEGX_OPC_ST4_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18d8000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "st_add", TILEGX_OPC_ST_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x1900000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "stnt", TILEGX_OPC_STNT, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x2860000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "stnt1", TILEGX_OPC_STNT1, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x285a000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "stnt1_add", TILEGX_OPC_STNT1_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18e0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "stnt2", TILEGX_OPC_STNT2, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x285c000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "stnt2_add", TILEGX_OPC_STNT2_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18e8000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "stnt4", TILEGX_OPC_STNT4, 0x2, 2, TREG_ZERO, 1, - { { 0, }, { 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x285e000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "stnt4_add", TILEGX_OPC_STNT4_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18f0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "stnt_add", TILEGX_OPC_STNT_ADD, 0x2, 3, TREG_ZERO, 1, - { { 0, }, { 15, 17, 34 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x18f8000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "sub", TILEGX_OPC_SUB, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000051440000ULL, - 0x2868000000000000ULL, - 0x00000000280c0000ULL, - 0x1806000000000000ULL, - -1ULL - } -#endif - }, - { "subx", TILEGX_OPC_SUBX, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000051400000ULL, - 0x2866000000000000ULL, - 0x0000000028080000ULL, - 0x1804000000000000ULL, - -1ULL - } -#endif - }, - { "subxsc", TILEGX_OPC_SUBXSC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000513c0000ULL, - 0x2864000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "swint0", TILEGX_OPC_SWINT0, 0x2, 0, TREG_ZERO, 0, - { { 0, }, { }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286b100000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "swint1", TILEGX_OPC_SWINT1, 0x2, 0, TREG_ZERO, 0, - { { 0, }, { }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286b180000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "swint2", TILEGX_OPC_SWINT2, 0x2, 0, TREG_ZERO, 0, - { { 0, }, { }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286b200000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "swint3", TILEGX_OPC_SWINT3, 0x2, 0, TREG_ZERO, 0, - { { 0, }, { }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286b280000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "tblidxb0", TILEGX_OPC_TBLIDXB0, 0x5, 2, TREG_ZERO, 1, - { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0ULL, - 0x00000000780ff000ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051489000ULL, - -1ULL, - 0x00000000300c9000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "tblidxb1", TILEGX_OPC_TBLIDXB1, 0x5, 2, TREG_ZERO, 1, - { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0ULL, - 0x00000000780ff000ULL, - 0ULL, - 0ULL - }, - { - 0x000000005148a000ULL, - -1ULL, - 0x00000000300ca000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "tblidxb2", TILEGX_OPC_TBLIDXB2, 0x5, 2, TREG_ZERO, 1, - { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0ULL, - 0x00000000780ff000ULL, - 0ULL, - 0ULL - }, - { - 0x000000005148b000ULL, - -1ULL, - 0x00000000300cb000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "tblidxb3", TILEGX_OPC_TBLIDXB3, 0x5, 2, TREG_ZERO, 1, - { { 23, 9 }, { 0, }, { 24, 11 }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffff000ULL, - 0ULL, - 0x00000000780ff000ULL, - 0ULL, - 0ULL - }, - { - 0x000000005148c000ULL, - -1ULL, - 0x00000000300cc000ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1add", TILEGX_OPC_V1ADD, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051500000ULL, - 0x286e000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1addi", TILEGX_OPC_V1ADDI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000040800000ULL, - 0x1908000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1adduc", TILEGX_OPC_V1ADDUC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000514c0000ULL, - 0x286c000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1adiffu", TILEGX_OPC_V1ADIFFU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051540000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1avgu", TILEGX_OPC_V1AVGU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051580000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1cmpeq", TILEGX_OPC_V1CMPEQ, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000515c0000ULL, - 0x2870000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1cmpeqi", TILEGX_OPC_V1CMPEQI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000040900000ULL, - 0x1910000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1cmples", TILEGX_OPC_V1CMPLES, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051600000ULL, - 0x2872000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1cmpleu", TILEGX_OPC_V1CMPLEU, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051640000ULL, - 0x2874000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1cmplts", TILEGX_OPC_V1CMPLTS, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051680000ULL, - 0x2876000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1cmpltsi", TILEGX_OPC_V1CMPLTSI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000040a00000ULL, - 0x1918000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1cmpltu", TILEGX_OPC_V1CMPLTU, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000516c0000ULL, - 0x2878000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1cmpltui", TILEGX_OPC_V1CMPLTUI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000040b00000ULL, - 0x1920000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1cmpne", TILEGX_OPC_V1CMPNE, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051700000ULL, - 0x287a000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1ddotpu", TILEGX_OPC_V1DDOTPU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052880000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1ddotpua", TILEGX_OPC_V1DDOTPUA, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052840000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1ddotpus", TILEGX_OPC_V1DDOTPUS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051780000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1ddotpusa", TILEGX_OPC_V1DDOTPUSA, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051740000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1dotp", TILEGX_OPC_V1DOTP, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051880000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1dotpa", TILEGX_OPC_V1DOTPA, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000517c0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1dotpu", TILEGX_OPC_V1DOTPU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052900000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1dotpua", TILEGX_OPC_V1DOTPUA, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000528c0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1dotpus", TILEGX_OPC_V1DOTPUS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051840000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1dotpusa", TILEGX_OPC_V1DOTPUSA, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051800000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1int_h", TILEGX_OPC_V1INT_H, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000518c0000ULL, - 0x287c000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1int_l", TILEGX_OPC_V1INT_L, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051900000ULL, - 0x287e000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1maxu", TILEGX_OPC_V1MAXU, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051940000ULL, - 0x2880000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1maxui", TILEGX_OPC_V1MAXUI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000040c00000ULL, - 0x1928000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1minu", TILEGX_OPC_V1MINU, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051980000ULL, - 0x2882000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1minui", TILEGX_OPC_V1MINUI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000040d00000ULL, - 0x1930000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1mnz", TILEGX_OPC_V1MNZ, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000519c0000ULL, - 0x2884000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1multu", TILEGX_OPC_V1MULTU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051a00000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1mulu", TILEGX_OPC_V1MULU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051a80000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1mulus", TILEGX_OPC_V1MULUS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051a40000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1mz", TILEGX_OPC_V1MZ, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051ac0000ULL, - 0x2886000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1sadau", TILEGX_OPC_V1SADAU, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051b00000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1sadu", TILEGX_OPC_V1SADU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051b40000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1shl", TILEGX_OPC_V1SHL, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051b80000ULL, - 0x2888000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1shli", TILEGX_OPC_V1SHLI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000601c0000ULL, - 0x300e000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1shrs", TILEGX_OPC_V1SHRS, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051bc0000ULL, - 0x288a000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1shrsi", TILEGX_OPC_V1SHRSI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000060200000ULL, - 0x3010000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1shru", TILEGX_OPC_V1SHRU, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051c00000ULL, - 0x288c000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1shrui", TILEGX_OPC_V1SHRUI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000060240000ULL, - 0x3012000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1sub", TILEGX_OPC_V1SUB, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051c80000ULL, - 0x2890000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v1subuc", TILEGX_OPC_V1SUBUC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051c40000ULL, - 0x288e000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2add", TILEGX_OPC_V2ADD, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051d00000ULL, - 0x2894000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2addi", TILEGX_OPC_V2ADDI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000040e00000ULL, - 0x1938000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2addsc", TILEGX_OPC_V2ADDSC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051cc0000ULL, - 0x2892000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2adiffs", TILEGX_OPC_V2ADIFFS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051d40000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2avgs", TILEGX_OPC_V2AVGS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051d80000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2cmpeq", TILEGX_OPC_V2CMPEQ, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051dc0000ULL, - 0x2896000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2cmpeqi", TILEGX_OPC_V2CMPEQI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000040f00000ULL, - 0x1940000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2cmples", TILEGX_OPC_V2CMPLES, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051e00000ULL, - 0x2898000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2cmpleu", TILEGX_OPC_V2CMPLEU, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051e40000ULL, - 0x289a000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2cmplts", TILEGX_OPC_V2CMPLTS, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051e80000ULL, - 0x289c000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2cmpltsi", TILEGX_OPC_V2CMPLTSI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000041000000ULL, - 0x1948000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2cmpltu", TILEGX_OPC_V2CMPLTU, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051ec0000ULL, - 0x289e000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2cmpltui", TILEGX_OPC_V2CMPLTUI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000041100000ULL, - 0x1950000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2cmpne", TILEGX_OPC_V2CMPNE, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051f00000ULL, - 0x28a0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2dotp", TILEGX_OPC_V2DOTP, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051f80000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2dotpa", TILEGX_OPC_V2DOTPA, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051f40000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2int_h", TILEGX_OPC_V2INT_H, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000051fc0000ULL, - 0x28a2000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2int_l", TILEGX_OPC_V2INT_L, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052000000ULL, - 0x28a4000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2maxs", TILEGX_OPC_V2MAXS, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052040000ULL, - 0x28a6000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2maxsi", TILEGX_OPC_V2MAXSI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000041200000ULL, - 0x1958000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2mins", TILEGX_OPC_V2MINS, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052080000ULL, - 0x28a8000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2minsi", TILEGX_OPC_V2MINSI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000041300000ULL, - 0x1960000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2mnz", TILEGX_OPC_V2MNZ, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000520c0000ULL, - 0x28aa000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2mulfsc", TILEGX_OPC_V2MULFSC, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052100000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2muls", TILEGX_OPC_V2MULS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052140000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2mults", TILEGX_OPC_V2MULTS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052180000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2mz", TILEGX_OPC_V2MZ, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000521c0000ULL, - 0x28ac000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2packh", TILEGX_OPC_V2PACKH, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052200000ULL, - 0x28ae000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2packl", TILEGX_OPC_V2PACKL, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052240000ULL, - 0x28b0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2packuc", TILEGX_OPC_V2PACKUC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052280000ULL, - 0x28b2000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2sadas", TILEGX_OPC_V2SADAS, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000522c0000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2sadau", TILEGX_OPC_V2SADAU, 0x1, 3, TREG_ZERO, 1, - { { 23, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052300000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2sads", TILEGX_OPC_V2SADS, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052340000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2sadu", TILEGX_OPC_V2SADU, 0x1, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 0, }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052380000ULL, - -1ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2shl", TILEGX_OPC_V2SHL, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052400000ULL, - 0x28b6000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2shli", TILEGX_OPC_V2SHLI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000060280000ULL, - 0x3014000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2shlsc", TILEGX_OPC_V2SHLSC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000523c0000ULL, - 0x28b4000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2shrs", TILEGX_OPC_V2SHRS, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052440000ULL, - 0x28b8000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2shrsi", TILEGX_OPC_V2SHRSI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000602c0000ULL, - 0x3016000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2shru", TILEGX_OPC_V2SHRU, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052480000ULL, - 0x28ba000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2shrui", TILEGX_OPC_V2SHRUI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 29 }, { 6, 7, 30 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000060300000ULL, - 0x3018000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2sub", TILEGX_OPC_V2SUB, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052500000ULL, - 0x28be000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v2subsc", TILEGX_OPC_V2SUBSC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000524c0000ULL, - 0x28bc000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v4add", TILEGX_OPC_V4ADD, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052580000ULL, - 0x28c2000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v4addsc", TILEGX_OPC_V4ADDSC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052540000ULL, - 0x28c0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v4int_h", TILEGX_OPC_V4INT_H, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000525c0000ULL, - 0x28c4000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v4int_l", TILEGX_OPC_V4INT_L, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052600000ULL, - 0x28c6000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v4packsc", TILEGX_OPC_V4PACKSC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052640000ULL, - 0x28c8000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v4shl", TILEGX_OPC_V4SHL, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000526c0000ULL, - 0x28cc000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v4shlsc", TILEGX_OPC_V4SHLSC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052680000ULL, - 0x28ca000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v4shrs", TILEGX_OPC_V4SHRS, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052700000ULL, - 0x28ce000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v4shru", TILEGX_OPC_V4SHRU, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052740000ULL, - 0x28d0000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v4sub", TILEGX_OPC_V4SUB, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x00000000527c0000ULL, - 0x28d4000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "v4subsc", TILEGX_OPC_V4SUBSC, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000052780000ULL, - 0x28d2000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "wh64", TILEGX_OPC_WH64, 0x2, 1, TREG_ZERO, 1, - { { 0, }, { 7 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0ULL, - 0xfffff80000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - -1ULL, - 0x286b300000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { "xor", TILEGX_OPC_XOR, 0xf, 3, TREG_ZERO, 1, - { { 8, 9, 16 }, { 6, 7, 17 }, { 10, 11, 18 }, { 12, 13, 19 }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ffc0000ULL, - 0xfffe000000000000ULL, - 0x00000000780c0000ULL, - 0x3c06000000000000ULL, - 0ULL - }, - { - 0x0000000052800000ULL, - 0x28d6000000000000ULL, - 0x00000000500c0000ULL, - 0x2c06000000000000ULL, - -1ULL - } -#endif - }, - { "xori", TILEGX_OPC_XORI, 0x3, 3, TREG_ZERO, 1, - { { 8, 9, 0 }, { 6, 7, 1 }, { 0, }, { 0, }, { 0, } }, -#ifndef DISASM_ONLY - { - 0xc00000007ff00000ULL, - 0xfff8000000000000ULL, - 0ULL, - 0ULL, - 0ULL - }, - { - 0x0000000041400000ULL, - 0x1968000000000000ULL, - -1ULL, - -1ULL, - -1ULL - } -#endif - }, - { NULL, TILEGX_OPC_NONE, 0, 0, TREG_ZERO, 0, { { 0, } }, -#ifndef DISASM_ONLY - { 0, }, { 0, } -#endif - } -}; - -#define BITFIELD(start, size) ((start) | (((1 << (size)) - 1) << 6)) -#define CHILD(array_index) (TILEGX_OPC_NONE + (array_index)) - -static const unsigned short decode_X0_fsm[936] = -{ - BITFIELD(22, 9) /* index 0 */, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BFEXTS, - TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTS, TILEGX_OPC_BFEXTU, - TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFEXTU, TILEGX_OPC_BFINS, - TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_BFINS, TILEGX_OPC_MM, - TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_MM, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(528), CHILD(578), - CHILD(583), CHILD(588), CHILD(593), CHILD(598), TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, CHILD(603), CHILD(620), CHILD(637), CHILD(654), CHILD(671), - CHILD(703), CHILD(797), CHILD(814), CHILD(831), CHILD(848), CHILD(865), - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, CHILD(889), TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), - CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), - CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), - CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), - CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), - CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), - CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), - CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), - CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), - CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), - CHILD(906), CHILD(906), CHILD(906), CHILD(906), CHILD(906), - BITFIELD(6, 2) /* index 513 */, - TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518), - BITFIELD(8, 2) /* index 518 */, - TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523), - BITFIELD(10, 2) /* index 523 */, - TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI, - BITFIELD(20, 2) /* index 528 */, - TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548), - BITFIELD(6, 2) /* index 533 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538), - BITFIELD(8, 2) /* index 538 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543), - BITFIELD(10, 2) /* index 543 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, - BITFIELD(0, 2) /* index 548 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553), - BITFIELD(2, 2) /* index 553 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558), - BITFIELD(4, 2) /* index 558 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563), - BITFIELD(6, 2) /* index 563 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568), - BITFIELD(8, 2) /* index 568 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573), - BITFIELD(10, 2) /* index 573 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, - BITFIELD(20, 2) /* index 578 */, - TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, TILEGX_OPC_ORI, - BITFIELD(20, 2) /* index 583 */, - TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI, TILEGX_OPC_V1CMPLTSI, - TILEGX_OPC_V1CMPLTUI, - BITFIELD(20, 2) /* index 588 */, - TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI, TILEGX_OPC_V2ADDI, - TILEGX_OPC_V2CMPEQI, - BITFIELD(20, 2) /* index 593 */, - TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI, TILEGX_OPC_V2MAXSI, - TILEGX_OPC_V2MINSI, - BITFIELD(20, 2) /* index 598 */, - TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(18, 4) /* index 603 */, - TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD, - TILEGX_OPC_AND, TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_CMPEQ, - TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, - TILEGX_OPC_CMPNE, TILEGX_OPC_CMULAF, TILEGX_OPC_CMULA, TILEGX_OPC_CMULFR, - BITFIELD(18, 4) /* index 620 */, - TILEGX_OPC_CMULF, TILEGX_OPC_CMULHR, TILEGX_OPC_CMULH, TILEGX_OPC_CMUL, - TILEGX_OPC_CRC32_32, TILEGX_OPC_CRC32_8, TILEGX_OPC_DBLALIGN2, - TILEGX_OPC_DBLALIGN4, TILEGX_OPC_DBLALIGN6, TILEGX_OPC_DBLALIGN, - TILEGX_OPC_FDOUBLE_ADDSUB, TILEGX_OPC_FDOUBLE_ADD_FLAGS, - TILEGX_OPC_FDOUBLE_MUL_FLAGS, TILEGX_OPC_FDOUBLE_PACK1, - TILEGX_OPC_FDOUBLE_PACK2, TILEGX_OPC_FDOUBLE_SUB_FLAGS, - BITFIELD(18, 4) /* index 637 */, - TILEGX_OPC_FDOUBLE_UNPACK_MAX, TILEGX_OPC_FDOUBLE_UNPACK_MIN, - TILEGX_OPC_FSINGLE_ADD1, TILEGX_OPC_FSINGLE_ADDSUB2, - TILEGX_OPC_FSINGLE_MUL1, TILEGX_OPC_FSINGLE_MUL2, TILEGX_OPC_FSINGLE_PACK2, - TILEGX_OPC_FSINGLE_SUB1, TILEGX_OPC_MNZ, TILEGX_OPC_MULAX, - TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HS_HU, TILEGX_OPC_MULA_HS_LS, - TILEGX_OPC_MULA_HS_LU, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_HU_LS, - BITFIELD(18, 4) /* index 654 */, - TILEGX_OPC_MULA_HU_LU, TILEGX_OPC_MULA_LS_LS, TILEGX_OPC_MULA_LS_LU, - TILEGX_OPC_MULA_LU_LU, TILEGX_OPC_MULX, TILEGX_OPC_MUL_HS_HS, - TILEGX_OPC_MUL_HS_HU, TILEGX_OPC_MUL_HS_LS, TILEGX_OPC_MUL_HS_LU, - TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_HU_LS, TILEGX_OPC_MUL_HU_LU, - TILEGX_OPC_MUL_LS_LS, TILEGX_OPC_MUL_LS_LU, TILEGX_OPC_MUL_LU_LU, - TILEGX_OPC_MZ, - BITFIELD(18, 4) /* index 671 */, - TILEGX_OPC_NOR, CHILD(688), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX, - TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD, - TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL, - TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_SHUFFLEBYTES, - TILEGX_OPC_SUBXSC, - BITFIELD(12, 2) /* index 688 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(693), - BITFIELD(14, 2) /* index 693 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(698), - BITFIELD(16, 2) /* index 698 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, - BITFIELD(18, 4) /* index 703 */, - TILEGX_OPC_SUBX, TILEGX_OPC_SUB, CHILD(720), TILEGX_OPC_V1ADDUC, - TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADIFFU, TILEGX_OPC_V1AVGU, - TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU, - TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE, - TILEGX_OPC_V1DDOTPUSA, TILEGX_OPC_V1DDOTPUS, TILEGX_OPC_V1DOTPA, - BITFIELD(12, 4) /* index 720 */, - TILEGX_OPC_NONE, CHILD(737), CHILD(742), CHILD(747), CHILD(752), CHILD(757), - CHILD(762), CHILD(767), CHILD(772), CHILD(777), CHILD(782), CHILD(787), - CHILD(792), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 737 */, - TILEGX_OPC_CLZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 742 */, - TILEGX_OPC_CTZ, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 747 */, - TILEGX_OPC_FNOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 752 */, - TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 757 */, - TILEGX_OPC_NOP, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 762 */, - TILEGX_OPC_PCNT, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 767 */, - TILEGX_OPC_REVBITS, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 772 */, - TILEGX_OPC_REVBYTES, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 777 */, - TILEGX_OPC_TBLIDXB0, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 782 */, - TILEGX_OPC_TBLIDXB1, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 787 */, - TILEGX_OPC_TBLIDXB2, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(16, 2) /* index 792 */, - TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(18, 4) /* index 797 */, - TILEGX_OPC_V1DOTPUSA, TILEGX_OPC_V1DOTPUS, TILEGX_OPC_V1DOTP, - TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1MAXU, - TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MULTU, TILEGX_OPC_V1MULUS, - TILEGX_OPC_V1MULU, TILEGX_OPC_V1MZ, TILEGX_OPC_V1SADAU, TILEGX_OPC_V1SADU, - TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS, - BITFIELD(18, 4) /* index 814 */, - TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC, TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC, - TILEGX_OPC_V2ADD, TILEGX_OPC_V2ADIFFS, TILEGX_OPC_V2AVGS, - TILEGX_OPC_V2CMPEQ, TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU, - TILEGX_OPC_V2CMPLTS, TILEGX_OPC_V2CMPLTU, TILEGX_OPC_V2CMPNE, - TILEGX_OPC_V2DOTPA, TILEGX_OPC_V2DOTP, TILEGX_OPC_V2INT_H, - BITFIELD(18, 4) /* index 831 */, - TILEGX_OPC_V2INT_L, TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ, - TILEGX_OPC_V2MULFSC, TILEGX_OPC_V2MULS, TILEGX_OPC_V2MULTS, TILEGX_OPC_V2MZ, - TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC, - TILEGX_OPC_V2SADAS, TILEGX_OPC_V2SADAU, TILEGX_OPC_V2SADS, - TILEGX_OPC_V2SADU, TILEGX_OPC_V2SHLSC, - BITFIELD(18, 4) /* index 848 */, - TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU, TILEGX_OPC_V2SUBSC, - TILEGX_OPC_V2SUB, TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H, - TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC, - TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC, - TILEGX_OPC_V4SUB, - BITFIELD(18, 3) /* index 865 */, - CHILD(874), CHILD(877), CHILD(880), CHILD(883), CHILD(886), TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(21, 1) /* index 874 */, - TILEGX_OPC_XOR, TILEGX_OPC_NONE, - BITFIELD(21, 1) /* index 877 */, - TILEGX_OPC_V1DDOTPUA, TILEGX_OPC_NONE, - BITFIELD(21, 1) /* index 880 */, - TILEGX_OPC_V1DDOTPU, TILEGX_OPC_NONE, - BITFIELD(21, 1) /* index 883 */, - TILEGX_OPC_V1DOTPUA, TILEGX_OPC_NONE, - BITFIELD(21, 1) /* index 886 */, - TILEGX_OPC_V1DOTPU, TILEGX_OPC_NONE, - BITFIELD(18, 4) /* index 889 */, - TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI, - TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI, - TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI, - TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, - BITFIELD(0, 2) /* index 906 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - CHILD(911), - BITFIELD(2, 2) /* index 911 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - CHILD(916), - BITFIELD(4, 2) /* index 916 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - CHILD(921), - BITFIELD(6, 2) /* index 921 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - CHILD(926), - BITFIELD(8, 2) /* index 926 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - CHILD(931), - BITFIELD(10, 2) /* index 931 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - TILEGX_OPC_INFOL, -}; - -static const unsigned short decode_X1_fsm[1266] = -{ - BITFIELD(53, 9) /* index 0 */, - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), CHILD(513), - CHILD(513), CHILD(513), CHILD(513), CHILD(513), TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, - TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_ADDXLI, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_BEQZT, - TILEGX_OPC_BEQZT, TILEGX_OPC_BEQZ, TILEGX_OPC_BEQZ, TILEGX_OPC_BGEZT, - TILEGX_OPC_BGEZT, TILEGX_OPC_BGEZ, TILEGX_OPC_BGEZ, TILEGX_OPC_BGTZT, - TILEGX_OPC_BGTZT, TILEGX_OPC_BGTZ, TILEGX_OPC_BGTZ, TILEGX_OPC_BLBCT, - TILEGX_OPC_BLBCT, TILEGX_OPC_BLBC, TILEGX_OPC_BLBC, TILEGX_OPC_BLBST, - TILEGX_OPC_BLBST, TILEGX_OPC_BLBS, TILEGX_OPC_BLBS, TILEGX_OPC_BLEZT, - TILEGX_OPC_BLEZT, TILEGX_OPC_BLEZ, TILEGX_OPC_BLEZ, TILEGX_OPC_BLTZT, - TILEGX_OPC_BLTZT, TILEGX_OPC_BLTZ, TILEGX_OPC_BLTZ, TILEGX_OPC_BNEZT, - TILEGX_OPC_BNEZT, TILEGX_OPC_BNEZ, TILEGX_OPC_BNEZ, CHILD(528), CHILD(578), - CHILD(598), CHILD(703), CHILD(723), CHILD(728), CHILD(753), CHILD(758), - CHILD(763), CHILD(768), CHILD(773), CHILD(778), TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_JAL, - TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, - TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, - TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, - TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, - TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, - TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, - TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, - TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_JAL, TILEGX_OPC_J, TILEGX_OPC_J, - TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, - TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, - TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, - TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, - TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, - TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, TILEGX_OPC_J, - CHILD(783), CHILD(800), CHILD(832), CHILD(849), CHILD(1168), CHILD(1185), - CHILD(1202), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1219), TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), CHILD(1236), - CHILD(1236), - BITFIELD(37, 2) /* index 513 */, - TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(518), - BITFIELD(39, 2) /* index 518 */, - TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, CHILD(523), - BITFIELD(41, 2) /* index 523 */, - TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_ADDLI, TILEGX_OPC_MOVELI, - BITFIELD(51, 2) /* index 528 */, - TILEGX_OPC_NONE, CHILD(533), TILEGX_OPC_ADDXI, CHILD(548), - BITFIELD(37, 2) /* index 533 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(538), - BITFIELD(39, 2) /* index 538 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(543), - BITFIELD(41, 2) /* index 543 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, - BITFIELD(31, 2) /* index 548 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(553), - BITFIELD(33, 2) /* index 553 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(558), - BITFIELD(35, 2) /* index 558 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(563), - BITFIELD(37, 2) /* index 563 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(568), - BITFIELD(39, 2) /* index 568 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(573), - BITFIELD(41, 2) /* index 573 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, - BITFIELD(51, 2) /* index 578 */, - TILEGX_OPC_CMPEQI, TILEGX_OPC_CMPLTSI, TILEGX_OPC_CMPLTUI, CHILD(583), - BITFIELD(31, 2) /* index 583 */, - TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(588), - BITFIELD(33, 2) /* index 588 */, - TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, CHILD(593), - BITFIELD(35, 2) /* index 593 */, - TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, TILEGX_OPC_LD1S_ADD, - TILEGX_OPC_PREFETCH_ADD_L1_FAULT, - BITFIELD(51, 2) /* index 598 */, - CHILD(603), CHILD(618), CHILD(633), CHILD(648), - BITFIELD(31, 2) /* index 603 */, - TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(608), - BITFIELD(33, 2) /* index 608 */, - TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, CHILD(613), - BITFIELD(35, 2) /* index 613 */, - TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, TILEGX_OPC_LD1U_ADD, - TILEGX_OPC_PREFETCH_ADD_L1, - BITFIELD(31, 2) /* index 618 */, - TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(623), - BITFIELD(33, 2) /* index 623 */, - TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, CHILD(628), - BITFIELD(35, 2) /* index 628 */, - TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, TILEGX_OPC_LD2S_ADD, - TILEGX_OPC_PREFETCH_ADD_L2_FAULT, - BITFIELD(31, 2) /* index 633 */, - TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(638), - BITFIELD(33, 2) /* index 638 */, - TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, CHILD(643), - BITFIELD(35, 2) /* index 643 */, - TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, TILEGX_OPC_LD2U_ADD, - TILEGX_OPC_PREFETCH_ADD_L2, - BITFIELD(31, 2) /* index 648 */, - CHILD(653), CHILD(653), CHILD(653), CHILD(673), - BITFIELD(43, 2) /* index 653 */, - CHILD(658), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, - BITFIELD(45, 2) /* index 658 */, - CHILD(663), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, - BITFIELD(47, 2) /* index 663 */, - CHILD(668), TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, - BITFIELD(49, 2) /* index 668 */, - TILEGX_OPC_LD4S_TLS, TILEGX_OPC_LD4S_ADD, TILEGX_OPC_LD4S_ADD, - TILEGX_OPC_LD4S_ADD, - BITFIELD(33, 2) /* index 673 */, - CHILD(653), CHILD(653), CHILD(653), CHILD(678), - BITFIELD(35, 2) /* index 678 */, - CHILD(653), CHILD(653), CHILD(653), CHILD(683), - BITFIELD(43, 2) /* index 683 */, - CHILD(688), TILEGX_OPC_PREFETCH_ADD_L3_FAULT, - TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, - BITFIELD(45, 2) /* index 688 */, - CHILD(693), TILEGX_OPC_PREFETCH_ADD_L3_FAULT, - TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, - BITFIELD(47, 2) /* index 693 */, - CHILD(698), TILEGX_OPC_PREFETCH_ADD_L3_FAULT, - TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, - BITFIELD(49, 2) /* index 698 */, - TILEGX_OPC_LD4S_TLS, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, - TILEGX_OPC_PREFETCH_ADD_L3_FAULT, TILEGX_OPC_PREFETCH_ADD_L3_FAULT, - BITFIELD(51, 2) /* index 703 */, - CHILD(708), TILEGX_OPC_LDNT1S_ADD, TILEGX_OPC_LDNT1U_ADD, - TILEGX_OPC_LDNT2S_ADD, - BITFIELD(31, 2) /* index 708 */, - TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(713), - BITFIELD(33, 2) /* index 713 */, - TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, CHILD(718), - BITFIELD(35, 2) /* index 718 */, - TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, TILEGX_OPC_LD4U_ADD, - TILEGX_OPC_PREFETCH_ADD_L3, - BITFIELD(51, 2) /* index 723 */, - TILEGX_OPC_LDNT2U_ADD, TILEGX_OPC_LDNT4S_ADD, TILEGX_OPC_LDNT4U_ADD, - TILEGX_OPC_LDNT_ADD, - BITFIELD(51, 2) /* index 728 */, - CHILD(733), TILEGX_OPC_LDNA_ADD, TILEGX_OPC_MFSPR, TILEGX_OPC_MTSPR, - BITFIELD(43, 2) /* index 733 */, - CHILD(738), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, - BITFIELD(45, 2) /* index 738 */, - CHILD(743), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, - BITFIELD(47, 2) /* index 743 */, - CHILD(748), TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, - BITFIELD(49, 2) /* index 748 */, - TILEGX_OPC_LD_TLS, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, TILEGX_OPC_LD_ADD, - BITFIELD(51, 2) /* index 753 */, - TILEGX_OPC_ORI, TILEGX_OPC_ST1_ADD, TILEGX_OPC_ST2_ADD, TILEGX_OPC_ST4_ADD, - BITFIELD(51, 2) /* index 758 */, - TILEGX_OPC_STNT1_ADD, TILEGX_OPC_STNT2_ADD, TILEGX_OPC_STNT4_ADD, - TILEGX_OPC_STNT_ADD, - BITFIELD(51, 2) /* index 763 */, - TILEGX_OPC_ST_ADD, TILEGX_OPC_V1ADDI, TILEGX_OPC_V1CMPEQI, - TILEGX_OPC_V1CMPLTSI, - BITFIELD(51, 2) /* index 768 */, - TILEGX_OPC_V1CMPLTUI, TILEGX_OPC_V1MAXUI, TILEGX_OPC_V1MINUI, - TILEGX_OPC_V2ADDI, - BITFIELD(51, 2) /* index 773 */, - TILEGX_OPC_V2CMPEQI, TILEGX_OPC_V2CMPLTSI, TILEGX_OPC_V2CMPLTUI, - TILEGX_OPC_V2MAXSI, - BITFIELD(51, 2) /* index 778 */, - TILEGX_OPC_V2MINSI, TILEGX_OPC_XORI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(49, 4) /* index 783 */, - TILEGX_OPC_NONE, TILEGX_OPC_ADDXSC, TILEGX_OPC_ADDX, TILEGX_OPC_ADD, - TILEGX_OPC_AND, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPEXCH4, TILEGX_OPC_CMPEXCH, - TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, - TILEGX_OPC_CMPNE, TILEGX_OPC_DBLALIGN2, TILEGX_OPC_DBLALIGN4, - TILEGX_OPC_DBLALIGN6, - BITFIELD(49, 4) /* index 800 */, - TILEGX_OPC_EXCH4, TILEGX_OPC_EXCH, TILEGX_OPC_FETCHADD4, - TILEGX_OPC_FETCHADDGEZ4, TILEGX_OPC_FETCHADDGEZ, TILEGX_OPC_FETCHADD, - TILEGX_OPC_FETCHAND4, TILEGX_OPC_FETCHAND, TILEGX_OPC_FETCHOR4, - TILEGX_OPC_FETCHOR, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, TILEGX_OPC_NOR, - CHILD(817), TILEGX_OPC_ROTL, TILEGX_OPC_SHL1ADDX, - BITFIELD(43, 2) /* index 817 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(822), - BITFIELD(45, 2) /* index 822 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(827), - BITFIELD(47, 2) /* index 827 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, - BITFIELD(49, 4) /* index 832 */, - TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADDX, TILEGX_OPC_SHL2ADD, - TILEGX_OPC_SHL3ADDX, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHLX, TILEGX_OPC_SHL, - TILEGX_OPC_SHRS, TILEGX_OPC_SHRUX, TILEGX_OPC_SHRU, TILEGX_OPC_ST1, - TILEGX_OPC_ST2, TILEGX_OPC_ST4, TILEGX_OPC_STNT1, TILEGX_OPC_STNT2, - TILEGX_OPC_STNT4, - BITFIELD(46, 7) /* index 849 */, - TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, - TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, TILEGX_OPC_STNT, - TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, - TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_ST, TILEGX_OPC_SUBXSC, - TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, - TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBXSC, TILEGX_OPC_SUBX, - TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, - TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, - TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, - TILEGX_OPC_SUB, TILEGX_OPC_SUB, TILEGX_OPC_SUB, CHILD(978), CHILD(987), - CHILD(1066), CHILD(1150), CHILD(1159), TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, - TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, - TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADDUC, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, - TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, - TILEGX_OPC_V1ADD, TILEGX_OPC_V1ADD, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, - TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, - TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, TILEGX_OPC_V1CMPEQ, - TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, - TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, - TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLES, TILEGX_OPC_V1CMPLEU, - TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, - TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLEU, - TILEGX_OPC_V1CMPLEU, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, - TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, - TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, TILEGX_OPC_V1CMPLTS, - TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, - TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, - TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPLTU, TILEGX_OPC_V1CMPNE, - TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, - TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1CMPNE, - TILEGX_OPC_V1CMPNE, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, - TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, - TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, TILEGX_OPC_V1INT_H, - TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, - TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, - TILEGX_OPC_V1INT_L, TILEGX_OPC_V1INT_L, - BITFIELD(43, 3) /* index 978 */, - TILEGX_OPC_NONE, TILEGX_OPC_DRAIN, TILEGX_OPC_DTLBPR, TILEGX_OPC_FINV, - TILEGX_OPC_FLUSHWB, TILEGX_OPC_FLUSH, TILEGX_OPC_FNOP, TILEGX_OPC_ICOH, - BITFIELD(43, 3) /* index 987 */, - CHILD(996), TILEGX_OPC_INV, TILEGX_OPC_IRET, TILEGX_OPC_JALRP, - TILEGX_OPC_JALR, TILEGX_OPC_JRP, TILEGX_OPC_JR, CHILD(1051), - BITFIELD(31, 2) /* index 996 */, - CHILD(1001), CHILD(1026), TILEGX_OPC_ILL, TILEGX_OPC_ILL, - BITFIELD(33, 2) /* index 1001 */, - TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(1006), - BITFIELD(35, 2) /* index 1006 */, - TILEGX_OPC_ILL, CHILD(1011), TILEGX_OPC_ILL, TILEGX_OPC_ILL, - BITFIELD(37, 2) /* index 1011 */, - TILEGX_OPC_ILL, CHILD(1016), TILEGX_OPC_ILL, TILEGX_OPC_ILL, - BITFIELD(39, 2) /* index 1016 */, - TILEGX_OPC_ILL, CHILD(1021), TILEGX_OPC_ILL, TILEGX_OPC_ILL, - BITFIELD(41, 2) /* index 1021 */, - TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_BPT, TILEGX_OPC_ILL, - BITFIELD(33, 2) /* index 1026 */, - TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_ILL, CHILD(1031), - BITFIELD(35, 2) /* index 1031 */, - TILEGX_OPC_ILL, CHILD(1036), TILEGX_OPC_ILL, TILEGX_OPC_ILL, - BITFIELD(37, 2) /* index 1036 */, - TILEGX_OPC_ILL, CHILD(1041), TILEGX_OPC_ILL, TILEGX_OPC_ILL, - BITFIELD(39, 2) /* index 1041 */, - TILEGX_OPC_ILL, CHILD(1046), TILEGX_OPC_ILL, TILEGX_OPC_ILL, - BITFIELD(41, 2) /* index 1046 */, - TILEGX_OPC_ILL, TILEGX_OPC_ILL, TILEGX_OPC_RAISE, TILEGX_OPC_ILL, - BITFIELD(31, 2) /* index 1051 */, - TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(1056), - BITFIELD(33, 2) /* index 1056 */, - TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(1061), - BITFIELD(35, 2) /* index 1061 */, - TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, - TILEGX_OPC_PREFETCH_L1_FAULT, - BITFIELD(43, 3) /* index 1066 */, - CHILD(1075), CHILD(1090), CHILD(1105), CHILD(1120), CHILD(1135), - TILEGX_OPC_LDNA, TILEGX_OPC_LDNT1S, TILEGX_OPC_LDNT1U, - BITFIELD(31, 2) /* index 1075 */, - TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1080), - BITFIELD(33, 2) /* index 1080 */, - TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(1085), - BITFIELD(35, 2) /* index 1085 */, - TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH, - BITFIELD(31, 2) /* index 1090 */, - TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1095), - BITFIELD(33, 2) /* index 1095 */, - TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(1100), - BITFIELD(35, 2) /* index 1100 */, - TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, - TILEGX_OPC_PREFETCH_L2_FAULT, - BITFIELD(31, 2) /* index 1105 */, - TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1110), - BITFIELD(33, 2) /* index 1110 */, - TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(1115), - BITFIELD(35, 2) /* index 1115 */, - TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2, - BITFIELD(31, 2) /* index 1120 */, - TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1125), - BITFIELD(33, 2) /* index 1125 */, - TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(1130), - BITFIELD(35, 2) /* index 1130 */, - TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, - TILEGX_OPC_PREFETCH_L3_FAULT, - BITFIELD(31, 2) /* index 1135 */, - TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1140), - BITFIELD(33, 2) /* index 1140 */, - TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(1145), - BITFIELD(35, 2) /* index 1145 */, - TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3, - BITFIELD(43, 3) /* index 1150 */, - TILEGX_OPC_LDNT2S, TILEGX_OPC_LDNT2U, TILEGX_OPC_LDNT4S, TILEGX_OPC_LDNT4U, - TILEGX_OPC_LDNT, TILEGX_OPC_LD, TILEGX_OPC_LNK, TILEGX_OPC_MF, - BITFIELD(43, 3) /* index 1159 */, - TILEGX_OPC_NAP, TILEGX_OPC_NOP, TILEGX_OPC_SWINT0, TILEGX_OPC_SWINT1, - TILEGX_OPC_SWINT2, TILEGX_OPC_SWINT3, TILEGX_OPC_WH64, TILEGX_OPC_NONE, - BITFIELD(49, 4) /* index 1168 */, - TILEGX_OPC_V1MAXU, TILEGX_OPC_V1MINU, TILEGX_OPC_V1MNZ, TILEGX_OPC_V1MZ, - TILEGX_OPC_V1SHL, TILEGX_OPC_V1SHRS, TILEGX_OPC_V1SHRU, TILEGX_OPC_V1SUBUC, - TILEGX_OPC_V1SUB, TILEGX_OPC_V2ADDSC, TILEGX_OPC_V2ADD, TILEGX_OPC_V2CMPEQ, - TILEGX_OPC_V2CMPLES, TILEGX_OPC_V2CMPLEU, TILEGX_OPC_V2CMPLTS, - TILEGX_OPC_V2CMPLTU, - BITFIELD(49, 4) /* index 1185 */, - TILEGX_OPC_V2CMPNE, TILEGX_OPC_V2INT_H, TILEGX_OPC_V2INT_L, - TILEGX_OPC_V2MAXS, TILEGX_OPC_V2MINS, TILEGX_OPC_V2MNZ, TILEGX_OPC_V2MZ, - TILEGX_OPC_V2PACKH, TILEGX_OPC_V2PACKL, TILEGX_OPC_V2PACKUC, - TILEGX_OPC_V2SHLSC, TILEGX_OPC_V2SHL, TILEGX_OPC_V2SHRS, TILEGX_OPC_V2SHRU, - TILEGX_OPC_V2SUBSC, TILEGX_OPC_V2SUB, - BITFIELD(49, 4) /* index 1202 */, - TILEGX_OPC_V4ADDSC, TILEGX_OPC_V4ADD, TILEGX_OPC_V4INT_H, - TILEGX_OPC_V4INT_L, TILEGX_OPC_V4PACKSC, TILEGX_OPC_V4SHLSC, - TILEGX_OPC_V4SHL, TILEGX_OPC_V4SHRS, TILEGX_OPC_V4SHRU, TILEGX_OPC_V4SUBSC, - TILEGX_OPC_V4SUB, TILEGX_OPC_XOR, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(49, 4) /* index 1219 */, - TILEGX_OPC_NONE, TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHLXI, - TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, TILEGX_OPC_SHRUXI, TILEGX_OPC_V1SHLI, - TILEGX_OPC_V1SHRSI, TILEGX_OPC_V1SHRUI, TILEGX_OPC_V2SHLI, - TILEGX_OPC_V2SHRSI, TILEGX_OPC_V2SHRUI, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, - BITFIELD(31, 2) /* index 1236 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - CHILD(1241), - BITFIELD(33, 2) /* index 1241 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - CHILD(1246), - BITFIELD(35, 2) /* index 1246 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - CHILD(1251), - BITFIELD(37, 2) /* index 1251 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - CHILD(1256), - BITFIELD(39, 2) /* index 1256 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - CHILD(1261), - BITFIELD(41, 2) /* index 1261 */, - TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, TILEGX_OPC_SHL16INSLI, - TILEGX_OPC_INFOL, -}; - -static const unsigned short decode_Y0_fsm[178] = -{ - BITFIELD(27, 4) /* index 0 */, - CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI, - TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(118), CHILD(123), - CHILD(128), CHILD(133), CHILD(153), CHILD(158), CHILD(163), CHILD(168), - CHILD(173), - BITFIELD(6, 2) /* index 17 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22), - BITFIELD(8, 2) /* index 22 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27), - BITFIELD(10, 2) /* index 27 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, - BITFIELD(0, 2) /* index 32 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37), - BITFIELD(2, 2) /* index 37 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42), - BITFIELD(4, 2) /* index 42 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47), - BITFIELD(6, 2) /* index 47 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52), - BITFIELD(8, 2) /* index 52 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57), - BITFIELD(10, 2) /* index 57 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, - BITFIELD(18, 2) /* index 62 */, - TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, - BITFIELD(15, 5) /* index 67 */, - TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, - TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, - TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD, - TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, - TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, - TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, - TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, - TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(100), - CHILD(109), TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(12, 3) /* index 100 */, - TILEGX_OPC_NONE, TILEGX_OPC_CLZ, TILEGX_OPC_CTZ, TILEGX_OPC_FNOP, - TILEGX_OPC_FSINGLE_PACK1, TILEGX_OPC_NOP, TILEGX_OPC_PCNT, - TILEGX_OPC_REVBITS, - BITFIELD(12, 3) /* index 109 */, - TILEGX_OPC_REVBYTES, TILEGX_OPC_TBLIDXB0, TILEGX_OPC_TBLIDXB1, - TILEGX_OPC_TBLIDXB2, TILEGX_OPC_TBLIDXB3, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - TILEGX_OPC_NONE, - BITFIELD(18, 2) /* index 118 */, - TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, - BITFIELD(18, 2) /* index 123 */, - TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE, TILEGX_OPC_MULAX, TILEGX_OPC_MULX, - BITFIELD(18, 2) /* index 128 */, - TILEGX_OPC_CMOVEQZ, TILEGX_OPC_CMOVNEZ, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, - BITFIELD(18, 2) /* index 133 */, - TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(138), TILEGX_OPC_XOR, - BITFIELD(12, 2) /* index 138 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(143), - BITFIELD(14, 2) /* index 143 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(148), - BITFIELD(16, 2) /* index 148 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, - BITFIELD(18, 2) /* index 153 */, - TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU, - BITFIELD(18, 2) /* index 158 */, - TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX, - TILEGX_OPC_SHL3ADDX, - BITFIELD(18, 2) /* index 163 */, - TILEGX_OPC_MUL_HS_HS, TILEGX_OPC_MUL_HU_HU, TILEGX_OPC_MUL_LS_LS, - TILEGX_OPC_MUL_LU_LU, - BITFIELD(18, 2) /* index 168 */, - TILEGX_OPC_MULA_HS_HS, TILEGX_OPC_MULA_HU_HU, TILEGX_OPC_MULA_LS_LS, - TILEGX_OPC_MULA_LU_LU, - BITFIELD(18, 2) /* index 173 */, - TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, -}; - -static const unsigned short decode_Y1_fsm[167] = -{ - BITFIELD(58, 4) /* index 0 */, - TILEGX_OPC_NONE, CHILD(17), TILEGX_OPC_ADDXI, CHILD(32), TILEGX_OPC_CMPEQI, - TILEGX_OPC_CMPLTSI, CHILD(62), CHILD(67), CHILD(117), CHILD(122), - CHILD(127), CHILD(132), CHILD(152), CHILD(157), CHILD(162), TILEGX_OPC_NONE, - BITFIELD(37, 2) /* index 17 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(22), - BITFIELD(39, 2) /* index 22 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, CHILD(27), - BITFIELD(41, 2) /* index 27 */, - TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_ADDI, TILEGX_OPC_MOVEI, - BITFIELD(31, 2) /* index 32 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(37), - BITFIELD(33, 2) /* index 37 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(42), - BITFIELD(35, 2) /* index 42 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(47), - BITFIELD(37, 2) /* index 47 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(52), - BITFIELD(39, 2) /* index 52 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, CHILD(57), - BITFIELD(41, 2) /* index 57 */, - TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_ANDI, TILEGX_OPC_INFO, - BITFIELD(49, 2) /* index 62 */, - TILEGX_OPC_ADDX, TILEGX_OPC_ADD, TILEGX_OPC_SUBX, TILEGX_OPC_SUB, - BITFIELD(47, 4) /* index 67 */, - TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL1ADD, - TILEGX_OPC_SHL1ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, - TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL2ADD, TILEGX_OPC_SHL3ADD, - TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, TILEGX_OPC_SHL3ADD, CHILD(84), - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_NONE, - BITFIELD(43, 3) /* index 84 */, - CHILD(93), CHILD(96), CHILD(99), CHILD(102), CHILD(105), CHILD(108), - CHILD(111), CHILD(114), - BITFIELD(46, 1) /* index 93 */, - TILEGX_OPC_NONE, TILEGX_OPC_FNOP, - BITFIELD(46, 1) /* index 96 */, - TILEGX_OPC_NONE, TILEGX_OPC_ILL, - BITFIELD(46, 1) /* index 99 */, - TILEGX_OPC_NONE, TILEGX_OPC_JALRP, - BITFIELD(46, 1) /* index 102 */, - TILEGX_OPC_NONE, TILEGX_OPC_JALR, - BITFIELD(46, 1) /* index 105 */, - TILEGX_OPC_NONE, TILEGX_OPC_JRP, - BITFIELD(46, 1) /* index 108 */, - TILEGX_OPC_NONE, TILEGX_OPC_JR, - BITFIELD(46, 1) /* index 111 */, - TILEGX_OPC_NONE, TILEGX_OPC_LNK, - BITFIELD(46, 1) /* index 114 */, - TILEGX_OPC_NONE, TILEGX_OPC_NOP, - BITFIELD(49, 2) /* index 117 */, - TILEGX_OPC_CMPLES, TILEGX_OPC_CMPLEU, TILEGX_OPC_CMPLTS, TILEGX_OPC_CMPLTU, - BITFIELD(49, 2) /* index 122 */, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_CMPEQ, TILEGX_OPC_CMPNE, - BITFIELD(49, 2) /* index 127 */, - TILEGX_OPC_NONE, TILEGX_OPC_NONE, TILEGX_OPC_MNZ, TILEGX_OPC_MZ, - BITFIELD(49, 2) /* index 132 */, - TILEGX_OPC_AND, TILEGX_OPC_NOR, CHILD(137), TILEGX_OPC_XOR, - BITFIELD(43, 2) /* index 137 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(142), - BITFIELD(45, 2) /* index 142 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, CHILD(147), - BITFIELD(47, 2) /* index 147 */, - TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_OR, TILEGX_OPC_MOVE, - BITFIELD(49, 2) /* index 152 */, - TILEGX_OPC_ROTL, TILEGX_OPC_SHL, TILEGX_OPC_SHRS, TILEGX_OPC_SHRU, - BITFIELD(49, 2) /* index 157 */, - TILEGX_OPC_NONE, TILEGX_OPC_SHL1ADDX, TILEGX_OPC_SHL2ADDX, - TILEGX_OPC_SHL3ADDX, - BITFIELD(49, 2) /* index 162 */, - TILEGX_OPC_ROTLI, TILEGX_OPC_SHLI, TILEGX_OPC_SHRSI, TILEGX_OPC_SHRUI, -}; - -static const unsigned short decode_Y2_fsm[118] = -{ - BITFIELD(62, 2) /* index 0 */, - TILEGX_OPC_NONE, CHILD(5), CHILD(66), CHILD(109), - BITFIELD(55, 3) /* index 5 */, - CHILD(14), CHILD(14), CHILD(14), CHILD(17), CHILD(40), CHILD(40), CHILD(40), - CHILD(43), - BITFIELD(26, 1) /* index 14 */, - TILEGX_OPC_LD1S, TILEGX_OPC_LD1U, - BITFIELD(26, 1) /* index 17 */, - CHILD(20), CHILD(30), - BITFIELD(51, 2) /* index 20 */, - TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, CHILD(25), - BITFIELD(53, 2) /* index 25 */, - TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, TILEGX_OPC_LD1S, - TILEGX_OPC_PREFETCH_L1_FAULT, - BITFIELD(51, 2) /* index 30 */, - TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, CHILD(35), - BITFIELD(53, 2) /* index 35 */, - TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_LD1U, TILEGX_OPC_PREFETCH, - BITFIELD(26, 1) /* index 40 */, - TILEGX_OPC_LD2S, TILEGX_OPC_LD2U, - BITFIELD(26, 1) /* index 43 */, - CHILD(46), CHILD(56), - BITFIELD(51, 2) /* index 46 */, - TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, CHILD(51), - BITFIELD(53, 2) /* index 51 */, - TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, TILEGX_OPC_LD2S, - TILEGX_OPC_PREFETCH_L2_FAULT, - BITFIELD(51, 2) /* index 56 */, - TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, CHILD(61), - BITFIELD(53, 2) /* index 61 */, - TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_LD2U, TILEGX_OPC_PREFETCH_L2, - BITFIELD(56, 2) /* index 66 */, - CHILD(71), CHILD(74), CHILD(90), CHILD(93), - BITFIELD(26, 1) /* index 71 */, - TILEGX_OPC_NONE, TILEGX_OPC_LD4S, - BITFIELD(26, 1) /* index 74 */, - TILEGX_OPC_NONE, CHILD(77), - BITFIELD(51, 2) /* index 77 */, - TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(82), - BITFIELD(53, 2) /* index 82 */, - TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, TILEGX_OPC_LD4S, CHILD(87), - BITFIELD(55, 1) /* index 87 */, - TILEGX_OPC_LD4S, TILEGX_OPC_PREFETCH_L3_FAULT, - BITFIELD(26, 1) /* index 90 */, - TILEGX_OPC_LD4U, TILEGX_OPC_LD, - BITFIELD(26, 1) /* index 93 */, - CHILD(96), TILEGX_OPC_LD, - BITFIELD(51, 2) /* index 96 */, - TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(101), - BITFIELD(53, 2) /* index 101 */, - TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, TILEGX_OPC_LD4U, CHILD(106), - BITFIELD(55, 1) /* index 106 */, - TILEGX_OPC_LD4U, TILEGX_OPC_PREFETCH_L3, - BITFIELD(26, 1) /* index 109 */, - CHILD(112), CHILD(115), - BITFIELD(57, 1) /* index 112 */, - TILEGX_OPC_ST1, TILEGX_OPC_ST4, - BITFIELD(57, 1) /* index 115 */, - TILEGX_OPC_ST2, TILEGX_OPC_ST, -}; - -#undef BITFIELD -#undef CHILD - -const unsigned short * const -tilegx_bundle_decoder_fsms[TILEGX_NUM_PIPELINE_ENCODINGS] = -{ - decode_X0_fsm, - decode_X1_fsm, - decode_Y0_fsm, - decode_Y1_fsm, - decode_Y2_fsm -}; - -const struct tilegx_operand tilegx_operands[35] = -{ - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X0), - 8, 1, 0, 0, 0, 0, - create_Imm8_X0, get_Imm8_X0 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_X1), - 8, 1, 0, 0, 0, 0, - create_Imm8_X1, get_Imm8_X1 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y0), - 8, 1, 0, 0, 0, 0, - create_Imm8_Y0, get_Imm8_Y0 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM8_Y1), - 8, 1, 0, 0, 0, 0, - create_Imm8_Y1, get_Imm8_Y1 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X0_HW0_LAST), - 16, 1, 0, 0, 0, 0, - create_Imm16_X0, get_Imm16_X0 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_IMM16_X1_HW0_LAST), - 16, 1, 0, 0, 0, 0, - create_Imm16_X1, get_Imm16_X1 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 0, 1, 0, 0, - create_Dest_X1, get_Dest_X1 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 0, 0, 0, - create_SrcA_X1, get_SrcA_X1 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 0, 1, 0, 0, - create_Dest_X0, get_Dest_X0 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 0, 0, 0, - create_SrcA_X0, get_SrcA_X0 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 0, 1, 0, 0, - create_Dest_Y0, get_Dest_Y0 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 0, 0, 0, - create_SrcA_Y0, get_SrcA_Y0 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 0, 1, 0, 0, - create_Dest_Y1, get_Dest_Y1 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 0, 0, 0, - create_SrcA_Y1, get_SrcA_Y1 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 0, 0, 0, - create_SrcA_Y2, get_SrcA_Y2 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 1, 0, 0, - create_SrcA_X1, get_SrcA_X1 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 0, 0, 0, - create_SrcB_X0, get_SrcB_X0 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 0, 0, 0, - create_SrcB_X1, get_SrcB_X1 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 0, 0, 0, - create_SrcB_Y0, get_SrcB_Y0 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 0, 0, 0, - create_SrcB_Y1, get_SrcB_Y1 - }, - { - TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_BROFF_X1), - 17, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES, - create_BrOff_X1, get_BrOff_X1 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMSTART_X0), - 6, 0, 0, 0, 0, 0, - create_BFStart_X0, get_BFStart_X0 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_MMEND_X0), - 6, 0, 0, 0, 0, 0, - create_BFEnd_X0, get_BFEnd_X0 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 1, 0, 0, - create_Dest_X0, get_Dest_X0 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 1, 0, 0, - create_Dest_Y0, get_Dest_Y0 - }, - { - TILEGX_OP_TYPE_ADDRESS, BFD_RELOC(TILEGX_JUMPOFF_X1), - 27, 1, 0, 0, 1, TILEGX_LOG2_BUNDLE_ALIGNMENT_IN_BYTES, - create_JumpOff_X1, get_JumpOff_X1 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 0, 1, 0, 0, - create_SrcBDest_Y2, get_SrcBDest_Y2 - }, - { - TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MF_IMM14_X1), - 14, 0, 0, 0, 0, 0, - create_MF_Imm14_X1, get_MF_Imm14_X1 - }, - { - TILEGX_OP_TYPE_SPR, BFD_RELOC(TILEGX_MT_IMM14_X1), - 14, 0, 0, 0, 0, 0, - create_MT_Imm14_X1, get_MT_Imm14_X1 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X0), - 6, 0, 0, 0, 0, 0, - create_ShAmt_X0, get_ShAmt_X0 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_X1), - 6, 0, 0, 0, 0, 0, - create_ShAmt_X1, get_ShAmt_X1 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y0), - 6, 0, 0, 0, 0, 0, - create_ShAmt_Y0, get_ShAmt_Y0 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_SHAMT_Y1), - 6, 0, 0, 0, 0, 0, - create_ShAmt_Y1, get_ShAmt_Y1 - }, - { - TILEGX_OP_TYPE_REGISTER, BFD_RELOC(NONE), - 6, 0, 1, 0, 0, 0, - create_SrcBDest_Y2, get_SrcBDest_Y2 - }, - { - TILEGX_OP_TYPE_IMMEDIATE, BFD_RELOC(TILEGX_DEST_IMM8_X1), - 8, 1, 0, 0, 0, 0, - create_Dest_Imm8_X1, get_Dest_Imm8_X1 - } -}; - -/* Given a set of bundle bits and a specific pipe, returns which - * instruction the bundle contains in that pipe. - */ -const struct tilegx_opcode * -find_opcode(tilegx_bundle_bits bits, tilegx_pipeline pipe) -{ - const unsigned short *table = tilegx_bundle_decoder_fsms[pipe]; - int index = 0; - - while (1) - { - unsigned short bitspec = table[index]; - unsigned int bitfield = - ((unsigned int)(bits >> (bitspec & 63))) & (bitspec >> 6); - - unsigned short next = table[index + 1 + bitfield]; - if (next <= TILEGX_OPC_NONE) - return &tilegx_opcodes[next]; - - index = next - TILEGX_OPC_NONE; - } -} - -int -parse_insn_tilegx(tilegx_bundle_bits bits, - unsigned long long pc, - struct tilegx_decoded_instruction - decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]) -{ - int num_instructions = 0; - int pipe; - - int min_pipe, max_pipe; - if ((bits & TILEGX_BUNDLE_MODE_MASK) == 0) - { - min_pipe = TILEGX_PIPELINE_X0; - max_pipe = TILEGX_PIPELINE_X1; - } - else - { - min_pipe = TILEGX_PIPELINE_Y0; - max_pipe = TILEGX_PIPELINE_Y2; - } - - /* For each pipe, find an instruction that fits. */ - for (pipe = min_pipe; pipe <= max_pipe; pipe++) - { - const struct tilegx_opcode *opc; - struct tilegx_decoded_instruction *d; - int i; - - d = &decoded[num_instructions++]; - opc = find_opcode (bits, (tilegx_pipeline)pipe); - d->opcode = opc; - - /* Decode each operand, sign extending, etc. as appropriate. */ - for (i = 0; i < opc->num_operands; i++) - { - const struct tilegx_operand *op = - &tilegx_operands[opc->operands[pipe][i]]; - int raw_opval = op->extract (bits); - long long opval; - - if (op->is_signed) - { - /* Sign-extend the operand. */ - int shift = (int)((sizeof(int) * 8) - op->num_bits); - raw_opval = (raw_opval << shift) >> shift; - } - - /* Adjust PC-relative scaled branch offsets. */ - if (op->type == TILEGX_OP_TYPE_ADDRESS) - opval = (raw_opval * TILEGX_BUNDLE_SIZE_IN_BYTES) + pc; - else - opval = raw_opval; - - /* Record the final value. */ - d->operands[i] = op; - d->operand_values[i] = opval; - } - } - - return num_instructions; -} - -struct tilegx_spr -{ - /* The number */ - int number; - - /* The name */ - const char *name; -}; - -static int -tilegx_spr_compare (const void *a_ptr, const void *b_ptr) -{ - const struct tilegx_spr *a = (const struct tilegx_spr *) a_ptr; - const struct tilegx_spr *b = (const struct tilegx_spr *) b_ptr; - return (a->number - b->number); -} - -const struct tilegx_spr tilegx_sprs[] = { - { 0, "MPL_MEM_ERROR_SET_0" }, - { 1, "MPL_MEM_ERROR_SET_1" }, - { 2, "MPL_MEM_ERROR_SET_2" }, - { 3, "MPL_MEM_ERROR_SET_3" }, - { 4, "MPL_MEM_ERROR" }, - { 5, "MEM_ERROR_CBOX_ADDR" }, - { 6, "MEM_ERROR_CBOX_STATUS" }, - { 7, "MEM_ERROR_ENABLE" }, - { 8, "MEM_ERROR_MBOX_ADDR" }, - { 9, "MEM_ERROR_MBOX_STATUS" }, - { 10, "SBOX_ERROR" }, - { 11, "XDN_DEMUX_ERROR" }, - { 256, "MPL_SINGLE_STEP_3_SET_0" }, - { 257, "MPL_SINGLE_STEP_3_SET_1" }, - { 258, "MPL_SINGLE_STEP_3_SET_2" }, - { 259, "MPL_SINGLE_STEP_3_SET_3" }, - { 260, "MPL_SINGLE_STEP_3" }, - { 261, "SINGLE_STEP_CONTROL_3" }, - { 512, "MPL_SINGLE_STEP_2_SET_0" }, - { 513, "MPL_SINGLE_STEP_2_SET_1" }, - { 514, "MPL_SINGLE_STEP_2_SET_2" }, - { 515, "MPL_SINGLE_STEP_2_SET_3" }, - { 516, "MPL_SINGLE_STEP_2" }, - { 517, "SINGLE_STEP_CONTROL_2" }, - { 768, "MPL_SINGLE_STEP_1_SET_0" }, - { 769, "MPL_SINGLE_STEP_1_SET_1" }, - { 770, "MPL_SINGLE_STEP_1_SET_2" }, - { 771, "MPL_SINGLE_STEP_1_SET_3" }, - { 772, "MPL_SINGLE_STEP_1" }, - { 773, "SINGLE_STEP_CONTROL_1" }, - { 1024, "MPL_SINGLE_STEP_0_SET_0" }, - { 1025, "MPL_SINGLE_STEP_0_SET_1" }, - { 1026, "MPL_SINGLE_STEP_0_SET_2" }, - { 1027, "MPL_SINGLE_STEP_0_SET_3" }, - { 1028, "MPL_SINGLE_STEP_0" }, - { 1029, "SINGLE_STEP_CONTROL_0" }, - { 1280, "MPL_IDN_COMPLETE_SET_0" }, - { 1281, "MPL_IDN_COMPLETE_SET_1" }, - { 1282, "MPL_IDN_COMPLETE_SET_2" }, - { 1283, "MPL_IDN_COMPLETE_SET_3" }, - { 1284, "MPL_IDN_COMPLETE" }, - { 1285, "IDN_COMPLETE_PENDING" }, - { 1536, "MPL_UDN_COMPLETE_SET_0" }, - { 1537, "MPL_UDN_COMPLETE_SET_1" }, - { 1538, "MPL_UDN_COMPLETE_SET_2" }, - { 1539, "MPL_UDN_COMPLETE_SET_3" }, - { 1540, "MPL_UDN_COMPLETE" }, - { 1541, "UDN_COMPLETE_PENDING" }, - { 1792, "MPL_ITLB_MISS_SET_0" }, - { 1793, "MPL_ITLB_MISS_SET_1" }, - { 1794, "MPL_ITLB_MISS_SET_2" }, - { 1795, "MPL_ITLB_MISS_SET_3" }, - { 1796, "MPL_ITLB_MISS" }, - { 1797, "ITLB_TSB_BASE_ADDR_0" }, - { 1798, "ITLB_TSB_BASE_ADDR_1" }, - { 1920, "ITLB_CURRENT_ATTR" }, - { 1921, "ITLB_CURRENT_PA" }, - { 1922, "ITLB_CURRENT_VA" }, - { 1923, "ITLB_INDEX" }, - { 1924, "ITLB_MATCH_0" }, - { 1925, "ITLB_PERF" }, - { 1926, "ITLB_PR" }, - { 1927, "ITLB_TSB_ADDR_0" }, - { 1928, "ITLB_TSB_ADDR_1" }, - { 1929, "ITLB_TSB_FILL_CURRENT_ATTR" }, - { 1930, "ITLB_TSB_FILL_MATCH" }, - { 1931, "NUMBER_ITLB" }, - { 1932, "REPLACEMENT_ITLB" }, - { 1933, "WIRED_ITLB" }, - { 2048, "MPL_ILL_SET_0" }, - { 2049, "MPL_ILL_SET_1" }, - { 2050, "MPL_ILL_SET_2" }, - { 2051, "MPL_ILL_SET_3" }, - { 2052, "MPL_ILL" }, - { 2304, "MPL_GPV_SET_0" }, - { 2305, "MPL_GPV_SET_1" }, - { 2306, "MPL_GPV_SET_2" }, - { 2307, "MPL_GPV_SET_3" }, - { 2308, "MPL_GPV" }, - { 2309, "GPV_REASON" }, - { 2560, "MPL_IDN_ACCESS_SET_0" }, - { 2561, "MPL_IDN_ACCESS_SET_1" }, - { 2562, "MPL_IDN_ACCESS_SET_2" }, - { 2563, "MPL_IDN_ACCESS_SET_3" }, - { 2564, "MPL_IDN_ACCESS" }, - { 2565, "IDN_DEMUX_COUNT_0" }, - { 2566, "IDN_DEMUX_COUNT_1" }, - { 2567, "IDN_FLUSH_EGRESS" }, - { 2568, "IDN_PENDING" }, - { 2569, "IDN_ROUTE_ORDER" }, - { 2570, "IDN_SP_FIFO_CNT" }, - { 2688, "IDN_DATA_AVAIL" }, - { 2816, "MPL_UDN_ACCESS_SET_0" }, - { 2817, "MPL_UDN_ACCESS_SET_1" }, - { 2818, "MPL_UDN_ACCESS_SET_2" }, - { 2819, "MPL_UDN_ACCESS_SET_3" }, - { 2820, "MPL_UDN_ACCESS" }, - { 2821, "UDN_DEMUX_COUNT_0" }, - { 2822, "UDN_DEMUX_COUNT_1" }, - { 2823, "UDN_DEMUX_COUNT_2" }, - { 2824, "UDN_DEMUX_COUNT_3" }, - { 2825, "UDN_FLUSH_EGRESS" }, - { 2826, "UDN_PENDING" }, - { 2827, "UDN_ROUTE_ORDER" }, - { 2828, "UDN_SP_FIFO_CNT" }, - { 2944, "UDN_DATA_AVAIL" }, - { 3072, "MPL_SWINT_3_SET_0" }, - { 3073, "MPL_SWINT_3_SET_1" }, - { 3074, "MPL_SWINT_3_SET_2" }, - { 3075, "MPL_SWINT_3_SET_3" }, - { 3076, "MPL_SWINT_3" }, - { 3328, "MPL_SWINT_2_SET_0" }, - { 3329, "MPL_SWINT_2_SET_1" }, - { 3330, "MPL_SWINT_2_SET_2" }, - { 3331, "MPL_SWINT_2_SET_3" }, - { 3332, "MPL_SWINT_2" }, - { 3584, "MPL_SWINT_1_SET_0" }, - { 3585, "MPL_SWINT_1_SET_1" }, - { 3586, "MPL_SWINT_1_SET_2" }, - { 3587, "MPL_SWINT_1_SET_3" }, - { 3588, "MPL_SWINT_1" }, - { 3840, "MPL_SWINT_0_SET_0" }, - { 3841, "MPL_SWINT_0_SET_1" }, - { 3842, "MPL_SWINT_0_SET_2" }, - { 3843, "MPL_SWINT_0_SET_3" }, - { 3844, "MPL_SWINT_0" }, - { 4096, "MPL_ILL_TRANS_SET_0" }, - { 4097, "MPL_ILL_TRANS_SET_1" }, - { 4098, "MPL_ILL_TRANS_SET_2" }, - { 4099, "MPL_ILL_TRANS_SET_3" }, - { 4100, "MPL_ILL_TRANS" }, - { 4101, "ILL_TRANS_REASON" }, - { 4102, "ILL_VA_PC" }, - { 4352, "MPL_UNALIGN_DATA_SET_0" }, - { 4353, "MPL_UNALIGN_DATA_SET_1" }, - { 4354, "MPL_UNALIGN_DATA_SET_2" }, - { 4355, "MPL_UNALIGN_DATA_SET_3" }, - { 4356, "MPL_UNALIGN_DATA" }, - { 4608, "MPL_DTLB_MISS_SET_0" }, - { 4609, "MPL_DTLB_MISS_SET_1" }, - { 4610, "MPL_DTLB_MISS_SET_2" }, - { 4611, "MPL_DTLB_MISS_SET_3" }, - { 4612, "MPL_DTLB_MISS" }, - { 4613, "DTLB_TSB_BASE_ADDR_0" }, - { 4614, "DTLB_TSB_BASE_ADDR_1" }, - { 4736, "AAR" }, - { 4737, "CACHE_PINNED_WAYS" }, - { 4738, "DTLB_BAD_ADDR" }, - { 4739, "DTLB_BAD_ADDR_REASON" }, - { 4740, "DTLB_CURRENT_ATTR" }, - { 4741, "DTLB_CURRENT_PA" }, - { 4742, "DTLB_CURRENT_VA" }, - { 4743, "DTLB_INDEX" }, - { 4744, "DTLB_MATCH_0" }, - { 4745, "DTLB_PERF" }, - { 4746, "DTLB_TSB_ADDR_0" }, - { 4747, "DTLB_TSB_ADDR_1" }, - { 4748, "DTLB_TSB_FILL_CURRENT_ATTR" }, - { 4749, "DTLB_TSB_FILL_MATCH" }, - { 4750, "NUMBER_DTLB" }, - { 4751, "REPLACEMENT_DTLB" }, - { 4752, "WIRED_DTLB" }, - { 4864, "MPL_DTLB_ACCESS_SET_0" }, - { 4865, "MPL_DTLB_ACCESS_SET_1" }, - { 4866, "MPL_DTLB_ACCESS_SET_2" }, - { 4867, "MPL_DTLB_ACCESS_SET_3" }, - { 4868, "MPL_DTLB_ACCESS" }, - { 5120, "MPL_IDN_FIREWALL_SET_0" }, - { 5121, "MPL_IDN_FIREWALL_SET_1" }, - { 5122, "MPL_IDN_FIREWALL_SET_2" }, - { 5123, "MPL_IDN_FIREWALL_SET_3" }, - { 5124, "MPL_IDN_FIREWALL" }, - { 5125, "IDN_DIRECTION_PROTECT" }, - { 5376, "MPL_UDN_FIREWALL_SET_0" }, - { 5377, "MPL_UDN_FIREWALL_SET_1" }, - { 5378, "MPL_UDN_FIREWALL_SET_2" }, - { 5379, "MPL_UDN_FIREWALL_SET_3" }, - { 5380, "MPL_UDN_FIREWALL" }, - { 5381, "UDN_DIRECTION_PROTECT" }, - { 5632, "MPL_TILE_TIMER_SET_0" }, - { 5633, "MPL_TILE_TIMER_SET_1" }, - { 5634, "MPL_TILE_TIMER_SET_2" }, - { 5635, "MPL_TILE_TIMER_SET_3" }, - { 5636, "MPL_TILE_TIMER" }, - { 5637, "TILE_TIMER_CONTROL" }, - { 5888, "MPL_AUX_TILE_TIMER_SET_0" }, - { 5889, "MPL_AUX_TILE_TIMER_SET_1" }, - { 5890, "MPL_AUX_TILE_TIMER_SET_2" }, - { 5891, "MPL_AUX_TILE_TIMER_SET_3" }, - { 5892, "MPL_AUX_TILE_TIMER" }, - { 5893, "AUX_TILE_TIMER_CONTROL" }, - { 6144, "MPL_IDN_TIMER_SET_0" }, - { 6145, "MPL_IDN_TIMER_SET_1" }, - { 6146, "MPL_IDN_TIMER_SET_2" }, - { 6147, "MPL_IDN_TIMER_SET_3" }, - { 6148, "MPL_IDN_TIMER" }, - { 6149, "IDN_DEADLOCK_COUNT" }, - { 6150, "IDN_DEADLOCK_TIMEOUT" }, - { 6400, "MPL_UDN_TIMER_SET_0" }, - { 6401, "MPL_UDN_TIMER_SET_1" }, - { 6402, "MPL_UDN_TIMER_SET_2" }, - { 6403, "MPL_UDN_TIMER_SET_3" }, - { 6404, "MPL_UDN_TIMER" }, - { 6405, "UDN_DEADLOCK_COUNT" }, - { 6406, "UDN_DEADLOCK_TIMEOUT" }, - { 6656, "MPL_IDN_AVAIL_SET_0" }, - { 6657, "MPL_IDN_AVAIL_SET_1" }, - { 6658, "MPL_IDN_AVAIL_SET_2" }, - { 6659, "MPL_IDN_AVAIL_SET_3" }, - { 6660, "MPL_IDN_AVAIL" }, - { 6661, "IDN_AVAIL_EN" }, - { 6912, "MPL_UDN_AVAIL_SET_0" }, - { 6913, "MPL_UDN_AVAIL_SET_1" }, - { 6914, "MPL_UDN_AVAIL_SET_2" }, - { 6915, "MPL_UDN_AVAIL_SET_3" }, - { 6916, "MPL_UDN_AVAIL" }, - { 6917, "UDN_AVAIL_EN" }, - { 7168, "MPL_IPI_3_SET_0" }, - { 7169, "MPL_IPI_3_SET_1" }, - { 7170, "MPL_IPI_3_SET_2" }, - { 7171, "MPL_IPI_3_SET_3" }, - { 7172, "MPL_IPI_3" }, - { 7173, "IPI_EVENT_3" }, - { 7174, "IPI_EVENT_RESET_3" }, - { 7175, "IPI_EVENT_SET_3" }, - { 7176, "IPI_MASK_3" }, - { 7177, "IPI_MASK_RESET_3" }, - { 7178, "IPI_MASK_SET_3" }, - { 7424, "MPL_IPI_2_SET_0" }, - { 7425, "MPL_IPI_2_SET_1" }, - { 7426, "MPL_IPI_2_SET_2" }, - { 7427, "MPL_IPI_2_SET_3" }, - { 7428, "MPL_IPI_2" }, - { 7429, "IPI_EVENT_2" }, - { 7430, "IPI_EVENT_RESET_2" }, - { 7431, "IPI_EVENT_SET_2" }, - { 7432, "IPI_MASK_2" }, - { 7433, "IPI_MASK_RESET_2" }, - { 7434, "IPI_MASK_SET_2" }, - { 7680, "MPL_IPI_1_SET_0" }, - { 7681, "MPL_IPI_1_SET_1" }, - { 7682, "MPL_IPI_1_SET_2" }, - { 7683, "MPL_IPI_1_SET_3" }, - { 7684, "MPL_IPI_1" }, - { 7685, "IPI_EVENT_1" }, - { 7686, "IPI_EVENT_RESET_1" }, - { 7687, "IPI_EVENT_SET_1" }, - { 7688, "IPI_MASK_1" }, - { 7689, "IPI_MASK_RESET_1" }, - { 7690, "IPI_MASK_SET_1" }, - { 7936, "MPL_IPI_0_SET_0" }, - { 7937, "MPL_IPI_0_SET_1" }, - { 7938, "MPL_IPI_0_SET_2" }, - { 7939, "MPL_IPI_0_SET_3" }, - { 7940, "MPL_IPI_0" }, - { 7941, "IPI_EVENT_0" }, - { 7942, "IPI_EVENT_RESET_0" }, - { 7943, "IPI_EVENT_SET_0" }, - { 7944, "IPI_MASK_0" }, - { 7945, "IPI_MASK_RESET_0" }, - { 7946, "IPI_MASK_SET_0" }, - { 8192, "MPL_PERF_COUNT_SET_0" }, - { 8193, "MPL_PERF_COUNT_SET_1" }, - { 8194, "MPL_PERF_COUNT_SET_2" }, - { 8195, "MPL_PERF_COUNT_SET_3" }, - { 8196, "MPL_PERF_COUNT" }, - { 8197, "PERF_COUNT_0" }, - { 8198, "PERF_COUNT_1" }, - { 8199, "PERF_COUNT_CTL" }, - { 8200, "PERF_COUNT_DN_CTL" }, - { 8201, "PERF_COUNT_STS" }, - { 8202, "WATCH_MASK" }, - { 8203, "WATCH_VAL" }, - { 8448, "MPL_AUX_PERF_COUNT_SET_0" }, - { 8449, "MPL_AUX_PERF_COUNT_SET_1" }, - { 8450, "MPL_AUX_PERF_COUNT_SET_2" }, - { 8451, "MPL_AUX_PERF_COUNT_SET_3" }, - { 8452, "MPL_AUX_PERF_COUNT" }, - { 8453, "AUX_PERF_COUNT_0" }, - { 8454, "AUX_PERF_COUNT_1" }, - { 8455, "AUX_PERF_COUNT_CTL" }, - { 8456, "AUX_PERF_COUNT_STS" }, - { 8704, "MPL_INTCTRL_3_SET_0" }, - { 8705, "MPL_INTCTRL_3_SET_1" }, - { 8706, "MPL_INTCTRL_3_SET_2" }, - { 8707, "MPL_INTCTRL_3_SET_3" }, - { 8708, "MPL_INTCTRL_3" }, - { 8709, "INTCTRL_3_STATUS" }, - { 8710, "INTERRUPT_MASK_3" }, - { 8711, "INTERRUPT_MASK_RESET_3" }, - { 8712, "INTERRUPT_MASK_SET_3" }, - { 8713, "INTERRUPT_VECTOR_BASE_3" }, - { 8714, "SINGLE_STEP_EN_0_3" }, - { 8715, "SINGLE_STEP_EN_1_3" }, - { 8716, "SINGLE_STEP_EN_2_3" }, - { 8717, "SINGLE_STEP_EN_3_3" }, - { 8832, "EX_CONTEXT_3_0" }, - { 8833, "EX_CONTEXT_3_1" }, - { 8834, "SYSTEM_SAVE_3_0" }, - { 8835, "SYSTEM_SAVE_3_1" }, - { 8836, "SYSTEM_SAVE_3_2" }, - { 8837, "SYSTEM_SAVE_3_3" }, - { 8960, "MPL_INTCTRL_2_SET_0" }, - { 8961, "MPL_INTCTRL_2_SET_1" }, - { 8962, "MPL_INTCTRL_2_SET_2" }, - { 8963, "MPL_INTCTRL_2_SET_3" }, - { 8964, "MPL_INTCTRL_2" }, - { 8965, "INTCTRL_2_STATUS" }, - { 8966, "INTERRUPT_MASK_2" }, - { 8967, "INTERRUPT_MASK_RESET_2" }, - { 8968, "INTERRUPT_MASK_SET_2" }, - { 8969, "INTERRUPT_VECTOR_BASE_2" }, - { 8970, "SINGLE_STEP_EN_0_2" }, - { 8971, "SINGLE_STEP_EN_1_2" }, - { 8972, "SINGLE_STEP_EN_2_2" }, - { 8973, "SINGLE_STEP_EN_3_2" }, - { 9088, "EX_CONTEXT_2_0" }, - { 9089, "EX_CONTEXT_2_1" }, - { 9090, "SYSTEM_SAVE_2_0" }, - { 9091, "SYSTEM_SAVE_2_1" }, - { 9092, "SYSTEM_SAVE_2_2" }, - { 9093, "SYSTEM_SAVE_2_3" }, - { 9216, "MPL_INTCTRL_1_SET_0" }, - { 9217, "MPL_INTCTRL_1_SET_1" }, - { 9218, "MPL_INTCTRL_1_SET_2" }, - { 9219, "MPL_INTCTRL_1_SET_3" }, - { 9220, "MPL_INTCTRL_1" }, - { 9221, "INTCTRL_1_STATUS" }, - { 9222, "INTERRUPT_MASK_1" }, - { 9223, "INTERRUPT_MASK_RESET_1" }, - { 9224, "INTERRUPT_MASK_SET_1" }, - { 9225, "INTERRUPT_VECTOR_BASE_1" }, - { 9226, "SINGLE_STEP_EN_0_1" }, - { 9227, "SINGLE_STEP_EN_1_1" }, - { 9228, "SINGLE_STEP_EN_2_1" }, - { 9229, "SINGLE_STEP_EN_3_1" }, - { 9344, "EX_CONTEXT_1_0" }, - { 9345, "EX_CONTEXT_1_1" }, - { 9346, "SYSTEM_SAVE_1_0" }, - { 9347, "SYSTEM_SAVE_1_1" }, - { 9348, "SYSTEM_SAVE_1_2" }, - { 9349, "SYSTEM_SAVE_1_3" }, - { 9472, "MPL_INTCTRL_0_SET_0" }, - { 9473, "MPL_INTCTRL_0_SET_1" }, - { 9474, "MPL_INTCTRL_0_SET_2" }, - { 9475, "MPL_INTCTRL_0_SET_3" }, - { 9476, "MPL_INTCTRL_0" }, - { 9477, "INTCTRL_0_STATUS" }, - { 9478, "INTERRUPT_MASK_0" }, - { 9479, "INTERRUPT_MASK_RESET_0" }, - { 9480, "INTERRUPT_MASK_SET_0" }, - { 9481, "INTERRUPT_VECTOR_BASE_0" }, - { 9482, "SINGLE_STEP_EN_0_0" }, - { 9483, "SINGLE_STEP_EN_1_0" }, - { 9484, "SINGLE_STEP_EN_2_0" }, - { 9485, "SINGLE_STEP_EN_3_0" }, - { 9600, "EX_CONTEXT_0_0" }, - { 9601, "EX_CONTEXT_0_1" }, - { 9602, "SYSTEM_SAVE_0_0" }, - { 9603, "SYSTEM_SAVE_0_1" }, - { 9604, "SYSTEM_SAVE_0_2" }, - { 9605, "SYSTEM_SAVE_0_3" }, - { 9728, "MPL_BOOT_ACCESS_SET_0" }, - { 9729, "MPL_BOOT_ACCESS_SET_1" }, - { 9730, "MPL_BOOT_ACCESS_SET_2" }, - { 9731, "MPL_BOOT_ACCESS_SET_3" }, - { 9732, "MPL_BOOT_ACCESS" }, - { 9733, "BIG_ENDIAN_CONFIG" }, - { 9734, "CACHE_INVALIDATION_COMPRESSION_MODE" }, - { 9735, "CACHE_INVALIDATION_MASK_0" }, - { 9736, "CACHE_INVALIDATION_MASK_1" }, - { 9737, "CACHE_INVALIDATION_MASK_2" }, - { 9738, "CBOX_CACHEASRAM_CONFIG" }, - { 9739, "CBOX_CACHE_CONFIG" }, - { 9740, "CBOX_HOME_MAP_ADDR" }, - { 9741, "CBOX_HOME_MAP_DATA" }, - { 9742, "CBOX_MMAP_0" }, - { 9743, "CBOX_MMAP_1" }, - { 9744, "CBOX_MMAP_2" }, - { 9745, "CBOX_MMAP_3" }, - { 9746, "CBOX_MSR" }, - { 9747, "DIAG_BCST_CTL" }, - { 9748, "DIAG_BCST_MASK" }, - { 9749, "DIAG_BCST_TRIGGER" }, - { 9750, "DIAG_MUX_CTL" }, - { 9751, "DIAG_TRACE_CTL" }, - { 9752, "DIAG_TRACE_DATA" }, - { 9753, "DIAG_TRACE_STS" }, - { 9754, "IDN_DEMUX_BUF_THRESH" }, - { 9755, "L1_I_PIN_WAY_0" }, - { 9756, "MEM_ROUTE_ORDER" }, - { 9757, "MEM_STRIPE_CONFIG" }, - { 9758, "PERF_COUNT_PLS" }, - { 9759, "PSEUDO_RANDOM_NUMBER_MODIFY" }, - { 9760, "QUIESCE_CTL" }, - { 9761, "RSHIM_COORD" }, - { 9762, "SBOX_CONFIG" }, - { 9763, "UDN_DEMUX_BUF_THRESH" }, - { 9764, "XDN_CORE_STARVATION_COUNT" }, - { 9765, "XDN_ROUND_ROBIN_ARB_CTL" }, - { 9856, "CYCLE_MODIFY" }, - { 9857, "I_AAR" }, - { 9984, "MPL_WORLD_ACCESS_SET_0" }, - { 9985, "MPL_WORLD_ACCESS_SET_1" }, - { 9986, "MPL_WORLD_ACCESS_SET_2" }, - { 9987, "MPL_WORLD_ACCESS_SET_3" }, - { 9988, "MPL_WORLD_ACCESS" }, - { 9989, "DONE" }, - { 9990, "DSTREAM_PF" }, - { 9991, "FAIL" }, - { 9992, "INTERRUPT_CRITICAL_SECTION" }, - { 9993, "PASS" }, - { 9994, "PSEUDO_RANDOM_NUMBER" }, - { 9995, "TILE_COORD" }, - { 9996, "TILE_RTF_HWM" }, - { 10112, "CMPEXCH_VALUE" }, - { 10113, "CYCLE" }, - { 10114, "EVENT_BEGIN" }, - { 10115, "EVENT_END" }, - { 10116, "PROC_STATUS" }, - { 10117, "SIM_CONTROL" }, - { 10118, "SIM_SOCKET" }, - { 10119, "STATUS_SATURATE" }, - { 10240, "MPL_I_ASID_SET_0" }, - { 10241, "MPL_I_ASID_SET_1" }, - { 10242, "MPL_I_ASID_SET_2" }, - { 10243, "MPL_I_ASID_SET_3" }, - { 10244, "MPL_I_ASID" }, - { 10245, "I_ASID" }, - { 10496, "MPL_D_ASID_SET_0" }, - { 10497, "MPL_D_ASID_SET_1" }, - { 10498, "MPL_D_ASID_SET_2" }, - { 10499, "MPL_D_ASID_SET_3" }, - { 10500, "MPL_D_ASID" }, - { 10501, "D_ASID" }, - { 10752, "MPL_DOUBLE_FAULT_SET_0" }, - { 10753, "MPL_DOUBLE_FAULT_SET_1" }, - { 10754, "MPL_DOUBLE_FAULT_SET_2" }, - { 10755, "MPL_DOUBLE_FAULT_SET_3" }, - { 10756, "MPL_DOUBLE_FAULT" }, - { 10757, "LAST_INTERRUPT_REASON" }, -}; - -const int tilegx_num_sprs = 441; - -const char * -get_tilegx_spr_name (int num) -{ - void *result; - struct tilegx_spr key; - - key.number = num; - result = bsearch((const void *) &key, (const void *) tilegx_sprs, - tilegx_num_sprs, sizeof (struct tilegx_spr), - tilegx_spr_compare); - - if (result == NULL) - { - return (NULL); - } - else - { - struct tilegx_spr *result_ptr = (struct tilegx_spr *) result; - return (result_ptr->name); - } -} - -int -print_insn_tilegx (unsigned char * memaddr) -{ - struct tilegx_decoded_instruction - decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]; - unsigned char opbuf[TILEGX_BUNDLE_SIZE_IN_BYTES]; - int i, num_instructions, num_printed; - tilegx_mnemonic padding_mnemonic; - - memcpy((void *)opbuf, (void *)memaddr, TILEGX_BUNDLE_SIZE_IN_BYTES); - - /* Parse the instructions in the bundle. */ - num_instructions = - parse_insn_tilegx (*(unsigned long long *)opbuf, (unsigned long long)memaddr, decoded); - - /* Print the instructions in the bundle. */ - printf("{ "); - num_printed = 0; - - /* Determine which nop opcode is used for padding and should be skipped. */ - padding_mnemonic = TILEGX_OPC_FNOP; - for (i = 0; i < num_instructions; i++) - { - if (!decoded[i].opcode->can_bundle) - { - /* Instructions that cannot be bundled are padded out with nops, - rather than fnops. Displaying them is always clutter. */ - padding_mnemonic = TILEGX_OPC_NOP; - break; - } - } - - for (i = 0; i < num_instructions; i++) - { - const struct tilegx_opcode *opcode = decoded[i].opcode; - const char *name; - int j; - - /* Do not print out fnops, unless everything is an fnop, in - which case we will print out just the last one. */ - if (opcode->mnemonic == padding_mnemonic - && (num_printed > 0 || i + 1 < num_instructions)) - continue; - - if (num_printed > 0) - printf(" ; "); - ++num_printed; - - name = opcode->name; - if (name == NULL) - name = "<invalid>"; - printf("%s", name); - - for (j = 0; j < opcode->num_operands; j++) - { - unsigned long long num; - const struct tilegx_operand *op; - const char *spr_name; - - if (j > 0) - printf (","); - printf (" "); - - num = decoded[i].operand_values[j]; - - op = decoded[i].operands[j]; - switch (op->type) - { - case TILEGX_OP_TYPE_REGISTER: - printf ("%s", tilegx_register_names[(int)num]); - break; - case TILEGX_OP_TYPE_SPR: - spr_name = get_tilegx_spr_name(num); - if (spr_name != NULL) - printf ("%s", spr_name); - else - printf ("%d", (int)num); - break; - case TILEGX_OP_TYPE_IMMEDIATE: - printf ("%d", (int)num); - break; - case TILEGX_OP_TYPE_ADDRESS: - printf ("0x%016llx", num); - break; - default: - abort (); - } - } - } - printf (" }\n"); - - return TILEGX_BUNDLE_SIZE_IN_BYTES; -} diff --git a/thirdparty/pcre2/src/sljit/sljitNativeTILEGX_64.c b/thirdparty/pcre2/src/sljit/sljitNativeTILEGX_64.c deleted file mode 100644 index 003f43a790..0000000000 --- a/thirdparty/pcre2/src/sljit/sljitNativeTILEGX_64.c +++ /dev/null @@ -1,2555 +0,0 @@ -/* - * Stack-less Just-In-Time compiler - * - * Copyright 2013-2013 Tilera Corporation(jiwang@tilera.com). All rights reserved. - * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* TileGX architecture. */ -/* Contributed by Tilera Corporation. */ -#include "sljitNativeTILEGX-encoder.c" - -#define SIMM_8BIT_MAX (0x7f) -#define SIMM_8BIT_MIN (-0x80) -#define SIMM_16BIT_MAX (0x7fff) -#define SIMM_16BIT_MIN (-0x8000) -#define SIMM_17BIT_MAX (0xffff) -#define SIMM_17BIT_MIN (-0x10000) -#define SIMM_32BIT_MAX (0x7fffffff) -#define SIMM_32BIT_MIN (-0x7fffffff - 1) -#define SIMM_48BIT_MAX (0x7fffffff0000L) -#define SIMM_48BIT_MIN (-0x800000000000L) -#define IMM16(imm) ((imm) & 0xffff) - -#define UIMM_16BIT_MAX (0xffff) - -#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) -#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) -#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) -#define ADDR_TMP (SLJIT_NUMBER_OF_REGISTERS + 5) -#define PIC_ADDR_REG TMP_REG2 - -static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { - 63, 0, 1, 2, 3, 4, 30, 31, 32, 33, 34, 54, 5, 16, 6, 7 -}; - -#define SLJIT_LOCALS_REG_mapped 54 -#define TMP_REG1_mapped 5 -#define TMP_REG2_mapped 16 -#define TMP_REG3_mapped 6 -#define ADDR_TMP_mapped 7 - -/* Flags are keept in volatile registers. */ -#define EQUAL_FLAG 8 -/* And carry flag as well. */ -#define ULESS_FLAG 9 -#define UGREATER_FLAG 10 -#define LESS_FLAG 11 -#define GREATER_FLAG 12 -#define OVERFLOW_FLAG 13 - -#define ZERO 63 -#define RA 55 -#define TMP_EREG1 14 -#define TMP_EREG2 15 - -#define LOAD_DATA 0x01 -#define WORD_DATA 0x00 -#define BYTE_DATA 0x02 -#define HALF_DATA 0x04 -#define INT_DATA 0x06 -#define SIGNED_DATA 0x08 -#define DOUBLE_DATA 0x10 - -/* Separates integer and floating point registers */ -#define GPR_REG 0xf - -#define MEM_MASK 0x1f - -#define WRITE_BACK 0x00020 -#define ARG_TEST 0x00040 -#define ALT_KEEP_CACHE 0x00080 -#define CUMULATIVE_OP 0x00100 -#define LOGICAL_OP 0x00200 -#define IMM_OP 0x00400 -#define SRC2_IMM 0x00800 - -#define UNUSED_DEST 0x01000 -#define REG_DEST 0x02000 -#define REG1_SOURCE 0x04000 -#define REG2_SOURCE 0x08000 -#define SLOW_SRC1 0x10000 -#define SLOW_SRC2 0x20000 -#define SLOW_DEST 0x40000 - -/* Only these flags are set. UNUSED_DEST is not set when no flags should be set. - */ -#define CHECK_FLAGS(list) (!(flags & UNUSED_DEST) || (op & GET_FLAGS(~(list)))) - -SLJIT_API_FUNC_ATTRIBUTE const char *sljit_get_platform_name(void) -{ - return "TileGX" SLJIT_CPUINFO; -} - -/* Length of an instruction word */ -typedef sljit_uw sljit_ins; - -struct jit_instr { - const struct tilegx_opcode* opcode; - tilegx_pipeline pipe; - unsigned long input_registers; - unsigned long output_registers; - int operand_value[4]; - int line; -}; - -/* Opcode Helper Macros */ -#define TILEGX_X_MODE 0 - -#define X_MODE create_Mode(TILEGX_X_MODE) - -#define FNOP_X0 \ - create_Opcode_X0(RRR_0_OPCODE_X0) | \ - create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \ - create_UnaryOpcodeExtension_X0(FNOP_UNARY_OPCODE_X0) - -#define FNOP_X1 \ - create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \ - create_UnaryOpcodeExtension_X1(FNOP_UNARY_OPCODE_X1) - -#define NOP \ - create_Mode(TILEGX_X_MODE) | FNOP_X0 | FNOP_X1 - -#define ANOP_X0 \ - create_Opcode_X0(RRR_0_OPCODE_X0) | \ - create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \ - create_UnaryOpcodeExtension_X0(NOP_UNARY_OPCODE_X0) - -#define BPT create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \ - create_UnaryOpcodeExtension_X1(ILL_UNARY_OPCODE_X1) | \ - create_Dest_X1(0x1C) | create_SrcA_X1(0x25) | ANOP_X0 - -#define ADD_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(ADD_RRR_0_OPCODE_X1) | FNOP_X0 - -#define ADDI_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \ - create_Imm8OpcodeExtension_X1(ADDI_IMM8_OPCODE_X1) | FNOP_X0 - -#define SUB_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(SUB_RRR_0_OPCODE_X1) | FNOP_X0 - -#define NOR_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(NOR_RRR_0_OPCODE_X1) | FNOP_X0 - -#define OR_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(OR_RRR_0_OPCODE_X1) | FNOP_X0 - -#define AND_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(AND_RRR_0_OPCODE_X1) | FNOP_X0 - -#define XOR_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(XOR_RRR_0_OPCODE_X1) | FNOP_X0 - -#define CMOVNEZ_X0 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \ - create_RRROpcodeExtension_X0(CMOVNEZ_RRR_0_OPCODE_X0) | FNOP_X1 - -#define CMOVEQZ_X0 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \ - create_RRROpcodeExtension_X0(CMOVEQZ_RRR_0_OPCODE_X0) | FNOP_X1 - -#define ADDLI_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(ADDLI_OPCODE_X1) | FNOP_X0 - -#define V4INT_L_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(V4INT_L_RRR_0_OPCODE_X1) | FNOP_X0 - -#define BFEXTU_X0 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X0(BF_OPCODE_X0) | \ - create_BFOpcodeExtension_X0(BFEXTU_BF_OPCODE_X0) | FNOP_X1 - -#define BFEXTS_X0 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X0(BF_OPCODE_X0) | \ - create_BFOpcodeExtension_X0(BFEXTS_BF_OPCODE_X0) | FNOP_X1 - -#define SHL16INSLI_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHL16INSLI_OPCODE_X1) | FNOP_X0 - -#define ST_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(ST_RRR_0_OPCODE_X1) | create_Dest_X1(0x0) | FNOP_X0 - -#define LD_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \ - create_UnaryOpcodeExtension_X1(LD_UNARY_OPCODE_X1) | FNOP_X0 - -#define JR_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \ - create_UnaryOpcodeExtension_X1(JR_UNARY_OPCODE_X1) | FNOP_X0 - -#define JALR_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(UNARY_RRR_0_OPCODE_X1) | \ - create_UnaryOpcodeExtension_X1(JALR_UNARY_OPCODE_X1) | FNOP_X0 - -#define CLZ_X0 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X0(RRR_0_OPCODE_X0) | \ - create_RRROpcodeExtension_X0(UNARY_RRR_0_OPCODE_X0) | \ - create_UnaryOpcodeExtension_X0(CNTLZ_UNARY_OPCODE_X0) | FNOP_X1 - -#define CMPLTUI_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \ - create_Imm8OpcodeExtension_X1(CMPLTUI_IMM8_OPCODE_X1) | FNOP_X0 - -#define CMPLTU_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(CMPLTU_RRR_0_OPCODE_X1) | FNOP_X0 - -#define CMPLTS_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(CMPLTS_RRR_0_OPCODE_X1) | FNOP_X0 - -#define XORI_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \ - create_Imm8OpcodeExtension_X1(XORI_IMM8_OPCODE_X1) | FNOP_X0 - -#define ORI_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \ - create_Imm8OpcodeExtension_X1(ORI_IMM8_OPCODE_X1) | FNOP_X0 - -#define ANDI_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(IMM8_OPCODE_X1) | \ - create_Imm8OpcodeExtension_X1(ANDI_IMM8_OPCODE_X1) | FNOP_X0 - -#define SHLI_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \ - create_ShiftOpcodeExtension_X1(SHLI_SHIFT_OPCODE_X1) | FNOP_X0 - -#define SHL_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(SHL_RRR_0_OPCODE_X1) | FNOP_X0 - -#define SHRSI_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \ - create_ShiftOpcodeExtension_X1(SHRSI_SHIFT_OPCODE_X1) | FNOP_X0 - -#define SHRS_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(SHRS_RRR_0_OPCODE_X1) | FNOP_X0 - -#define SHRUI_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(SHIFT_OPCODE_X1) | \ - create_ShiftOpcodeExtension_X1(SHRUI_SHIFT_OPCODE_X1) | FNOP_X0 - -#define SHRU_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(RRR_0_OPCODE_X1) | \ - create_RRROpcodeExtension_X1(SHRU_RRR_0_OPCODE_X1) | FNOP_X0 - -#define BEQZ_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(BRANCH_OPCODE_X1) | \ - create_BrType_X1(BEQZ_BRANCH_OPCODE_X1) | FNOP_X0 - -#define BNEZ_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(BRANCH_OPCODE_X1) | \ - create_BrType_X1(BNEZ_BRANCH_OPCODE_X1) | FNOP_X0 - -#define J_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(JUMP_OPCODE_X1) | \ - create_JumpOpcodeExtension_X1(J_JUMP_OPCODE_X1) | FNOP_X0 - -#define JAL_X1 \ - create_Mode(TILEGX_X_MODE) | create_Opcode_X1(JUMP_OPCODE_X1) | \ - create_JumpOpcodeExtension_X1(JAL_JUMP_OPCODE_X1) | FNOP_X0 - -#define DEST_X0(x) create_Dest_X0(x) -#define SRCA_X0(x) create_SrcA_X0(x) -#define SRCB_X0(x) create_SrcB_X0(x) -#define DEST_X1(x) create_Dest_X1(x) -#define SRCA_X1(x) create_SrcA_X1(x) -#define SRCB_X1(x) create_SrcB_X1(x) -#define IMM16_X1(x) create_Imm16_X1(x) -#define IMM8_X1(x) create_Imm8_X1(x) -#define BFSTART_X0(x) create_BFStart_X0(x) -#define BFEND_X0(x) create_BFEnd_X0(x) -#define SHIFTIMM_X1(x) create_ShAmt_X1(x) -#define JOFF_X1(x) create_JumpOff_X1(x) -#define BOFF_X1(x) create_BrOff_X1(x) - -static const tilegx_mnemonic data_transfer_insts[16] = { - /* u w s */ TILEGX_OPC_ST /* st */, - /* u w l */ TILEGX_OPC_LD /* ld */, - /* u b s */ TILEGX_OPC_ST1 /* st1 */, - /* u b l */ TILEGX_OPC_LD1U /* ld1u */, - /* u h s */ TILEGX_OPC_ST2 /* st2 */, - /* u h l */ TILEGX_OPC_LD2U /* ld2u */, - /* u i s */ TILEGX_OPC_ST4 /* st4 */, - /* u i l */ TILEGX_OPC_LD4U /* ld4u */, - /* s w s */ TILEGX_OPC_ST /* st */, - /* s w l */ TILEGX_OPC_LD /* ld */, - /* s b s */ TILEGX_OPC_ST1 /* st1 */, - /* s b l */ TILEGX_OPC_LD1S /* ld1s */, - /* s h s */ TILEGX_OPC_ST2 /* st2 */, - /* s h l */ TILEGX_OPC_LD2S /* ld2s */, - /* s i s */ TILEGX_OPC_ST4 /* st4 */, - /* s i l */ TILEGX_OPC_LD4S /* ld4s */, -}; - -#ifdef TILEGX_JIT_DEBUG -static sljit_s32 push_inst_debug(struct sljit_compiler *compiler, sljit_ins ins, int line) -{ - sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins)); - FAIL_IF(!ptr); - *ptr = ins; - compiler->size++; - printf("|%04d|S0|:\t\t", line); - print_insn_tilegx(ptr); - return SLJIT_SUCCESS; -} - -static sljit_s32 push_inst_nodebug(struct sljit_compiler *compiler, sljit_ins ins) -{ - sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins)); - FAIL_IF(!ptr); - *ptr = ins; - compiler->size++; - return SLJIT_SUCCESS; -} - -#define push_inst(a, b) push_inst_debug(a, b, __LINE__) -#else -static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins) -{ - sljit_ins *ptr = (sljit_ins *)ensure_buf(compiler, sizeof(sljit_ins)); - FAIL_IF(!ptr); - *ptr = ins; - compiler->size++; - return SLJIT_SUCCESS; -} -#endif - -#define BUNDLE_FORMAT_MASK(p0, p1, p2) \ - ((p0) | ((p1) << 8) | ((p2) << 16)) - -#define BUNDLE_FORMAT(p0, p1, p2) \ - { \ - { \ - (tilegx_pipeline)(p0), \ - (tilegx_pipeline)(p1), \ - (tilegx_pipeline)(p2) \ - }, \ - BUNDLE_FORMAT_MASK(1 << (p0), 1 << (p1), (1 << (p2))) \ - } - -#define NO_PIPELINE TILEGX_NUM_PIPELINE_ENCODINGS - -#define tilegx_is_x_pipeline(p) ((int)(p) <= (int)TILEGX_PIPELINE_X1) - -#define PI(encoding) \ - push_inst(compiler, encoding) - -#define PB3(opcode, dst, srca, srcb) \ - push_3_buffer(compiler, opcode, dst, srca, srcb, __LINE__) - -#define PB2(opcode, dst, src) \ - push_2_buffer(compiler, opcode, dst, src, __LINE__) - -#define JR(reg) \ - push_jr_buffer(compiler, TILEGX_OPC_JR, reg, __LINE__) - -#define ADD(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_ADD, dst, srca, srcb, __LINE__) - -#define SUB(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_SUB, dst, srca, srcb, __LINE__) - -#define MUL(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_MULX, dst, srca, srcb, __LINE__) - -#define NOR(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_NOR, dst, srca, srcb, __LINE__) - -#define OR(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_OR, dst, srca, srcb, __LINE__) - -#define XOR(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_XOR, dst, srca, srcb, __LINE__) - -#define AND(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_AND, dst, srca, srcb, __LINE__) - -#define CLZ(dst, src) \ - push_2_buffer(compiler, TILEGX_OPC_CLZ, dst, src, __LINE__) - -#define SHLI(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_SHLI, dst, srca, srcb, __LINE__) - -#define SHRUI(dst, srca, imm) \ - push_3_buffer(compiler, TILEGX_OPC_SHRUI, dst, srca, imm, __LINE__) - -#define XORI(dst, srca, imm) \ - push_3_buffer(compiler, TILEGX_OPC_XORI, dst, srca, imm, __LINE__) - -#define ORI(dst, srca, imm) \ - push_3_buffer(compiler, TILEGX_OPC_ORI, dst, srca, imm, __LINE__) - -#define CMPLTU(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_CMPLTU, dst, srca, srcb, __LINE__) - -#define CMPLTS(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_CMPLTS, dst, srca, srcb, __LINE__) - -#define CMPLTUI(dst, srca, imm) \ - push_3_buffer(compiler, TILEGX_OPC_CMPLTUI, dst, srca, imm, __LINE__) - -#define CMOVNEZ(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_CMOVNEZ, dst, srca, srcb, __LINE__) - -#define CMOVEQZ(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_CMOVEQZ, dst, srca, srcb, __LINE__) - -#define ADDLI(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_ADDLI, dst, srca, srcb, __LINE__) - -#define SHL16INSLI(dst, srca, srcb) \ - push_3_buffer(compiler, TILEGX_OPC_SHL16INSLI, dst, srca, srcb, __LINE__) - -#define LD_ADD(dst, addr, adjust) \ - push_3_buffer(compiler, TILEGX_OPC_LD_ADD, dst, addr, adjust, __LINE__) - -#define ST_ADD(src, addr, adjust) \ - push_3_buffer(compiler, TILEGX_OPC_ST_ADD, src, addr, adjust, __LINE__) - -#define LD(dst, addr) \ - push_2_buffer(compiler, TILEGX_OPC_LD, dst, addr, __LINE__) - -#define BFEXTU(dst, src, start, end) \ - push_4_buffer(compiler, TILEGX_OPC_BFEXTU, dst, src, start, end, __LINE__) - -#define BFEXTS(dst, src, start, end) \ - push_4_buffer(compiler, TILEGX_OPC_BFEXTS, dst, src, start, end, __LINE__) - -#define ADD_SOLO(dest, srca, srcb) \ - push_inst(compiler, ADD_X1 | DEST_X1(dest) | SRCA_X1(srca) | SRCB_X1(srcb)) - -#define ADDI_SOLO(dest, srca, imm) \ - push_inst(compiler, ADDI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM8_X1(imm)) - -#define ADDLI_SOLO(dest, srca, imm) \ - push_inst(compiler, ADDLI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM16_X1(imm)) - -#define SHL16INSLI_SOLO(dest, srca, imm) \ - push_inst(compiler, SHL16INSLI_X1 | DEST_X1(dest) | SRCA_X1(srca) | IMM16_X1(imm)) - -#define JALR_SOLO(reg) \ - push_inst(compiler, JALR_X1 | SRCA_X1(reg)) - -#define JR_SOLO(reg) \ - push_inst(compiler, JR_X1 | SRCA_X1(reg)) - -struct Format { - /* Mapping of bundle issue slot to assigned pipe. */ - tilegx_pipeline pipe[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]; - - /* Mask of pipes used by this bundle. */ - unsigned int pipe_mask; -}; - -const struct Format formats[] = -{ - /* In Y format we must always have something in Y2, since it has - * no fnop, so this conveys that Y2 must always be used. */ - BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2, NO_PIPELINE), - BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2, NO_PIPELINE), - BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0, NO_PIPELINE), - BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1, NO_PIPELINE), - - /* Y format has three instructions. */ - BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2), - BUNDLE_FORMAT(TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1), - BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y2), - BUNDLE_FORMAT(TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0), - BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y0, TILEGX_PIPELINE_Y1), - BUNDLE_FORMAT(TILEGX_PIPELINE_Y2, TILEGX_PIPELINE_Y1, TILEGX_PIPELINE_Y0), - - /* X format has only two instructions. */ - BUNDLE_FORMAT(TILEGX_PIPELINE_X0, TILEGX_PIPELINE_X1, NO_PIPELINE), - BUNDLE_FORMAT(TILEGX_PIPELINE_X1, TILEGX_PIPELINE_X0, NO_PIPELINE) -}; - - -struct jit_instr inst_buf[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]; -unsigned long inst_buf_index; - -tilegx_pipeline get_any_valid_pipe(const struct tilegx_opcode* opcode) -{ - /* FIXME: tile: we could pregenerate this. */ - int pipe; - for (pipe = 0; ((opcode->pipes & (1 << pipe)) == 0 && pipe < TILEGX_NUM_PIPELINE_ENCODINGS); pipe++) - ; - return (tilegx_pipeline)(pipe); -} - -void insert_nop(tilegx_mnemonic opc, int line) -{ - const struct tilegx_opcode* opcode = NULL; - - memmove(&inst_buf[1], &inst_buf[0], inst_buf_index * sizeof inst_buf[0]); - - opcode = &tilegx_opcodes[opc]; - inst_buf[0].opcode = opcode; - inst_buf[0].pipe = get_any_valid_pipe(opcode); - inst_buf[0].input_registers = 0; - inst_buf[0].output_registers = 0; - inst_buf[0].line = line; - ++inst_buf_index; -} - -const struct Format* compute_format() -{ - unsigned int compatible_pipes = BUNDLE_FORMAT_MASK( - inst_buf[0].opcode->pipes, - inst_buf[1].opcode->pipes, - (inst_buf_index == 3 ? inst_buf[2].opcode->pipes : (1 << NO_PIPELINE))); - - const struct Format* match = NULL; - const struct Format *b = NULL; - unsigned int i; - for (i = 0; i < sizeof formats / sizeof formats[0]; i++) { - b = &formats[i]; - if ((b->pipe_mask & compatible_pipes) == b->pipe_mask) { - match = b; - break; - } - } - - return match; -} - -sljit_s32 assign_pipes() -{ - unsigned long output_registers = 0; - unsigned int i = 0; - - if (inst_buf_index == 1) { - tilegx_mnemonic opc = inst_buf[0].opcode->can_bundle - ? TILEGX_OPC_FNOP : TILEGX_OPC_NOP; - insert_nop(opc, __LINE__); - } - - const struct Format* match = compute_format(); - - if (match == NULL) - return -1; - - for (i = 0; i < inst_buf_index; i++) { - - if ((i > 0) && ((inst_buf[i].input_registers & output_registers) != 0)) - return -1; - - if ((i > 0) && ((inst_buf[i].output_registers & output_registers) != 0)) - return -1; - - /* Don't include Rzero in the match set, to avoid triggering - needlessly on 'prefetch' instrs. */ - - output_registers |= inst_buf[i].output_registers & 0xFFFFFFFFFFFFFFL; - - inst_buf[i].pipe = match->pipe[i]; - } - - /* If only 2 instrs, and in Y-mode, insert a nop. */ - if (inst_buf_index == 2 && !tilegx_is_x_pipeline(match->pipe[0])) { - insert_nop(TILEGX_OPC_FNOP, __LINE__); - - /* Select the yet unassigned pipe. */ - tilegx_pipeline pipe = (tilegx_pipeline)(((TILEGX_PIPELINE_Y0 - + TILEGX_PIPELINE_Y1 + TILEGX_PIPELINE_Y2) - - (inst_buf[1].pipe + inst_buf[2].pipe))); - - inst_buf[0].pipe = pipe; - } - - return 0; -} - -tilegx_bundle_bits get_bundle_bit(struct jit_instr *inst) -{ - int i, val; - const struct tilegx_opcode* opcode = inst->opcode; - tilegx_bundle_bits bits = opcode->fixed_bit_values[inst->pipe]; - - const struct tilegx_operand* operand = NULL; - for (i = 0; i < opcode->num_operands; i++) { - operand = &tilegx_operands[opcode->operands[inst->pipe][i]]; - val = inst->operand_value[i]; - - bits |= operand->insert(val); - } - - return bits; -} - -static sljit_s32 update_buffer(struct sljit_compiler *compiler) -{ - int i; - int orig_index = inst_buf_index; - struct jit_instr inst0 = inst_buf[0]; - struct jit_instr inst1 = inst_buf[1]; - struct jit_instr inst2 = inst_buf[2]; - tilegx_bundle_bits bits = 0; - - /* If the bundle is valid as is, perform the encoding and return 1. */ - if (assign_pipes() == 0) { - for (i = 0; i < inst_buf_index; i++) { - bits |= get_bundle_bit(inst_buf + i); -#ifdef TILEGX_JIT_DEBUG - printf("|%04d", inst_buf[i].line); -#endif - } -#ifdef TILEGX_JIT_DEBUG - if (inst_buf_index == 3) - printf("|M0|:\t"); - else - printf("|M0|:\t\t"); - print_insn_tilegx(&bits); -#endif - - inst_buf_index = 0; - -#ifdef TILEGX_JIT_DEBUG - return push_inst_nodebug(compiler, bits); -#else - return push_inst(compiler, bits); -#endif - } - - /* If the bundle is invalid, split it in two. First encode the first two - (or possibly 1) instructions, and then the last, separately. Note that - assign_pipes may have re-ordered the instrs (by inserting no-ops in - lower slots) so we need to reset them. */ - - inst_buf_index = orig_index - 1; - inst_buf[0] = inst0; - inst_buf[1] = inst1; - inst_buf[2] = inst2; - if (assign_pipes() == 0) { - for (i = 0; i < inst_buf_index; i++) { - bits |= get_bundle_bit(inst_buf + i); -#ifdef TILEGX_JIT_DEBUG - printf("|%04d", inst_buf[i].line); -#endif - } - -#ifdef TILEGX_JIT_DEBUG - if (inst_buf_index == 3) - printf("|M1|:\t"); - else - printf("|M1|:\t\t"); - print_insn_tilegx(&bits); -#endif - - if ((orig_index - 1) == 2) { - inst_buf[0] = inst2; - inst_buf_index = 1; - } else if ((orig_index - 1) == 1) { - inst_buf[0] = inst1; - inst_buf_index = 1; - } else - SLJIT_UNREACHABLE(); - -#ifdef TILEGX_JIT_DEBUG - return push_inst_nodebug(compiler, bits); -#else - return push_inst(compiler, bits); -#endif - } else { - /* We had 3 instrs of which the first 2 can't live in the same bundle. - Split those two. Note that we don't try to then combine the second - and third instr into a single bundle. First instruction: */ - inst_buf_index = 1; - inst_buf[0] = inst0; - inst_buf[1] = inst1; - inst_buf[2] = inst2; - if (assign_pipes() == 0) { - for (i = 0; i < inst_buf_index; i++) { - bits |= get_bundle_bit(inst_buf + i); -#ifdef TILEGX_JIT_DEBUG - printf("|%04d", inst_buf[i].line); -#endif - } - -#ifdef TILEGX_JIT_DEBUG - if (inst_buf_index == 3) - printf("|M2|:\t"); - else - printf("|M2|:\t\t"); - print_insn_tilegx(&bits); -#endif - - inst_buf[0] = inst1; - inst_buf[1] = inst2; - inst_buf_index = orig_index - 1; -#ifdef TILEGX_JIT_DEBUG - return push_inst_nodebug(compiler, bits); -#else - return push_inst(compiler, bits); -#endif - } else - SLJIT_UNREACHABLE(); - } - - SLJIT_UNREACHABLE(); -} - -static sljit_s32 flush_buffer(struct sljit_compiler *compiler) -{ - while (inst_buf_index != 0) { - FAIL_IF(update_buffer(compiler)); - } - return SLJIT_SUCCESS; -} - -static sljit_s32 push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line) -{ - if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) - FAIL_IF(update_buffer(compiler)); - - const struct tilegx_opcode* opcode = &tilegx_opcodes[opc]; - inst_buf[inst_buf_index].opcode = opcode; - inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode); - inst_buf[inst_buf_index].operand_value[0] = op0; - inst_buf[inst_buf_index].operand_value[1] = op1; - inst_buf[inst_buf_index].operand_value[2] = op2; - inst_buf[inst_buf_index].operand_value[3] = op3; - inst_buf[inst_buf_index].input_registers = 1L << op1; - inst_buf[inst_buf_index].output_registers = 1L << op0; - inst_buf[inst_buf_index].line = line; - inst_buf_index++; - - return SLJIT_SUCCESS; -} - -static sljit_s32 push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int line) -{ - if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) - FAIL_IF(update_buffer(compiler)); - - const struct tilegx_opcode* opcode = &tilegx_opcodes[opc]; - inst_buf[inst_buf_index].opcode = opcode; - inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode); - inst_buf[inst_buf_index].operand_value[0] = op0; - inst_buf[inst_buf_index].operand_value[1] = op1; - inst_buf[inst_buf_index].operand_value[2] = op2; - inst_buf[inst_buf_index].line = line; - - switch (opc) { - case TILEGX_OPC_ST_ADD: - inst_buf[inst_buf_index].input_registers = (1L << op0) | (1L << op1); - inst_buf[inst_buf_index].output_registers = 1L << op0; - break; - case TILEGX_OPC_LD_ADD: - inst_buf[inst_buf_index].input_registers = 1L << op1; - inst_buf[inst_buf_index].output_registers = (1L << op0) | (1L << op1); - break; - case TILEGX_OPC_ADD: - case TILEGX_OPC_AND: - case TILEGX_OPC_SUB: - case TILEGX_OPC_MULX: - case TILEGX_OPC_OR: - case TILEGX_OPC_XOR: - case TILEGX_OPC_NOR: - case TILEGX_OPC_SHL: - case TILEGX_OPC_SHRU: - case TILEGX_OPC_SHRS: - case TILEGX_OPC_CMPLTU: - case TILEGX_OPC_CMPLTS: - case TILEGX_OPC_CMOVEQZ: - case TILEGX_OPC_CMOVNEZ: - inst_buf[inst_buf_index].input_registers = (1L << op1) | (1L << op2); - inst_buf[inst_buf_index].output_registers = 1L << op0; - break; - case TILEGX_OPC_ADDLI: - case TILEGX_OPC_XORI: - case TILEGX_OPC_ORI: - case TILEGX_OPC_SHLI: - case TILEGX_OPC_SHRUI: - case TILEGX_OPC_SHRSI: - case TILEGX_OPC_SHL16INSLI: - case TILEGX_OPC_CMPLTUI: - case TILEGX_OPC_CMPLTSI: - inst_buf[inst_buf_index].input_registers = 1L << op1; - inst_buf[inst_buf_index].output_registers = 1L << op0; - break; - default: - printf("unrecoginzed opc: %s\n", opcode->name); - SLJIT_UNREACHABLE(); - } - - inst_buf_index++; - - return SLJIT_SUCCESS; -} - -static sljit_s32 push_2_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int line) -{ - if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) - FAIL_IF(update_buffer(compiler)); - - const struct tilegx_opcode* opcode = &tilegx_opcodes[opc]; - inst_buf[inst_buf_index].opcode = opcode; - inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode); - inst_buf[inst_buf_index].operand_value[0] = op0; - inst_buf[inst_buf_index].operand_value[1] = op1; - inst_buf[inst_buf_index].line = line; - - switch (opc) { - case TILEGX_OPC_BEQZ: - case TILEGX_OPC_BNEZ: - inst_buf[inst_buf_index].input_registers = 1L << op0; - break; - case TILEGX_OPC_ST: - case TILEGX_OPC_ST1: - case TILEGX_OPC_ST2: - case TILEGX_OPC_ST4: - inst_buf[inst_buf_index].input_registers = (1L << op0) | (1L << op1); - inst_buf[inst_buf_index].output_registers = 0; - break; - case TILEGX_OPC_CLZ: - case TILEGX_OPC_LD: - case TILEGX_OPC_LD1U: - case TILEGX_OPC_LD1S: - case TILEGX_OPC_LD2U: - case TILEGX_OPC_LD2S: - case TILEGX_OPC_LD4U: - case TILEGX_OPC_LD4S: - inst_buf[inst_buf_index].input_registers = 1L << op1; - inst_buf[inst_buf_index].output_registers = 1L << op0; - break; - default: - printf("unrecoginzed opc: %s\n", opcode->name); - SLJIT_UNREACHABLE(); - } - - inst_buf_index++; - - return SLJIT_SUCCESS; -} - -static sljit_s32 push_0_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int line) -{ - if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) - FAIL_IF(update_buffer(compiler)); - - const struct tilegx_opcode* opcode = &tilegx_opcodes[opc]; - inst_buf[inst_buf_index].opcode = opcode; - inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode); - inst_buf[inst_buf_index].input_registers = 0; - inst_buf[inst_buf_index].output_registers = 0; - inst_buf[inst_buf_index].line = line; - inst_buf_index++; - - return SLJIT_SUCCESS; -} - -static sljit_s32 push_jr_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int line) -{ - if (inst_buf_index == TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE) - FAIL_IF(update_buffer(compiler)); - - const struct tilegx_opcode* opcode = &tilegx_opcodes[opc]; - inst_buf[inst_buf_index].opcode = opcode; - inst_buf[inst_buf_index].pipe = get_any_valid_pipe(opcode); - inst_buf[inst_buf_index].operand_value[0] = op0; - inst_buf[inst_buf_index].input_registers = 1L << op0; - inst_buf[inst_buf_index].output_registers = 0; - inst_buf[inst_buf_index].line = line; - inst_buf_index++; - - return flush_buffer(compiler); -} - -static SLJIT_INLINE sljit_ins * detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code) -{ - sljit_sw diff; - sljit_uw target_addr; - sljit_ins *inst; - - if (jump->flags & SLJIT_REWRITABLE_JUMP) - return code_ptr; - - if (jump->flags & JUMP_ADDR) - target_addr = jump->u.target; - else { - SLJIT_ASSERT(jump->flags & JUMP_LABEL); - target_addr = (sljit_uw)(code + jump->u.label->size); - } - - inst = (sljit_ins *)jump->addr; - if (jump->flags & IS_COND) - inst--; - - diff = ((sljit_sw) target_addr - (sljit_sw) inst) >> 3; - if (diff <= SIMM_17BIT_MAX && diff >= SIMM_17BIT_MIN) { - jump->flags |= PATCH_B; - - if (!(jump->flags & IS_COND)) { - if (jump->flags & IS_JAL) { - jump->flags &= ~(PATCH_B); - jump->flags |= PATCH_J; - inst[0] = JAL_X1; - -#ifdef TILEGX_JIT_DEBUG - printf("[runtime relocate]%04d:\t", __LINE__); - print_insn_tilegx(inst); -#endif - } else { - inst[0] = BEQZ_X1 | SRCA_X1(ZERO); - -#ifdef TILEGX_JIT_DEBUG - printf("[runtime relocate]%04d:\t", __LINE__); - print_insn_tilegx(inst); -#endif - } - - return inst; - } - - inst[0] = inst[0] ^ (0x7L << 55); - -#ifdef TILEGX_JIT_DEBUG - printf("[runtime relocate]%04d:\t", __LINE__); - print_insn_tilegx(inst); -#endif - jump->addr -= sizeof(sljit_ins); - return inst; - } - - if (jump->flags & IS_COND) { - if ((target_addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL)) { - jump->flags |= PATCH_J; - inst[0] = (inst[0] & ~(BOFF_X1(-1))) | BOFF_X1(2); - inst[1] = J_X1; - return inst + 1; - } - - return code_ptr; - } - - if ((target_addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL)) { - jump->flags |= PATCH_J; - - if (jump->flags & IS_JAL) { - inst[0] = JAL_X1; - -#ifdef TILEGX_JIT_DEBUG - printf("[runtime relocate]%04d:\t", __LINE__); - print_insn_tilegx(inst); -#endif - - } else { - inst[0] = J_X1; - -#ifdef TILEGX_JIT_DEBUG - printf("[runtime relocate]%04d:\t", __LINE__); - print_insn_tilegx(inst); -#endif - } - - return inst; - } - - return code_ptr; -} - -SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compiler) -{ - 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_uw addr; - - struct sljit_label *label; - struct sljit_jump *jump; - struct sljit_const *const_; - - CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_generate_code(compiler)); - reverse_buf(compiler); - - code = (sljit_ins *)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); - PTR_FAIL_WITH_EXEC_IF(code); - buf = compiler->buf; - - code_ptr = code; - word_count = 0; - label = compiler->labels; - jump = compiler->jumps; - const_ = compiler->consts; - do { - buf_ptr = (sljit_ins *)buf->memory; - buf_end = buf_ptr + (buf->used_size >> 3); - do { - *code_ptr = *buf_ptr++; - SLJIT_ASSERT(!label || label->size >= word_count); - SLJIT_ASSERT(!jump || jump->addr >= word_count); - SLJIT_ASSERT(!const_ || const_->addr >= word_count); - /* These structures are ordered by their address. */ - if (label && label->size == word_count) { - /* Just recording the address. */ - label->addr = (sljit_uw) code_ptr; - label->size = code_ptr - code; - label = label->next; - } - - if (jump && jump->addr == word_count) { - if (jump->flags & IS_JAL) - jump->addr = (sljit_uw)(code_ptr - 4); - else - jump->addr = (sljit_uw)(code_ptr - 3); - - code_ptr = detect_jump_type(jump, code_ptr, code); - jump = jump->next; - } - - if (const_ && const_->addr == word_count) { - /* Just recording the address. */ - const_->addr = (sljit_uw) code_ptr; - const_ = const_->next; - } - - code_ptr++; - word_count++; - } while (buf_ptr < buf_end); - - buf = buf->next; - } while (buf); - - if (label && label->size == word_count) { - label->addr = (sljit_uw) code_ptr; - label->size = code_ptr - code; - label = label->next; - } - - SLJIT_ASSERT(!label); - SLJIT_ASSERT(!jump); - SLJIT_ASSERT(!const_); - SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size); - - jump = compiler->jumps; - while (jump) { - do { - addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target; - buf_ptr = (sljit_ins *)jump->addr; - - if (jump->flags & PATCH_B) { - addr = (sljit_sw)(addr - (jump->addr)) >> 3; - SLJIT_ASSERT((sljit_sw) addr <= SIMM_17BIT_MAX && (sljit_sw) addr >= SIMM_17BIT_MIN); - buf_ptr[0] = (buf_ptr[0] & ~(BOFF_X1(-1))) | BOFF_X1(addr); - -#ifdef TILEGX_JIT_DEBUG - printf("[runtime relocate]%04d:\t", __LINE__); - print_insn_tilegx(buf_ptr); -#endif - break; - } - - if (jump->flags & PATCH_J) { - SLJIT_ASSERT((addr & ~0x3FFFFFFFL) == ((jump->addr + sizeof(sljit_ins)) & ~0x3FFFFFFFL)); - addr = (sljit_sw)(addr - (jump->addr)) >> 3; - buf_ptr[0] = (buf_ptr[0] & ~(JOFF_X1(-1))) | JOFF_X1(addr); - -#ifdef TILEGX_JIT_DEBUG - printf("[runtime relocate]%04d:\t", __LINE__); - print_insn_tilegx(buf_ptr); -#endif - break; - } - - SLJIT_ASSERT(!(jump->flags & IS_JAL)); - - /* Set the fields of immediate loads. */ - buf_ptr[0] = (buf_ptr[0] & ~(0xFFFFL << 43)) | (((addr >> 32) & 0xFFFFL) << 43); - buf_ptr[1] = (buf_ptr[1] & ~(0xFFFFL << 43)) | (((addr >> 16) & 0xFFFFL) << 43); - buf_ptr[2] = (buf_ptr[2] & ~(0xFFFFL << 43)) | ((addr & 0xFFFFL) << 43); - } while (0); - - jump = jump->next; - } - - compiler->error = SLJIT_ERR_COMPILED; - compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins); - SLJIT_CACHE_FLUSH(code, code_ptr); - return code; -} - -static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm) -{ - - if (imm <= SIMM_16BIT_MAX && imm >= SIMM_16BIT_MIN) - return ADDLI(dst_ar, ZERO, imm); - - if (imm <= SIMM_32BIT_MAX && imm >= SIMM_32BIT_MIN) { - FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 16)); - return SHL16INSLI(dst_ar, dst_ar, imm); - } - - if (imm <= SIMM_48BIT_MAX && imm >= SIMM_48BIT_MIN) { - FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 32)); - FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16)); - return SHL16INSLI(dst_ar, dst_ar, imm); - } - - FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 48)); - FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 32)); - FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16)); - return SHL16INSLI(dst_ar, dst_ar, imm); -} - -static sljit_s32 emit_const(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm, int flush) -{ - /* Should *not* be optimized as load_immediate, as pcre relocation - mechanism will match this fixed 4-instruction pattern. */ - if (flush) { - FAIL_IF(ADDLI_SOLO(dst_ar, ZERO, imm >> 32)); - FAIL_IF(SHL16INSLI_SOLO(dst_ar, dst_ar, imm >> 16)); - return SHL16INSLI_SOLO(dst_ar, dst_ar, imm); - } - - FAIL_IF(ADDLI(dst_ar, ZERO, imm >> 32)); - FAIL_IF(SHL16INSLI(dst_ar, dst_ar, imm >> 16)); - return SHL16INSLI(dst_ar, dst_ar, imm); -} - -static sljit_s32 emit_const_64(struct sljit_compiler *compiler, sljit_s32 dst_ar, sljit_sw imm, int flush) -{ - /* Should *not* be optimized as load_immediate, as pcre relocation - mechanism will match this fixed 4-instruction pattern. */ - if (flush) { - FAIL_IF(ADDLI_SOLO(reg_map[dst_ar], ZERO, imm >> 48)); - FAIL_IF(SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm >> 32)); - FAIL_IF(SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm >> 16)); - return SHL16INSLI_SOLO(reg_map[dst_ar], reg_map[dst_ar], imm); - } - - FAIL_IF(ADDLI(reg_map[dst_ar], ZERO, imm >> 48)); - FAIL_IF(SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm >> 32)); - FAIL_IF(SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm >> 16)); - return SHL16INSLI(reg_map[dst_ar], reg_map[dst_ar], imm); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, - sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) -{ - sljit_ins base; - sljit_s32 i, tmp; - - CHECK_ERROR(); - CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); - - local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); - local_size = (local_size + 7) & ~7; - compiler->local_size = local_size; - - if (local_size <= SIMM_16BIT_MAX) { - /* Frequent case. */ - FAIL_IF(ADDLI(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, -local_size)); - base = SLJIT_LOCALS_REG_mapped; - } else { - FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, local_size)); - FAIL_IF(ADD(TMP_REG2_mapped, SLJIT_LOCALS_REG_mapped, ZERO)); - FAIL_IF(SUB(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped)); - base = TMP_REG2_mapped; - local_size = 0; - } - - /* Save the return address. */ - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8)); - FAIL_IF(ST_ADD(ADDR_TMP_mapped, RA, -8)); - - /* Save the S registers. */ - tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; - for (i = SLJIT_S0; i >= tmp; i--) { - FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8)); - } - - /* Save the R registers that need to be reserved. */ - for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { - FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8)); - } - - /* Move the arguments to S registers. */ - for (i = 0; i < args; i++) { - FAIL_IF(ADD(reg_map[SLJIT_S0 - i], i, ZERO)); - } - - return SLJIT_SUCCESS; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler, - sljit_s32 options, sljit_s32 args, sljit_s32 scratches, sljit_s32 saveds, - sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size) -{ - CHECK_ERROR(); - CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); - set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); - - local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); - compiler->local_size = (local_size + 7) & ~7; - - return SLJIT_SUCCESS; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw) -{ - sljit_s32 local_size; - sljit_ins base; - sljit_s32 i, tmp; - sljit_s32 saveds; - - CHECK_ERROR(); - CHECK(check_sljit_emit_return(compiler, op, src, srcw)); - - FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); - - local_size = compiler->local_size; - if (local_size <= SIMM_16BIT_MAX) - base = SLJIT_LOCALS_REG_mapped; - else { - FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, local_size)); - FAIL_IF(ADD(TMP_REG1_mapped, SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped)); - base = TMP_REG1_mapped; - local_size = 0; - } - - /* Restore the return address. */ - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8)); - FAIL_IF(LD_ADD(RA, ADDR_TMP_mapped, -8)); - - /* Restore the S registers. */ - saveds = compiler->saveds; - tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; - for (i = SLJIT_S0; i >= tmp; i--) { - FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8)); - } - - /* Restore the R registers that need to be reserved. */ - for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { - FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8)); - } - - if (compiler->local_size <= SIMM_16BIT_MAX) - FAIL_IF(ADDLI(SLJIT_LOCALS_REG_mapped, SLJIT_LOCALS_REG_mapped, compiler->local_size)); - else - FAIL_IF(ADD(SLJIT_LOCALS_REG_mapped, TMP_REG1_mapped, ZERO)); - - return JR(RA); -} - -/* reg_ar is an absoulute register! */ - -/* Can perform an operation using at most 1 instruction. */ -static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw) -{ - SLJIT_ASSERT(arg & SLJIT_MEM); - - if ((!(flags & WRITE_BACK) || !(arg & REG_MASK)) - && !(arg & OFFS_REG_MASK) && argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) { - /* Works for both absoulte and relative addresses. */ - if (SLJIT_UNLIKELY(flags & ARG_TEST)) - return 1; - - FAIL_IF(ADDLI(ADDR_TMP_mapped, reg_map[arg & REG_MASK], argw)); - - if (flags & LOAD_DATA) - FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, ADDR_TMP_mapped)); - else - FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], ADDR_TMP_mapped, reg_ar)); - - return -1; - } - - return 0; -} - -/* See getput_arg below. - Note: can_cache is called only for binary operators. Those - operators always uses word arguments without write back. */ -static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) -{ - SLJIT_ASSERT((arg & SLJIT_MEM) && (next_arg & SLJIT_MEM)); - - /* Simple operation except for updates. */ - if (arg & OFFS_REG_MASK) { - argw &= 0x3; - next_argw &= 0x3; - if (argw && argw == next_argw - && (arg == next_arg || (arg & OFFS_REG_MASK) == (next_arg & OFFS_REG_MASK))) - return 1; - return 0; - } - - if (arg == next_arg) { - if (((next_argw - argw) <= SIMM_16BIT_MAX - && (next_argw - argw) >= SIMM_16BIT_MIN)) - return 1; - - return 0; - } - - return 0; -} - -/* Emit the necessary instructions. See can_cache above. */ -static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw) -{ - sljit_s32 tmp_ar, base; - - SLJIT_ASSERT(arg & SLJIT_MEM); - if (!(next_arg & SLJIT_MEM)) { - next_arg = 0; - next_argw = 0; - } - - if ((flags & MEM_MASK) <= GPR_REG && (flags & LOAD_DATA)) - tmp_ar = reg_ar; - else - tmp_ar = TMP_REG1_mapped; - - base = arg & REG_MASK; - - if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) { - argw &= 0x3; - - if ((flags & WRITE_BACK) && reg_ar == reg_map[base]) { - SLJIT_ASSERT(!(flags & LOAD_DATA) && reg_map[TMP_REG1] != reg_ar); - FAIL_IF(ADD(TMP_REG1_mapped, reg_ar, ZERO)); - reg_ar = TMP_REG1_mapped; - } - - /* Using the cache. */ - if (argw == compiler->cache_argw) { - if (!(flags & WRITE_BACK)) { - if (arg == compiler->cache_arg) { - if (flags & LOAD_DATA) - return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped); - else - return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar); - } - - if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) { - if (arg == next_arg && argw == (next_argw & 0x3)) { - compiler->cache_arg = arg; - compiler->cache_argw = argw; - FAIL_IF(ADD(TMP_REG3_mapped, reg_map[base], TMP_REG3_mapped)); - if (flags & LOAD_DATA) - return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped); - else - return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar); - } - - FAIL_IF(ADD(tmp_ar, reg_map[base], TMP_REG3_mapped)); - if (flags & LOAD_DATA) - return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar); - else - return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar); - } - } else { - if ((SLJIT_MEM | (arg & OFFS_REG_MASK)) == compiler->cache_arg) { - FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped)); - if (flags & LOAD_DATA) - return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]); - else - return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar); - } - } - } - - if (SLJIT_UNLIKELY(argw)) { - compiler->cache_arg = SLJIT_MEM | (arg & OFFS_REG_MASK); - compiler->cache_argw = argw; - FAIL_IF(SHLI(TMP_REG3_mapped, reg_map[OFFS_REG(arg)], argw)); - } - - if (!(flags & WRITE_BACK)) { - if (arg == next_arg && argw == (next_argw & 0x3)) { - compiler->cache_arg = arg; - compiler->cache_argw = argw; - FAIL_IF(ADD(TMP_REG3_mapped, reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3])); - tmp_ar = TMP_REG3_mapped; - } else - FAIL_IF(ADD(tmp_ar, reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3])); - - if (flags & LOAD_DATA) - return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar); - else - return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar); - } - - FAIL_IF(ADD(reg_map[base], reg_map[base], reg_map[!argw ? OFFS_REG(arg) : TMP_REG3])); - - if (flags & LOAD_DATA) - return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]); - else - return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar); - } - - if (SLJIT_UNLIKELY(flags & WRITE_BACK) && base) { - /* Update only applies if a base register exists. */ - if (reg_ar == reg_map[base]) { - SLJIT_ASSERT(!(flags & LOAD_DATA) && TMP_REG1_mapped != reg_ar); - if (argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, reg_map[base], argw)); - if (flags & LOAD_DATA) - FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, ADDR_TMP_mapped)); - else - FAIL_IF(PB2(data_transfer_insts[flags & MEM_MASK], ADDR_TMP_mapped, reg_ar)); - - if (argw) - return ADDLI(reg_map[base], reg_map[base], argw); - - return SLJIT_SUCCESS; - } - - FAIL_IF(ADD(TMP_REG1_mapped, reg_ar, ZERO)); - reg_ar = TMP_REG1_mapped; - } - - if (argw <= SIMM_16BIT_MAX && argw >= SIMM_16BIT_MIN) { - if (argw) - FAIL_IF(ADDLI(reg_map[base], reg_map[base], argw)); - } else { - if (compiler->cache_arg == SLJIT_MEM - && argw - compiler->cache_argw <= SIMM_16BIT_MAX - && argw - compiler->cache_argw >= SIMM_16BIT_MIN) { - if (argw != compiler->cache_argw) { - FAIL_IF(ADD(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw)); - compiler->cache_argw = argw; - } - - FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped)); - } else { - compiler->cache_arg = SLJIT_MEM; - compiler->cache_argw = argw; - FAIL_IF(load_immediate(compiler, TMP_REG3_mapped, argw)); - FAIL_IF(ADD(reg_map[base], reg_map[base], TMP_REG3_mapped)); - } - } - - if (flags & LOAD_DATA) - return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, reg_map[base]); - else - return PB2(data_transfer_insts[flags & MEM_MASK], reg_map[base], reg_ar); - } - - if (compiler->cache_arg == arg - && argw - compiler->cache_argw <= SIMM_16BIT_MAX - && argw - compiler->cache_argw >= SIMM_16BIT_MIN) { - if (argw != compiler->cache_argw) { - FAIL_IF(ADDLI(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw)); - compiler->cache_argw = argw; - } - - if (flags & LOAD_DATA) - return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped); - else - return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar); - } - - if (compiler->cache_arg == SLJIT_MEM - && argw - compiler->cache_argw <= SIMM_16BIT_MAX - && argw - compiler->cache_argw >= SIMM_16BIT_MIN) { - if (argw != compiler->cache_argw) - FAIL_IF(ADDLI(TMP_REG3_mapped, TMP_REG3_mapped, argw - compiler->cache_argw)); - } else { - compiler->cache_arg = SLJIT_MEM; - FAIL_IF(load_immediate(compiler, TMP_REG3_mapped, argw)); - } - - compiler->cache_argw = argw; - - if (!base) { - if (flags & LOAD_DATA) - return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped); - else - return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar); - } - - if (arg == next_arg - && next_argw - argw <= SIMM_16BIT_MAX - && next_argw - argw >= SIMM_16BIT_MIN) { - compiler->cache_arg = arg; - FAIL_IF(ADD(TMP_REG3_mapped, TMP_REG3_mapped, reg_map[base])); - if (flags & LOAD_DATA) - return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, TMP_REG3_mapped); - else - return PB2(data_transfer_insts[flags & MEM_MASK], TMP_REG3_mapped, reg_ar); - } - - FAIL_IF(ADD(tmp_ar, TMP_REG3_mapped, reg_map[base])); - - if (flags & LOAD_DATA) - return PB2(data_transfer_insts[flags & MEM_MASK], reg_ar, tmp_ar); - else - return PB2(data_transfer_insts[flags & MEM_MASK], tmp_ar, reg_ar); -} - -static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw) -{ - if (getput_arg_fast(compiler, flags, reg_ar, arg, argw)) - return compiler->error; - - compiler->cache_arg = 0; - compiler->cache_argw = 0; - return getput_arg(compiler, flags, reg_ar, arg, argw, 0, 0); -} - -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) -{ - if (getput_arg_fast(compiler, flags, reg, arg1, arg1w)) - return compiler->error; - return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); - ADJUST_LOCAL_OFFSET(dst, dstw); - - /* For UNUSED dst. Uncommon, but possible. */ - if (dst == SLJIT_UNUSED) - return SLJIT_SUCCESS; - - if (FAST_IS_REG(dst)) - return ADD(reg_map[dst], RA, ZERO); - - /* Memory. */ - return emit_op_mem(compiler, WORD_DATA, RA, dst, dstw); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); - - if (FAST_IS_REG(src)) - FAIL_IF(ADD(RA, reg_map[src], ZERO)); - - else if (src & SLJIT_MEM) - FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RA, src, srcw)); - - else if (src & SLJIT_IMM) - FAIL_IF(load_immediate(compiler, RA, srcw)); - - return JR(RA); -} - -static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_s32 src1, sljit_sw src2) -{ - sljit_s32 overflow_ra = 0; - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - case SLJIT_MOV_P: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if (dst != src2) - return ADD(reg_map[dst], reg_map[src2], ZERO); - return SLJIT_SUCCESS; - - case SLJIT_MOV_U32: - case SLJIT_MOV_S32: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { - if (op == SLJIT_MOV_S32) - return BFEXTS(reg_map[dst], reg_map[src2], 0, 31); - - return BFEXTU(reg_map[dst], reg_map[src2], 0, 31); - } else if (dst != src2) { - SLJIT_ASSERT(src2 == 0); - return ADD(reg_map[dst], reg_map[src2], ZERO); - } - - return SLJIT_SUCCESS; - - case SLJIT_MOV_U8: - case SLJIT_MOV_S8: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { - if (op == SLJIT_MOV_S8) - return BFEXTS(reg_map[dst], reg_map[src2], 0, 7); - - return BFEXTU(reg_map[dst], reg_map[src2], 0, 7); - } else if (dst != src2) { - SLJIT_ASSERT(src2 == 0); - return ADD(reg_map[dst], reg_map[src2], ZERO); - } - - return SLJIT_SUCCESS; - - case SLJIT_MOV_U16: - case SLJIT_MOV_S16: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) { - if (op == SLJIT_MOV_S16) - return BFEXTS(reg_map[dst], reg_map[src2], 0, 15); - - return BFEXTU(reg_map[dst], reg_map[src2], 0, 15); - } else if (dst != src2) { - SLJIT_ASSERT(src2 == 0); - return ADD(reg_map[dst], reg_map[src2], ZERO); - } - - return SLJIT_SUCCESS; - - case SLJIT_NOT: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if (op & SLJIT_SET_E) - FAIL_IF(NOR(EQUAL_FLAG, reg_map[src2], reg_map[src2])); - if (CHECK_FLAGS(SLJIT_SET_E)) - FAIL_IF(NOR(reg_map[dst], reg_map[src2], reg_map[src2])); - - return SLJIT_SUCCESS; - - case SLJIT_CLZ: - SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM)); - if (op & SLJIT_SET_E) - FAIL_IF(CLZ(EQUAL_FLAG, reg_map[src2])); - if (CHECK_FLAGS(SLJIT_SET_E)) - FAIL_IF(CLZ(reg_map[dst], reg_map[src2])); - - return SLJIT_SUCCESS; - - case SLJIT_ADD: - if (flags & SRC2_IMM) { - if (op & SLJIT_SET_O) { - FAIL_IF(SHRUI(TMP_EREG1, reg_map[src1], 63)); - if (src2 < 0) - FAIL_IF(XORI(TMP_EREG1, TMP_EREG1, 1)); - } - - if (op & SLJIT_SET_E) - FAIL_IF(ADDLI(EQUAL_FLAG, reg_map[src1], src2)); - - if (op & SLJIT_SET_C) { - if (src2 >= 0) - FAIL_IF(ORI(ULESS_FLAG ,reg_map[src1], src2)); - else { - FAIL_IF(ADDLI(ULESS_FLAG ,ZERO, src2)); - FAIL_IF(OR(ULESS_FLAG,reg_map[src1],ULESS_FLAG)); - } - } - - /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E)) - FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], src2)); - - if (op & SLJIT_SET_O) { - FAIL_IF(SHRUI(OVERFLOW_FLAG, reg_map[dst], 63)); - - if (src2 < 0) - FAIL_IF(XORI(OVERFLOW_FLAG, OVERFLOW_FLAG, 1)); - } - } else { - if (op & SLJIT_SET_O) { - FAIL_IF(XOR(TMP_EREG1, reg_map[src1], reg_map[src2])); - FAIL_IF(SHRUI(TMP_EREG1, TMP_EREG1, 63)); - - if (src1 != dst) - overflow_ra = reg_map[src1]; - else if (src2 != dst) - overflow_ra = reg_map[src2]; - else { - /* Rare ocasion. */ - FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO)); - overflow_ra = TMP_EREG2; - } - } - - if (op & SLJIT_SET_E) - FAIL_IF(ADD(EQUAL_FLAG ,reg_map[src1], reg_map[src2])); - - if (op & SLJIT_SET_C) - FAIL_IF(OR(ULESS_FLAG,reg_map[src1], reg_map[src2])); - - /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E)) - FAIL_IF(ADD(reg_map[dst],reg_map[src1], reg_map[src2])); - - if (op & SLJIT_SET_O) { - FAIL_IF(XOR(OVERFLOW_FLAG,reg_map[dst], overflow_ra)); - FAIL_IF(SHRUI(OVERFLOW_FLAG, OVERFLOW_FLAG, 63)); - } - } - - /* a + b >= a | b (otherwise, the carry should be set to 1). */ - if (op & SLJIT_SET_C) - FAIL_IF(CMPLTU(ULESS_FLAG ,reg_map[dst] ,ULESS_FLAG)); - - if (op & SLJIT_SET_O) - return CMOVNEZ(OVERFLOW_FLAG, TMP_EREG1, ZERO); - - return SLJIT_SUCCESS; - - case SLJIT_ADDC: - if (flags & SRC2_IMM) { - if (op & SLJIT_SET_C) { - if (src2 >= 0) - FAIL_IF(ORI(TMP_EREG1, reg_map[src1], src2)); - else { - FAIL_IF(ADDLI(TMP_EREG1, ZERO, src2)); - FAIL_IF(OR(TMP_EREG1, reg_map[src1], TMP_EREG1)); - } - } - - FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], src2)); - - } else { - if (op & SLJIT_SET_C) - FAIL_IF(OR(TMP_EREG1, reg_map[src1], reg_map[src2])); - - /* dst may be the same as src1 or src2. */ - FAIL_IF(ADD(reg_map[dst], reg_map[src1], reg_map[src2])); - } - - if (op & SLJIT_SET_C) - FAIL_IF(CMPLTU(TMP_EREG1, reg_map[dst], TMP_EREG1)); - - FAIL_IF(ADD(reg_map[dst], reg_map[dst], ULESS_FLAG)); - - if (!(op & SLJIT_SET_C)) - return SLJIT_SUCCESS; - - /* Set TMP_EREG2 (dst == 0) && (ULESS_FLAG == 1). */ - FAIL_IF(CMPLTUI(TMP_EREG2, reg_map[dst], 1)); - FAIL_IF(AND(TMP_EREG2, TMP_EREG2, ULESS_FLAG)); - /* Set carry flag. */ - return OR(ULESS_FLAG, TMP_EREG2, TMP_EREG1); - - case SLJIT_SUB: - if ((flags & SRC2_IMM) && ((op & (SLJIT_SET_U | SLJIT_SET_S)) || src2 == SIMM_16BIT_MIN)) { - FAIL_IF(ADDLI(TMP_REG2_mapped, ZERO, src2)); - src2 = TMP_REG2; - flags &= ~SRC2_IMM; - } - - if (flags & SRC2_IMM) { - if (op & SLJIT_SET_O) { - FAIL_IF(SHRUI(TMP_EREG1,reg_map[src1], 63)); - - if (src2 < 0) - FAIL_IF(XORI(TMP_EREG1, TMP_EREG1, 1)); - - if (src1 != dst) - overflow_ra = reg_map[src1]; - else { - /* Rare ocasion. */ - FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO)); - overflow_ra = TMP_EREG2; - } - } - - if (op & SLJIT_SET_E) - FAIL_IF(ADDLI(EQUAL_FLAG, reg_map[src1], -src2)); - - if (op & SLJIT_SET_C) { - FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); - FAIL_IF(CMPLTU(ULESS_FLAG, reg_map[src1], ADDR_TMP_mapped)); - } - - /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E)) - FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], -src2)); - - } else { - - if (op & SLJIT_SET_O) { - FAIL_IF(XOR(TMP_EREG1, reg_map[src1], reg_map[src2])); - FAIL_IF(SHRUI(TMP_EREG1, TMP_EREG1, 63)); - - if (src1 != dst) - overflow_ra = reg_map[src1]; - else { - /* Rare ocasion. */ - FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO)); - overflow_ra = TMP_EREG2; - } - } - - if (op & SLJIT_SET_E) - FAIL_IF(SUB(EQUAL_FLAG, reg_map[src1], reg_map[src2])); - - if (op & (SLJIT_SET_U | SLJIT_SET_C)) - FAIL_IF(CMPLTU(ULESS_FLAG, reg_map[src1], reg_map[src2])); - - if (op & SLJIT_SET_U) - FAIL_IF(CMPLTU(UGREATER_FLAG, reg_map[src2], reg_map[src1])); - - if (op & SLJIT_SET_S) { - FAIL_IF(CMPLTS(LESS_FLAG ,reg_map[src1] ,reg_map[src2])); - FAIL_IF(CMPLTS(GREATER_FLAG ,reg_map[src2] ,reg_map[src1])); - } - - /* dst may be the same as src1 or src2. */ - if (CHECK_FLAGS(SLJIT_SET_E | SLJIT_SET_U | SLJIT_SET_S | SLJIT_SET_C)) - FAIL_IF(SUB(reg_map[dst], reg_map[src1], reg_map[src2])); - } - - if (op & SLJIT_SET_O) { - FAIL_IF(XOR(OVERFLOW_FLAG, reg_map[dst], overflow_ra)); - FAIL_IF(SHRUI(OVERFLOW_FLAG, OVERFLOW_FLAG, 63)); - return CMOVEQZ(OVERFLOW_FLAG, TMP_EREG1, ZERO); - } - - return SLJIT_SUCCESS; - - case SLJIT_SUBC: - if ((flags & SRC2_IMM) && src2 == SIMM_16BIT_MIN) { - FAIL_IF(ADDLI(TMP_REG2_mapped, ZERO, src2)); - src2 = TMP_REG2; - flags &= ~SRC2_IMM; - } - - if (flags & SRC2_IMM) { - if (op & SLJIT_SET_C) { - FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, -src2)); - FAIL_IF(CMPLTU(TMP_EREG1, reg_map[src1], ADDR_TMP_mapped)); - } - - /* dst may be the same as src1 or src2. */ - FAIL_IF(ADDLI(reg_map[dst], reg_map[src1], -src2)); - - } else { - if (op & SLJIT_SET_C) - FAIL_IF(CMPLTU(TMP_EREG1, reg_map[src1], reg_map[src2])); - /* dst may be the same as src1 or src2. */ - FAIL_IF(SUB(reg_map[dst], reg_map[src1], reg_map[src2])); - } - - if (op & SLJIT_SET_C) - FAIL_IF(CMOVEQZ(TMP_EREG1, reg_map[dst], ULESS_FLAG)); - - FAIL_IF(SUB(reg_map[dst], reg_map[dst], ULESS_FLAG)); - - if (op & SLJIT_SET_C) - FAIL_IF(ADD(ULESS_FLAG, TMP_EREG1, ZERO)); - - return SLJIT_SUCCESS; - - case SLJIT_MUL: - if (flags & SRC2_IMM) { - FAIL_IF(load_immediate(compiler, TMP_REG2_mapped, src2)); - src2 = TMP_REG2; - flags &= ~SRC2_IMM; - } - - FAIL_IF(MUL(reg_map[dst], reg_map[src1], reg_map[src2])); - - return SLJIT_SUCCESS; - -#define EMIT_LOGICAL(op_imm, op_norm) \ - if (flags & SRC2_IMM) { \ - FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); \ - if (op & SLJIT_SET_E) \ - FAIL_IF(push_3_buffer( \ - compiler, op_norm, EQUAL_FLAG, reg_map[src1], \ - ADDR_TMP_mapped, __LINE__)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ - FAIL_IF(push_3_buffer( \ - compiler, op_norm, reg_map[dst], reg_map[src1], \ - ADDR_TMP_mapped, __LINE__)); \ - } else { \ - if (op & SLJIT_SET_E) \ - FAIL_IF(push_3_buffer( \ - compiler, op_norm, EQUAL_FLAG, reg_map[src1], \ - reg_map[src2], __LINE__)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ - FAIL_IF(push_3_buffer( \ - compiler, op_norm, reg_map[dst], reg_map[src1], \ - reg_map[src2], __LINE__)); \ - } - - case SLJIT_AND: - EMIT_LOGICAL(TILEGX_OPC_ANDI, TILEGX_OPC_AND); - return SLJIT_SUCCESS; - - case SLJIT_OR: - EMIT_LOGICAL(TILEGX_OPC_ORI, TILEGX_OPC_OR); - return SLJIT_SUCCESS; - - case SLJIT_XOR: - EMIT_LOGICAL(TILEGX_OPC_XORI, TILEGX_OPC_XOR); - return SLJIT_SUCCESS; - -#define EMIT_SHIFT(op_imm, op_norm) \ - if (flags & SRC2_IMM) { \ - if (op & SLJIT_SET_E) \ - FAIL_IF(push_3_buffer( \ - compiler, op_imm, EQUAL_FLAG, reg_map[src1], \ - src2 & 0x3F, __LINE__)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ - FAIL_IF(push_3_buffer( \ - compiler, op_imm, reg_map[dst], reg_map[src1], \ - src2 & 0x3F, __LINE__)); \ - } else { \ - if (op & SLJIT_SET_E) \ - FAIL_IF(push_3_buffer( \ - compiler, op_norm, EQUAL_FLAG, reg_map[src1], \ - reg_map[src2], __LINE__)); \ - if (CHECK_FLAGS(SLJIT_SET_E)) \ - FAIL_IF(push_3_buffer( \ - compiler, op_norm, reg_map[dst], reg_map[src1], \ - reg_map[src2], __LINE__)); \ - } - - case SLJIT_SHL: - EMIT_SHIFT(TILEGX_OPC_SHLI, TILEGX_OPC_SHL); - return SLJIT_SUCCESS; - - case SLJIT_LSHR: - EMIT_SHIFT(TILEGX_OPC_SHRUI, TILEGX_OPC_SHRU); - return SLJIT_SUCCESS; - - case SLJIT_ASHR: - EMIT_SHIFT(TILEGX_OPC_SHRSI, TILEGX_OPC_SHRS); - return SLJIT_SUCCESS; - } - - SLJIT_UNREACHABLE(); - return SLJIT_SUCCESS; -} - -static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags, sljit_s32 dst, sljit_sw dstw, sljit_s32 src1, sljit_sw src1w, sljit_s32 src2, sljit_sw src2w) -{ - /* arg1 goes to TMP_REG1 or src reg. - arg2 goes to TMP_REG2, imm or src reg. - TMP_REG3 can be used for caching. - result goes to TMP_REG2, so put result can use TMP_REG1 and TMP_REG3. */ - sljit_s32 dst_r = TMP_REG2; - sljit_s32 src1_r; - sljit_sw src2_r = 0; - sljit_s32 sugg_src2_r = TMP_REG2; - - if (!(flags & ALT_KEEP_CACHE)) { - compiler->cache_arg = 0; - compiler->cache_argw = 0; - } - - if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) { - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32 && !(src2 & SLJIT_MEM)) - return SLJIT_SUCCESS; - if (GET_FLAGS(op)) - flags |= UNUSED_DEST; - } else if (FAST_IS_REG(dst)) { - dst_r = dst; - flags |= REG_DEST; - if (op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) - sugg_src2_r = dst_r; - } else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1_mapped, dst, dstw)) - flags |= SLOW_DEST; - - if (flags & IMM_OP) { - if ((src2 & SLJIT_IMM) && src2w) { - if ((!(flags & LOGICAL_OP) - && (src2w <= SIMM_16BIT_MAX && src2w >= SIMM_16BIT_MIN)) - || ((flags & LOGICAL_OP) && !(src2w & ~UIMM_16BIT_MAX))) { - flags |= SRC2_IMM; - src2_r = src2w; - } - } - - if (!(flags & SRC2_IMM) && (flags & CUMULATIVE_OP) && (src1 & SLJIT_IMM) && src1w) { - if ((!(flags & LOGICAL_OP) - && (src1w <= SIMM_16BIT_MAX && src1w >= SIMM_16BIT_MIN)) - || ((flags & LOGICAL_OP) && !(src1w & ~UIMM_16BIT_MAX))) { - flags |= SRC2_IMM; - src2_r = src1w; - - /* And swap arguments. */ - src1 = src2; - src1w = src2w; - src2 = SLJIT_IMM; - /* src2w = src2_r unneeded. */ - } - } - } - - /* Source 1. */ - if (FAST_IS_REG(src1)) { - src1_r = src1; - flags |= REG1_SOURCE; - } else if (src1 & SLJIT_IMM) { - if (src1w) { - FAIL_IF(load_immediate(compiler, TMP_REG1_mapped, src1w)); - src1_r = TMP_REG1; - } else - src1_r = 0; - } else { - if (getput_arg_fast(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w)) - FAIL_IF(compiler->error); - else - flags |= SLOW_SRC1; - src1_r = TMP_REG1; - } - - /* Source 2. */ - if (FAST_IS_REG(src2)) { - src2_r = src2; - flags |= REG2_SOURCE; - if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) - dst_r = src2_r; - } else if (src2 & SLJIT_IMM) { - if (!(flags & SRC2_IMM)) { - if (src2w) { - FAIL_IF(load_immediate(compiler, reg_map[sugg_src2_r], src2w)); - src2_r = sugg_src2_r; - } else { - src2_r = 0; - if ((op >= SLJIT_MOV && op <= SLJIT_MOVU_S32) && (dst & SLJIT_MEM)) - dst_r = 0; - } - } - } else { - if (getput_arg_fast(compiler, flags | LOAD_DATA, reg_map[sugg_src2_r], src2, src2w)) - FAIL_IF(compiler->error); - else - flags |= SLOW_SRC2; - src2_r = sugg_src2_r; - } - - if ((flags & (SLOW_SRC1 | SLOW_SRC2)) == (SLOW_SRC1 | SLOW_SRC2)) { - SLJIT_ASSERT(src2_r == TMP_REG2); - if (!can_cache(src1, src1w, src2, src2w) && can_cache(src1, src1w, dst, dstw)) { - FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2_mapped, src2, src2w, src1, src1w)); - FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, dst, dstw)); - } else { - FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, src2, src2w)); - FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG2_mapped, src2, src2w, dst, dstw)); - } - } else if (flags & SLOW_SRC1) - FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, TMP_REG1_mapped, src1, src1w, dst, dstw)); - else if (flags & SLOW_SRC2) - FAIL_IF(getput_arg(compiler, flags | LOAD_DATA, reg_map[sugg_src2_r], src2, src2w, dst, dstw)); - - FAIL_IF(emit_single_op(compiler, op, flags, dst_r, src1_r, src2_r)); - - if (dst & SLJIT_MEM) { - if (!(flags & SLOW_DEST)) { - getput_arg_fast(compiler, flags, reg_map[dst_r], dst, dstw); - return compiler->error; - } - - return getput_arg(compiler, flags, reg_map[dst_r], dst, dstw, 0, 0); - } - - return SLJIT_SUCCESS; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw, sljit_s32 type) -{ - sljit_s32 sugg_dst_ar, dst_ar; - sljit_s32 flags = GET_ALL_FLAGS(op); - sljit_s32 mem_type = (op & SLJIT_I32_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA; - - CHECK_ERROR(); - CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); - ADJUST_LOCAL_OFFSET(dst, dstw); - - op = GET_OPCODE(op); - if (op == SLJIT_MOV_S32 || op == SLJIT_MOV_U32) - mem_type = INT_DATA | SIGNED_DATA; - sugg_dst_ar = reg_map[(op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2]; - - compiler->cache_arg = 0; - compiler->cache_argw = 0; - if (op >= SLJIT_ADD && (src & SLJIT_MEM)) { - ADJUST_LOCAL_OFFSET(src, srcw); - FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw)); - src = TMP_REG1; - srcw = 0; - } - - switch (type & 0xff) { - case SLJIT_EQUAL: - case SLJIT_NOT_EQUAL: - FAIL_IF(CMPLTUI(sugg_dst_ar, EQUAL_FLAG, 1)); - dst_ar = sugg_dst_ar; - break; - case SLJIT_LESS: - case SLJIT_GREATER_EQUAL: - dst_ar = ULESS_FLAG; - break; - case SLJIT_GREATER: - case SLJIT_LESS_EQUAL: - dst_ar = UGREATER_FLAG; - break; - case SLJIT_SIG_LESS: - case SLJIT_SIG_GREATER_EQUAL: - dst_ar = LESS_FLAG; - break; - case SLJIT_SIG_GREATER: - case SLJIT_SIG_LESS_EQUAL: - dst_ar = GREATER_FLAG; - break; - case SLJIT_OVERFLOW: - case SLJIT_NOT_OVERFLOW: - dst_ar = OVERFLOW_FLAG; - break; - case SLJIT_MUL_OVERFLOW: - case SLJIT_MUL_NOT_OVERFLOW: - FAIL_IF(CMPLTUI(sugg_dst_ar, OVERFLOW_FLAG, 1)); - dst_ar = sugg_dst_ar; - type ^= 0x1; /* Flip type bit for the XORI below. */ - break; - - default: - SLJIT_UNREACHABLE(); - dst_ar = sugg_dst_ar; - break; - } - - if (type & 0x1) { - FAIL_IF(XORI(sugg_dst_ar, dst_ar, 1)); - dst_ar = sugg_dst_ar; - } - - if (op >= SLJIT_ADD) { - if (TMP_REG2_mapped != dst_ar) - FAIL_IF(ADD(TMP_REG2_mapped, dst_ar, ZERO)); - return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0); - } - - if (dst & SLJIT_MEM) - return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw); - - if (sugg_dst_ar != dst_ar) - return ADD(sugg_dst_ar, dst_ar, ZERO); - - return SLJIT_SUCCESS; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op) { - CHECK_ERROR(); - CHECK(check_sljit_emit_op0(compiler, op)); - - op = GET_OPCODE(op); - switch (op) { - case SLJIT_NOP: - return push_0_buffer(compiler, TILEGX_OPC_FNOP, __LINE__); - - case SLJIT_BREAKPOINT: - return PI(BPT); - - case SLJIT_LMUL_UW: - case SLJIT_LMUL_SW: - case SLJIT_DIVMOD_UW: - case SLJIT_DIVMOD_SW: - case SLJIT_DIV_UW: - case SLJIT_DIV_SW: - SLJIT_UNREACHABLE(); - } - - return SLJIT_SUCCESS; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); - ADJUST_LOCAL_OFFSET(dst, dstw); - ADJUST_LOCAL_OFFSET(src, srcw); - - switch (GET_OPCODE(op)) { - case SLJIT_MOV: - case SLJIT_MOV_P: - return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_MOV_U32: - return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_MOV_S32: - return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_MOV_U8: - return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8) srcw : srcw); - - case SLJIT_MOV_S8: - return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8) srcw : srcw); - - case SLJIT_MOV_U16: - return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16) srcw : srcw); - - case SLJIT_MOV_S16: - return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16) srcw : srcw); - - case SLJIT_MOVU: - case SLJIT_MOVU_P: - return emit_op(compiler, SLJIT_MOV, WORD_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_MOVU_U32: - return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_MOVU_S32: - return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_MOVU_U8: - return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8) srcw : srcw); - - case SLJIT_MOVU_S8: - return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8) srcw : srcw); - - case SLJIT_MOVU_U16: - return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16) srcw : srcw); - - case SLJIT_MOVU_S16: - return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA | WRITE_BACK, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16) srcw : srcw); - - case SLJIT_NOT: - return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw); - - case SLJIT_NEG: - return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw); - - case SLJIT_CLZ: - return emit_op(compiler, op, (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); - } - - return SLJIT_SUCCESS; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(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(); - CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); - ADJUST_LOCAL_OFFSET(dst, dstw); - ADJUST_LOCAL_OFFSET(src1, src1w); - ADJUST_LOCAL_OFFSET(src2, src2w); - - switch (GET_OPCODE(op)) { - case SLJIT_ADD: - case SLJIT_ADDC: - return emit_op(compiler, op, CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); - - case SLJIT_SUB: - case SLJIT_SUBC: - return emit_op(compiler, op, IMM_OP, dst, dstw, src1, src1w, src2, src2w); - - case SLJIT_MUL: - return emit_op(compiler, op, CUMULATIVE_OP, dst, dstw, src1, src1w, src2, src2w); - - case SLJIT_AND: - case SLJIT_OR: - case SLJIT_XOR: - return emit_op(compiler, op, CUMULATIVE_OP | LOGICAL_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w); - - case SLJIT_SHL: - case SLJIT_LSHR: - case SLJIT_ASHR: - if (src2 & SLJIT_IMM) - src2w &= 0x3f; - if (op & SLJIT_I32_OP) - src2w &= 0x1f; - - return emit_op(compiler, op, IMM_OP, dst, dstw, src1, src1w, src2, src2w); - } - - return SLJIT_SUCCESS; -} - -SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_compiler *compiler) -{ - struct sljit_label *label; - - flush_buffer(compiler); - - CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_label(compiler)); - - if (compiler->last_label && compiler->last_label->size == compiler->size) - return compiler->last_label; - - label = (struct sljit_label *)ensure_abuf(compiler, sizeof(struct sljit_label)); - PTR_FAIL_IF(!label); - set_label(label, compiler); - return label; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 src, sljit_sw srcw) -{ - sljit_s32 src_r = TMP_REG2; - struct sljit_jump *jump = NULL; - - flush_buffer(compiler); - - CHECK_ERROR(); - CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); - - if (FAST_IS_REG(src)) { - if (reg_map[src] != 0) - src_r = src; - else - FAIL_IF(ADD_SOLO(TMP_REG2_mapped, reg_map[src], ZERO)); - } - - if (type >= SLJIT_CALL0) { - SLJIT_ASSERT(reg_map[PIC_ADDR_REG] == 16 && PIC_ADDR_REG == TMP_REG2); - if (src & (SLJIT_IMM | SLJIT_MEM)) { - if (src & SLJIT_IMM) - FAIL_IF(emit_const(compiler, reg_map[PIC_ADDR_REG], srcw, 1)); - else { - SLJIT_ASSERT(src_r == TMP_REG2 && (src & SLJIT_MEM)); - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); - } - - FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO)); - - FAIL_IF(ADDI_SOLO(54, 54, -16)); - - FAIL_IF(JALR_SOLO(reg_map[PIC_ADDR_REG])); - - return ADDI_SOLO(54, 54, 16); - } - - /* Register input. */ - if (type >= SLJIT_CALL1) - FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO)); - - FAIL_IF(ADD_SOLO(reg_map[PIC_ADDR_REG], reg_map[src_r], ZERO)); - - FAIL_IF(ADDI_SOLO(54, 54, -16)); - - FAIL_IF(JALR_SOLO(reg_map[src_r])); - - return ADDI_SOLO(54, 54, 16); - } - - if (src & SLJIT_IMM) { - jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump)); - FAIL_IF(!jump); - set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0)); - jump->u.target = srcw; - FAIL_IF(emit_const(compiler, TMP_REG2_mapped, 0, 1)); - - if (type >= SLJIT_FAST_CALL) { - FAIL_IF(ADD_SOLO(ZERO, ZERO, ZERO)); - jump->addr = compiler->size; - FAIL_IF(JR_SOLO(reg_map[src_r])); - } else { - jump->addr = compiler->size; - FAIL_IF(JR_SOLO(reg_map[src_r])); - } - - return SLJIT_SUCCESS; - - } else if (src & SLJIT_MEM) { - FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); - flush_buffer(compiler); - } - - FAIL_IF(JR_SOLO(reg_map[src_r])); - - if (jump) - jump->addr = compiler->size; - - return SLJIT_SUCCESS; -} - -#define BR_Z(src) \ - inst = BEQZ_X1 | SRCA_X1(src); \ - flags = IS_COND; - -#define BR_NZ(src) \ - inst = BNEZ_X1 | SRCA_X1(src); \ - flags = IS_COND; - -SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compiler *compiler, sljit_s32 type) -{ - struct sljit_jump *jump; - sljit_ins inst; - sljit_s32 flags = 0; - - flush_buffer(compiler); - - CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_jump(compiler, type)); - - jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump)); - PTR_FAIL_IF(!jump); - set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP); - type &= 0xff; - - switch (type) { - case SLJIT_EQUAL: - BR_NZ(EQUAL_FLAG); - break; - case SLJIT_NOT_EQUAL: - BR_Z(EQUAL_FLAG); - break; - case SLJIT_LESS: - BR_Z(ULESS_FLAG); - break; - case SLJIT_GREATER_EQUAL: - BR_NZ(ULESS_FLAG); - break; - case SLJIT_GREATER: - BR_Z(UGREATER_FLAG); - break; - case SLJIT_LESS_EQUAL: - BR_NZ(UGREATER_FLAG); - break; - case SLJIT_SIG_LESS: - BR_Z(LESS_FLAG); - break; - case SLJIT_SIG_GREATER_EQUAL: - BR_NZ(LESS_FLAG); - break; - case SLJIT_SIG_GREATER: - BR_Z(GREATER_FLAG); - break; - case SLJIT_SIG_LESS_EQUAL: - BR_NZ(GREATER_FLAG); - break; - case SLJIT_OVERFLOW: - case SLJIT_MUL_OVERFLOW: - BR_Z(OVERFLOW_FLAG); - break; - case SLJIT_NOT_OVERFLOW: - case SLJIT_MUL_NOT_OVERFLOW: - BR_NZ(OVERFLOW_FLAG); - break; - default: - /* Not conditional branch. */ - inst = 0; - break; - } - - jump->flags |= flags; - - if (inst) { - inst = inst | ((type <= SLJIT_JUMP) ? BOFF_X1(5) : BOFF_X1(6)); - PTR_FAIL_IF(PI(inst)); - } - - PTR_FAIL_IF(emit_const(compiler, TMP_REG2_mapped, 0, 1)); - if (type <= SLJIT_JUMP) { - jump->addr = compiler->size; - PTR_FAIL_IF(JR_SOLO(TMP_REG2_mapped)); - } else { - SLJIT_ASSERT(reg_map[PIC_ADDR_REG] == 16 && PIC_ADDR_REG == TMP_REG2); - /* Cannot be optimized out if type is >= CALL0. */ - jump->flags |= IS_JAL | (type >= SLJIT_CALL0 ? SLJIT_REWRITABLE_JUMP : 0); - PTR_FAIL_IF(ADD_SOLO(0, reg_map[SLJIT_R0], ZERO)); - jump->addr = compiler->size; - PTR_FAIL_IF(JALR_SOLO(TMP_REG2_mapped)); - } - - return jump; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 dst, sljit_sw dstw, sljit_s32 src, sljit_sw srcw) -{ - SLJIT_UNREACHABLE(); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(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_UNREACHABLE(); -} - -SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value) -{ - struct sljit_const *const_; - sljit_s32 reg; - - flush_buffer(compiler); - - CHECK_ERROR_PTR(); - CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); - ADJUST_LOCAL_OFFSET(dst, dstw); - - const_ = (struct sljit_const *)ensure_abuf(compiler, sizeof(struct sljit_const)); - PTR_FAIL_IF(!const_); - set_const(const_, compiler); - - reg = FAST_IS_REG(dst) ? dst : TMP_REG2; - - PTR_FAIL_IF(emit_const_64(compiler, reg, init_value, 1)); - - if (dst & SLJIT_MEM) - PTR_FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, TMP_REG2, 0)); - return const_; -} - -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target) -{ - sljit_ins *inst = (sljit_ins *)addr; - - inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_target >> 32) & 0xffff) << 43); - inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_target >> 16) & 0xffff) << 43); - inst[2] = (inst[2] & ~(0xFFFFL << 43)) | ((new_target & 0xffff) << 43); - SLJIT_CACHE_FLUSH(inst, inst + 3); -} - -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant) -{ - sljit_ins *inst = (sljit_ins *)addr; - - inst[0] = (inst[0] & ~(0xFFFFL << 43)) | (((new_constant >> 48) & 0xFFFFL) << 43); - inst[1] = (inst[1] & ~(0xFFFFL << 43)) | (((new_constant >> 32) & 0xFFFFL) << 43); - inst[2] = (inst[2] & ~(0xFFFFL << 43)) | (((new_constant >> 16) & 0xFFFFL) << 43); - inst[3] = (inst[3] & ~(0xFFFFL << 43)) | ((new_constant & 0xFFFFL) << 43); - SLJIT_CACHE_FLUSH(inst, inst + 4); -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) -{ - CHECK_REG_INDEX(check_sljit_get_register_index(reg)); - return reg_map[reg]; -} - -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler, - void *instruction, sljit_s32 size) -{ - CHECK_ERROR(); - CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); - return SLJIT_ERR_UNSUPPORTED; -} - diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c index 34a3a3d940..79a7e8bba5 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c @@ -76,6 +76,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + /* Emit ENDBR32 at function entry if needed. */ + FAIL_IF(emit_endbranch(compiler)); + args = get_arg_count(arg_types); compiler->args = args; @@ -307,14 +310,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size)); #endif - size = 2 + (compiler->scratches > 7 ? (compiler->scratches - 7) : 0) + + size = 2 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) + (compiler->saveds <= 3 ? compiler->saveds : 3); #if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL) if (compiler->args > 2) size += 2; -#else - if (compiler->args > 0) - size += 2; #endif inst = (sljit_u8*)ensure_buf(compiler, 1 + size); FAIL_IF(!inst); @@ -367,6 +367,8 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3) && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66) && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66)); + /* We don't support (%ebp). */ + SLJIT_ASSERT(!(b & SLJIT_MEM) || immb || reg_map[b & REG_MASK] != 5); size &= 0xf; inst_size = size; @@ -863,14 +865,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) +static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { sljit_u8 *inst; - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); - CHECK_EXTRA_REGS(src, srcw, (void)0); if (FAST_IS_REG(src)) { @@ -894,3 +892,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler RET(); return SLJIT_SUCCESS; } + +static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler) +{ + sljit_s32 size, saved_size; + sljit_s32 has_f64_aligment; + + /* Don't adjust shadow stack if it isn't enabled. */ + if (!cpu_has_shadow_stack ()) + return SLJIT_SUCCESS; + + SLJIT_ASSERT(compiler->args >= 0); + SLJIT_ASSERT(compiler->local_size > 0); + +#if !defined(__APPLE__) + has_f64_aligment = compiler->options & SLJIT_F64_ALIGNMENT; +#else + has_f64_aligment = 0; +#endif + + size = compiler->local_size; + saved_size = (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) + (compiler->saveds <= 3 ? compiler->saveds : 3)) * sizeof(sljit_uw); + if (has_f64_aligment) { + /* mov TMP_REG1, [esp + local_size]. */ + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), size); + /* mov TMP_REG1, [TMP_REG1+ saved_size]. */ + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), saved_size); + /* Move return address to [esp]. */ + EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, TMP_REG1, 0); + size = 0; + } else + size += saved_size; + + return adjust_shadow_stack(compiler, SLJIT_UNUSED, 0, SLJIT_SP, size); +} diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c index 5758711954..e85b56a61a 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c @@ -135,6 +135,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size); + /* Emit ENDBR64 at function entry if needed. */ + FAIL_IF(emit_endbranch(compiler)); + compiler->mode32 = 0; #ifdef _WIN64 @@ -796,14 +799,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler * return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) +static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src, sljit_sw srcw) { sljit_u8 *inst; - CHECK_ERROR(); - CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); - ADJUST_LOCAL_OFFSET(src, srcw); - if (FAST_IS_REG(src)) { if (reg_map[src] < 8) { inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 1); @@ -898,3 +897,22 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign, return SLJIT_SUCCESS; } + +static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler) +{ + sljit_s32 tmp, size; + + /* Don't adjust shadow stack if it isn't enabled. */ + if (!cpu_has_shadow_stack ()) + return SLJIT_SUCCESS; + + size = compiler->local_size; + tmp = compiler->scratches; + if (tmp >= SLJIT_FIRST_SAVED_REG) + size += (tmp - SLJIT_FIRST_SAVED_REG + 1) * sizeof(sljit_uw); + tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG; + if (SLJIT_S0 >= tmp) + size += (SLJIT_S0 - tmp + 1) * sizeof(sljit_uw); + + return adjust_shadow_stack(compiler, SLJIT_UNUSED, 0, SLJIT_SP, size); +} diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c index 6296da5382..ddcc5ebf76 100644 --- a/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c +++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c @@ -506,7 +506,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil reverse_buf(compiler); /* Second code generation pass. */ - code = (sljit_u8*)SLJIT_MALLOC_EXEC(compiler->size); + code = (sljit_u8*)SLJIT_MALLOC_EXEC(compiler->size, compiler->exec_allocator_data); PTR_FAIL_WITH_EXEC_IF(code); buf = compiler->buf; @@ -557,7 +557,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil SLJIT_ASSERT(put_label->label); put_label->addr = (sljit_uw)code_ptr; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) - code_ptr = generate_put_label_code(put_label, code_ptr, (sljit_uw)(SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size)); + code_ptr = generate_put_label_code(put_label, code_ptr, (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code, executable_offset) + put_label->label->size); #endif put_label = put_label->next; break; @@ -629,7 +629,11 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil compiler->error = SLJIT_ERR_COMPILED; compiler->executable_offset = executable_offset; compiler->executable_size = code_ptr - code; - return (void*)(code + executable_offset); + + code = (sljit_u8*)SLJIT_ADD_EXEC_OFFSET(code, executable_offset); + + SLJIT_UPDATE_WX_FLAGS(code, (sljit_u8*)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset), 1); + return (void*)code; } SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) @@ -657,6 +661,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type) get_cpu_features(); return cpu_has_cmov; + case SLJIT_HAS_PREFETCH: + return 1; + case SLJIT_HAS_SSE2: #if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) if (cpu_has_sse2 == -1) @@ -702,6 +709,166 @@ static SLJIT_INLINE sljit_s32 emit_sse2_store(struct sljit_compiler *compiler, static SLJIT_INLINE sljit_s32 emit_sse2_load(struct sljit_compiler *compiler, sljit_s32 single, sljit_s32 dst, sljit_s32 src, sljit_sw srcw); +static sljit_s32 emit_cmp_binary(struct sljit_compiler *compiler, + sljit_s32 src1, sljit_sw src1w, + sljit_s32 src2, sljit_sw src2w); + +static SLJIT_INLINE sljit_s32 emit_endbranch(struct sljit_compiler *compiler) +{ +#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) + /* Emit endbr32/endbr64 when CET is enabled. */ + sljit_u8 *inst; + inst = (sljit_u8*)ensure_buf(compiler, 1 + 4); + FAIL_IF(!inst); + INC_SIZE(4); + *inst++ = 0xf3; + *inst++ = 0x0f; + *inst++ = 0x1e; +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + *inst = 0xfb; +#else + *inst = 0xfa; +#endif +#else /* !SLJIT_CONFIG_X86_CET */ + SLJIT_UNUSED_ARG(compiler); +#endif /* SLJIT_CONFIG_X86_CET */ + return SLJIT_SUCCESS; +} + +#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__) + +static SLJIT_INLINE sljit_s32 emit_rdssp(struct sljit_compiler *compiler, sljit_s32 reg) +{ + sljit_u8 *inst; + sljit_s32 size; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + size = 5; +#else + size = 4; +#endif + + inst = (sljit_u8*)ensure_buf(compiler, 1 + size); + FAIL_IF(!inst); + INC_SIZE(size); + *inst++ = 0xf3; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B); +#endif + *inst++ = 0x0f; + *inst++ = 0x1e; + *inst = (0x3 << 6) | (0x1 << 3) | (reg_map[reg] & 0x7); + return SLJIT_SUCCESS; +} + +static SLJIT_INLINE sljit_s32 emit_incssp(struct sljit_compiler *compiler, sljit_s32 reg) +{ + sljit_u8 *inst; + sljit_s32 size; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + size = 5; +#else + size = 4; +#endif + + inst = (sljit_u8*)ensure_buf(compiler, 1 + size); + FAIL_IF(!inst); + INC_SIZE(size); + *inst++ = 0xf3; +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + *inst++ = REX_W | (reg_map[reg] <= 7 ? 0 : REX_B); +#endif + *inst++ = 0x0f; + *inst++ = 0xae; + *inst = (0x3 << 6) | (0x5 << 3) | (reg_map[reg] & 0x7); + return SLJIT_SUCCESS; +} + +#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */ + +static SLJIT_INLINE sljit_s32 cpu_has_shadow_stack(void) +{ +#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__) + return _get_ssp() != 0; +#else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */ + return 0; +#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */ +} + +static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compiler, + sljit_s32 src, sljit_sw srcw, sljit_s32 base, sljit_sw disp) +{ +#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__) + sljit_u8 *inst, *jz_after_cmp_inst; + sljit_uw size_jz_after_cmp_inst; + + sljit_uw size_before_rdssp_inst = compiler->size; + + /* Generate "RDSSP TMP_REG1". */ + FAIL_IF(emit_rdssp(compiler, TMP_REG1)); + + /* Load return address on shadow stack into TMP_REG1. */ +#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) + SLJIT_ASSERT(reg_map[TMP_REG1] == 5); + + /* Hand code unsupported "mov 0x0(%ebp),%ebp". */ + inst = (sljit_u8*)ensure_buf(compiler, 1 + 3); + FAIL_IF(!inst); + INC_SIZE(3); + *inst++ = 0x8b; + *inst++ = 0x6d; + *inst = 0; +#else /* !SLJIT_CONFIG_X86_32 */ + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), 0); +#endif /* SLJIT_CONFIG_X86_32 */ + + if (src == SLJIT_UNUSED) { + /* Return address is on stack. */ + src = SLJIT_MEM1(base); + srcw = disp; + } + + /* Compare return address against TMP_REG1. */ + FAIL_IF(emit_cmp_binary (compiler, TMP_REG1, 0, src, srcw)); + + /* Generate JZ to skip shadow stack ajdustment when shadow + stack matches normal stack. */ + inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!inst); + INC_SIZE(2); + *inst++ = get_jump_code(SLJIT_EQUAL) - 0x10; + size_jz_after_cmp_inst = compiler->size; + jz_after_cmp_inst = inst; + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + /* REX_W is not necessary. */ + compiler->mode32 = 1; +#endif + /* Load 1 into TMP_REG1. */ + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, 1); + + /* Generate "INCSSP TMP_REG1". */ + FAIL_IF(emit_incssp(compiler, TMP_REG1)); + + /* Jump back to "RDSSP TMP_REG1" to check shadow stack again. */ + inst = (sljit_u8*)ensure_buf(compiler, 1 + 2); + FAIL_IF(!inst); + INC_SIZE(2); + *inst++ = JMP_i8; + *inst = size_before_rdssp_inst - compiler->size; + + *jz_after_cmp_inst = compiler->size - size_jz_after_cmp_inst; +#else /* !SLJIT_CONFIG_X86_CET || !__SHSTK__ */ + SLJIT_UNUSED_ARG(compiler); + SLJIT_UNUSED_ARG(src); + SLJIT_UNUSED_ARG(srcw); + SLJIT_UNUSED_ARG(base); + SLJIT_UNUSED_ARG(disp); +#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */ + return SLJIT_SUCCESS; +} + #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #include "sljitNativeX86_32.c" #else @@ -905,6 +1072,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); #endif break; + case SLJIT_ENDBR: + return emit_endbranch(compiler); + case SLJIT_SKIP_FRAMES_BEFORE_RETURN: + return skip_frames_before_return(compiler); } return SLJIT_SUCCESS; @@ -1074,12 +1245,12 @@ static sljit_s32 emit_prefetch(struct sljit_compiler *compiler, sljit_s32 op, *inst++ = GROUP_0F; *inst++ = PREFETCH; - if (op >= SLJIT_MOV_U8 && op <= SLJIT_MOV_S8) - *inst |= (3 << 3); - else if (op >= SLJIT_MOV_U16 && op <= SLJIT_MOV_S16) - *inst |= (2 << 3); - else + if (op == SLJIT_PREFETCH_L1) *inst |= (1 << 3); + else if (op == SLJIT_PREFETCH_L2) + *inst |= (2 << 3); + else if (op == SLJIT_PREFETCH_L3) + *inst |= (3 << 3); return SLJIT_SUCCESS; } @@ -1284,12 +1455,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile compiler->mode32 = op_flags & SLJIT_I32_OP; #endif - if (dst == SLJIT_UNUSED && !HAS_FLAGS(op)) { - if (op <= SLJIT_MOV_P && (src & SLJIT_MEM)) - return emit_prefetch(compiler, op, src, srcw); - return SLJIT_SUCCESS; - } - op = GET_OPCODE(op); if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) { @@ -2150,6 +2315,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile if (!HAS_FLAGS(op)) { if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED) return compiler->error; + if (SLOW_IS_REG(dst) && src2 == dst) { + FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), dst, 0, dst, 0, src1, src1w)); + return emit_unary(compiler, NEG_rm, dst, 0, dst, 0); + } } if (dst == SLJIT_UNUSED) @@ -2186,6 +2355,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile return SLJIT_SUCCESS; } +SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op, + sljit_s32 src, sljit_sw srcw) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_src(compiler, op, src, srcw)); + ADJUST_LOCAL_OFFSET(src, srcw); + + CHECK_EXTRA_REGS(src, srcw, (void)0); + + switch (op) { + case SLJIT_FAST_RETURN: + return emit_fast_return(compiler, src, srcw); + case SLJIT_SKIP_FRAMES_BEFORE_FAST_RETURN: + /* Don't adjust shadow stack if it isn't enabled. */ + if (!cpu_has_shadow_stack ()) + return SLJIT_SUCCESS; + return adjust_shadow_stack(compiler, src, srcw, SLJIT_UNUSED, 0); + case SLJIT_PREFETCH_L1: + case SLJIT_PREFETCH_L2: + case SLJIT_PREFETCH_L3: + case SLJIT_PREFETCH_ONCE: + return emit_prefetch(compiler, op, src, srcw); + } + + return SLJIT_SUCCESS; +} + SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg) { CHECK_REG_INDEX(check_sljit_get_register_index(reg)); @@ -2926,15 +3122,21 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct slj SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset) { SLJIT_UNUSED_ARG(executable_offset); + + SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 0); #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) sljit_unaligned_store_sw((void*)addr, new_target - (addr + 4) - (sljit_uw)executable_offset); #else sljit_unaligned_store_sw((void*)addr, (sljit_sw) new_target); #endif + 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_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); } diff --git a/thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c b/thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c index 8a5b2b3cfe..147175afa6 100644 --- a/thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c +++ b/thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c @@ -70,92 +70,112 @@ struct chunk_header { void *executable; - int fd; }; /* alloc_chunk / free_chunk : * allocate executable system memory chunks * the size is always divisible by CHUNK_SIZE - allocator_grab_lock / allocator_release_lock : - * make the allocator thread safe - * can be empty if the OS (or the application) does not support threading + SLJIT_ALLOCATOR_LOCK / SLJIT_ALLOCATOR_UNLOCK : + * provided as part of sljitUtils * only the allocator requires this lock, sljit is fully thread safe as it only uses local variables */ +#ifndef __NetBSD__ +#include <sys/stat.h> #include <fcntl.h> +#include <stdio.h> +#include <string.h> #ifndef O_NOATIME #define O_NOATIME 0 #endif -#ifdef __O_TMPFILE +/* this is a linux extension available since kernel 3.11 */ #ifndef O_TMPFILE -#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) -#endif +#define O_TMPFILE 020200000 #endif -int mkostemp(char *template, int flags); +#ifndef _GNU_SOURCE char *secure_getenv(const char *name); +int mkostemp(char *template, int flags); +#endif static SLJIT_INLINE int create_tempfile(void) { int fd; - char tmp_name[256]; - size_t tmp_name_len; + size_t tmp_name_len = 0; char *dir; - size_t len; - -#ifdef P_tmpdir - len = (P_tmpdir != NULL) ? strlen(P_tmpdir) : 0; + struct stat st; +#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED + mode_t mode; +#endif - if (len > 0 && len < sizeof(tmp_name)) { - strcpy(tmp_name, P_tmpdir); - tmp_name_len = len; - } - else { - strcpy(tmp_name, "/tmp"); - tmp_name_len = 4; +#ifdef HAVE_MEMFD_CREATE + /* this is a GNU extension, make sure to use -D_GNU_SOURCE */ + fd = memfd_create("sljit", MFD_CLOEXEC); + if (fd != -1) { + fchmod(fd, 0); + return fd; } -#else - strcpy(tmp_name, "/tmp"); - tmp_name_len = 4; #endif dir = secure_getenv("TMPDIR"); + if (dir) { - len = strlen(dir); - if (len > 0 && len < sizeof(tmp_name)) { - strcpy(tmp_name, dir); - tmp_name_len = len; + tmp_name_len = strlen(dir); + if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)) { + if ((stat(dir, &st) == 0) && S_ISDIR(st.st_mode)) + strcpy(tmp_name, dir); } } +#ifdef P_tmpdir + if (!tmp_name_len) { + tmp_name_len = strlen(P_tmpdir); + if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)) + strcpy(tmp_name, P_tmpdir); + } +#endif + if (!tmp_name_len) { + strcpy(tmp_name, "/tmp"); + tmp_name_len = 4; + } + SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name)); - while (tmp_name_len > 0 && tmp_name[tmp_name_len - 1] == '/') { - tmp_name_len--; - tmp_name[tmp_name_len] = '\0'; - } + if (tmp_name[tmp_name_len - 1] == '/') + tmp_name[--tmp_name_len] = '\0'; -#ifdef O_TMPFILE - fd = open(tmp_name, O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, S_IRUSR | S_IWUSR); +#ifdef __linux__ + /* + * the previous trimming might had left an empty string if TMPDIR="/" + * so work around the problem below + */ + fd = open(tmp_name_len ? tmp_name : "/", + O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, 0); if (fd != -1) return fd; #endif if (tmp_name_len + 7 >= sizeof(tmp_name)) - { return -1; - } strcpy(tmp_name + tmp_name_len, "/XXXXXX"); +#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED + mode = umask(0777); +#endif fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME); +#if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED + umask(mode); +#else + fchmod(fd, 0); +#endif if (fd == -1) - return fd; + return -1; if (unlink(tmp_name)) { close(fd); @@ -189,23 +209,52 @@ static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size) retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0); if (retval->executable == MAP_FAILED) { - munmap(retval, size); + munmap((void *)retval, size); close(fd); return NULL; } - retval->fd = fd; + close(fd); return retval; } +#else +/* + * MAP_REMAPDUP is a NetBSD extension available sinde 8.0, make sure to + * adjust your feature macros (ex: -D_NETBSD_SOURCE) as needed + */ +static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size) +{ + struct chunk_header *retval; + + retval = (struct chunk_header *)mmap(NULL, size, + PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC), + MAP_ANON | MAP_SHARED, -1, 0); + + if (retval == MAP_FAILED) + return NULL; + + retval->executable = mremap(retval, size, NULL, size, MAP_REMAPDUP); + if (retval->executable == MAP_FAILED) { + munmap((void *)retval, size); + return NULL; + } + + if (mprotect(retval->executable, size, PROT_READ | PROT_EXEC) == -1) { + munmap(retval->executable, size); + munmap((void *)retval, size); + return NULL; + } + + return retval; +} +#endif /* NetBSD */ static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size) { struct chunk_header *header = ((struct chunk_header *)chunk) - 1; - int fd = header->fd; munmap(header->executable, size); - munmap(header, size); - close(fd); + munmap((void *)header, size); } /* --------------------------------------------------------------------- */ @@ -272,7 +321,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) sljit_uw chunk_size; sljit_sw executable_offset; - allocator_grab_lock(); + SLJIT_ALLOCATOR_LOCK(); if (size < (64 - sizeof(struct block_header))) size = (64 - sizeof(struct block_header)); size = ALIGN_SIZE(size); @@ -297,7 +346,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) } allocated_size += size; header->size = size; - allocator_release_lock(); + SLJIT_ALLOCATOR_UNLOCK(); return MEM_START(header); } free_block = free_block->next; @@ -308,7 +357,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) chunk_header = alloc_chunk(chunk_size); if (!chunk_header) { - allocator_release_lock(); + SLJIT_ALLOCATOR_UNLOCK(); return NULL; } @@ -342,7 +391,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) next_header->size = 1; next_header->prev_size = chunk_size; next_header->executable_offset = executable_offset; - allocator_release_lock(); + SLJIT_ALLOCATOR_UNLOCK(); return MEM_START(header); } @@ -351,7 +400,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) struct block_header *header; struct free_block* free_block; - allocator_grab_lock(); + SLJIT_ALLOCATOR_LOCK(); header = AS_BLOCK_HEADER(ptr, -(sljit_sw)sizeof(struct block_header)); header = AS_BLOCK_HEADER(header, -header->executable_offset); allocated_size -= header->size; @@ -385,11 +434,13 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) if (total_size - free_block->size > (allocated_size * 3 / 2)) { total_size -= free_block->size; sljit_remove_free_block(free_block); - free_chunk(free_block, free_block->size + sizeof(struct block_header)); + free_chunk(free_block, free_block->size + + sizeof(struct chunk_header) + + sizeof(struct block_header)); } } - allocator_release_lock(); + SLJIT_ALLOCATOR_UNLOCK(); } SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) @@ -397,7 +448,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) struct free_block* free_block; struct free_block* next_free_block; - allocator_grab_lock(); + SLJIT_ALLOCATOR_LOCK(); free_block = free_blocks; while (free_block) { @@ -406,13 +457,15 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) AS_BLOCK_HEADER(free_block, free_block->size)->size == 1) { total_size -= free_block->size; sljit_remove_free_block(free_block); - free_chunk(free_block, free_block->size + sizeof(struct block_header)); + free_chunk(free_block, free_block->size + + sizeof(struct chunk_header) + + sizeof(struct block_header)); } free_block = next_free_block; } SLJIT_ASSERT((total_size && free_blocks) || (!total_size && !free_blocks)); - allocator_release_lock(); + SLJIT_ALLOCATOR_UNLOCK(); } SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr) diff --git a/thirdparty/pcre2/src/sljit/sljitUtils.c b/thirdparty/pcre2/src/sljit/sljitUtils.c index 857492a174..08ca35cf37 100644 --- a/thirdparty/pcre2/src/sljit/sljitUtils.c +++ b/thirdparty/pcre2/src/sljit/sljitUtils.c @@ -28,220 +28,225 @@ /* Locks */ /* ------------------------------------------------------------------------ */ -#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) || (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) +/* Executable Allocator */ +#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \ + && !(defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR) #if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) +#define SLJIT_ALLOCATOR_LOCK() +#define SLJIT_ALLOCATOR_UNLOCK() +#elif !(defined _WIN32) +#include <pthread.h> + +static pthread_mutex_t allocator_lock = PTHREAD_MUTEX_INITIALIZER; -#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) +#define SLJIT_ALLOCATOR_LOCK() pthread_mutex_lock(&allocator_lock) +#define SLJIT_ALLOCATOR_UNLOCK() pthread_mutex_unlock(&allocator_lock) +#else /* windows */ +static HANDLE allocator_lock; static SLJIT_INLINE void allocator_grab_lock(void) { - /* Always successful. */ + HANDLE lock; + if (SLJIT_UNLIKELY(!allocator_lock)) { + lock = CreateMutex(NULL, FALSE, NULL); + if (InterlockedCompareExchangePointer(&allocator_lock, lock, NULL)) + CloseHandle(lock); + } + WaitForSingleObject(allocator_lock, INFINITE); } -static SLJIT_INLINE void allocator_release_lock(void) -{ - /* Always successful. */ -} +#define SLJIT_ALLOCATOR_LOCK() allocator_grab_lock() +#define SLJIT_ALLOCATOR_UNLOCK() ReleaseMutex(allocator_lock) +#endif /* thread implementation */ +#endif /* SLJIT_EXECUTABLE_ALLOCATOR && !SLJIT_WX_EXECUTABLE_ALLOCATOR */ -#endif /* SLJIT_EXECUTABLE_ALLOCATOR */ +/* ------------------------------------------------------------------------ */ +/* Stack */ +/* ------------------------------------------------------------------------ */ -#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) +#if ((defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \ + && !(defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION)) \ + || ((defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) \ + && !((defined SLJIT_PROT_EXECUTABLE_ALLOCATOR && SLJIT_PROT_EXECUTABLE_ALLOCATOR) \ + || (defined SLJIT_WX_EXECUTABLE_ALLOCATOR && SLJIT_WX_EXECUTABLE_ALLOCATOR))) -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void) -{ - /* Always successful. */ -} +#ifndef _WIN32 +/* Provides mmap function. */ +#include <sys/types.h> +#include <sys/mman.h> -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void) -{ - /* Always successful. */ -} +#ifndef MAP_ANON +#ifdef MAP_ANONYMOUS +#define MAP_ANON MAP_ANONYMOUS +#endif /* MAP_ANONYMOUS */ +#endif /* !MAP_ANON */ -#endif /* SLJIT_UTIL_GLOBAL_LOCK */ +#ifndef MAP_ANON -#elif defined(_WIN32) /* SLJIT_SINGLE_THREADED */ +#include <fcntl.h> -#include "windows.h" +#ifdef O_CLOEXEC +#define SLJIT_CLOEXEC O_CLOEXEC +#else /* !O_CLOEXEC */ +#define SLJIT_CLOEXEC 0 +#endif /* O_CLOEXEC */ -#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) +/* Some old systems do not have MAP_ANON. */ +static int dev_zero = -1; -static HANDLE allocator_mutex = 0; +#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) -static SLJIT_INLINE void allocator_grab_lock(void) +static SLJIT_INLINE int open_dev_zero(void) { - /* No idea what to do if an error occures. Static mutexes should never fail... */ - if (!allocator_mutex) - allocator_mutex = CreateMutex(NULL, TRUE, NULL); - else - WaitForSingleObject(allocator_mutex, INFINITE); -} + dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC); -static SLJIT_INLINE void allocator_release_lock(void) -{ - ReleaseMutex(allocator_mutex); + return dev_zero < 0; } -#endif /* SLJIT_EXECUTABLE_ALLOCATOR */ +#else /* !SLJIT_SINGLE_THREADED */ -#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) +#include <pthread.h> -static HANDLE global_mutex = 0; +static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER; -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void) +static SLJIT_INLINE int open_dev_zero(void) { - /* No idea what to do if an error occures. Static mutexes should never fail... */ - if (!global_mutex) - global_mutex = CreateMutex(NULL, TRUE, NULL); - else - WaitForSingleObject(global_mutex, INFINITE); -} + pthread_mutex_lock(&dev_zero_mutex); + if (SLJIT_UNLIKELY(dev_zero < 0)) + dev_zero = open("/dev/zero", O_RDWR | SLJIT_CLOEXEC); -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void) -{ - ReleaseMutex(global_mutex); + pthread_mutex_unlock(&dev_zero_mutex); + return dev_zero < 0; } -#endif /* SLJIT_UTIL_GLOBAL_LOCK */ - -#else /* _WIN32 */ - -#if (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) - -#include <pthread.h> +#endif /* SLJIT_SINGLE_THREADED */ +#undef SLJIT_CLOEXEC +#endif /* !MAP_ANON */ +#endif /* !_WIN32 */ +#endif /* open_dev_zero */ -static pthread_mutex_t allocator_mutex = PTHREAD_MUTEX_INITIALIZER; +#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) \ + || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) -static SLJIT_INLINE void allocator_grab_lock(void) -{ - pthread_mutex_lock(&allocator_mutex); -} +#ifdef _WIN32 -static SLJIT_INLINE void allocator_release_lock(void) -{ - pthread_mutex_unlock(&allocator_mutex); +static SLJIT_INLINE sljit_sw get_page_alignment(void) { + SYSTEM_INFO si; + static sljit_sw sljit_page_align; + if (!sljit_page_align) { + GetSystemInfo(&si); + sljit_page_align = si.dwPageSize - 1; + } + return sljit_page_align; } -#endif /* SLJIT_EXECUTABLE_ALLOCATOR */ - -#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK) - -#include <pthread.h> +#else -static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER; +#include <unistd.h> -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_grab_lock(void) -{ - pthread_mutex_lock(&global_mutex); +static SLJIT_INLINE sljit_sw get_page_alignment(void) { + static sljit_sw sljit_page_align; + if (!sljit_page_align) { + sljit_page_align = sysconf(_SC_PAGESIZE); + /* Should never happen. */ + if (sljit_page_align < 0) + sljit_page_align = 4096; + sljit_page_align--; + } + return sljit_page_align; } -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_release_lock(void) -{ - pthread_mutex_unlock(&global_mutex); -} +#endif /* _WIN32 */ -#endif /* SLJIT_UTIL_GLOBAL_LOCK */ +#endif /* get_page_alignment() */ -#endif /* _WIN32 */ +#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) -/* ------------------------------------------------------------------------ */ -/* Stack */ -/* ------------------------------------------------------------------------ */ +#if (defined SLJIT_UTIL_SIMPLE_STACK_ALLOCATION && SLJIT_UTIL_SIMPLE_STACK_ALLOCATION) -#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) || (defined SLJIT_EXECUTABLE_ALLOCATOR && SLJIT_EXECUTABLE_ALLOCATOR) +SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data) +{ + struct sljit_stack *stack; + void *ptr; -#ifdef _WIN32 -#include "windows.h" -#else -/* Provides mmap function. */ -#include <sys/types.h> -#include <sys/mman.h> -#ifndef MAP_ANON -#ifdef MAP_ANONYMOUS -#define MAP_ANON MAP_ANONYMOUS -#endif -#endif -/* For detecting the page size. */ -#include <unistd.h> + SLJIT_UNUSED_ARG(allocator_data); -#ifndef MAP_ANON + if (start_size > max_size || start_size < 1) + return NULL; -#include <fcntl.h> + stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data); + if (stack == NULL) + return NULL; -/* Some old systems does not have MAP_ANON. */ -static sljit_s32 dev_zero = -1; + ptr = SLJIT_MALLOC(max_size, allocator_data); + if (ptr == NULL) { + SLJIT_FREE(stack, allocator_data); + return NULL; + } -#if (defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) + stack->min_start = (sljit_u8 *)ptr; + stack->end = stack->min_start + max_size; + stack->start = stack->end - start_size; + stack->top = stack->end; + return stack; +} -static SLJIT_INLINE sljit_s32 open_dev_zero(void) +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data) { - dev_zero = open("/dev/zero", O_RDWR); - return dev_zero < 0; + SLJIT_UNUSED_ARG(allocator_data); + SLJIT_FREE((void*)stack->min_start, allocator_data); + SLJIT_FREE(stack, allocator_data); } -#else /* SLJIT_SINGLE_THREADED */ - -#include <pthread.h> - -static pthread_mutex_t dev_zero_mutex = PTHREAD_MUTEX_INITIALIZER; - -static SLJIT_INLINE sljit_s32 open_dev_zero(void) +SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start) { - pthread_mutex_lock(&dev_zero_mutex); - /* The dev_zero might be initialized by another thread during the waiting. */ - if (dev_zero < 0) { - dev_zero = open("/dev/zero", O_RDWR); - } - pthread_mutex_unlock(&dev_zero_mutex); - return dev_zero < 0; + if ((new_start < stack->min_start) || (new_start >= stack->end)) + return NULL; + stack->start = new_start; + return new_start; } -#endif /* SLJIT_SINGLE_THREADED */ +#else /* !SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */ -#endif +#ifdef _WIN32 -#endif +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data) +{ + SLJIT_UNUSED_ARG(allocator_data); + VirtualFree((void*)stack->min_start, 0, MEM_RELEASE); + SLJIT_FREE(stack, allocator_data); +} -#endif /* SLJIT_UTIL_STACK || SLJIT_EXECUTABLE_ALLOCATOR */ +#else /* !_WIN32 */ -#if (defined SLJIT_UTIL_STACK && SLJIT_UTIL_STACK) +SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data) +{ + SLJIT_UNUSED_ARG(allocator_data); + munmap((void*)stack->min_start, stack->end - stack->min_start); + SLJIT_FREE(stack, allocator_data); +} -/* Planning to make it even more clever in the future. */ -static sljit_sw sljit_page_align = 0; +#endif /* _WIN32 */ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(sljit_uw start_size, sljit_uw max_size, void *allocator_data) { struct sljit_stack *stack; void *ptr; -#ifdef _WIN32 - SYSTEM_INFO si; -#endif + sljit_sw page_align; SLJIT_UNUSED_ARG(allocator_data); + if (start_size > max_size || start_size < 1) return NULL; -#ifdef _WIN32 - if (!sljit_page_align) { - GetSystemInfo(&si); - sljit_page_align = si.dwPageSize - 1; - } -#else - if (!sljit_page_align) { - sljit_page_align = sysconf(_SC_PAGESIZE); - /* Should never happen. */ - if (sljit_page_align < 0) - sljit_page_align = 4096; - sljit_page_align--; - } -#endif - stack = (struct sljit_stack*)SLJIT_MALLOC(sizeof(struct sljit_stack), allocator_data); - if (!stack) + if (stack == NULL) return NULL; /* Align max_size. */ - max_size = (max_size + sljit_page_align) & ~sljit_page_align; + page_align = get_page_alignment(); + max_size = (max_size + page_align) & ~page_align; #ifdef _WIN32 ptr = VirtualAlloc(NULL, max_size, MEM_RESERVE, PAGE_READWRITE); @@ -258,18 +263,16 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(slj sljit_free_stack(stack, allocator_data); return NULL; } -#else +#else /* !_WIN32 */ #ifdef MAP_ANON ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); -#else - if (dev_zero < 0) { - if (open_dev_zero()) { - SLJIT_FREE(stack, allocator_data); - return NULL; - } +#else /* !MAP_ANON */ + if (SLJIT_UNLIKELY((dev_zero < 0) && open_dev_zero())) { + SLJIT_FREE(stack, allocator_data); + return NULL; } ptr = mmap(NULL, max_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, dev_zero, 0); -#endif +#endif /* MAP_ANON */ if (ptr == MAP_FAILED) { SLJIT_FREE(stack, allocator_data); return NULL; @@ -277,35 +280,28 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(slj stack->min_start = (sljit_u8 *)ptr; stack->end = stack->min_start + max_size; stack->start = stack->end - start_size; -#endif +#endif /* _WIN32 */ + stack->top = stack->end; return stack; } -#undef PAGE_ALIGN - -SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data) -{ - SLJIT_UNUSED_ARG(allocator_data); -#ifdef _WIN32 - VirtualFree((void*)stack->min_start, 0, MEM_RELEASE); -#else - munmap((void*)stack->min_start, stack->end - stack->min_start); -#endif - SLJIT_FREE(stack, allocator_data); -} - SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_stack *stack, sljit_u8 *new_start) { +#if defined _WIN32 || defined(POSIX_MADV_DONTNEED) sljit_uw aligned_old_start; sljit_uw aligned_new_start; + sljit_sw page_align; +#endif if ((new_start < stack->min_start) || (new_start >= stack->end)) return NULL; #ifdef _WIN32 - aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; - aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; + page_align = get_page_alignment(); + + aligned_new_start = (sljit_uw)new_start & ~page_align; + aligned_old_start = ((sljit_uw)stack->start) & ~page_align; if (aligned_new_start != aligned_old_start) { if (aligned_new_start < aligned_old_start) { if (!VirtualAlloc((void*)aligned_new_start, aligned_old_start - aligned_new_start, MEM_COMMIT, PAGE_READWRITE)) @@ -316,24 +312,26 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_st return NULL; } } -#else - if (stack->start < new_start) { - aligned_new_start = (sljit_uw)new_start & ~sljit_page_align; - aligned_old_start = ((sljit_uw)stack->start) & ~sljit_page_align; - /* If madvise is available, we release the unnecessary space. */ -#if defined(MADV_DONTNEED) - if (aligned_new_start > aligned_old_start) - madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_DONTNEED); #elif defined(POSIX_MADV_DONTNEED) - if (aligned_new_start > aligned_old_start) + if (stack->start < new_start) { + page_align = get_page_alignment(); + + aligned_new_start = (sljit_uw)new_start & ~page_align; + aligned_old_start = ((sljit_uw)stack->start) & ~page_align; + + if (aligned_new_start > aligned_old_start) { posix_madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, POSIX_MADV_DONTNEED); -#endif +#ifdef MADV_FREE + madvise((void*)aligned_old_start, aligned_new_start - aligned_old_start, MADV_FREE); +#endif /* MADV_FREE */ + } } -#endif +#endif /* _WIN32 */ + stack->start = new_start; return new_start; } -#endif /* SLJIT_UTIL_STACK */ +#endif /* SLJIT_UTIL_SIMPLE_STACK_ALLOCATION */ -#endif +#endif /* SLJIT_UTIL_STACK */ diff --git a/thirdparty/pcre2/src/sljit/sljitWXExecAllocator.c b/thirdparty/pcre2/src/sljit/sljitWXExecAllocator.c new file mode 100644 index 0000000000..6ef71f7d83 --- /dev/null +++ b/thirdparty/pcre2/src/sljit/sljitWXExecAllocator.c @@ -0,0 +1,225 @@ +/* + * Stack-less Just-In-Time compiler + * + * Copyright Zoltan Herczeg (hzmester@freemail.hu). All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + This file contains a simple W^X executable memory allocator for POSIX + like systems and Windows + + In *NIX, MAP_ANON is required (that is considered a feature) so make + sure to set the right availability macros for your system or the code + will fail to build. + + If your system doesn't support mapping of anonymous pages (ex: IRIX) it + is also likely that it doesn't need this allocator and should be using + the standard one instead. + + It allocates a separate map for each code block and may waste a lot of + memory, because whatever was requested, will be rounded up to the page + size (minimum 4KB, but could be even bigger). + + It changes the page permissions (RW <-> RX) as needed and therefore, if you + will be updating the code after it has been generated, need to make sure to + block any concurrent execution, or could result in a SIGBUS, that could + even manifest itself at a different address than the one that was being + modified. + + Only use if you are unable to use the regular allocator because of security + restrictions and adding exceptions to your application or the system are + not possible. +*/ + +#define SLJIT_UPDATE_WX_FLAGS(from, to, enable_exec) \ + sljit_update_wx_flags((from), (to), (enable_exec)) + +#ifndef _WIN32 +#include <sys/types.h> +#include <sys/mman.h> + +#ifdef __NetBSD__ +#if defined(PROT_MPROTECT) +#define check_se_protected(ptr, size) (0) +#define SLJIT_PROT_WX PROT_MPROTECT(PROT_EXEC) +#else /* !PROT_MPROTECT */ +#ifdef _NETBSD_SOURCE +#include <sys/param.h> +#else /* !_NETBSD_SOURCE */ +typedef unsigned int u_int; +#define devmajor_t sljit_s32 +#endif /* _NETBSD_SOURCE */ +#include <sys/sysctl.h> +#include <unistd.h> + +#define check_se_protected(ptr, size) netbsd_se_protected() + +static SLJIT_INLINE int netbsd_se_protected(void) +{ + int mib[3]; + int paxflags; + size_t len = sizeof(paxflags); + + mib[0] = CTL_PROC; + mib[1] = getpid(); + mib[2] = PROC_PID_PAXFLAGS; + + if (SLJIT_UNLIKELY(sysctl(mib, 3, &paxflags, &len, NULL, 0) < 0)) + return -1; + + return (paxflags & CTL_PROC_PAXFLAGS_MPROTECT) ? -1 : 0; +} +#endif /* PROT_MPROTECT */ +#else /* POSIX */ +#define check_se_protected(ptr, size) generic_se_protected(ptr, size) + +static SLJIT_INLINE int generic_se_protected(void *ptr, sljit_uw size) +{ + if (SLJIT_LIKELY(!mprotect(ptr, size, PROT_EXEC))) + return mprotect(ptr, size, PROT_READ | PROT_WRITE); + + return -1; +} +#endif /* NetBSD */ + +#if defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED +#define SLJIT_SE_LOCK() +#define SLJIT_SE_UNLOCK() +#else /* !SLJIT_SINGLE_THREADED */ +#include <pthread.h> +#define SLJIT_SE_LOCK() pthread_mutex_lock(&se_lock) +#define SLJIT_SE_UNLOCK() pthread_mutex_unlock(&se_lock) +#endif /* SLJIT_SINGLE_THREADED */ + +#ifndef SLJIT_PROT_WX +#define SLJIT_PROT_WX 0 +#endif /* !SLJIT_PROT_WX */ + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) +{ +#if !(defined SLJIT_SINGLE_THREADED && SLJIT_SINGLE_THREADED) + static pthread_mutex_t se_lock = PTHREAD_MUTEX_INITIALIZER; +#endif + static int se_protected = !SLJIT_PROT_WX; + sljit_uw* ptr; + + if (SLJIT_UNLIKELY(se_protected < 0)) + return NULL; + + size += sizeof(sljit_uw); + ptr = (sljit_uw*)mmap(NULL, size, PROT_READ | PROT_WRITE | SLJIT_PROT_WX, + MAP_PRIVATE | MAP_ANON, -1, 0); + + if (ptr == MAP_FAILED) + return NULL; + + if (SLJIT_UNLIKELY(se_protected > 0)) { + SLJIT_SE_LOCK(); + se_protected = check_se_protected(ptr, size); + SLJIT_SE_UNLOCK(); + if (SLJIT_UNLIKELY(se_protected < 0)) { + munmap((void *)ptr, size); + return NULL; + } + } + + *ptr++ = size; + return ptr; +} + +#undef SLJIT_PROT_WX +#undef SLJIT_SE_UNLOCK +#undef SLJIT_SE_LOCK + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) +{ + sljit_uw *start_ptr = ((sljit_uw*)ptr) - 1; + munmap((void*)start_ptr, *start_ptr); +} + +static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec) +{ + sljit_uw page_mask = (sljit_uw)get_page_alignment(); + sljit_uw start = (sljit_uw)from; + sljit_uw end = (sljit_uw)to; + int prot = PROT_READ | (enable_exec ? PROT_EXEC : PROT_WRITE); + + SLJIT_ASSERT(start < end); + + start &= ~page_mask; + end = (end + page_mask) & ~page_mask; + + mprotect((void*)start, end - start, prot); +} + +#else /* windows */ + +SLJIT_API_FUNC_ATTRIBUTE void* sljit_malloc_exec(sljit_uw size) +{ + sljit_uw *ptr; + + size += sizeof(sljit_uw); + ptr = (sljit_uw*)VirtualAlloc(NULL, size, + MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + + if (!ptr) + return NULL; + + *ptr++ = size; + + return ptr; +} + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_exec(void* ptr) +{ + sljit_uw start = (sljit_uw)ptr - sizeof(sljit_uw); +#if defined(SLJIT_DEBUG) && SLJIT_DEBUG + sljit_uw page_mask = (sljit_uw)get_page_alignment(); + + SLJIT_ASSERT(!(start & page_mask)); +#endif + VirtualFree((void*)start, 0, MEM_RELEASE); +} + +static void sljit_update_wx_flags(void *from, void *to, sljit_s32 enable_exec) +{ + DWORD oldprot; + sljit_uw page_mask = (sljit_uw)get_page_alignment(); + sljit_uw start = (sljit_uw)from; + sljit_uw end = (sljit_uw)to; + DWORD prot = enable_exec ? PAGE_EXECUTE : PAGE_READWRITE; + + SLJIT_ASSERT(start < end); + + start &= ~page_mask; + end = (end + page_mask) & ~page_mask; + + VirtualProtect((void*)start, end - start, prot, &oldprot); +} + +#endif /* !windows */ + +SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void) +{ + /* This allocator does not keep unused memory for future allocations. */ +} diff --git a/thirdparty/spirv-reflect/LICENSE b/thirdparty/spirv-reflect/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/thirdparty/spirv-reflect/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h b/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h index a61a2d2935..949f1980e7 100644 --- a/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h +++ b/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h @@ -1,5 +1,5 @@ /* -** Copyright (c) 2014-2018 The Khronos Group Inc. +** Copyright (c) 2014-2020 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and/or associated documentation files (the "Materials"), @@ -31,13 +31,16 @@ /* ** Enumeration tokens for SPIR-V, in various styles: -** C, C++, C++11, JSON, Lua, Python +** C, C++, C++11, JSON, Lua, Python, C#, D ** ** - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL ** - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL ** - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL ** - Lua will use tables, e.g.: spv.SourceLanguage.GLSL ** - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] +** - C# will use enum classes in the Specification class located in the "Spv" namespace, +** e.g.: Spv.Specification.SourceLanguage.GLSL +** - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL ** ** Some tokens act like mask values, which can be OR'd together, ** while others are mutually exclusive. The mask-like ones have @@ -50,12 +53,12 @@ typedef unsigned int SpvId; -#define SPV_VERSION 0x10300 -#define SPV_REVISION 1 +#define SPV_VERSION 0x10500 +#define SPV_REVISION 4 static const unsigned int SpvMagicNumber = 0x07230203; -static const unsigned int SpvVersion = 0x00010300; -static const unsigned int SpvRevision = 1; +static const unsigned int SpvVersion = 0x00010500; +static const unsigned int SpvRevision = 4; static const unsigned int SpvOpCodeMask = 0xffff; static const unsigned int SpvWordCountShift = 16; @@ -77,6 +80,20 @@ typedef enum SpvExecutionModel_ { SpvExecutionModelFragment = 4, SpvExecutionModelGLCompute = 5, SpvExecutionModelKernel = 6, + SpvExecutionModelTaskNV = 5267, + SpvExecutionModelMeshNV = 5268, + SpvExecutionModelRayGenerationKHR = 5313, + SpvExecutionModelRayGenerationNV = 5313, + SpvExecutionModelIntersectionKHR = 5314, + SpvExecutionModelIntersectionNV = 5314, + SpvExecutionModelAnyHitKHR = 5315, + SpvExecutionModelAnyHitNV = 5315, + SpvExecutionModelClosestHitKHR = 5316, + SpvExecutionModelClosestHitNV = 5316, + SpvExecutionModelMissKHR = 5317, + SpvExecutionModelMissNV = 5317, + SpvExecutionModelCallableKHR = 5318, + SpvExecutionModelCallableNV = 5318, SpvExecutionModelMax = 0x7fffffff, } SpvExecutionModel; @@ -84,6 +101,8 @@ typedef enum SpvAddressingModel_ { SpvAddressingModelLogical = 0, SpvAddressingModelPhysical32 = 1, SpvAddressingModelPhysical64 = 2, + SpvAddressingModelPhysicalStorageBuffer64 = 5348, + SpvAddressingModelPhysicalStorageBuffer64EXT = 5348, SpvAddressingModelMax = 0x7fffffff, } SpvAddressingModel; @@ -91,6 +110,8 @@ typedef enum SpvMemoryModel_ { SpvMemoryModelSimple = 0, SpvMemoryModelGLSL450 = 1, SpvMemoryModelOpenCL = 2, + SpvMemoryModelVulkan = 3, + SpvMemoryModelVulkanKHR = 3, SpvMemoryModelMax = 0x7fffffff, } SpvMemoryModel; @@ -134,7 +155,27 @@ typedef enum SpvExecutionMode_ { SpvExecutionModeLocalSizeId = 38, SpvExecutionModeLocalSizeHintId = 39, SpvExecutionModePostDepthCoverage = 4446, + SpvExecutionModeDenormPreserve = 4459, + SpvExecutionModeDenormFlushToZero = 4460, + SpvExecutionModeSignedZeroInfNanPreserve = 4461, + SpvExecutionModeRoundingModeRTE = 4462, + SpvExecutionModeRoundingModeRTZ = 4463, SpvExecutionModeStencilRefReplacingEXT = 5027, + SpvExecutionModeOutputLinesNV = 5269, + SpvExecutionModeOutputPrimitivesNV = 5270, + SpvExecutionModeDerivativeGroupQuadsNV = 5289, + SpvExecutionModeDerivativeGroupLinearNV = 5290, + SpvExecutionModeOutputTrianglesNV = 5298, + SpvExecutionModePixelInterlockOrderedEXT = 5366, + SpvExecutionModePixelInterlockUnorderedEXT = 5367, + SpvExecutionModeSampleInterlockOrderedEXT = 5368, + SpvExecutionModeSampleInterlockUnorderedEXT = 5369, + SpvExecutionModeShadingRateInterlockOrderedEXT = 5370, + SpvExecutionModeShadingRateInterlockUnorderedEXT = 5371, + SpvExecutionModeMaxWorkgroupSizeINTEL = 5893, + SpvExecutionModeMaxWorkDimINTEL = 5894, + SpvExecutionModeNoGlobalOffsetINTEL = 5895, + SpvExecutionModeNumSIMDWorkitemsINTEL = 5896, SpvExecutionModeMax = 0x7fffffff, } SpvExecutionMode; @@ -152,6 +193,21 @@ typedef enum SpvStorageClass_ { SpvStorageClassAtomicCounter = 10, SpvStorageClassImage = 11, SpvStorageClassStorageBuffer = 12, + SpvStorageClassCallableDataKHR = 5328, + SpvStorageClassCallableDataNV = 5328, + SpvStorageClassIncomingCallableDataKHR = 5329, + SpvStorageClassIncomingCallableDataNV = 5329, + SpvStorageClassRayPayloadKHR = 5338, + SpvStorageClassRayPayloadNV = 5338, + SpvStorageClassHitAttributeKHR = 5339, + SpvStorageClassHitAttributeNV = 5339, + SpvStorageClassIncomingRayPayloadKHR = 5342, + SpvStorageClassIncomingRayPayloadNV = 5342, + SpvStorageClassShaderRecordBufferKHR = 5343, + SpvStorageClassShaderRecordBufferNV = 5343, + SpvStorageClassPhysicalStorageBuffer = 5349, + SpvStorageClassPhysicalStorageBufferEXT = 5349, + SpvStorageClassCodeSectionINTEL = 5605, SpvStorageClassMax = 0x7fffffff, } SpvStorageClass; @@ -222,6 +278,8 @@ typedef enum SpvImageFormat_ { SpvImageFormatRg8ui = 37, SpvImageFormatR16ui = 38, SpvImageFormatR8ui = 39, + SpvImageFormatR64ui = 40, + SpvImageFormatR64i = 41, SpvImageFormatMax = 0x7fffffff, } SpvImageFormat; @@ -279,6 +337,16 @@ typedef enum SpvImageOperandsShift_ { SpvImageOperandsConstOffsetsShift = 5, SpvImageOperandsSampleShift = 6, SpvImageOperandsMinLodShift = 7, + SpvImageOperandsMakeTexelAvailableShift = 8, + SpvImageOperandsMakeTexelAvailableKHRShift = 8, + SpvImageOperandsMakeTexelVisibleShift = 9, + SpvImageOperandsMakeTexelVisibleKHRShift = 9, + SpvImageOperandsNonPrivateTexelShift = 10, + SpvImageOperandsNonPrivateTexelKHRShift = 10, + SpvImageOperandsVolatileTexelShift = 11, + SpvImageOperandsVolatileTexelKHRShift = 11, + SpvImageOperandsSignExtendShift = 12, + SpvImageOperandsZeroExtendShift = 13, SpvImageOperandsMax = 0x7fffffff, } SpvImageOperandsShift; @@ -292,6 +360,16 @@ typedef enum SpvImageOperandsMask_ { SpvImageOperandsConstOffsetsMask = 0x00000020, SpvImageOperandsSampleMask = 0x00000040, SpvImageOperandsMinLodMask = 0x00000080, + SpvImageOperandsMakeTexelAvailableMask = 0x00000100, + SpvImageOperandsMakeTexelAvailableKHRMask = 0x00000100, + SpvImageOperandsMakeTexelVisibleMask = 0x00000200, + SpvImageOperandsMakeTexelVisibleKHRMask = 0x00000200, + SpvImageOperandsNonPrivateTexelMask = 0x00000400, + SpvImageOperandsNonPrivateTexelKHRMask = 0x00000400, + SpvImageOperandsVolatileTexelMask = 0x00000800, + SpvImageOperandsVolatileTexelKHRMask = 0x00000800, + SpvImageOperandsSignExtendMask = 0x00001000, + SpvImageOperandsZeroExtendMask = 0x00002000, } SpvImageOperandsMask; typedef enum SpvFPFastMathModeShift_ { @@ -372,6 +450,7 @@ typedef enum SpvDecoration_ { SpvDecorationNonWritable = 24, SpvDecorationNonReadable = 25, SpvDecorationUniform = 26, + SpvDecorationUniformId = 27, SpvDecorationSaturatedConversion = 28, SpvDecorationStream = 29, SpvDecorationLocation = 30, @@ -392,13 +471,41 @@ typedef enum SpvDecoration_ { SpvDecorationMaxByteOffset = 45, SpvDecorationAlignmentId = 46, SpvDecorationMaxByteOffsetId = 47, + SpvDecorationNoSignedWrap = 4469, + SpvDecorationNoUnsignedWrap = 4470, SpvDecorationExplicitInterpAMD = 4999, SpvDecorationOverrideCoverageNV = 5248, SpvDecorationPassthroughNV = 5250, SpvDecorationViewportRelativeNV = 5252, SpvDecorationSecondaryViewportRelativeNV = 5256, + SpvDecorationPerPrimitiveNV = 5271, + SpvDecorationPerViewNV = 5272, + SpvDecorationPerTaskNV = 5273, + SpvDecorationPerVertexNV = 5285, + SpvDecorationNonUniform = 5300, + SpvDecorationNonUniformEXT = 5300, + SpvDecorationRestrictPointer = 5355, + SpvDecorationRestrictPointerEXT = 5355, + SpvDecorationAliasedPointer = 5356, + SpvDecorationAliasedPointerEXT = 5356, + SpvDecorationReferencedIndirectlyINTEL = 5602, + SpvDecorationCounterBuffer = 5634, SpvDecorationHlslCounterBufferGOOGLE = 5634, SpvDecorationHlslSemanticGOOGLE = 5635, + SpvDecorationUserSemantic = 5635, + SpvDecorationUserTypeGOOGLE = 5636, + SpvDecorationRegisterINTEL = 5825, + SpvDecorationMemoryINTEL = 5826, + SpvDecorationNumbanksINTEL = 5827, + SpvDecorationBankwidthINTEL = 5828, + SpvDecorationMaxPrivateCopiesINTEL = 5829, + SpvDecorationSinglepumpINTEL = 5830, + SpvDecorationDoublepumpINTEL = 5831, + SpvDecorationMaxReplicatesINTEL = 5832, + SpvDecorationSimpleDualPortINTEL = 5833, + SpvDecorationMergeINTEL = 5834, + SpvDecorationBankBitsINTEL = 5835, + SpvDecorationForcePow2DepthINTEL = 5836, SpvDecorationMax = 0x7fffffff, } SpvDecoration; @@ -457,8 +564,10 @@ typedef enum SpvBuiltIn_ { SpvBuiltInBaseVertex = 4424, SpvBuiltInBaseInstance = 4425, SpvBuiltInDrawIndex = 4426, + SpvBuiltInPrimitiveShadingRateKHR = 4432, SpvBuiltInDeviceIndex = 4438, SpvBuiltInViewIndex = 4440, + SpvBuiltInShadingRateKHR = 4444, SpvBuiltInBaryCoordNoPerspAMD = 4992, SpvBuiltInBaryCoordNoPerspCentroidAMD = 4993, SpvBuiltInBaryCoordNoPerspSampleAMD = 4994, @@ -473,6 +582,52 @@ typedef enum SpvBuiltIn_ { SpvBuiltInPositionPerViewNV = 5261, SpvBuiltInViewportMaskPerViewNV = 5262, SpvBuiltInFullyCoveredEXT = 5264, + SpvBuiltInTaskCountNV = 5274, + SpvBuiltInPrimitiveCountNV = 5275, + SpvBuiltInPrimitiveIndicesNV = 5276, + SpvBuiltInClipDistancePerViewNV = 5277, + SpvBuiltInCullDistancePerViewNV = 5278, + SpvBuiltInLayerPerViewNV = 5279, + SpvBuiltInMeshViewCountNV = 5280, + SpvBuiltInMeshViewIndicesNV = 5281, + SpvBuiltInBaryCoordNV = 5286, + SpvBuiltInBaryCoordNoPerspNV = 5287, + SpvBuiltInFragSizeEXT = 5292, + SpvBuiltInFragmentSizeNV = 5292, + SpvBuiltInFragInvocationCountEXT = 5293, + SpvBuiltInInvocationsPerPixelNV = 5293, + SpvBuiltInLaunchIdKHR = 5319, + SpvBuiltInLaunchIdNV = 5319, + SpvBuiltInLaunchSizeKHR = 5320, + SpvBuiltInLaunchSizeNV = 5320, + SpvBuiltInWorldRayOriginKHR = 5321, + SpvBuiltInWorldRayOriginNV = 5321, + SpvBuiltInWorldRayDirectionKHR = 5322, + SpvBuiltInWorldRayDirectionNV = 5322, + SpvBuiltInObjectRayOriginKHR = 5323, + SpvBuiltInObjectRayOriginNV = 5323, + SpvBuiltInObjectRayDirectionKHR = 5324, + SpvBuiltInObjectRayDirectionNV = 5324, + SpvBuiltInRayTminKHR = 5325, + SpvBuiltInRayTminNV = 5325, + SpvBuiltInRayTmaxKHR = 5326, + SpvBuiltInRayTmaxNV = 5326, + SpvBuiltInInstanceCustomIndexKHR = 5327, + SpvBuiltInInstanceCustomIndexNV = 5327, + SpvBuiltInObjectToWorldKHR = 5330, + SpvBuiltInObjectToWorldNV = 5330, + SpvBuiltInWorldToObjectKHR = 5331, + SpvBuiltInWorldToObjectNV = 5331, + SpvBuiltInHitTNV = 5332, + SpvBuiltInHitKindKHR = 5333, + SpvBuiltInHitKindNV = 5333, + SpvBuiltInIncomingRayFlagsKHR = 5351, + SpvBuiltInIncomingRayFlagsNV = 5351, + SpvBuiltInRayGeometryIndexKHR = 5352, + SpvBuiltInWarpsPerSMNV = 5374, + SpvBuiltInSMCountNV = 5375, + SpvBuiltInWarpIDNV = 5376, + SpvBuiltInSMIDNV = 5377, SpvBuiltInMax = 0x7fffffff, } SpvBuiltIn; @@ -493,6 +648,18 @@ typedef enum SpvLoopControlShift_ { SpvLoopControlDontUnrollShift = 1, SpvLoopControlDependencyInfiniteShift = 2, SpvLoopControlDependencyLengthShift = 3, + SpvLoopControlMinIterationsShift = 4, + SpvLoopControlMaxIterationsShift = 5, + SpvLoopControlIterationMultipleShift = 6, + SpvLoopControlPeelCountShift = 7, + SpvLoopControlPartialCountShift = 8, + SpvLoopControlInitiationIntervalINTELShift = 16, + SpvLoopControlMaxConcurrencyINTELShift = 17, + SpvLoopControlDependencyArrayINTELShift = 18, + SpvLoopControlPipelineEnableINTELShift = 19, + SpvLoopControlLoopCoalesceINTELShift = 20, + SpvLoopControlMaxInterleavingINTELShift = 21, + SpvLoopControlSpeculatedIterationsINTELShift = 22, SpvLoopControlMax = 0x7fffffff, } SpvLoopControlShift; @@ -502,6 +669,18 @@ typedef enum SpvLoopControlMask_ { SpvLoopControlDontUnrollMask = 0x00000002, SpvLoopControlDependencyInfiniteMask = 0x00000004, SpvLoopControlDependencyLengthMask = 0x00000008, + SpvLoopControlMinIterationsMask = 0x00000010, + SpvLoopControlMaxIterationsMask = 0x00000020, + SpvLoopControlIterationMultipleMask = 0x00000040, + SpvLoopControlPeelCountMask = 0x00000080, + SpvLoopControlPartialCountMask = 0x00000100, + SpvLoopControlInitiationIntervalINTELMask = 0x00010000, + SpvLoopControlMaxConcurrencyINTELMask = 0x00020000, + SpvLoopControlDependencyArrayINTELMask = 0x00040000, + SpvLoopControlPipelineEnableINTELMask = 0x00080000, + SpvLoopControlLoopCoalesceINTELMask = 0x00100000, + SpvLoopControlMaxInterleavingINTELMask = 0x00200000, + SpvLoopControlSpeculatedIterationsINTELMask = 0x00400000, } SpvLoopControlMask; typedef enum SpvFunctionControlShift_ { @@ -531,6 +710,13 @@ typedef enum SpvMemorySemanticsShift_ { SpvMemorySemanticsCrossWorkgroupMemoryShift = 9, SpvMemorySemanticsAtomicCounterMemoryShift = 10, SpvMemorySemanticsImageMemoryShift = 11, + SpvMemorySemanticsOutputMemoryShift = 12, + SpvMemorySemanticsOutputMemoryKHRShift = 12, + SpvMemorySemanticsMakeAvailableShift = 13, + SpvMemorySemanticsMakeAvailableKHRShift = 13, + SpvMemorySemanticsMakeVisibleShift = 14, + SpvMemorySemanticsMakeVisibleKHRShift = 14, + SpvMemorySemanticsVolatileShift = 15, SpvMemorySemanticsMax = 0x7fffffff, } SpvMemorySemanticsShift; @@ -546,12 +732,25 @@ typedef enum SpvMemorySemanticsMask_ { SpvMemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, SpvMemorySemanticsAtomicCounterMemoryMask = 0x00000400, SpvMemorySemanticsImageMemoryMask = 0x00000800, + SpvMemorySemanticsOutputMemoryMask = 0x00001000, + SpvMemorySemanticsOutputMemoryKHRMask = 0x00001000, + SpvMemorySemanticsMakeAvailableMask = 0x00002000, + SpvMemorySemanticsMakeAvailableKHRMask = 0x00002000, + SpvMemorySemanticsMakeVisibleMask = 0x00004000, + SpvMemorySemanticsMakeVisibleKHRMask = 0x00004000, + SpvMemorySemanticsVolatileMask = 0x00008000, } SpvMemorySemanticsMask; typedef enum SpvMemoryAccessShift_ { SpvMemoryAccessVolatileShift = 0, SpvMemoryAccessAlignedShift = 1, SpvMemoryAccessNontemporalShift = 2, + SpvMemoryAccessMakePointerAvailableShift = 3, + SpvMemoryAccessMakePointerAvailableKHRShift = 3, + SpvMemoryAccessMakePointerVisibleShift = 4, + SpvMemoryAccessMakePointerVisibleKHRShift = 4, + SpvMemoryAccessNonPrivatePointerShift = 5, + SpvMemoryAccessNonPrivatePointerKHRShift = 5, SpvMemoryAccessMax = 0x7fffffff, } SpvMemoryAccessShift; @@ -560,6 +759,12 @@ typedef enum SpvMemoryAccessMask_ { SpvMemoryAccessVolatileMask = 0x00000001, SpvMemoryAccessAlignedMask = 0x00000002, SpvMemoryAccessNontemporalMask = 0x00000004, + SpvMemoryAccessMakePointerAvailableMask = 0x00000008, + SpvMemoryAccessMakePointerAvailableKHRMask = 0x00000008, + SpvMemoryAccessMakePointerVisibleMask = 0x00000010, + SpvMemoryAccessMakePointerVisibleKHRMask = 0x00000010, + SpvMemoryAccessNonPrivatePointerMask = 0x00000020, + SpvMemoryAccessNonPrivatePointerKHRMask = 0x00000020, } SpvMemoryAccessMask; typedef enum SpvScope_ { @@ -568,6 +773,9 @@ typedef enum SpvScope_ { SpvScopeWorkgroup = 2, SpvScopeSubgroup = 3, SpvScopeInvocation = 4, + SpvScopeQueueFamily = 5, + SpvScopeQueueFamilyKHR = 5, + SpvScopeShaderCallKHR = 6, SpvScopeMax = 0x7fffffff, } SpvScope; @@ -667,6 +875,9 @@ typedef enum SpvCapability_ { SpvCapabilityGroupNonUniformShuffleRelative = 66, SpvCapabilityGroupNonUniformClustered = 67, SpvCapabilityGroupNonUniformQuad = 68, + SpvCapabilityShaderLayer = 69, + SpvCapabilityShaderViewportIndex = 70, + SpvCapabilityFragmentShadingRateKHR = 4422, SpvCapabilitySubgroupBallotKHR = 4423, SpvCapabilityDrawParameters = 4427, SpvCapabilitySubgroupVoteKHR = 4431, @@ -682,11 +893,25 @@ typedef enum SpvCapability_ { SpvCapabilityVariablePointers = 4442, SpvCapabilityAtomicStorageOps = 4445, SpvCapabilitySampleMaskPostDepthCoverage = 4447, + SpvCapabilityStorageBuffer8BitAccess = 4448, + SpvCapabilityUniformAndStorageBuffer8BitAccess = 4449, + SpvCapabilityStoragePushConstant8 = 4450, + SpvCapabilityDenormPreserve = 4464, + SpvCapabilityDenormFlushToZero = 4465, + SpvCapabilitySignedZeroInfNanPreserve = 4466, + SpvCapabilityRoundingModeRTE = 4467, + SpvCapabilityRoundingModeRTZ = 4468, + SpvCapabilityRayQueryProvisionalKHR = 4471, + SpvCapabilityRayQueryKHR = 4472, + SpvCapabilityRayTraversalPrimitiveCullingKHR = 4478, + SpvCapabilityRayTracingKHR = 4479, SpvCapabilityFloat16ImageAMD = 5008, SpvCapabilityImageGatherBiasLodAMD = 5009, SpvCapabilityFragmentMaskAMD = 5010, SpvCapabilityStencilExportEXT = 5013, SpvCapabilityImageReadWriteLodAMD = 5015, + SpvCapabilityInt64ImageEXT = 5016, + SpvCapabilityShaderClockKHR = 5055, SpvCapabilitySampleMaskOverrideCoverageNV = 5249, SpvCapabilityGeometryShaderPassthroughNV = 5251, SpvCapabilityShaderViewportIndexLayerEXT = 5254, @@ -695,13 +920,137 @@ typedef enum SpvCapability_ { SpvCapabilityShaderStereoViewNV = 5259, SpvCapabilityPerViewAttributesNV = 5260, SpvCapabilityFragmentFullyCoveredEXT = 5265, + SpvCapabilityMeshShadingNV = 5266, + SpvCapabilityImageFootprintNV = 5282, + SpvCapabilityFragmentBarycentricNV = 5284, + SpvCapabilityComputeDerivativeGroupQuadsNV = 5288, + SpvCapabilityFragmentDensityEXT = 5291, + SpvCapabilityShadingRateNV = 5291, SpvCapabilityGroupNonUniformPartitionedNV = 5297, + SpvCapabilityShaderNonUniform = 5301, + SpvCapabilityShaderNonUniformEXT = 5301, + SpvCapabilityRuntimeDescriptorArray = 5302, + SpvCapabilityRuntimeDescriptorArrayEXT = 5302, + SpvCapabilityInputAttachmentArrayDynamicIndexing = 5303, + SpvCapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, + SpvCapabilityUniformTexelBufferArrayDynamicIndexing = 5304, + SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, + SpvCapabilityStorageTexelBufferArrayDynamicIndexing = 5305, + SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, + SpvCapabilityUniformBufferArrayNonUniformIndexing = 5306, + SpvCapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, + SpvCapabilitySampledImageArrayNonUniformIndexing = 5307, + SpvCapabilitySampledImageArrayNonUniformIndexingEXT = 5307, + SpvCapabilityStorageBufferArrayNonUniformIndexing = 5308, + SpvCapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, + SpvCapabilityStorageImageArrayNonUniformIndexing = 5309, + SpvCapabilityStorageImageArrayNonUniformIndexingEXT = 5309, + SpvCapabilityInputAttachmentArrayNonUniformIndexing = 5310, + SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, + SpvCapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, + SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, + SpvCapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, + SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, + SpvCapabilityRayTracingNV = 5340, + SpvCapabilityVulkanMemoryModel = 5345, + SpvCapabilityVulkanMemoryModelKHR = 5345, + SpvCapabilityVulkanMemoryModelDeviceScope = 5346, + SpvCapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + SpvCapabilityPhysicalStorageBufferAddresses = 5347, + SpvCapabilityPhysicalStorageBufferAddressesEXT = 5347, + SpvCapabilityComputeDerivativeGroupLinearNV = 5350, + SpvCapabilityRayTracingProvisionalKHR = 5353, + SpvCapabilityCooperativeMatrixNV = 5357, + SpvCapabilityFragmentShaderSampleInterlockEXT = 5363, + SpvCapabilityFragmentShaderShadingRateInterlockEXT = 5372, + SpvCapabilityShaderSMBuiltinsNV = 5373, + SpvCapabilityFragmentShaderPixelInterlockEXT = 5378, + SpvCapabilityDemoteToHelperInvocationEXT = 5379, SpvCapabilitySubgroupShuffleINTEL = 5568, SpvCapabilitySubgroupBufferBlockIOINTEL = 5569, SpvCapabilitySubgroupImageBlockIOINTEL = 5570, + SpvCapabilitySubgroupImageMediaBlockIOINTEL = 5579, + SpvCapabilityIntegerFunctions2INTEL = 5584, + SpvCapabilityFunctionPointersINTEL = 5603, + SpvCapabilityIndirectReferencesINTEL = 5604, + SpvCapabilitySubgroupAvcMotionEstimationINTEL = 5696, + SpvCapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, + SpvCapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, + SpvCapabilityFPGAMemoryAttributesINTEL = 5824, + SpvCapabilityUnstructuredLoopControlsINTEL = 5886, + SpvCapabilityFPGALoopControlsINTEL = 5888, + SpvCapabilityKernelAttributesINTEL = 5892, + SpvCapabilityFPGAKernelAttributesINTEL = 5897, + SpvCapabilityBlockingPipesINTEL = 5945, + SpvCapabilityFPGARegINTEL = 5948, + SpvCapabilityAtomicFloat32AddEXT = 6033, + SpvCapabilityAtomicFloat64AddEXT = 6034, SpvCapabilityMax = 0x7fffffff, } SpvCapability; +typedef enum SpvRayFlagsShift_ { + SpvRayFlagsOpaqueKHRShift = 0, + SpvRayFlagsNoOpaqueKHRShift = 1, + SpvRayFlagsTerminateOnFirstHitKHRShift = 2, + SpvRayFlagsSkipClosestHitShaderKHRShift = 3, + SpvRayFlagsCullBackFacingTrianglesKHRShift = 4, + SpvRayFlagsCullFrontFacingTrianglesKHRShift = 5, + SpvRayFlagsCullOpaqueKHRShift = 6, + SpvRayFlagsCullNoOpaqueKHRShift = 7, + SpvRayFlagsSkipTrianglesKHRShift = 8, + SpvRayFlagsSkipAABBsKHRShift = 9, + SpvRayFlagsMax = 0x7fffffff, +} SpvRayFlagsShift; + +typedef enum SpvRayFlagsMask_ { + SpvRayFlagsMaskNone = 0, + SpvRayFlagsOpaqueKHRMask = 0x00000001, + SpvRayFlagsNoOpaqueKHRMask = 0x00000002, + SpvRayFlagsTerminateOnFirstHitKHRMask = 0x00000004, + SpvRayFlagsSkipClosestHitShaderKHRMask = 0x00000008, + SpvRayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, + SpvRayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, + SpvRayFlagsCullOpaqueKHRMask = 0x00000040, + SpvRayFlagsCullNoOpaqueKHRMask = 0x00000080, + SpvRayFlagsSkipTrianglesKHRMask = 0x00000100, + SpvRayFlagsSkipAABBsKHRMask = 0x00000200, +} SpvRayFlagsMask; + +typedef enum SpvRayQueryIntersection_ { + SpvRayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, + SpvRayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, + SpvRayQueryIntersectionMax = 0x7fffffff, +} SpvRayQueryIntersection; + +typedef enum SpvRayQueryCommittedIntersectionType_ { + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, + SpvRayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, + SpvRayQueryCommittedIntersectionTypeMax = 0x7fffffff, +} SpvRayQueryCommittedIntersectionType; + +typedef enum SpvRayQueryCandidateIntersectionType_ { + SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, + SpvRayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, + SpvRayQueryCandidateIntersectionTypeMax = 0x7fffffff, +} SpvRayQueryCandidateIntersectionType; + +typedef enum SpvFragmentShadingRateShift_ { + SpvFragmentShadingRateVertical2PixelsShift = 0, + SpvFragmentShadingRateVertical4PixelsShift = 1, + SpvFragmentShadingRateHorizontal2PixelsShift = 2, + SpvFragmentShadingRateHorizontal4PixelsShift = 3, + SpvFragmentShadingRateMax = 0x7fffffff, +} SpvFragmentShadingRateShift; + +typedef enum SpvFragmentShadingRateMask_ { + SpvFragmentShadingRateMaskNone = 0, + SpvFragmentShadingRateVertical2PixelsMask = 0x00000001, + SpvFragmentShadingRateVertical4PixelsMask = 0x00000002, + SpvFragmentShadingRateHorizontal2PixelsMask = 0x00000004, + SpvFragmentShadingRateHorizontal4PixelsMask = 0x00000008, +} SpvFragmentShadingRateMask; + typedef enum SpvOp_ { SpvOpNop = 0, SpvOpUndef = 1, @@ -1043,12 +1392,29 @@ typedef enum SpvOp_ { SpvOpGroupNonUniformLogicalXor = 364, SpvOpGroupNonUniformQuadBroadcast = 365, SpvOpGroupNonUniformQuadSwap = 366, + SpvOpCopyLogical = 400, + SpvOpPtrEqual = 401, + SpvOpPtrNotEqual = 402, + SpvOpPtrDiff = 403, + SpvOpTerminateInvocation = 4416, SpvOpSubgroupBallotKHR = 4421, SpvOpSubgroupFirstInvocationKHR = 4422, SpvOpSubgroupAllKHR = 4428, SpvOpSubgroupAnyKHR = 4429, SpvOpSubgroupAllEqualKHR = 4430, SpvOpSubgroupReadInvocationKHR = 4432, + SpvOpTraceRayKHR = 4445, + SpvOpExecuteCallableKHR = 4446, + SpvOpConvertUToAccelerationStructureKHR = 4447, + SpvOpIgnoreIntersectionKHR = 4448, + SpvOpTerminateRayKHR = 4449, + SpvOpTypeRayQueryKHR = 4472, + SpvOpRayQueryInitializeKHR = 4473, + SpvOpRayQueryTerminateKHR = 4474, + SpvOpRayQueryGenerateIntersectionKHR = 4475, + SpvOpRayQueryConfirmIntersectionKHR = 4476, + SpvOpRayQueryProceedKHR = 4477, + SpvOpRayQueryGetIntersectionTypeKHR = 4479, SpvOpGroupIAddNonUniformAMD = 5000, SpvOpGroupFAddNonUniformAMD = 5001, SpvOpGroupFMinNonUniformAMD = 5002, @@ -1059,7 +1425,27 @@ typedef enum SpvOp_ { SpvOpGroupSMaxNonUniformAMD = 5007, SpvOpFragmentMaskFetchAMD = 5011, SpvOpFragmentFetchAMD = 5012, + SpvOpReadClockKHR = 5056, + SpvOpImageSampleFootprintNV = 5283, SpvOpGroupNonUniformPartitionNV = 5296, + SpvOpWritePackedPrimitiveIndices4x8NV = 5299, + SpvOpReportIntersectionKHR = 5334, + SpvOpReportIntersectionNV = 5334, + SpvOpIgnoreIntersectionNV = 5335, + SpvOpTerminateRayNV = 5336, + SpvOpTraceNV = 5337, + SpvOpTypeAccelerationStructureKHR = 5341, + SpvOpTypeAccelerationStructureNV = 5341, + SpvOpExecuteCallableNV = 5344, + SpvOpTypeCooperativeMatrixNV = 5358, + SpvOpCooperativeMatrixLoadNV = 5359, + SpvOpCooperativeMatrixStoreNV = 5360, + SpvOpCooperativeMatrixMulAddNV = 5361, + SpvOpCooperativeMatrixLengthNV = 5362, + SpvOpBeginInvocationInterlockEXT = 5364, + SpvOpEndInvocationInterlockEXT = 5365, + SpvOpDemoteToHelperInvocationEXT = 5380, + SpvOpIsHelperInvocationEXT = 5381, SpvOpSubgroupShuffleINTEL = 5571, SpvOpSubgroupShuffleDownINTEL = 5572, SpvOpSubgroupShuffleUpINTEL = 5573, @@ -1068,10 +1454,739 @@ typedef enum SpvOp_ { SpvOpSubgroupBlockWriteINTEL = 5576, SpvOpSubgroupImageBlockReadINTEL = 5577, SpvOpSubgroupImageBlockWriteINTEL = 5578, + SpvOpSubgroupImageMediaBlockReadINTEL = 5580, + SpvOpSubgroupImageMediaBlockWriteINTEL = 5581, + SpvOpUCountLeadingZerosINTEL = 5585, + SpvOpUCountTrailingZerosINTEL = 5586, + SpvOpAbsISubINTEL = 5587, + SpvOpAbsUSubINTEL = 5588, + SpvOpIAddSatINTEL = 5589, + SpvOpUAddSatINTEL = 5590, + SpvOpIAverageINTEL = 5591, + SpvOpUAverageINTEL = 5592, + SpvOpIAverageRoundedINTEL = 5593, + SpvOpUAverageRoundedINTEL = 5594, + SpvOpISubSatINTEL = 5595, + SpvOpUSubSatINTEL = 5596, + SpvOpIMul32x16INTEL = 5597, + SpvOpUMul32x16INTEL = 5598, + SpvOpFunctionPointerINTEL = 5600, + SpvOpFunctionPointerCallINTEL = 5601, + SpvOpDecorateString = 5632, SpvOpDecorateStringGOOGLE = 5632, + SpvOpMemberDecorateString = 5633, SpvOpMemberDecorateStringGOOGLE = 5633, + SpvOpVmeImageINTEL = 5699, + SpvOpTypeVmeImageINTEL = 5700, + SpvOpTypeAvcImePayloadINTEL = 5701, + SpvOpTypeAvcRefPayloadINTEL = 5702, + SpvOpTypeAvcSicPayloadINTEL = 5703, + SpvOpTypeAvcMcePayloadINTEL = 5704, + SpvOpTypeAvcMceResultINTEL = 5705, + SpvOpTypeAvcImeResultINTEL = 5706, + SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, + SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, + SpvOpTypeAvcImeSingleReferenceStreaminINTEL = 5709, + SpvOpTypeAvcImeDualReferenceStreaminINTEL = 5710, + SpvOpTypeAvcRefResultINTEL = 5711, + SpvOpTypeAvcSicResultINTEL = 5712, + SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, + SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, + SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, + SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, + SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, + SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, + SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, + SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, + SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, + SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, + SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, + SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, + SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, + SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, + SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, + SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, + SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, + SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, + SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, + SpvOpSubgroupAvcMceConvertToImePayloadINTEL = 5732, + SpvOpSubgroupAvcMceConvertToImeResultINTEL = 5733, + SpvOpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, + SpvOpSubgroupAvcMceConvertToRefResultINTEL = 5735, + SpvOpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, + SpvOpSubgroupAvcMceConvertToSicResultINTEL = 5737, + SpvOpSubgroupAvcMceGetMotionVectorsINTEL = 5738, + SpvOpSubgroupAvcMceGetInterDistortionsINTEL = 5739, + SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, + SpvOpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, + SpvOpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, + SpvOpSubgroupAvcMceGetInterDirectionsINTEL = 5743, + SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, + SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, + SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, + SpvOpSubgroupAvcImeInitializeINTEL = 5747, + SpvOpSubgroupAvcImeSetSingleReferenceINTEL = 5748, + SpvOpSubgroupAvcImeSetDualReferenceINTEL = 5749, + SpvOpSubgroupAvcImeRefWindowSizeINTEL = 5750, + SpvOpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, + SpvOpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, + SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, + SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, + SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, + SpvOpSubgroupAvcImeSetWeightedSadINTEL = 5756, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, + SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, + SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, + SpvOpSubgroupAvcImeConvertToMceResultINTEL = 5765, + SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, + SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, + SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, + SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, + SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, + SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, + SpvOpSubgroupAvcImeGetBorderReachedINTEL = 5776, + SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, + SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, + SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, + SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, + SpvOpSubgroupAvcFmeInitializeINTEL = 5781, + SpvOpSubgroupAvcBmeInitializeINTEL = 5782, + SpvOpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, + SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, + SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, + SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, + SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, + SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, + SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, + SpvOpSubgroupAvcRefConvertToMceResultINTEL = 5790, + SpvOpSubgroupAvcSicInitializeINTEL = 5791, + SpvOpSubgroupAvcSicConfigureSkcINTEL = 5792, + SpvOpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, + SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, + SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, + SpvOpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, + SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, + SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, + SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, + SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, + SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, + SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, + SpvOpSubgroupAvcSicEvaluateIpeINTEL = 5803, + SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, + SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, + SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, + SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, + SpvOpSubgroupAvcSicConvertToMceResultINTEL = 5808, + SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, + SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, + SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, + SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, + SpvOpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, + SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, + SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, + SpvOpSubgroupAvcSicGetInterRawSadsINTEL = 5816, + SpvOpLoopControlINTEL = 5887, + SpvOpReadPipeBlockingINTEL = 5946, + SpvOpWritePipeBlockingINTEL = 5947, + SpvOpFPGARegINTEL = 5949, + SpvOpRayQueryGetRayTMinKHR = 6016, + SpvOpRayQueryGetRayFlagsKHR = 6017, + SpvOpRayQueryGetIntersectionTKHR = 6018, + SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, + SpvOpRayQueryGetIntersectionInstanceIdKHR = 6020, + SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, + SpvOpRayQueryGetIntersectionGeometryIndexKHR = 6022, + SpvOpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, + SpvOpRayQueryGetIntersectionBarycentricsKHR = 6024, + SpvOpRayQueryGetIntersectionFrontFaceKHR = 6025, + SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, + SpvOpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, + SpvOpRayQueryGetIntersectionObjectRayOriginKHR = 6028, + SpvOpRayQueryGetWorldRayDirectionKHR = 6029, + SpvOpRayQueryGetWorldRayOriginKHR = 6030, + SpvOpRayQueryGetIntersectionObjectToWorldKHR = 6031, + SpvOpRayQueryGetIntersectionWorldToObjectKHR = 6032, + SpvOpAtomicFAddEXT = 6035, SpvOpMax = 0x7fffffff, } SpvOp; -#endif // #ifndef spirv_H +#ifdef SPV_ENABLE_UTILITY_CODE +inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultType) { + *hasResult = *hasResultType = false; + switch (opcode) { + default: /* unknown opcode */ break; + case SpvOpNop: *hasResult = false; *hasResultType = false; break; + case SpvOpUndef: *hasResult = true; *hasResultType = true; break; + case SpvOpSourceContinued: *hasResult = false; *hasResultType = false; break; + case SpvOpSource: *hasResult = false; *hasResultType = false; break; + case SpvOpSourceExtension: *hasResult = false; *hasResultType = false; break; + case SpvOpName: *hasResult = false; *hasResultType = false; break; + case SpvOpMemberName: *hasResult = false; *hasResultType = false; break; + case SpvOpString: *hasResult = true; *hasResultType = false; break; + case SpvOpLine: *hasResult = false; *hasResultType = false; break; + case SpvOpExtension: *hasResult = false; *hasResultType = false; break; + case SpvOpExtInstImport: *hasResult = true; *hasResultType = false; break; + case SpvOpExtInst: *hasResult = true; *hasResultType = true; break; + case SpvOpMemoryModel: *hasResult = false; *hasResultType = false; break; + case SpvOpEntryPoint: *hasResult = false; *hasResultType = false; break; + case SpvOpExecutionMode: *hasResult = false; *hasResultType = false; break; + case SpvOpCapability: *hasResult = false; *hasResultType = false; break; + case SpvOpTypeVoid: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeBool: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeInt: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeFloat: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeVector: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeMatrix: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeImage: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeSampler: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeSampledImage: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeArray: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeStruct: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeOpaque: *hasResult = true; *hasResultType = false; break; + case SpvOpTypePointer: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeFunction: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeEvent: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeReserveId: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeQueue: *hasResult = true; *hasResultType = false; break; + case SpvOpTypePipe: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; + case SpvOpConstantTrue: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantFalse: *hasResult = true; *hasResultType = true; break; + case SpvOpConstant: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantComposite: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantSampler: *hasResult = true; *hasResultType = true; break; + case SpvOpConstantNull: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstant: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; + case SpvOpSpecConstantOp: *hasResult = true; *hasResultType = true; break; + case SpvOpFunction: *hasResult = true; *hasResultType = true; break; + case SpvOpFunctionParameter: *hasResult = true; *hasResultType = true; break; + case SpvOpFunctionEnd: *hasResult = false; *hasResultType = false; break; + case SpvOpFunctionCall: *hasResult = true; *hasResultType = true; break; + case SpvOpVariable: *hasResult = true; *hasResultType = true; break; + case SpvOpImageTexelPointer: *hasResult = true; *hasResultType = true; break; + case SpvOpLoad: *hasResult = true; *hasResultType = true; break; + case SpvOpStore: *hasResult = false; *hasResultType = false; break; + case SpvOpCopyMemory: *hasResult = false; *hasResultType = false; break; + case SpvOpCopyMemorySized: *hasResult = false; *hasResultType = false; break; + case SpvOpAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpArrayLength: *hasResult = true; *hasResultType = true; break; + case SpvOpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; + case SpvOpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; + case SpvOpDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpMemberDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpDecorationGroup: *hasResult = true; *hasResultType = false; break; + case SpvOpGroupDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; + case SpvOpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorShuffle: *hasResult = true; *hasResultType = true; break; + case SpvOpCompositeConstruct: *hasResult = true; *hasResultType = true; break; + case SpvOpCompositeExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpCompositeInsert: *hasResult = true; *hasResultType = true; break; + case SpvOpCopyObject: *hasResult = true; *hasResultType = true; break; + case SpvOpTranspose: *hasResult = true; *hasResultType = true; break; + case SpvOpSampledImage: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageFetch: *hasResult = true; *hasResultType = true; break; + case SpvOpImageGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageDrefGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageRead: *hasResult = true; *hasResultType = true; break; + case SpvOpImageWrite: *hasResult = false; *hasResultType = false; break; + case SpvOpImage: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryFormat: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryOrder: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQuerySize: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQueryLevels: *hasResult = true; *hasResultType = true; break; + case SpvOpImageQuerySamples: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertFToU: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertFToS: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertSToF: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertUToF: *hasResult = true; *hasResultType = true; break; + case SpvOpUConvert: *hasResult = true; *hasResultType = true; break; + case SpvOpSConvert: *hasResult = true; *hasResultType = true; break; + case SpvOpFConvert: *hasResult = true; *hasResultType = true; break; + case SpvOpQuantizeToF16: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertPtrToU: *hasResult = true; *hasResultType = true; break; + case SpvOpSatConvertSToU: *hasResult = true; *hasResultType = true; break; + case SpvOpSatConvertUToS: *hasResult = true; *hasResultType = true; break; + case SpvOpConvertUToPtr: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; + case SpvOpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; + case SpvOpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; + case SpvOpBitcast: *hasResult = true; *hasResultType = true; break; + case SpvOpSNegate: *hasResult = true; *hasResultType = true; break; + case SpvOpFNegate: *hasResult = true; *hasResultType = true; break; + case SpvOpIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpFAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpISub: *hasResult = true; *hasResultType = true; break; + case SpvOpFSub: *hasResult = true; *hasResultType = true; break; + case SpvOpIMul: *hasResult = true; *hasResultType = true; break; + case SpvOpFMul: *hasResult = true; *hasResultType = true; break; + case SpvOpUDiv: *hasResult = true; *hasResultType = true; break; + case SpvOpSDiv: *hasResult = true; *hasResultType = true; break; + case SpvOpFDiv: *hasResult = true; *hasResultType = true; break; + case SpvOpUMod: *hasResult = true; *hasResultType = true; break; + case SpvOpSRem: *hasResult = true; *hasResultType = true; break; + case SpvOpSMod: *hasResult = true; *hasResultType = true; break; + case SpvOpFRem: *hasResult = true; *hasResultType = true; break; + case SpvOpFMod: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; + case SpvOpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; + case SpvOpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; + case SpvOpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; + case SpvOpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; + case SpvOpOuterProduct: *hasResult = true; *hasResultType = true; break; + case SpvOpDot: *hasResult = true; *hasResultType = true; break; + case SpvOpIAddCarry: *hasResult = true; *hasResultType = true; break; + case SpvOpISubBorrow: *hasResult = true; *hasResultType = true; break; + case SpvOpUMulExtended: *hasResult = true; *hasResultType = true; break; + case SpvOpSMulExtended: *hasResult = true; *hasResultType = true; break; + case SpvOpAny: *hasResult = true; *hasResultType = true; break; + case SpvOpAll: *hasResult = true; *hasResultType = true; break; + case SpvOpIsNan: *hasResult = true; *hasResultType = true; break; + case SpvOpIsInf: *hasResult = true; *hasResultType = true; break; + case SpvOpIsFinite: *hasResult = true; *hasResultType = true; break; + case SpvOpIsNormal: *hasResult = true; *hasResultType = true; break; + case SpvOpSignBitSet: *hasResult = true; *hasResultType = true; break; + case SpvOpLessOrGreater: *hasResult = true; *hasResultType = true; break; + case SpvOpOrdered: *hasResult = true; *hasResultType = true; break; + case SpvOpUnordered: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalOr: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpLogicalNot: *hasResult = true; *hasResultType = true; break; + case SpvOpSelect: *hasResult = true; *hasResultType = true; break; + case SpvOpIEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpINotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpUGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpSGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpULessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpSLessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpULessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpSLessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdLessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordLessThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpShiftRightLogical: *hasResult = true; *hasResultType = true; break; + case SpvOpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; + case SpvOpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; + case SpvOpBitwiseOr: *hasResult = true; *hasResultType = true; break; + case SpvOpBitwiseXor: *hasResult = true; *hasResultType = true; break; + case SpvOpBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpNot: *hasResult = true; *hasResultType = true; break; + case SpvOpBitFieldInsert: *hasResult = true; *hasResultType = true; break; + case SpvOpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpBitReverse: *hasResult = true; *hasResultType = true; break; + case SpvOpBitCount: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdx: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdy: *hasResult = true; *hasResultType = true; break; + case SpvOpFwidth: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdxFine: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdyFine: *hasResult = true; *hasResultType = true; break; + case SpvOpFwidthFine: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdxCoarse: *hasResult = true; *hasResultType = true; break; + case SpvOpDPdyCoarse: *hasResult = true; *hasResultType = true; break; + case SpvOpFwidthCoarse: *hasResult = true; *hasResultType = true; break; + case SpvOpEmitVertex: *hasResult = false; *hasResultType = false; break; + case SpvOpEndPrimitive: *hasResult = false; *hasResultType = false; break; + case SpvOpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; + case SpvOpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; + case SpvOpControlBarrier: *hasResult = false; *hasResultType = false; break; + case SpvOpMemoryBarrier: *hasResult = false; *hasResultType = false; break; + case SpvOpAtomicLoad: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicStore: *hasResult = false; *hasResultType = false; break; + case SpvOpAtomicExchange: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicISub: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicSMin: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicUMin: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicSMax: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicUMax: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicOr: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicXor: *hasResult = true; *hasResultType = true; break; + case SpvOpPhi: *hasResult = true; *hasResultType = true; break; + case SpvOpLoopMerge: *hasResult = false; *hasResultType = false; break; + case SpvOpSelectionMerge: *hasResult = false; *hasResultType = false; break; + case SpvOpLabel: *hasResult = true; *hasResultType = false; break; + case SpvOpBranch: *hasResult = false; *hasResultType = false; break; + case SpvOpBranchConditional: *hasResult = false; *hasResultType = false; break; + case SpvOpSwitch: *hasResult = false; *hasResultType = false; break; + case SpvOpKill: *hasResult = false; *hasResultType = false; break; + case SpvOpReturn: *hasResult = false; *hasResultType = false; break; + case SpvOpReturnValue: *hasResult = false; *hasResultType = false; break; + case SpvOpUnreachable: *hasResult = false; *hasResultType = false; break; + case SpvOpLifetimeStart: *hasResult = false; *hasResultType = false; break; + case SpvOpLifetimeStop: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupAll: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupAny: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupBroadcast: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMax: *hasResult = true; *hasResultType = true; break; + case SpvOpReadPipe: *hasResult = true; *hasResultType = true; break; + case SpvOpWritePipe: *hasResult = true; *hasResultType = true; break; + case SpvOpReservedReadPipe: *hasResult = true; *hasResultType = true; break; + case SpvOpReservedWritePipe: *hasResult = true; *hasResultType = true; break; + case SpvOpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case SpvOpCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case SpvOpIsValidReserveId: *hasResult = true; *hasResultType = true; break; + case SpvOpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; + case SpvOpEnqueueMarker: *hasResult = true; *hasResultType = true; break; + case SpvOpEnqueueKernel: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; + case SpvOpRetainEvent: *hasResult = false; *hasResultType = false; break; + case SpvOpReleaseEvent: *hasResult = false; *hasResultType = false; break; + case SpvOpCreateUserEvent: *hasResult = true; *hasResultType = true; break; + case SpvOpIsValidEvent: *hasResult = true; *hasResultType = true; break; + case SpvOpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; + case SpvOpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; + case SpvOpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; + case SpvOpBuildNDRange: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseFetch: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; + case SpvOpNoLine: *hasResult = false; *hasResultType = false; break; + case SpvOpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; + case SpvOpImageSparseRead: *hasResult = true; *hasResultType = true; break; + case SpvOpSizeOf: *hasResult = true; *hasResultType = true; break; + case SpvOpTypePipeStorage: *hasResult = true; *hasResultType = false; break; + case SpvOpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; + case SpvOpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; + case SpvOpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; + case SpvOpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; + case SpvOpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; + case SpvOpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; + case SpvOpModuleProcessed: *hasResult = false; *hasResultType = false; break; + case SpvOpExecutionModeId: *hasResult = false; *hasResultType = false; break; + case SpvOpDecorateId: *hasResult = false; *hasResultType = false; break; + case SpvOpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; + case SpvOpCopyLogical: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrNotEqual: *hasResult = true; *hasResultType = true; break; + case SpvOpPtrDiff: *hasResult = true; *hasResultType = true; break; + case SpvOpTerminateInvocation: *hasResult = false; *hasResultType = false; break; + case SpvOpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpTraceRayKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpConvertUToAccelerationStructureKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpIgnoreIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpTerminateRayKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break; + case SpvOpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; + case SpvOpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; + case SpvOpReadClockKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; + case SpvOpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; + case SpvOpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; + case SpvOpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; + case SpvOpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTerminateRayNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTraceNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; + case SpvOpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; + case SpvOpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; + case SpvOpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; + case SpvOpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; + case SpvOpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; + case SpvOpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; + case SpvOpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case SpvOpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; + case SpvOpDemoteToHelperInvocationEXT: *hasResult = false; *hasResultType = false; break; + case SpvOpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIAverageINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUAverageINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpISubSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpDecorateString: *hasResult = false; *hasResultType = false; break; + case SpvOpMemberDecorateString: *hasResult = false; *hasResultType = false; break; + case SpvOpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; + case SpvOpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpLoopControlINTEL: *hasResult = false; *hasResultType = false; break; + case SpvOpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpFPGARegINTEL: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; + case SpvOpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break; + } +} +#endif /* SPV_ENABLE_UTILITY_CODE */ + +#endif diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c index 3df963d1ae..0fc979a8a4 100644 --- a/thirdparty/spirv-reflect/spirv_reflect.c +++ b/thirdparty/spirv-reflect/spirv_reflect.c @@ -27,6 +27,13 @@ #include <stdlib.h> #endif +#if defined(SPIRV_REFLECT_ENABLE_ASSERTS) + #define SPV_REFLECT_ASSERT(COND) \ + assert(COND); +#else +#define SPV_REFLECT_ASSERT(COND) +#endif + // Temporary enums until these make it into SPIR-V/Vulkan // clang-format off enum { @@ -192,7 +199,7 @@ typedef struct Parser { SpvSourceLanguage source_language; uint32_t source_language_version; uint32_t source_file_id; - String source_embedded; + const char* source_embedded; size_t node_count; Node* nodes; uint32_t entry_point_count; @@ -552,6 +559,7 @@ static void DestroyParser(Parser* p_parser) SafeFree(p_parser->nodes); SafeFree(p_parser->strings); + SafeFree(p_parser->source_embedded); SafeFree(p_parser->functions); SafeFree(p_parser->access_chains); p_parser->node_count = 0; @@ -605,6 +613,7 @@ static SpvReflectResult ParseNodes(Parser* p_parser) } // Mark source file id node p_parser->source_file_id = (uint32_t)INVALID_VALUE; + p_parser->source_embedded = NULL; // Function node uint32_t function_node = (uint32_t)INVALID_VALUE; @@ -645,6 +654,48 @@ static SpvReflectResult ParseNodes(Parser* p_parser) if (p_node->word_count >= 4) { CHECKED_READU32(p_parser, p_node->word_offset + 3, p_parser->source_file_id); } + if (p_node->word_count >= 5) { + const char* p_source = (const char*)(p_parser->spirv_code + p_node->word_offset + 4); + + const size_t source_len = strlen(p_source); + char* p_source_temp = (char*)calloc(source_len + 1, sizeof(char*)); + + if (IsNull(p_source_temp)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + #ifdef _WIN32 + strcpy_s(p_source_temp, source_len + 1, p_source); + #else + strcpy(p_source_temp, p_source); + #endif + + p_parser->source_embedded = p_source_temp; + } + } + break; + + case SpvOpSourceContinued: { + const char* p_source = (const char*)(p_parser->spirv_code + p_node->word_offset + 1); + + const size_t source_len = strlen(p_source); + const size_t embedded_source_len = strlen(p_parser->source_embedded); + char* p_continued_source = (char*)calloc(source_len + embedded_source_len + 1, sizeof(char*)); + + if (IsNull(p_continued_source)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + #ifdef _WIN32 + strcpy_s(p_continued_source, embedded_source_len + 1, p_parser->source_embedded); + strcat_s(p_continued_source, source_len + 1, p_source); + #else + strcpy(p_continued_source, p_parser->source_embedded); + strcat(p_continued_source, p_source); + #endif + + SafeFree(p_parser->source_embedded); + p_parser->source_embedded = p_continued_source; } break; @@ -680,6 +731,8 @@ static SpvReflectResult ParseNodes(Parser* p_parser) case SpvOpTypeReserveId: case SpvOpTypeQueue: case SpvOpTypePipe: + case SpvOpTypeAccelerationStructureKHR: + case SpvOpTypeRayQueryKHR: { CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_id); p_node->is_type = true; @@ -889,7 +942,7 @@ static SpvReflectResult ParseStrings(Parser* p_parser) ++string_index; } } - + return SPV_REFLECT_RESULT_SUCCESS; } @@ -909,6 +962,25 @@ static SpvReflectResult ParseSource(Parser* p_parser, SpvReflectShaderModule* p_ } } } + + //Source code + if (IsNotNull(p_parser->source_embedded)) + { + const size_t source_len = strlen(p_parser->source_embedded); + char* p_source = (char*)calloc(source_len + 1, sizeof(char*)); + + if (IsNull(p_source)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + + #ifdef _WIN32 + strcpy_s(p_source, source_len + 1, p_parser->source_embedded); + #else + strcpy(p_source, p_parser->source_embedded); + #endif + + p_module->source_source = p_source; + } } return SPV_REFLECT_RESULT_SUCCESS; @@ -1486,6 +1558,7 @@ static SpvReflectResult ParseType( } else { result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); } } break; @@ -1501,6 +1574,7 @@ static SpvReflectResult ParseType( } else { result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); } p_type->traits.numeric.matrix.row_count = p_type->traits.numeric.vector.component_count; p_type->traits.numeric.matrix.stride = p_node->decorations.matrix_stride; @@ -1536,7 +1610,8 @@ static SpvReflectResult ParseType( result = ParseType(p_parser, p_next_node, NULL, p_module, p_type); } else { - result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); } } break; @@ -1567,6 +1642,7 @@ static SpvReflectResult ParseType( p_type->traits.array.dims_count += 1; } else { result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); } } // Parse next dimension or element type @@ -1577,6 +1653,7 @@ static SpvReflectResult ParseType( } else { result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); } } } @@ -1592,6 +1669,7 @@ static SpvReflectResult ParseType( } else { result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); } } break; @@ -1608,6 +1686,7 @@ static SpvReflectResult ParseType( Node* p_member_node = FindNode(p_parser, member_id); if (IsNull(p_member_node)) { result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); break; } @@ -1643,9 +1722,15 @@ static SpvReflectResult ParseType( } else { result = SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + SPV_REFLECT_ASSERT(false); } } break; + + case SpvOpTypeAccelerationStructureKHR: { + p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE; + } + break; } if (result == SPV_REFLECT_RESULT_SUCCESS) { @@ -1718,7 +1803,9 @@ static SpvReflectResult ParseDescriptorBindings(Parser* p_parser, SpvReflectShad for (size_t i = 0; i < p_parser->node_count; ++i) { Node* p_node = &(p_parser->nodes[i]); if ((p_node->op != SpvOpVariable) || - ((p_node->storage_class != SpvStorageClassUniform) && (p_node->storage_class != SpvStorageClassUniformConstant))) + ((p_node->storage_class != SpvStorageClassUniform) && + (p_node->storage_class != SpvStorageClassStorageBuffer) && + (p_node->storage_class != SpvStorageClassUniformConstant))) { continue; } @@ -1752,7 +1839,9 @@ static SpvReflectResult ParseDescriptorBindings(Parser* p_parser, SpvReflectShad for (size_t i = 0; i < p_parser->node_count; ++i) { Node* p_node = &(p_parser->nodes[i]); if ((p_node->op != SpvOpVariable) || - ((p_node->storage_class != SpvStorageClassUniform) && (p_node->storage_class != SpvStorageClassUniformConstant)))\ + ((p_node->storage_class != SpvStorageClassUniform) && + (p_node->storage_class != SpvStorageClassStorageBuffer) && + (p_node->storage_class != SpvStorageClassUniformConstant))) { continue; } @@ -1764,8 +1853,11 @@ static SpvReflectResult ParseDescriptorBindings(Parser* p_parser, SpvReflectShad if (IsNull(p_type)) { return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; } - // If the type is a pointer, resolve it + // If the type is a pointer, resolve it. We need to retain the storage class + // from the pointer so that we can use it to deduce deescriptor types. + SpvStorageClass pointer_storage_class = SpvStorageClassMax; if (p_type->op == SpvOpTypePointer) { + pointer_storage_class = p_type->storage_class; // Find the type's node Node* p_type_node = FindNode(p_parser, p_type->id); if (IsNull(p_type_node)) { @@ -1788,6 +1880,18 @@ static SpvReflectResult ParseDescriptorBindings(Parser* p_parser, SpvReflectShad p_descriptor->uav_counter_id = p_node->decorations.uav_counter_buffer.value; p_descriptor->type_description = p_type; + // If this is in the StorageBuffer storage class, it's for sure a storage + // buffer descriptor. We need to handle this case earlier because in SPIR-V + // there are two ways to indicate a storage buffer: + // 1) Uniform storage class + BufferBlock decoration, or + // 2) StorageBuffer storage class + Buffer decoration. + // The 1) way is deprecated since SPIR-V v1.3. But the Buffer decoration is + // also used together with Uniform storage class to mean uniform buffer.. + // We'll handle the pre-v1.3 cases in ParseDescriptorType(). + if (pointer_storage_class == SpvStorageClassStorageBuffer) { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER; + } + // Copy image traits if ((p_type->type_flags & SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK) == SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE) { memcpy(&p_descriptor->image, &p_type->traits.image, sizeof(p_descriptor->image)); @@ -1840,78 +1944,84 @@ static SpvReflectResult ParseDescriptorType(SpvReflectShaderModule* p_module) SpvReflectDescriptorBinding* p_descriptor = &(p_module->descriptor_bindings[descriptor_index]); SpvReflectTypeDescription* p_type = p_descriptor->type_description; - switch (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK) { - default: assert(false && "unknown type flag"); break; + if ((int)p_descriptor->descriptor_type == (int)INVALID_VALUE) { + switch (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK) { + default: assert(false && "unknown type flag"); break; - case SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE: { - if (p_descriptor->image.dim == SpvDimBuffer) { - switch (p_descriptor->image.sampled) { - default: assert(false && "unknown texel buffer sampled value"); break; - case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; break; - case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; break; + case SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE: { + if (p_descriptor->image.dim == SpvDimBuffer) { + switch (p_descriptor->image.sampled) { + default: assert(false && "unknown texel buffer sampled value"); break; + case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; break; + case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; break; + } } - } - else if(p_descriptor->image.dim == SpvDimSubpassData) { - p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; - } - else { - switch (p_descriptor->image.sampled) { - default: assert(false && "unknown image sampled value"); break; - case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE; break; - case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE; break; + else if(p_descriptor->image.dim == SpvDimSubpassData) { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; + } + else { + switch (p_descriptor->image.sampled) { + default: assert(false && "unknown image sampled value"); break; + case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE; break; + case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE; break; + } } } - } - break; + break; - case SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER: { - p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER; - } - break; + case SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER: { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER; + } + break; - case (SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE | SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE): { - // This is a workaround for: https://github.com/KhronosGroup/glslang/issues/1096 - if (p_descriptor->image.dim == SpvDimBuffer) { - switch (p_descriptor->image.sampled) { - default: assert(false && "unknown texel buffer sampled value"); break; - case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; break; - case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; break; + case (SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE | SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE): { + // This is a workaround for: https://github.com/KhronosGroup/glslang/issues/1096 + if (p_descriptor->image.dim == SpvDimBuffer) { + switch (p_descriptor->image.sampled) { + default: assert(false && "unknown texel buffer sampled value"); break; + case IMAGE_SAMPLED: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; break; + case IMAGE_STORAGE: p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; break; + } + } + else { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; } } - else { - p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - } - } - break; + break; - case SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK: { - if (p_type->decoration_flags & SPV_REFLECT_DECORATION_BLOCK) { - p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - } - else if (p_type->decoration_flags & SPV_REFLECT_DECORATION_BUFFER_BLOCK) { - p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER; + case SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK: { + if (p_type->decoration_flags & SPV_REFLECT_DECORATION_BLOCK) { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + } + else if (p_type->decoration_flags & SPV_REFLECT_DECORATION_BUFFER_BLOCK) { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER; + } + else { + assert(false && "unknown struct"); + } } - else { - assert(false && "unknown struct"); + break; + + case SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE: { + p_descriptor->descriptor_type = SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; } + break; } - break; } switch (p_descriptor->descriptor_type) { - case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SAMPLER; break; - case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : p_descriptor->resource_type = (SpvReflectResourceType)(SPV_REFLECT_RESOURCE_FLAG_SAMPLER | SPV_REFLECT_RESOURCE_FLAG_SRV); break; - case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; break; - case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break; - case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; break; - case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break; - case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_CBV; break; - case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_CBV; break; - case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break; - case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break; - - case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: - break; + case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SAMPLER; break; + case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : p_descriptor->resource_type = (SpvReflectResourceType)(SPV_REFLECT_RESOURCE_FLAG_SAMPLER | SPV_REFLECT_RESOURCE_FLAG_SRV); break; + case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_CBV; break; + case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_CBV; break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break; + case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_UAV; break; + case SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT : break; + case SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR : p_descriptor->resource_type = SPV_REFLECT_RESOURCE_FLAG_SRV; break; } } @@ -1950,7 +2060,7 @@ static SpvReflectResult ParseUAVCounterBindings(SpvReflectShaderModule* p_module memset(name, 0, MAX_NODE_NAME_LENGTH); memcpy(name, p_descriptor->name, descriptor_name_length); -#if defined(WIN32) +#if defined(_WIN32) strcat_s(name, MAX_NODE_NAME_LENGTH, k_count_tag); #else strcat(name, k_count_tag); @@ -2188,6 +2298,29 @@ static SpvReflectResult ParseDescriptorBlockVariableSizes( return SPV_REFLECT_RESULT_SUCCESS; } +static void MarkSelfAndAllMemberVarsAsUsed(SpvReflectBlockVariable* p_var) +{ + // Clear the current variable's USED flag + p_var->flags &= ~SPV_REFLECT_VARIABLE_FLAGS_UNUSED; + + SpvOp op_type = p_var->type_description->op; + switch (op_type) { + default: break; + + case SpvOpTypeArray: { + } + break; + + case SpvOpTypeStruct: { + for (uint32_t i = 0; i < p_var->member_count; ++i) { + SpvReflectBlockVariable* p_member_var = &p_var->members[i]; + MarkSelfAndAllMemberVarsAsUsed(p_member_var); + } + } + break; + } +} + static SpvReflectResult ParseDescriptorBlockVariableUsage( Parser* p_parser, SpvReflectShaderModule* p_module, @@ -2201,7 +2334,7 @@ static SpvReflectResult ParseDescriptorBlockVariableUsage( (void)p_access_chain; (void)p_var; - // Clear the current variable's USED flag + // Clear the current variable's UNUSED flag p_var->flags &= ~SPV_REFLECT_VARIABLE_FLAGS_UNUSED; // Parsing arrays requires overriding the op type for @@ -2229,19 +2362,33 @@ static SpvReflectResult ParseDescriptorBlockVariableUsage( if (p_type == NULL) { return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; } - // Next access index + // Next access chain index index_index += 1; } - // Parse current var again with a type override and advanced index index - SpvReflectResult result = ParseDescriptorBlockVariableUsage( - p_parser, - p_module, - p_access_chain, - index_index, - p_type->op, - p_var); - if (result != SPV_REFLECT_RESULT_SUCCESS) { - return result; + + // Only continue parsing if there's remaining indices in the access + // chain. If the end of the access chain has been reach then all + // remaining variables (including those in struct hierarchies) + // are considered USED. + // + // See: https://github.com/KhronosGroup/SPIRV-Reflect/issues/78 + // + if (index_index < p_access_chain->index_count) { + // Parse current var again with a type override and advanced index index + SpvReflectResult result = ParseDescriptorBlockVariableUsage( + p_parser, + p_module, + p_access_chain, + index_index, + p_type->op, + p_var); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } + } + else { + // Clear UNUSED flag for remaining variables + MarkSelfAndAllMemberVarsAsUsed(p_var); } } break; @@ -2251,26 +2398,52 @@ static SpvReflectResult ParseDescriptorBlockVariableUsage( if (p_var->member_count == 0) { return SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_BLOCK_DATA; } - + // Get member variable at the access's chain current index uint32_t index = p_access_chain->indexes[index_index]; - if (index >= p_var->member_count) { return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_BLOCK_MEMBER_REFERENCE; } - SpvReflectBlockVariable* p_member_var = &p_var->members[index]; + + // Next access chain index + index_index += 1; + + // Only continue parsing if there's remaining indices in the access + // chain. If the end of the access chain has been reach then all + // remaining variables (including those in struct hierarchies) + // are considered USED. + // + // See: https://github.com/KhronosGroup/SPIRV-Reflect/issues/78 + // if (index_index < p_access_chain->index_count) { - SpvReflectResult result = ParseDescriptorBlockVariableUsage( - p_parser, - p_module, - p_access_chain, - index_index + 1, - (SpvOp)INVALID_VALUE, - p_member_var); - if (result != SPV_REFLECT_RESULT_SUCCESS) { - return result; - } + SpvReflectResult result = ParseDescriptorBlockVariableUsage( + p_parser, + p_module, + p_access_chain, + index_index, + (SpvOp)INVALID_VALUE, + p_member_var); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + return result; + } } + else { + // Clear UNUSED flag for remaining variables + MarkSelfAndAllMemberVarsAsUsed(p_member_var); + } + //SpvReflectBlockVariable* p_member_var = &p_var->members[index]; + //if (index_index < p_access_chain->index_count) { + // SpvReflectResult result = ParseDescriptorBlockVariableUsage( + // p_parser, + // p_module, + // p_access_chain, + // index_index + 1, + // (SpvOp)INVALID_VALUE, + // p_member_var); + // if (result != SPV_REFLECT_RESULT_SUCCESS) { + // return result; + // } + //} } break; } @@ -2342,39 +2515,69 @@ static SpvReflectResult ParseFormat( ) { SpvReflectResult result = SPV_REFLECT_RESULT_ERROR_INTERNAL_ERROR; - bool signedness = p_type->traits.numeric.scalar.signedness; + bool signedness = (p_type->traits.numeric.scalar.signedness != 0); + uint32_t bit_width = p_type->traits.numeric.scalar.width; if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_VECTOR) { uint32_t component_count = p_type->traits.numeric.vector.component_count; if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_FLOAT) { - switch (component_count) { - case 2: *p_format = SPV_REFLECT_FORMAT_R32G32_SFLOAT; break; - case 3: *p_format = SPV_REFLECT_FORMAT_R32G32B32_SFLOAT; break; - case 4: *p_format = SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT; break; + switch (bit_width) { + case 32: { + switch (component_count) { + case 2: *p_format = SPV_REFLECT_FORMAT_R32G32_SFLOAT; break; + case 3: *p_format = SPV_REFLECT_FORMAT_R32G32B32_SFLOAT; break; + case 4: *p_format = SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT; break; + } + } + case 64: { + switch (component_count) { + case 2: *p_format = SPV_REFLECT_FORMAT_R64G64_SFLOAT; break; + case 3: *p_format = SPV_REFLECT_FORMAT_R64G64B64_SFLOAT; break; + case 4: *p_format = SPV_REFLECT_FORMAT_R64G64B64A64_SFLOAT; break; + } + } } result = SPV_REFLECT_RESULT_SUCCESS; } else if (p_type->type_flags & (SPV_REFLECT_TYPE_FLAG_INT | SPV_REFLECT_TYPE_FLAG_BOOL)) { - switch (component_count) { - case 2: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32_SINT : SPV_REFLECT_FORMAT_R32G32_UINT; break; - case 3: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32B32_SINT : SPV_REFLECT_FORMAT_R32G32B32_UINT; break; - case 4: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32B32A32_SINT : SPV_REFLECT_FORMAT_R32G32B32A32_UINT; break; + switch (bit_width) { + case 32: { + switch (component_count) { + case 2: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32_SINT : SPV_REFLECT_FORMAT_R32G32_UINT; break; + case 3: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32B32_SINT : SPV_REFLECT_FORMAT_R32G32B32_UINT; break; + case 4: *p_format = signedness ? SPV_REFLECT_FORMAT_R32G32B32A32_SINT : SPV_REFLECT_FORMAT_R32G32B32A32_UINT; break; + } + } + case 64: { + switch (component_count) { + case 2: *p_format = signedness ? SPV_REFLECT_FORMAT_R64G64_SINT : SPV_REFLECT_FORMAT_R64G64_UINT; break; + case 3: *p_format = signedness ? SPV_REFLECT_FORMAT_R64G64B64_SINT : SPV_REFLECT_FORMAT_R64G64B64_UINT; break; + case 4: *p_format = signedness ? SPV_REFLECT_FORMAT_R64G64B64A64_SINT : SPV_REFLECT_FORMAT_R64G64B64A64_UINT; break; + } + } } result = SPV_REFLECT_RESULT_SUCCESS; } } else if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_FLOAT) { - *p_format = SPV_REFLECT_FORMAT_R32_SFLOAT; + switch(bit_width) { + case 32: + *p_format = SPV_REFLECT_FORMAT_R32_SFLOAT; + break; + case 64: + *p_format = SPV_REFLECT_FORMAT_R64_SFLOAT; + break; + } result = SPV_REFLECT_RESULT_SUCCESS; } else if (p_type->type_flags & (SPV_REFLECT_TYPE_FLAG_INT | SPV_REFLECT_TYPE_FLAG_BOOL)) { - if (signedness) { - *p_format = SPV_REFLECT_FORMAT_R32_SINT; - result = SPV_REFLECT_RESULT_SUCCESS; - } - else { - *p_format = SPV_REFLECT_FORMAT_R32_UINT; - result = SPV_REFLECT_RESULT_SUCCESS; - } + switch(bit_width) { + case 32: + *p_format = signedness ? SPV_REFLECT_FORMAT_R32_SINT : SPV_REFLECT_FORMAT_R32_UINT; break; + break; + case 64: + *p_format = signedness ? SPV_REFLECT_FORMAT_R64_SINT : SPV_REFLECT_FORMAT_R64_UINT; break; + } + result = SPV_REFLECT_RESULT_SUCCESS; } else if (p_type->type_flags & SPV_REFLECT_TYPE_FLAG_STRUCT) { *p_format = SPV_REFLECT_FORMAT_UNDEFINED; @@ -2410,6 +2613,7 @@ static SpvReflectResult ParseInterfaceVariable( SpvReflectInterfaceVariable* p_member_var = &p_var->members[member_index]; SpvReflectResult result = ParseInterfaceVariable(p_parser, p_member_decorations, p_module, p_member_type, p_member_var, p_has_built_in); if (result != SPV_REFLECT_RESULT_SUCCESS) { + SPV_REFLECT_ASSERT(false); return result; } } @@ -2427,9 +2631,13 @@ static SpvReflectResult ParseInterfaceVariable( *p_has_built_in |= p_type_node_decorations->is_built_in; - SpvReflectResult result = ParseFormat(p_var->type_description, &p_var->format); - if (result != SPV_REFLECT_RESULT_SUCCESS) { - return result; + // Only parse format for interface variables that are input or output + if ((p_var->storage_class == SpvStorageClassInput) || (p_var->storage_class == SpvStorageClassOutput)) { + SpvReflectResult result = ParseFormat(p_var->type_description, &p_var->format); + if (result != SPV_REFLECT_RESULT_SUCCESS) { + SPV_REFLECT_ASSERT(false); + return result; + } } return SPV_REFLECT_RESULT_SUCCESS; @@ -2439,50 +2647,57 @@ static SpvReflectResult ParseInterfaceVariables( Parser* p_parser, SpvReflectShaderModule* p_module, SpvReflectEntryPoint* p_entry, - size_t io_var_count, - uint32_t* io_vars + uint32_t interface_variable_count, + uint32_t* p_interface_variable_ids ) { - if (io_var_count == 0) { + if (interface_variable_count == 0) { return SPV_REFLECT_RESULT_SUCCESS; } - p_entry->input_variable_count = 0; - p_entry->output_variable_count = 0; - for (size_t i = 0; i < io_var_count; ++i) { - uint32_t var_result_id = *(io_vars + i); - Node* p_node = FindNode(p_parser, var_result_id); - if (IsNull(p_node)) { - return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; - } - - if (p_node->storage_class == SpvStorageClassInput) { - p_entry->input_variable_count += 1; - } - else if (p_node->storage_class == SpvStorageClassOutput) { - p_entry->output_variable_count += 1; - } - } - - if (p_entry->input_variable_count > 0) { - p_entry->input_variables = (SpvReflectInterfaceVariable*)calloc(p_entry->input_variable_count, sizeof(*(p_entry->input_variables))); - if (IsNull(p_entry->input_variables)) { - return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; - } - } - - - if (p_entry->output_variable_count > 0) { - p_entry->output_variables = (SpvReflectInterfaceVariable*)calloc(p_entry->output_variable_count, sizeof(*(p_entry->output_variables))); - if (IsNull(p_entry->output_variables)) { + p_entry->interface_variable_count = interface_variable_count; + p_entry->input_variable_count = 0; + p_entry->output_variable_count = 0; + for (size_t i = 0; i < interface_variable_count; ++i) { + uint32_t var_result_id = *(p_interface_variable_ids + i); + Node* p_node = FindNode(p_parser, var_result_id); + if (IsNull(p_node)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; + } + + if (p_node->storage_class == SpvStorageClassInput) { + p_entry->input_variable_count += 1; + } + else if (p_node->storage_class == SpvStorageClassOutput) { + p_entry->output_variable_count += 1; + } + } + + if (p_entry->input_variable_count > 0) { + p_entry->input_variables = (SpvReflectInterfaceVariable**)calloc(p_entry->input_variable_count, sizeof(*(p_entry->input_variables))); + if (IsNull(p_entry->input_variables)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + if (p_entry->output_variable_count > 0) { + p_entry->output_variables = (SpvReflectInterfaceVariable**)calloc(p_entry->output_variable_count, sizeof(*(p_entry->output_variables))); + if (IsNull(p_entry->output_variables)) { + return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; + } + } + + if (p_entry->interface_variable_count > 0) { + p_entry->interface_variables = (SpvReflectInterfaceVariable*)calloc(p_entry->interface_variable_count, sizeof(*(p_entry->interface_variables))); + if (IsNull(p_entry->interface_variables)) { return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; } } size_t input_index = 0; size_t output_index = 0; - for (size_t i = 0; i < io_var_count; ++i) { - uint32_t var_result_id = *(io_vars + i); + for (size_t i = 0; i < interface_variable_count; ++i) { + uint32_t var_result_id = *(p_interface_variable_ids + i); Node* p_node = FindNode(p_parser, var_result_id); if (IsNull(p_node)) { return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; @@ -2511,22 +2726,8 @@ static SpvReflectResult ParseInterfaceVariables( return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ID_REFERENCE; } - SpvReflectInterfaceVariable* p_var = NULL; - if (p_node->storage_class == SpvStorageClassInput) { - p_var = &(p_entry->input_variables[input_index]); - p_var->storage_class = SpvStorageClassInput; - ++input_index; - } - else if (p_node->storage_class == SpvStorageClassOutput) { - p_var = &(p_entry->output_variables[output_index]); - p_var->storage_class = SpvStorageClassOutput; - ++output_index; - } else { - // interface variables can only have input or output storage classes; - // anything else is either a new addition or an error. - assert(false && "Unsupported storage class for interface variable"); - return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_STORAGE_CLASS; - } + SpvReflectInterfaceVariable* p_var = &(p_entry->interface_variables[i]); + p_var->storage_class = p_node->storage_class; bool has_built_in = p_node->decorations.is_built_in; SpvReflectResult result = ParseInterfaceVariable( @@ -2537,9 +2738,20 @@ static SpvReflectResult ParseInterfaceVariables( p_var, &has_built_in); if (result != SPV_REFLECT_RESULT_SUCCESS) { + SPV_REFLECT_ASSERT(false); return result; } + // Input and output variables + if (p_var->storage_class == SpvStorageClassInput) { + p_entry->input_variables[input_index] = p_var; + ++input_index; + } + else if (p_node->storage_class == SpvStorageClassOutput) { + p_entry->output_variables[output_index] = p_var; + ++output_index; + } + // SPIR-V result id p_var->spirv_id = p_node->result_id; // Name @@ -2809,6 +3021,14 @@ static SpvReflectResult ParseEntryPoints(Parser* p_parser, SpvReflectShaderModul case SpvExecutionModelGeometry : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT; break; case SpvExecutionModelFragment : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT; break; case SpvExecutionModelGLCompute : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT; break; + case SpvExecutionModelTaskNV : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_TASK_BIT_NV; break; + case SpvExecutionModelMeshNV : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV; break; + case SpvExecutionModelRayGenerationKHR : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_RAYGEN_BIT_KHR; break; + case SpvExecutionModelIntersectionKHR : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_INTERSECTION_BIT_KHR; break; + case SpvExecutionModelAnyHitKHR : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_ANY_HIT_BIT_KHR; break; + case SpvExecutionModelClosestHitKHR : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; break; + case SpvExecutionModelMissKHR : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_MISS_BIT_KHR; break; + case SpvExecutionModelCallableKHR : p_entry_point->shader_stage = SPV_REFLECT_SHADER_STAGE_CALLABLE_BIT_KHR; break; } ++entry_point_index; @@ -2823,11 +3043,11 @@ static SpvReflectResult ParseEntryPoints(Parser* p_parser, SpvReflectShaderModul p_entry_point->name = (const char*)(p_parser->spirv_code + p_node->word_offset + name_start_word_offset); uint32_t name_word_count = RoundUp(name_length_with_terminator, SPIRV_WORD_SIZE) / SPIRV_WORD_SIZE; - size_t interface_variable_count = (p_node->word_count - (name_start_word_offset + name_word_count)); - uint32_t* interface_variables = NULL; + uint32_t interface_variable_count = (p_node->word_count - (name_start_word_offset + name_word_count)); + uint32_t* p_interface_variables = NULL; if (interface_variable_count > 0) { - interface_variables = (uint32_t*)calloc(interface_variable_count, sizeof(*(interface_variables))); - if (IsNull(interface_variables)) { + p_interface_variables = (uint32_t*)calloc(interface_variable_count, sizeof(*(p_interface_variables))); + if (IsNull(p_interface_variables)) { return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED; } } @@ -2836,7 +3056,7 @@ static SpvReflectResult ParseEntryPoints(Parser* p_parser, SpvReflectShaderModul uint32_t var_result_id = (uint32_t)INVALID_VALUE; uint32_t offset = name_start_word_offset + name_word_count + var_index; CHECKED_READU32(p_parser, p_node->word_offset + offset, var_result_id); - interface_variables[var_index] = var_result_id; + p_interface_variables[var_index] = var_result_id; } result = ParseInterfaceVariables( @@ -2844,11 +3064,11 @@ static SpvReflectResult ParseEntryPoints(Parser* p_parser, SpvReflectShaderModul p_module, p_entry_point, interface_variable_count, - interface_variables); + p_interface_variables); if (result != SPV_REFLECT_RESULT_SUCCESS) { return result; } - SafeFree(interface_variables); + SafeFree(p_interface_variables); result = ParseStaticallyUsedResources( p_parser, @@ -2869,6 +3089,104 @@ static SpvReflectResult ParseEntryPoints(Parser* p_parser, SpvReflectShaderModul return SPV_REFLECT_RESULT_SUCCESS; } +static SpvReflectResult ParseExecutionModes(Parser* p_parser, SpvReflectShaderModule* p_module) +{ + assert(IsNotNull(p_parser)); + assert(IsNotNull(p_parser->nodes)); + assert(IsNotNull(p_module)); + + if (IsNotNull(p_parser) && IsNotNull(p_parser->spirv_code) && IsNotNull(p_parser->nodes)) { + for (size_t node_idx = 0; node_idx < p_parser->node_count; ++node_idx) { + Node* p_node = &(p_parser->nodes[node_idx]); + if (p_node->op != SpvOpExecutionMode) { + continue; + } + + // Read entry point id + uint32_t entry_point_id = 0; + CHECKED_READU32(p_parser, p_node->word_offset + 1, entry_point_id); + + // Find entry point + SpvReflectEntryPoint* p_entry_point = NULL; + for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) { + if (p_module->entry_points[entry_point_idx].id == entry_point_id) { + p_entry_point = &p_module->entry_points[entry_point_idx]; + break; + } + } + // Bail if entry point is null + if (IsNull(p_entry_point)) { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ENTRY_POINT; + } + + // Read execution mode + uint32_t execution_mode = (uint32_t)INVALID_VALUE; + CHECKED_READU32(p_parser, p_node->word_offset + 2, execution_mode); + + // Parse execution mode + switch (execution_mode) { + default: { + return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_EXECUTION_MODE; + } + break; + + case SpvExecutionModeInvocations: + case SpvExecutionModeSpacingEqual: + case SpvExecutionModeSpacingFractionalEven: + case SpvExecutionModeSpacingFractionalOdd: + case SpvExecutionModeVertexOrderCw: + case SpvExecutionModeVertexOrderCcw: + case SpvExecutionModePixelCenterInteger: + case SpvExecutionModeOriginUpperLeft: + case SpvExecutionModeOriginLowerLeft: + case SpvExecutionModeEarlyFragmentTests: + case SpvExecutionModePointMode: + case SpvExecutionModeXfb: + case SpvExecutionModeDepthReplacing: + case SpvExecutionModeDepthGreater: + case SpvExecutionModeDepthLess: + case SpvExecutionModeDepthUnchanged: + break; + + case SpvExecutionModeLocalSize: { + CHECKED_READU32(p_parser, p_node->word_offset + 3, p_entry_point->local_size.x); + CHECKED_READU32(p_parser, p_node->word_offset + 4, p_entry_point->local_size.y); + CHECKED_READU32(p_parser, p_node->word_offset + 5, p_entry_point->local_size.z); + } + break; + + case SpvExecutionModeLocalSizeHint: + case SpvExecutionModeInputPoints: + case SpvExecutionModeInputLines: + case SpvExecutionModeInputLinesAdjacency: + case SpvExecutionModeTriangles: + case SpvExecutionModeInputTrianglesAdjacency: + case SpvExecutionModeQuads: + case SpvExecutionModeIsolines: + case SpvExecutionModeOutputVertices: + case SpvExecutionModeOutputPoints: + case SpvExecutionModeOutputLineStrip: + case SpvExecutionModeOutputTriangleStrip: + case SpvExecutionModeVecTypeHint: + case SpvExecutionModeContractionOff: + case SpvExecutionModeInitializer: + case SpvExecutionModeFinalizer: + case SpvExecutionModeSubgroupSize: + case SpvExecutionModeSubgroupsPerWorkgroup: + case SpvExecutionModeSubgroupsPerWorkgroupId: + case SpvExecutionModeLocalSizeId: + case SpvExecutionModeLocalSizeHintId: + case SpvExecutionModePostDepthCoverage: + case SpvExecutionModeStencilRefReplacingEXT: + case SpvExecutionModeOutputPrimitivesNV: + case SpvExecutionModeOutputTrianglesNV: + break; + } + } + } + return SPV_REFLECT_RESULT_SUCCESS; +} + static SpvReflectResult ParsePushConstantBlocks(Parser* p_parser, SpvReflectShaderModule* p_module) { for (size_t i = 0; i < p_parser->node_count; ++i) { @@ -3180,24 +3498,31 @@ SpvReflectResult spvReflectCreateShaderModule( if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseNodes(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseStrings(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseSource(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseFunctions(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseMemberCounts(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseNames(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseDecorations(&parser); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } // Start of reflection data parsing @@ -3215,24 +3540,31 @@ SpvReflectResult spvReflectCreateShaderModule( } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseTypes(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseDescriptorBindings(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseDescriptorType(p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseUAVCounterBindings(p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseDescriptorBlocks(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParsePushConstantBlocks(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = ParseEntryPoints(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS && p_module->entry_point_count > 0) { SpvReflectEntryPoint* p_entry = &(p_module->entry_points[0]); @@ -3244,12 +3576,20 @@ SpvReflectResult spvReflectCreateShaderModule( p_module->input_variables = p_entry->input_variables; p_module->output_variable_count = p_entry->output_variable_count; p_module->output_variables = p_entry->output_variables; + p_module->interface_variable_count = p_entry->interface_variable_count; + p_module->interface_variables = p_entry->interface_variables; } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = DisambiguateStorageBufferSrvUav(p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } if (result == SPV_REFLECT_RESULT_SUCCESS) { result = SynchronizeDescriptorSets(p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); + } + if (result == SPV_REFLECT_RESULT_SUCCESS) { + result = ParseExecutionModes(&parser, p_module); + SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS); } // Destroy module if parse was not successful @@ -3319,6 +3659,8 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module) return; } + SafeFree(p_module->source_source); + // Descriptor set bindings for (size_t i = 0; i < p_module->descriptor_set_count; ++i) { SpvReflectDescriptorSet* p_set = &p_module->descriptor_sets[i]; @@ -3335,11 +3677,8 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module) // Entry points for (size_t i = 0; i < p_module->entry_point_count; ++i) { SpvReflectEntryPoint* p_entry = &p_module->entry_points[i]; - for (size_t j = 0; j < p_entry->input_variable_count; j++) { - SafeFreeInterfaceVariable(&p_entry->input_variables[j]); - } - for (size_t j = 0; j < p_entry->output_variable_count; j++) { - SafeFreeInterfaceVariable(&p_entry->output_variables[j]); + for (size_t j = 0; j < p_entry->interface_variable_count; j++) { + SafeFreeInterfaceVariable(&p_entry->interface_variables[j]); } for (uint32_t j = 0; j < p_entry->descriptor_set_count; ++j) { SafeFree(p_entry->descriptor_sets[j].bindings); @@ -3347,6 +3686,7 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module) SafeFree(p_entry->descriptor_sets); SafeFree(p_entry->input_variables); SafeFree(p_entry->output_variables); + SafeFree(p_entry->interface_variables); SafeFree(p_entry->used_uniforms); SafeFree(p_entry->used_push_constants); } @@ -3552,6 +3892,73 @@ SpvReflectResult spvReflectEnumerateEntryPointDescriptorSets( return SPV_REFLECT_RESULT_SUCCESS; } +SpvReflectResult spvReflectEnumerateInterfaceVariables( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +) +{ + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + if (IsNotNull(pp_variables)) { + if (*p_count != p_module->interface_variable_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectInterfaceVariable* p_var = &p_module->interface_variables[index]; + pp_variables[index] = p_var; + } + } + else { + *p_count = p_module->interface_variable_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + +SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +) +{ + if (IsNull(p_module)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + if (IsNull(p_count)) { + return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; + } + + const SpvReflectEntryPoint* p_entry = + spvReflectGetEntryPoint(p_module, entry_point); + if (IsNull(p_entry)) { + return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; + } + + if (IsNotNull(pp_variables)) { + if (*p_count != p_entry->interface_variable_count) { + return SPV_REFLECT_RESULT_ERROR_COUNT_MISMATCH; + } + + for (uint32_t index = 0; index < *p_count; ++index) { + SpvReflectInterfaceVariable* p_var = &p_entry->interface_variables[index]; + pp_variables[index] = p_var; + } + } + else { + *p_count = p_entry->interface_variable_count; + } + + return SPV_REFLECT_RESULT_SUCCESS; +} + SpvReflectResult spvReflectEnumerateInputVariables( const SpvReflectShaderModule* p_module, uint32_t* p_count, @@ -3571,7 +3978,7 @@ SpvReflectResult spvReflectEnumerateInputVariables( } for (uint32_t index = 0; index < *p_count; ++index) { - SpvReflectInterfaceVariable* p_var = (SpvReflectInterfaceVariable*)&p_module->input_variables[index]; + SpvReflectInterfaceVariable* p_var = p_module->input_variables[index]; pp_variables[index] = p_var; } } @@ -3608,7 +4015,7 @@ SpvReflectResult spvReflectEnumerateEntryPointInputVariables( } for (uint32_t index = 0; index < *p_count; ++index) { - SpvReflectInterfaceVariable* p_var = (SpvReflectInterfaceVariable*)&p_entry->input_variables[index]; + SpvReflectInterfaceVariable* p_var = p_entry->input_variables[index]; pp_variables[index] = p_var; } } @@ -3638,7 +4045,7 @@ SpvReflectResult spvReflectEnumerateOutputVariables( } for (uint32_t index = 0; index < *p_count; ++index) { - SpvReflectInterfaceVariable* p_var = (SpvReflectInterfaceVariable*)&p_module->output_variables[index]; + SpvReflectInterfaceVariable* p_var = p_module->output_variables[index]; pp_variables[index] = p_var; } } @@ -3675,7 +4082,7 @@ SpvReflectResult spvReflectEnumerateEntryPointOutputVariables( } for (uint32_t index = 0; index < *p_count; ++index) { - SpvReflectInterfaceVariable* p_var = (SpvReflectInterfaceVariable*)&p_entry->output_variables[index]; + SpvReflectInterfaceVariable* p_var = p_entry->output_variables[index]; pp_variables[index] = p_var; } } @@ -3907,7 +4314,7 @@ const SpvReflectInterfaceVariable* spvReflectGetInputVariableByLocation( const SpvReflectInterfaceVariable* p_var = NULL; if (IsNotNull(p_module)) { for (uint32_t index = 0; index < p_module->input_variable_count; ++index) { - const SpvReflectInterfaceVariable* p_potential = &p_module->input_variables[index]; + const SpvReflectInterfaceVariable* p_potential = p_module->input_variables[index]; if (p_potential->location == location) { p_var = p_potential; } @@ -3955,7 +4362,7 @@ const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableByLocatio return NULL; } for (uint32_t index = 0; index < p_entry->input_variable_count; ++index) { - const SpvReflectInterfaceVariable* p_potential = &p_entry->input_variables[index]; + const SpvReflectInterfaceVariable* p_potential = p_entry->input_variables[index]; if (p_potential->location == location) { p_var = p_potential; } @@ -3991,7 +4398,7 @@ const SpvReflectInterfaceVariable* spvReflectGetInputVariableBySemantic( const SpvReflectInterfaceVariable* p_var = NULL; if (IsNotNull(p_module)) { for (uint32_t index = 0; index < p_module->input_variable_count; ++index) { - const SpvReflectInterfaceVariable* p_potential = &p_module->input_variables[index]; + const SpvReflectInterfaceVariable* p_potential = p_module->input_variables[index]; if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) { p_var = p_potential; } @@ -4035,7 +4442,7 @@ const SpvReflectInterfaceVariable* spvReflectGetEntryPointInputVariableBySemanti return NULL; } for (uint32_t index = 0; index < p_entry->input_variable_count; ++index) { - const SpvReflectInterfaceVariable* p_potential = &p_entry->input_variables[index]; + const SpvReflectInterfaceVariable* p_potential = p_entry->input_variables[index]; if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) { p_var = p_potential; } @@ -4065,7 +4472,7 @@ const SpvReflectInterfaceVariable* spvReflectGetOutputVariableByLocation( const SpvReflectInterfaceVariable* p_var = NULL; if (IsNotNull(p_module)) { for (uint32_t index = 0; index < p_module->output_variable_count; ++index) { - const SpvReflectInterfaceVariable* p_potential = &p_module->output_variables[index]; + const SpvReflectInterfaceVariable* p_potential = p_module->output_variables[index]; if (p_potential->location == location) { p_var = p_potential; } @@ -4112,7 +4519,7 @@ const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableByLocati return NULL; } for (uint32_t index = 0; index < p_entry->output_variable_count; ++index) { - const SpvReflectInterfaceVariable* p_potential = &p_entry->output_variables[index]; + const SpvReflectInterfaceVariable* p_potential = p_entry->output_variables[index]; if (p_potential->location == location) { p_var = p_potential; } @@ -4148,7 +4555,7 @@ const SpvReflectInterfaceVariable* spvReflectGetOutputVariableBySemantic( const SpvReflectInterfaceVariable* p_var = NULL; if (IsNotNull(p_module)) { for (uint32_t index = 0; index < p_module->output_variable_count; ++index) { - const SpvReflectInterfaceVariable* p_potential = &p_module->output_variables[index]; + const SpvReflectInterfaceVariable* p_potential = p_module->output_variables[index]; if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) { p_var = p_potential; } @@ -4191,7 +4598,7 @@ const SpvReflectInterfaceVariable* spvReflectGetEntryPointOutputVariableBySemant return NULL; } for (uint32_t index = 0; index < p_entry->output_variable_count; ++index) { - const SpvReflectInterfaceVariable* p_potential = &p_entry->output_variables[index]; + const SpvReflectInterfaceVariable* p_potential = p_entry->output_variables[index]; if (p_potential->semantic != NULL && strcmp(p_potential->semantic, semantic) == 0) { p_var = p_potential; } @@ -4297,13 +4704,13 @@ SpvReflectResult spvReflectChangeDescriptorBindingNumbers( return SPV_REFLECT_RESULT_ERROR_RANGE_EXCEEDED; } // Binding number - if (new_binding_number != SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE) { + if (new_binding_number != (uint32_t)SPV_REFLECT_BINDING_NUMBER_DONT_CHANGE) { uint32_t* p_code = p_module->_internal->spirv_code + p_target_descriptor->word_offset.binding; *p_code = new_binding_number; p_target_descriptor->binding = new_binding_number; } // Set number - if (new_set_binding != SPV_REFLECT_SET_NUMBER_DONT_CHANGE) { + if (new_set_binding != (uint32_t)SPV_REFLECT_SET_NUMBER_DONT_CHANGE) { uint32_t* p_code = p_module->_internal->spirv_code + p_target_descriptor->word_offset.set; *p_code = new_set_binding; p_target_descriptor->set = new_set_binding; @@ -4311,7 +4718,7 @@ SpvReflectResult spvReflectChangeDescriptorBindingNumbers( } SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS; - if (new_set_binding != SPV_REFLECT_SET_NUMBER_DONT_CHANGE) { + if (new_set_binding != (uint32_t)SPV_REFLECT_SET_NUMBER_DONT_CHANGE) { result = SynchronizeDescriptorSets(p_module); } return result; @@ -4352,7 +4759,7 @@ SpvReflectResult spvReflectChangeDescriptorSetNumber( } SpvReflectResult result = SPV_REFLECT_RESULT_SUCCESS; - if (IsNotNull(p_target_set) && new_set_number != SPV_REFLECT_SET_NUMBER_DONT_CHANGE) { + if (IsNotNull(p_target_set) && new_set_number != (uint32_t)SPV_REFLECT_SET_NUMBER_DONT_CHANGE) { for (uint32_t index = 0; index < p_target_set->binding_count; ++index) { SpvReflectDescriptorBinding* p_descriptor = p_target_set->bindings[index]; if (p_descriptor->word_offset.set > (p_module->_internal->spirv_word_count - 1)) { @@ -4398,8 +4805,8 @@ SpvReflectResult spvReflectChangeInputVariableLocation( return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; } for (uint32_t index = 0; index < p_module->input_variable_count; ++index) { - if(&p_module->input_variables[index] == p_input_variable) { - return ChangeVariableLocation(p_module, &p_module->input_variables[index], new_location); + if(p_module->input_variables[index] == p_input_variable) { + return ChangeVariableLocation(p_module, p_module->input_variables[index], new_location); } } return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; @@ -4418,8 +4825,8 @@ SpvReflectResult spvReflectChangeOutputVariableLocation( return SPV_REFLECT_RESULT_ERROR_NULL_POINTER; } for (uint32_t index = 0; index < p_module->output_variable_count; ++index) { - if(&p_module->output_variables[index] == p_output_variable) { - return ChangeVariableLocation(p_module, &p_module->output_variables[index], new_location); + if(p_module->output_variables[index] == p_output_variable) { + return ChangeVariableLocation(p_module, p_module->output_variables[index], new_location); } } return SPV_REFLECT_RESULT_ERROR_ELEMENT_NOT_FOUND; diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h index 6554aaa2cf..a5a956e9e8 100644 --- a/thirdparty/spirv-reflect/spirv_reflect.h +++ b/thirdparty/spirv-reflect/spirv_reflect.h @@ -72,26 +72,29 @@ typedef enum SpvReflectResult { SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_INSTRUCTION, SPV_REFLECT_RESULT_ERROR_SPIRV_UNEXPECTED_BLOCK_DATA, SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_BLOCK_MEMBER_REFERENCE, + SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ENTRY_POINT, + SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_EXECUTION_MODE, } SpvReflectResult; /*! @enum SpvReflectTypeFlagBits */ typedef enum SpvReflectTypeFlagBits { - SPV_REFLECT_TYPE_FLAG_UNDEFINED = 0x00000000, - SPV_REFLECT_TYPE_FLAG_VOID = 0x00000001, - SPV_REFLECT_TYPE_FLAG_BOOL = 0x00000002, - SPV_REFLECT_TYPE_FLAG_INT = 0x00000004, - SPV_REFLECT_TYPE_FLAG_FLOAT = 0x00000008, - SPV_REFLECT_TYPE_FLAG_VECTOR = 0x00000100, - SPV_REFLECT_TYPE_FLAG_MATRIX = 0x00000200, - SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE = 0x00010000, - SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER = 0x00020000, - SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE = 0x00040000, - SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK = 0x00080000, - SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK = 0x000F0000, - SPV_REFLECT_TYPE_FLAG_STRUCT = 0x10000000, - SPV_REFLECT_TYPE_FLAG_ARRAY = 0x20000000, + SPV_REFLECT_TYPE_FLAG_UNDEFINED = 0x00000000, + SPV_REFLECT_TYPE_FLAG_VOID = 0x00000001, + SPV_REFLECT_TYPE_FLAG_BOOL = 0x00000002, + SPV_REFLECT_TYPE_FLAG_INT = 0x00000004, + SPV_REFLECT_TYPE_FLAG_FLOAT = 0x00000008, + SPV_REFLECT_TYPE_FLAG_VECTOR = 0x00000100, + SPV_REFLECT_TYPE_FLAG_MATRIX = 0x00000200, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_IMAGE = 0x00010000, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLER = 0x00020000, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_SAMPLED_IMAGE = 0x00040000, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_BLOCK = 0x00080000, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE = 0x00100000, + SPV_REFLECT_TYPE_FLAG_EXTERNAL_MASK = 0x00FF0000, + SPV_REFLECT_TYPE_FLAG_STRUCT = 0x10000000, + SPV_REFLECT_TYPE_FLAG_ARRAY = 0x20000000, } SpvReflectTypeFlagBits; typedef uint32_t SpvReflectTypeFlags; @@ -141,6 +144,18 @@ typedef enum SpvReflectFormat { SPV_REFLECT_FORMAT_R32G32B32A32_UINT = 107, // = VK_FORMAT_R32G32B32A32_UINT SPV_REFLECT_FORMAT_R32G32B32A32_SINT = 108, // = VK_FORMAT_R32G32B32A32_SINT SPV_REFLECT_FORMAT_R32G32B32A32_SFLOAT = 109, // = VK_FORMAT_R32G32B32A32_SFLOAT + SPV_REFLECT_FORMAT_R64_UINT = 110, // = VK_FORMAT_R64_UINT + SPV_REFLECT_FORMAT_R64_SINT = 111, // = VK_FORMAT_R64_SINT + SPV_REFLECT_FORMAT_R64_SFLOAT = 112, // = VK_FORMAT_R64_SFLOAT + SPV_REFLECT_FORMAT_R64G64_UINT = 113, // = VK_FORMAT_R64G64_UINT + SPV_REFLECT_FORMAT_R64G64_SINT = 114, // = VK_FORMAT_R64G64_SINT + SPV_REFLECT_FORMAT_R64G64_SFLOAT = 115, // = VK_FORMAT_R64G64_SFLOAT + SPV_REFLECT_FORMAT_R64G64B64_UINT = 116, // = VK_FORMAT_R64G64B64_UINT + SPV_REFLECT_FORMAT_R64G64B64_SINT = 117, // = VK_FORMAT_R64G64B64_SINT + SPV_REFLECT_FORMAT_R64G64B64_SFLOAT = 118, // = VK_FORMAT_R64G64B64_FLOAT + SPV_REFLECT_FORMAT_R64G64B64A64_UINT = 119, // = VK_FORMAT_R64G64B64A64_UINT + SPV_REFLECT_FORMAT_R64G64B64A64_SINT = 120, // = VK_FORMAT_R64G64B64A64_SINT + SPV_REFLECT_FORMAT_R64G64B64A64_SFLOAT = 121, // = VK_FORMAT_R64G64B64A64_SFLOAT } SpvReflectFormat; /*! @enum SpvReflectVariableFlagBits @@ -157,17 +172,18 @@ typedef uint32_t SpvReflectVariableFlags; */ typedef enum SpvReflectDescriptorType { - SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER = 0, // = VK_DESCRIPTOR_TYPE_SAMPLER - SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, // = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER - SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2, // = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE - SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3, // = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE - SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4, // = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER - SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5, // = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER - SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6, // = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER - SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7, // = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER - SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, // = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC - SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, // = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC - SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, // = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER = 0, // = VK_DESCRIPTOR_TYPE_SAMPLER + SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1, // = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2, // = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3, // = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4, // = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER + SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5, // = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER + SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6, // = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7, // = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8, // = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC + SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9, // = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC + SPV_REFLECT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10, // = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + SPV_REFLECT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000 // = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR } SpvReflectDescriptorType; /*! @enum SpvReflectShaderStageFlagBits @@ -180,6 +196,15 @@ typedef enum SpvReflectShaderStageFlagBits { SPV_REFLECT_SHADER_STAGE_GEOMETRY_BIT = 0x00000008, // = VK_SHADER_STAGE_GEOMETRY_BIT SPV_REFLECT_SHADER_STAGE_FRAGMENT_BIT = 0x00000010, // = VK_SHADER_STAGE_FRAGMENT_BIT SPV_REFLECT_SHADER_STAGE_COMPUTE_BIT = 0x00000020, // = VK_SHADER_STAGE_COMPUTE_BIT + SPV_REFLECT_SHADER_STAGE_TASK_BIT_NV = 0x00000040, // = VK_SHADER_STAGE_TASK_BIT_NV + SPV_REFLECT_SHADER_STAGE_MESH_BIT_NV = 0x00000080, // = VK_SHADER_STAGE_MESH_BIT_NV + SPV_REFLECT_SHADER_STAGE_RAYGEN_BIT_KHR = 0x00000100, // VK_SHADER_STAGE_RAYGEN_BIT_KHR + SPV_REFLECT_SHADER_STAGE_ANY_HIT_BIT_KHR = 0x00000200, // VK_SHADER_STAGE_ANY_HIT_BIT_KHR + SPV_REFLECT_SHADER_STAGE_CLOSEST_HIT_BIT_KHR = 0x00000400, // VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR + SPV_REFLECT_SHADER_STAGE_MISS_BIT_KHR = 0x00000800, // VK_SHADER_STAGE_MISS_BIT_KHR + SPV_REFLECT_SHADER_STAGE_INTERSECTION_BIT_KHR = 0x00001000, // VK_SHADER_STAGE_INTERSECTION_BIT_KHR + SPV_REFLECT_SHADER_STAGE_CALLABLE_BIT_KHR = 0x00002000, // VK_SHADER_STAGE_CALLABLE_BIT_KHR + } SpvReflectShaderStageFlagBits; /*! @enum SpvReflectGenerator @@ -365,10 +390,12 @@ typedef struct SpvReflectEntryPoint { SpvExecutionModel spirv_execution_model; SpvReflectShaderStageFlagBits shader_stage; - uint32_t input_variable_count; - SpvReflectInterfaceVariable* input_variables; - uint32_t output_variable_count; - SpvReflectInterfaceVariable* output_variables; + uint32_t input_variable_count; + SpvReflectInterfaceVariable** input_variables; + uint32_t output_variable_count; + SpvReflectInterfaceVariable** output_variables; + uint32_t interface_variable_count; + SpvReflectInterfaceVariable* interface_variables; uint32_t descriptor_set_count; SpvReflectDescriptorSet* descriptor_sets; @@ -377,6 +404,12 @@ typedef struct SpvReflectEntryPoint { uint32_t* used_uniforms; uint32_t used_push_constant_count; uint32_t* used_push_constants; + + struct LocalSize { + uint32_t x; + uint32_t y; + uint32_t z; + } local_size; } SpvReflectEntryPoint; /*! @struct SpvReflectShaderModule @@ -398,10 +431,12 @@ typedef struct SpvReflectShaderModule { SpvReflectDescriptorBinding* descriptor_bindings; uint32_t descriptor_set_count; SpvReflectDescriptorSet descriptor_sets[SPV_REFLECT_MAX_DESCRIPTOR_SETS]; - uint32_t input_variable_count; - SpvReflectInterfaceVariable* input_variables; - uint32_t output_variable_count; - SpvReflectInterfaceVariable* output_variables; + uint32_t input_variable_count; + SpvReflectInterfaceVariable** input_variables; + uint32_t output_variable_count; + SpvReflectInterfaceVariable** output_variables; + uint32_t interface_variable_count; + SpvReflectInterfaceVariable* interface_variables; uint32_t push_constant_block_count; SpvReflectBlockVariable* push_constant_blocks; @@ -582,6 +617,58 @@ SpvReflectResult spvReflectEnumerateEntryPointDescriptorSets( ); +/*! @fn spvReflectEnumerateInterfaceVariables + @brief If the module contains multiple entry points, this will only get + the interface variables for the first one. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_variables is NULL, the module's interface variable + count will be stored here. + If pp_variables is not NULL, *p_count must contain + the module's interface variable count. + @param pp_variables If NULL, the module's interface variable count will be + written to *p_count. + If non-NULL, pp_variables must point to an array with + *p_count entries, where pointers to the module's + interface variables will be written. The caller must not + free the interface variables written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateInterfaceVariables( + const SpvReflectShaderModule* p_module, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +); + +/*! @fn spvReflectEnumerateEntryPointInterfaceVariables + @brief Enumerate the interface variables for a given entry point. + @param entry_point The name of the entry point to get the interface variables for. + @param p_module Pointer to an instance of SpvReflectShaderModule. + @param p_count If pp_variables is NULL, the entry point's interface variable + count will be stored here. + If pp_variables is not NULL, *p_count must contain + the entry point's interface variable count. + @param pp_variables If NULL, the entry point's interface variable count will be + written to *p_count. + If non-NULL, pp_variables must point to an array with + *p_count entries, where pointers to the entry point's + interface variables will be written. The caller must not + free the interface variables written to this array. + @return If successful, returns SPV_REFLECT_RESULT_SUCCESS. + Otherwise, the error code indicates the cause of the + failure. + +*/ +SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables( + const SpvReflectShaderModule* p_module, + const char* entry_point, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +); + + /*! @fn spvReflectEnumerateInputVariables @brief If the module contains multiple entry points, this will only get the input variables for the first one. @@ -1310,10 +1397,12 @@ public: SpvReflectResult EnumerateEntryPointDescriptorBindings(const char* entry_point, uint32_t* p_count, SpvReflectDescriptorBinding** pp_bindings) const; SpvReflectResult EnumerateDescriptorSets( uint32_t* p_count, SpvReflectDescriptorSet** pp_sets) const ; SpvReflectResult EnumerateEntryPointDescriptorSets(const char* entry_point, uint32_t* p_count, SpvReflectDescriptorSet** pp_sets) const ; + SpvReflectResult EnumerateInterfaceVariables(uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const; + SpvReflectResult EnumerateEntryPointInterfaceVariables(const char* entry_point, uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const; SpvReflectResult EnumerateInputVariables(uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const; - SpvReflectResult EnumerateEntryPointInputVariables(const char* entry_point, uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const; + SpvReflectResult EnumerateEntryPointInputVariables(const char* entry_point, uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const; SpvReflectResult EnumerateOutputVariables(uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const; - SpvReflectResult EnumerateEntryPointOutputVariables(const char* entry_point, uint32_t* p_count,SpvReflectInterfaceVariable** pp_variables) const; + SpvReflectResult EnumerateEntryPointOutputVariables(const char* entry_point, uint32_t* p_count, SpvReflectInterfaceVariable** pp_variables) const; SpvReflectResult EnumeratePushConstantBlocks(uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const; SpvReflectResult EnumerateEntryPointPushConstantBlocks(const char* entry_point, uint32_t* p_count, SpvReflectBlockVariable** pp_blocks) const; SPV_REFLECT_DEPRECATED("Renamed to EnumeratePushConstantBlocks") @@ -1361,6 +1450,11 @@ public: SpvReflectResult ChangeOutputVariableLocation(const SpvReflectInterfaceVariable* p_output_variable, uint32_t new_location); private: + // Make noncopyable + ShaderModule(const ShaderModule&); + ShaderModule& operator=(const ShaderModule&); + +private: mutable SpvReflectResult m_result = SPV_REFLECT_RESULT_NOT_READY; SpvReflectShaderModule m_module = {}; }; @@ -1591,6 +1685,48 @@ inline SpvReflectResult ShaderModule::EnumerateEntryPointDescriptorSets( } +/*! @fn EnumerateInterfaceVariables + + @param count + @param pp_variables + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateInterfaceVariables( + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +) const +{ + m_result = spvReflectEnumerateInterfaceVariables( + &m_module, + p_count, + pp_variables); + return m_result; +} + +/*! @fn EnumerateEntryPointInterfaceVariables + + @param entry_point + @param count + @param pp_variables + @return + +*/ +inline SpvReflectResult ShaderModule::EnumerateEntryPointInterfaceVariables( + const char* entry_point, + uint32_t* p_count, + SpvReflectInterfaceVariable** pp_variables +) const +{ + m_result = spvReflectEnumerateEntryPointInterfaceVariables( + &m_module, + entry_point, + p_count, + pp_variables); + return m_result; +} + + /*! @fn EnumerateInputVariables @param count diff --git a/thirdparty/zstd/common/bitstream.h b/thirdparty/zstd/common/bitstream.h index 37b99c01ee..d9a2730104 100644 --- a/thirdparty/zstd/common/bitstream.h +++ b/thirdparty/zstd/common/bitstream.h @@ -17,7 +17,6 @@ #if defined (__cplusplus) extern "C" { #endif - /* * This API consists of small unitary functions, which must be inlined for best performance. * Since link-time-optimization is not available for all compilers, @@ -36,10 +35,12 @@ extern "C" { /*========================================= * Target specific =========================================*/ -#if defined(__BMI__) && defined(__GNUC__) -# include <immintrin.h> /* support for bextr (experimental) */ -#elif defined(__ICCARM__) -# include <intrinsics.h> +#ifndef ZSTD_NO_INTRINSICS +# if defined(__BMI__) && defined(__GNUC__) +# include <immintrin.h> /* support for bextr (experimental) */ +# elif defined(__ICCARM__) +# include <intrinsics.h> +# endif #endif #define STREAM_ACCUMULATOR_MIN_32 25 @@ -141,8 +142,12 @@ MEM_STATIC unsigned BIT_highbit32 (U32 val) assert(val != 0); { # if defined(_MSC_VER) /* Visual */ - unsigned long r=0; - return _BitScanReverse ( &r, val ) ? (unsigned)r : 0; +# if STATIC_BMI2 == 1 + return _lzcnt_u32(val) ^ 31; +# else + unsigned long r = 0; + return _BitScanReverse(&r, val) ? (unsigned)r : 0; +# endif # elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */ return __builtin_clz (val) ^ 31; # elif defined(__ICCARM__) /* IAR Intrinsic */ @@ -198,7 +203,7 @@ MEM_STATIC size_t BIT_initCStream(BIT_CStream_t* bitC, MEM_STATIC void BIT_addBits(BIT_CStream_t* bitC, size_t value, unsigned nbBits) { - MEM_STATIC_ASSERT(BIT_MASK_SIZE == 32); + DEBUG_STATIC_ASSERT(BIT_MASK_SIZE == 32); assert(nbBits < BIT_MASK_SIZE); assert(nbBits + bitC->bitPos < sizeof(bitC->bitContainer) * 8); bitC->bitContainer |= (value & BIT_mask[nbBits]) << bitC->bitPos; @@ -271,7 +276,7 @@ MEM_STATIC size_t BIT_closeCStream(BIT_CStream_t* bitC) */ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, size_t srcSize) { - if (srcSize < 1) { memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); } + if (srcSize < 1) { ZSTD_memset(bitD, 0, sizeof(*bitD)); return ERROR(srcSize_wrong); } bitD->start = (const char*)srcBuffer; bitD->limitPtr = bitD->start + sizeof(bitD->bitContainer); @@ -317,12 +322,12 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si return srcSize; } -MEM_STATIC size_t BIT_getUpperBits(size_t bitContainer, U32 const start) +MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getUpperBits(size_t bitContainer, U32 const start) { return bitContainer >> start; } -MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) +MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 const nbBits) { U32 const regMask = sizeof(bitContainer)*8 - 1; /* if start > regMask, bitstream is corrupted, and result is undefined */ @@ -330,10 +335,14 @@ MEM_STATIC size_t BIT_getMiddleBits(size_t bitContainer, U32 const start, U32 co return (bitContainer >> (start & regMask)) & BIT_mask[nbBits]; } -MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) +MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) { +#if defined(STATIC_BMI2) && STATIC_BMI2 == 1 + return _bzhi_u64(bitContainer, nbBits); +#else assert(nbBits < BIT_MASK_SIZE); return bitContainer & BIT_mask[nbBits]; +#endif } /*! BIT_lookBits() : @@ -342,7 +351,7 @@ MEM_STATIC size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits) * On 32-bits, maxNbBits==24. * On 64-bits, maxNbBits==56. * @return : value extracted */ -MEM_STATIC size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) +MEM_STATIC FORCE_INLINE_ATTR size_t BIT_lookBits(const BIT_DStream_t* bitD, U32 nbBits) { /* arbitrate between double-shift and shift+mask */ #if 1 @@ -365,7 +374,7 @@ MEM_STATIC size_t BIT_lookBitsFast(const BIT_DStream_t* bitD, U32 nbBits) return (bitD->bitContainer << (bitD->bitsConsumed & regMask)) >> (((regMask+1)-nbBits) & regMask); } -MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) +MEM_STATIC FORCE_INLINE_ATTR void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) { bitD->bitsConsumed += nbBits; } @@ -374,7 +383,7 @@ MEM_STATIC void BIT_skipBits(BIT_DStream_t* bitD, U32 nbBits) * Read (consume) next n bits from local register and update. * Pay attention to not read more than nbBits contained into local register. * @return : extracted value. */ -MEM_STATIC size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits) +MEM_STATIC FORCE_INLINE_ATTR size_t BIT_readBits(BIT_DStream_t* bitD, unsigned nbBits) { size_t const value = BIT_lookBits(bitD, nbBits); BIT_skipBits(bitD, nbBits); diff --git a/thirdparty/zstd/common/compiler.h b/thirdparty/zstd/common/compiler.h index 95e9483521..3e454f38c1 100644 --- a/thirdparty/zstd/common/compiler.h +++ b/thirdparty/zstd/common/compiler.h @@ -39,6 +39,17 @@ #endif /** + On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC). + This explictly marks such functions as __cdecl so that the code will still compile + if a CC other than __cdecl has been made the default. +*/ +#if defined(_MSC_VER) +# define WIN_CDECL __cdecl +#else +# define WIN_CDECL +#endif + +/** * FORCE_INLINE_TEMPLATE is used to define C "templates", which take constant * parameters. They must be inlined for the compiler to eliminate the constant * branches. @@ -114,12 +125,12 @@ # include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ # define PREFETCH_L1(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) # define PREFETCH_L2(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T1) -# elif defined(__aarch64__) -# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))) -# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))) # elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) # define PREFETCH_L1(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) # define PREFETCH_L2(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 2 /* locality */) +# elif defined(__aarch64__) +# define PREFETCH_L1(ptr) __asm__ __volatile__("prfm pldl1keep, %0" ::"Q"(*(ptr))) +# define PREFETCH_L2(ptr) __asm__ __volatile__("prfm pldl2keep, %0" ::"Q"(*(ptr))) # else # define PREFETCH_L1(ptr) (void)(ptr) /* disabled */ # define PREFETCH_L2(ptr) (void)(ptr) /* disabled */ @@ -172,4 +183,106 @@ # pragma warning(disable : 4324) /* disable: C4324: padded structure */ #endif +/*Like DYNAMIC_BMI2 but for compile time determination of BMI2 support*/ +#ifndef STATIC_BMI2 +# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_I86)) +# ifdef __AVX2__ //MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 +# define STATIC_BMI2 1 +# endif +# endif +#endif + +#ifndef STATIC_BMI2 + #define STATIC_BMI2 0 +#endif + +/* compat. with non-clang compilers */ +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +/* compat. with non-clang compilers */ +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + +/* detects whether we are being compiled under msan */ +#ifndef ZSTD_MEMORY_SANITIZER +# if __has_feature(memory_sanitizer) +# define ZSTD_MEMORY_SANITIZER 1 +# else +# define ZSTD_MEMORY_SANITIZER 0 +# endif +#endif + +#if ZSTD_MEMORY_SANITIZER +/* Not all platforms that support msan provide sanitizers/msan_interface.h. + * We therefore declare the functions we need ourselves, rather than trying to + * include the header file... */ +#include <stddef.h> /* size_t */ +#define ZSTD_DEPS_NEED_STDINT +#include "zstd_deps.h" /* intptr_t */ + +/* Make memory region fully initialized (without changing its contents). */ +void __msan_unpoison(const volatile void *a, size_t size); + +/* Make memory region fully uninitialized (without changing its contents). + This is a legacy interface that does not update origin information. Use + __msan_allocated_memory() instead. */ +void __msan_poison(const volatile void *a, size_t size); + +/* Returns the offset of the first (at least partially) poisoned byte in the + memory range, or -1 if the whole range is good. */ +intptr_t __msan_test_shadow(const volatile void *x, size_t size); +#endif + +/* detects whether we are being compiled under asan */ +#ifndef ZSTD_ADDRESS_SANITIZER +# if __has_feature(address_sanitizer) +# define ZSTD_ADDRESS_SANITIZER 1 +# elif defined(__SANITIZE_ADDRESS__) +# define ZSTD_ADDRESS_SANITIZER 1 +# else +# define ZSTD_ADDRESS_SANITIZER 0 +# endif +#endif + +#if ZSTD_ADDRESS_SANITIZER +/* Not all platforms that support asan provide sanitizers/asan_interface.h. + * We therefore declare the functions we need ourselves, rather than trying to + * include the header file... */ +#include <stddef.h> /* size_t */ + +/** + * Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable. + * + * This memory must be previously allocated by your program. Instrumented + * code is forbidden from accessing addresses in this region until it is + * unpoisoned. This function is not guaranteed to poison the entire region - + * it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan + * alignment restrictions. + * + * \note This function is not thread-safe because no two threads can poison or + * unpoison memory in the same memory region simultaneously. + * + * \param addr Start of memory region. + * \param size Size of memory region. */ +void __asan_poison_memory_region(void const volatile *addr, size_t size); + +/** + * Marks a memory region (<c>[addr, addr+size)</c>) as addressable. + * + * This memory must be previously allocated by your program. Accessing + * addresses in this region is allowed until this region is poisoned again. + * This function could unpoison a super-region of <c>[addr, addr+size)</c> due + * to ASan alignment restrictions. + * + * \note This function is not thread-safe because no two threads can + * poison or unpoison memory in the same memory region simultaneously. + * + * \param addr Start of memory region. + * \param size Size of memory region. */ +void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +#endif + #endif /* ZSTD_COMPILER_H */ diff --git a/thirdparty/zstd/common/cpu.h b/thirdparty/zstd/common/cpu.h index 6e8a974f62..cb210593ea 100644 --- a/thirdparty/zstd/common/cpu.h +++ b/thirdparty/zstd/common/cpu.h @@ -16,8 +16,6 @@ * https://github.com/facebook/folly/blob/master/folly/CpuId.h */ -#include <string.h> - #include "mem.h" #ifdef _MSC_VER diff --git a/thirdparty/zstd/common/debug.h b/thirdparty/zstd/common/debug.h index ac6224888d..8b5734366c 100644 --- a/thirdparty/zstd/common/debug.h +++ b/thirdparty/zstd/common/debug.h @@ -51,15 +51,6 @@ extern "C" { #endif -/* DEBUGFILE can be defined externally, - * typically through compiler command line. - * note : currently useless. - * Value must be stderr or stdout */ -#ifndef DEBUGFILE -# define DEBUGFILE stderr -#endif - - /* recommended values for DEBUGLEVEL : * 0 : release mode, no debug, all run-time checks disabled * 1 : enables assert() only, no display @@ -76,7 +67,8 @@ extern "C" { */ #if (DEBUGLEVEL>=1) -# include <assert.h> +# define ZSTD_DEPS_NEED_ASSERT +# include "zstd_deps.h" #else # ifndef assert /* assert may be already defined, due to prior #include <assert.h> */ # define assert(condition) ((void)0) /* disable assert (default) */ @@ -84,7 +76,8 @@ extern "C" { #endif #if (DEBUGLEVEL>=2) -# include <stdio.h> +# define ZSTD_DEPS_NEED_IO +# include "zstd_deps.h" extern int g_debuglevel; /* the variable is only declared, it actually lives in debug.c, and is shared by the whole process. @@ -92,14 +85,14 @@ extern int g_debuglevel; /* the variable is only declared, It's useful when enabling very verbose levels on selective conditions (such as position in src) */ -# define RAWLOG(l, ...) { \ - if (l<=g_debuglevel) { \ - fprintf(stderr, __VA_ARGS__); \ +# define RAWLOG(l, ...) { \ + if (l<=g_debuglevel) { \ + ZSTD_DEBUG_PRINT(__VA_ARGS__); \ } } -# define DEBUGLOG(l, ...) { \ - if (l<=g_debuglevel) { \ - fprintf(stderr, __FILE__ ": " __VA_ARGS__); \ - fprintf(stderr, " \n"); \ +# define DEBUGLOG(l, ...) { \ + if (l<=g_debuglevel) { \ + ZSTD_DEBUG_PRINT(__FILE__ ": " __VA_ARGS__); \ + ZSTD_DEBUG_PRINT(" \n"); \ } } #else # define RAWLOG(l, ...) {} /* disabled */ diff --git a/thirdparty/zstd/common/entropy_common.c b/thirdparty/zstd/common/entropy_common.c index 9d3e4e8e36..f9fcb1acfc 100644 --- a/thirdparty/zstd/common/entropy_common.c +++ b/thirdparty/zstd/common/entropy_common.c @@ -38,8 +38,31 @@ const char* HUF_getErrorName(size_t code) { return ERR_getErrorName(code); } /*-************************************************************** * FSE NCount encoding-decoding ****************************************************************/ -size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, - const void* headerBuffer, size_t hbSize) +static U32 FSE_ctz(U32 val) +{ + assert(val != 0); + { +# if defined(_MSC_VER) /* Visual */ + unsigned long r=0; + return _BitScanForward(&r, val) ? (unsigned)r : 0; +# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ + return __builtin_ctz(val); +# elif defined(__ICCARM__) /* IAR Intrinsic */ + return __CTZ(val); +# else /* Software version */ + U32 count = 0; + while ((val & 1) == 0) { + val >>= 1; + ++count; + } + return count; +# endif + } +} + +FORCE_INLINE_TEMPLATE +size_t FSE_readNCount_body(short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) { const BYTE* const istart = (const BYTE*) headerBuffer; const BYTE* const iend = istart + hbSize; @@ -50,23 +73,23 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t U32 bitStream; int bitCount; unsigned charnum = 0; + unsigned const maxSV1 = *maxSVPtr + 1; int previous0 = 0; - if (hbSize < 4) { - /* This function only works when hbSize >= 4 */ - char buffer[4]; - memset(buffer, 0, sizeof(buffer)); - memcpy(buffer, headerBuffer, hbSize); + if (hbSize < 8) { + /* This function only works when hbSize >= 8 */ + char buffer[8] = {0}; + ZSTD_memcpy(buffer, headerBuffer, hbSize); { size_t const countSize = FSE_readNCount(normalizedCounter, maxSVPtr, tableLogPtr, buffer, sizeof(buffer)); if (FSE_isError(countSize)) return countSize; if (countSize > hbSize) return ERROR(corruption_detected); return countSize; } } - assert(hbSize >= 4); + assert(hbSize >= 8); /* init */ - memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */ + ZSTD_memset(normalizedCounter, 0, (*maxSVPtr+1) * sizeof(normalizedCounter[0])); /* all symbols not present in NCount have a frequency of 0 */ bitStream = MEM_readLE32(ip); nbBits = (bitStream & 0xF) + FSE_MIN_TABLELOG; /* extract tableLog */ if (nbBits > FSE_TABLELOG_ABSOLUTE_MAX) return ERROR(tableLog_tooLarge); @@ -77,36 +100,58 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t threshold = 1<<nbBits; nbBits++; - while ((remaining>1) & (charnum<=*maxSVPtr)) { + for (;;) { if (previous0) { - unsigned n0 = charnum; - while ((bitStream & 0xFFFF) == 0xFFFF) { - n0 += 24; - if (ip < iend-5) { - ip += 2; - bitStream = MEM_readLE32(ip) >> bitCount; + /* Count the number of repeats. Each time the + * 2-bit repeat code is 0b11 there is another + * repeat. + * Avoid UB by setting the high bit to 1. + */ + int repeats = FSE_ctz(~bitStream | 0x80000000) >> 1; + while (repeats >= 12) { + charnum += 3 * 12; + if (LIKELY(ip <= iend-7)) { + ip += 3; } else { - bitStream >>= 16; - bitCount += 16; - } } - while ((bitStream & 3) == 3) { - n0 += 3; - bitStream >>= 2; - bitCount += 2; + bitCount -= (int)(8 * (iend - 7 - ip)); + bitCount &= 31; + ip = iend - 4; + } + bitStream = MEM_readLE32(ip) >> bitCount; + repeats = FSE_ctz(~bitStream | 0x80000000) >> 1; } - n0 += bitStream & 3; + charnum += 3 * repeats; + bitStream >>= 2 * repeats; + bitCount += 2 * repeats; + + /* Add the final repeat which isn't 0b11. */ + assert((bitStream & 3) < 3); + charnum += bitStream & 3; bitCount += 2; - if (n0 > *maxSVPtr) return ERROR(maxSymbolValue_tooSmall); - while (charnum < n0) normalizedCounter[charnum++] = 0; - if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { + + /* This is an error, but break and return an error + * at the end, because returning out of a loop makes + * it harder for the compiler to optimize. + */ + if (charnum >= maxSV1) break; + + /* We don't need to set the normalized count to 0 + * because we already memset the whole buffer to 0. + */ + + if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { assert((bitCount >> 3) <= 3); /* For first condition to work */ ip += bitCount>>3; bitCount &= 7; - bitStream = MEM_readLE32(ip) >> bitCount; } else { - bitStream >>= 2; - } } - { int const max = (2*threshold-1) - remaining; + bitCount -= (int)(8 * (iend - 4 - ip)); + bitCount &= 31; + ip = iend - 4; + } + bitStream = MEM_readLE32(ip) >> bitCount; + } + { + int const max = (2*threshold-1) - remaining; int count; if ((bitStream & (threshold-1)) < (U32)max) { @@ -119,24 +164,43 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t } count--; /* extra accuracy */ - remaining -= count < 0 ? -count : count; /* -1 means +1 */ + /* When it matters (small blocks), this is a + * predictable branch, because we don't use -1. + */ + if (count >= 0) { + remaining -= count; + } else { + assert(count == -1); + remaining += count; + } normalizedCounter[charnum++] = (short)count; previous0 = !count; - while (remaining < threshold) { - nbBits--; - threshold >>= 1; + + assert(threshold > 1); + if (remaining < threshold) { + /* This branch can be folded into the + * threshold update condition because we + * know that threshold > 1. + */ + if (remaining <= 1) break; + nbBits = BIT_highbit32(remaining) + 1; + threshold = 1 << (nbBits - 1); } + if (charnum >= maxSV1) break; - if ((ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { + if (LIKELY(ip <= iend-7) || (ip + (bitCount>>3) <= iend-4)) { ip += bitCount>>3; bitCount &= 7; } else { bitCount -= (int)(8 * (iend - 4 - ip)); + bitCount &= 31; ip = iend - 4; } - bitStream = MEM_readLE32(ip) >> (bitCount & 31); - } } /* while ((remaining>1) & (charnum<=*maxSVPtr)) */ + bitStream = MEM_readLE32(ip) >> bitCount; + } } if (remaining != 1) return ERROR(corruption_detected); + /* Only possible when there are too many zeros. */ + if (charnum > maxSV1) return ERROR(maxSymbolValue_tooSmall); if (bitCount > 32) return ERROR(corruption_detected); *maxSVPtr = charnum-1; @@ -144,6 +208,43 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t return ip-istart; } +/* Avoids the FORCE_INLINE of the _body() function. */ +static size_t FSE_readNCount_body_default( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); +} + +#if DYNAMIC_BMI2 +TARGET_ATTRIBUTE("bmi2") static size_t FSE_readNCount_body_bmi2( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + return FSE_readNCount_body(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); +} +#endif + +size_t FSE_readNCount_bmi2( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize, int bmi2) +{ +#if DYNAMIC_BMI2 + if (bmi2) { + return FSE_readNCount_body_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); + } +#endif + (void)bmi2; + return FSE_readNCount_body_default(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize); +} + +size_t FSE_readNCount( + short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr, + const void* headerBuffer, size_t hbSize) +{ + return FSE_readNCount_bmi2(normalizedCounter, maxSVPtr, tableLogPtr, headerBuffer, hbSize, /* bmi2 */ 0); +} + /*! HUF_readStats() : Read compact Huffman tree, saved by HUF_writeCTable(). @@ -156,6 +257,17 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, const void* src, size_t srcSize) { + U32 wksp[HUF_READ_STATS_WORKSPACE_SIZE_U32]; + return HUF_readStats_wksp(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, wksp, sizeof(wksp), /* bmi2 */ 0); +} + +FORCE_INLINE_TEMPLATE size_t +HUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize, + int bmi2) +{ U32 weightTotal; const BYTE* ip = (const BYTE*) src; size_t iSize; @@ -163,7 +275,7 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, if (!srcSize) return ERROR(srcSize_wrong); iSize = ip[0]; - /* memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ + /* ZSTD_memset(huffWeight, 0, hwSize); *//* is not necessary, even though some analyzer complain ... */ if (iSize >= 128) { /* special header */ oSize = iSize - 127; @@ -177,14 +289,14 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, huffWeight[n+1] = ip[n/2] & 15; } } } else { /* header compressed with FSE (normal case) */ - FSE_DTable fseWorkspace[FSE_DTABLE_SIZE_U32(6)]; /* 6 is max possible tableLog for HUF header (maybe even 5, to be tested) */ if (iSize+1 > srcSize) return ERROR(srcSize_wrong); - oSize = FSE_decompress_wksp(huffWeight, hwSize-1, ip+1, iSize, fseWorkspace, 6); /* max (hwSize-1) values decoded, as last one is implied */ + /* max (hwSize-1) values decoded, as last one is implied */ + oSize = FSE_decompress_wksp_bmi2(huffWeight, hwSize-1, ip+1, iSize, 6, workSpace, wkspSize, bmi2); if (FSE_isError(oSize)) return oSize; } /* collect weight stats */ - memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32)); + ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32)); weightTotal = 0; { U32 n; for (n=0; n<oSize; n++) { if (huffWeight[n] >= HUF_TABLELOG_MAX) return ERROR(corruption_detected); @@ -214,3 +326,37 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, *nbSymbolsPtr = (U32)(oSize+1); return iSize+1; } + +/* Avoids the FORCE_INLINE of the _body() function. */ +static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize) +{ + return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 0); +} + +#if DYNAMIC_BMI2 +static TARGET_ATTRIBUTE("bmi2") size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize) +{ + return HUF_readStats_body(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize, 1); +} +#endif + +size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, U32* rankStats, + U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workSpace, size_t wkspSize, + int bmi2) +{ +#if DYNAMIC_BMI2 + if (bmi2) { + return HUF_readStats_body_bmi2(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize); + } +#endif + (void)bmi2; + return HUF_readStats_body_default(huffWeight, hwSize, rankStats, nbSymbolsPtr, tableLogPtr, src, srcSize, workSpace, wkspSize); +} diff --git a/thirdparty/zstd/common/error_private.c b/thirdparty/zstd/common/error_private.c index cd437529c1..45bba5305b 100644 --- a/thirdparty/zstd/common/error_private.c +++ b/thirdparty/zstd/common/error_private.c @@ -48,6 +48,7 @@ const char* ERR_getErrorString(ERR_enum code) case PREFIX(frameIndex_tooLarge): return "Frame index is too large"; case PREFIX(seekableIO): return "An I/O error occurred when reading/seeking"; case PREFIX(dstBuffer_wrong): return "Destination buffer is wrong"; + case PREFIX(srcBuffer_wrong): return "Source buffer is wrong"; case PREFIX(maxCode): default: return notErrorCode; } diff --git a/thirdparty/zstd/common/error_private.h b/thirdparty/zstd/common/error_private.h index 982cf8e9fe..71b37b8dfa 100644 --- a/thirdparty/zstd/common/error_private.h +++ b/thirdparty/zstd/common/error_private.h @@ -21,7 +21,7 @@ extern "C" { /* **************************************** * Dependencies ******************************************/ -#include <stddef.h> /* size_t */ +#include "zstd_deps.h" /* size_t */ #include "zstd_errors.h" /* enum list */ diff --git a/thirdparty/zstd/common/fse.h b/thirdparty/zstd/common/fse.h index ff54e70ea7..dd5fc44e80 100644 --- a/thirdparty/zstd/common/fse.h +++ b/thirdparty/zstd/common/fse.h @@ -23,7 +23,7 @@ extern "C" { /*-***************************************** * Dependencies ******************************************/ -#include <stddef.h> /* size_t, ptrdiff_t */ +#include "zstd_deps.h" /* size_t, ptrdiff_t */ /*-***************************************** @@ -137,10 +137,16 @@ FSE_PUBLIC_API unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize /*! FSE_normalizeCount(): normalize counts so that sum(count[]) == Power_of_2 (2^tableLog) 'normalizedCounter' is a table of short, of minimum size (maxSymbolValue+1). + useLowProbCount is a boolean parameter which trades off compressed size for + faster header decoding. When it is set to 1, the compressed data will be slightly + smaller. And when it is set to 0, FSE_readNCount() and FSE_buildDTable() will be + faster. If you are compressing a small amount of data (< 2 KB) then useLowProbCount=0 + is a good default, since header deserialization makes a big speed difference. + Otherwise, useLowProbCount=1 is a good default, since the speed difference is small. @return : tableLog, or an errorCode, which can be tested using FSE_isError() */ FSE_PUBLIC_API size_t FSE_normalizeCount(short* normalizedCounter, unsigned tableLog, - const unsigned* count, size_t srcSize, unsigned maxSymbolValue); + const unsigned* count, size_t srcSize, unsigned maxSymbolValue, unsigned useLowProbCount); /*! FSE_NCountWriteBound(): Provides the maximum possible size of an FSE normalized table, given 'maxSymbolValue' and 'tableLog'. @@ -228,6 +234,13 @@ FSE_PUBLIC_API size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, const void* rBuffer, size_t rBuffSize); +/*! FSE_readNCount_bmi2(): + * Same as FSE_readNCount() but pass bmi2=1 when your CPU supports BMI2 and 0 otherwise. + */ +FSE_PUBLIC_API size_t FSE_readNCount_bmi2(short* normalizedCounter, + unsigned* maxSymbolValuePtr, unsigned* tableLogPtr, + const void* rBuffer, size_t rBuffSize, int bmi2); + /*! Constructor and Destructor of FSE_DTable. Note that its size depends on 'tableLog' */ typedef unsigned FSE_DTable; /* don't allocate that. It's just a way to be more restrictive than void* */ @@ -288,12 +301,12 @@ If there is an error, the function will return an error code, which can be teste *******************************************/ /* FSE buffer bounds */ #define FSE_NCOUNTBOUND 512 -#define FSE_BLOCKBOUND(size) (size + (size>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */) +#define FSE_BLOCKBOUND(size) ((size) + ((size)>>7) + 4 /* fse states */ + sizeof(size_t) /* bitContainer */) #define FSE_COMPRESSBOUND(size) (FSE_NCOUNTBOUND + FSE_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ /* It is possible to statically allocate FSE CTable/DTable as a table of FSE_CTable/FSE_DTable using below macros */ -#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<(maxTableLog-1)) + ((maxSymbolValue+1)*2)) -#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<maxTableLog)) +#define FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) (1 + (1<<((maxTableLog)-1)) + (((maxSymbolValue)+1)*2)) +#define FSE_DTABLE_SIZE_U32(maxTableLog) (1 + (1<<(maxTableLog))) /* or use the size to malloc() space directly. Pay attention to alignment restrictions though */ #define FSE_CTABLE_SIZE(maxTableLog, maxSymbolValue) (FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(FSE_CTable)) @@ -309,9 +322,9 @@ unsigned FSE_optimalTableLog_internal(unsigned maxTableLog, size_t srcSize, unsi /* FSE_compress_wksp() : * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). - * FSE_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable. + * FSE_COMPRESS_WKSP_SIZE_U32() provides the minimum size required for `workSpace` as a table of FSE_CTable. */ -#define FSE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) ) +#define FSE_COMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ( FSE_CTABLE_SIZE_U32(maxTableLog, maxSymbolValue) + ((maxTableLog > 12) ? (1 << (maxTableLog - 2)) : 1024) ) size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); size_t FSE_buildCTable_raw (FSE_CTable* ct, unsigned nbBits); @@ -322,18 +335,30 @@ size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue); /* FSE_buildCTable_wksp() : * Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`). - * `wkspSize` must be >= `(1<<tableLog)`. + * `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`. */ +#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (maxSymbolValue + 2 + (1ull << (tableLog - 2))) +#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)) size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); +#define FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) (sizeof(short) * (maxSymbolValue + 1) + (1ULL << maxTableLog) + 8) +#define FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) ((FSE_BUILD_DTABLE_WKSP_SIZE(maxTableLog, maxSymbolValue) + sizeof(unsigned) - 1) / sizeof(unsigned)) +FSE_PUBLIC_API size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); +/**< Same as FSE_buildDTable(), using an externally allocated `workspace` produced with `FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxSymbolValue)` */ + size_t FSE_buildDTable_raw (FSE_DTable* dt, unsigned nbBits); /**< build a fake FSE_DTable, designed to read a flat distribution where each symbol uses nbBits */ size_t FSE_buildDTable_rle (FSE_DTable* dt, unsigned char symbolValue); /**< build a fake FSE_DTable, designed to always generate the same symbolValue */ -size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog); -/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DTABLE_SIZE_U32(maxLog)` */ +#define FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) (FSE_DTABLE_SIZE_U32(maxTableLog) + FSE_BUILD_DTABLE_WKSP_SIZE_U32(maxTableLog, maxSymbolValue)) +#define FSE_DECOMPRESS_WKSP_SIZE(maxTableLog, maxSymbolValue) (FSE_DECOMPRESS_WKSP_SIZE_U32(maxTableLog, maxSymbolValue) * sizeof(unsigned)) +size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize); +/**< same as FSE_decompress(), using an externally allocated `workSpace` produced with `FSE_DECOMPRESS_WKSP_SIZE_U32(maxLog, maxSymbolValue)` */ + +size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2); +/**< Same as FSE_decompress_wksp() but with dynamic BMI2 support. Pass 1 if your CPU supports BMI2 or 0 if it doesn't. */ typedef enum { FSE_repeat_none, /**< Cannot use the previous table */ @@ -644,6 +669,9 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) #ifndef FSE_DEFAULT_MEMORY_USAGE # define FSE_DEFAULT_MEMORY_USAGE 13 #endif +#if (FSE_DEFAULT_MEMORY_USAGE > FSE_MAX_MEMORY_USAGE) +# error "FSE_DEFAULT_MEMORY_USAGE must be <= FSE_MAX_MEMORY_USAGE" +#endif /*!FSE_MAX_SYMBOL_VALUE : * Maximum symbol value authorized. @@ -677,7 +705,7 @@ MEM_STATIC unsigned FSE_endOfDState(const FSE_DState_t* DStatePtr) # error "FSE_MAX_TABLELOG > FSE_TABLELOG_ABSOLUTE_MAX is not supported" #endif -#define FSE_TABLESTEP(tableSize) ((tableSize>>1) + (tableSize>>3) + 3) +#define FSE_TABLESTEP(tableSize) (((tableSize)>>1) + ((tableSize)>>3) + 3) #endif /* FSE_STATIC_LINKING_ONLY */ diff --git a/thirdparty/zstd/common/fse_decompress.c b/thirdparty/zstd/common/fse_decompress.c index bcc2223ccc..c164430f99 100644 --- a/thirdparty/zstd/common/fse_decompress.c +++ b/thirdparty/zstd/common/fse_decompress.c @@ -16,13 +16,14 @@ /* ************************************************************** * Includes ****************************************************************/ -#include <stdlib.h> /* malloc, free, qsort */ -#include <string.h> /* memcpy, memset */ +#include "debug.h" /* assert */ #include "bitstream.h" #include "compiler.h" #define FSE_STATIC_LINKING_ONLY #include "fse.h" #include "error_private.h" +#define ZSTD_DEPS_NEED_MALLOC +#include "zstd_deps.h" /* ************************************************************** @@ -59,25 +60,27 @@ FSE_DTable* FSE_createDTable (unsigned tableLog) { if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; - return (FSE_DTable*)malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) ); + return (FSE_DTable*)ZSTD_malloc( FSE_DTABLE_SIZE_U32(tableLog) * sizeof (U32) ); } void FSE_freeDTable (FSE_DTable* dt) { - free(dt); + ZSTD_free(dt); } -size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) +static size_t FSE_buildDTable_internal(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize) { void* const tdPtr = dt+1; /* because *dt is unsigned, 32-bits aligned on 32-bits */ FSE_DECODE_TYPE* const tableDecode = (FSE_DECODE_TYPE*) (tdPtr); - U16 symbolNext[FSE_MAX_SYMBOL_VALUE+1]; + U16* symbolNext = (U16*)workSpace; + BYTE* spread = (BYTE*)(symbolNext + maxSymbolValue + 1); U32 const maxSV1 = maxSymbolValue + 1; U32 const tableSize = 1 << tableLog; U32 highThreshold = tableSize-1; /* Sanity Checks */ + if (FSE_BUILD_DTABLE_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(maxSymbolValue_tooLarge); if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(maxSymbolValue_tooLarge); if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); @@ -95,11 +98,57 @@ size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned if (normalizedCounter[s] >= largeLimit) DTableH.fastMode=0; symbolNext[s] = normalizedCounter[s]; } } } - memcpy(dt, &DTableH, sizeof(DTableH)); + ZSTD_memcpy(dt, &DTableH, sizeof(DTableH)); } /* Spread symbols */ - { U32 const tableMask = tableSize-1; + if (highThreshold == tableSize - 1) { + size_t const tableMask = tableSize-1; + size_t const step = FSE_TABLESTEP(tableSize); + /* First lay down the symbols in order. + * We use a uint64_t to lay down 8 bytes at a time. This reduces branch + * misses since small blocks generally have small table logs, so nearly + * all symbols have counts <= 8. We ensure we have 8 bytes at the end of + * our buffer to handle the over-write. + */ + { + U64 const add = 0x0101010101010101ull; + size_t pos = 0; + U64 sv = 0; + U32 s; + for (s=0; s<maxSV1; ++s, sv += add) { + int i; + int const n = normalizedCounter[s]; + MEM_write64(spread + pos, sv); + for (i = 8; i < n; i += 8) { + MEM_write64(spread + pos + i, sv); + } + pos += n; + } + } + /* Now we spread those positions across the table. + * The benefit of doing it in two stages is that we avoid the the + * variable size inner loop, which caused lots of branch misses. + * Now we can run through all the positions without any branch misses. + * We unroll the loop twice, since that is what emperically worked best. + */ + { + size_t position = 0; + size_t s; + size_t const unroll = 2; + assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */ + for (s = 0; s < (size_t)tableSize; s += unroll) { + size_t u; + for (u = 0; u < unroll; ++u) { + size_t const uPosition = (position + (u * step)) & tableMask; + tableDecode[uPosition].symbol = spread[s + u]; + } + position = (position + (unroll * step)) & tableMask; + } + assert(position == 0); + } + } else { + U32 const tableMask = tableSize-1; U32 const step = FSE_TABLESTEP(tableSize); U32 s, position = 0; for (s=0; s<maxSV1; s++) { @@ -124,6 +173,11 @@ size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned return 0; } +size_t FSE_buildDTable_wksp(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize) +{ + return FSE_buildDTable_internal(dt, normalizedCounter, maxSymbolValue, tableLog, workSpace, wkspSize); +} + #ifndef FSE_COMMONDEFS_ONLY @@ -251,36 +305,89 @@ size_t FSE_decompress_usingDTable(void* dst, size_t originalSize, } -size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog) +size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize) +{ + return FSE_decompress_wksp_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, /* bmi2 */ 0); +} + +FORCE_INLINE_TEMPLATE size_t FSE_decompress_wksp_body( + void* dst, size_t dstCapacity, + const void* cSrc, size_t cSrcSize, + unsigned maxLog, void* workSpace, size_t wkspSize, + int bmi2) { const BYTE* const istart = (const BYTE*)cSrc; const BYTE* ip = istart; short counting[FSE_MAX_SYMBOL_VALUE+1]; unsigned tableLog; unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE; + FSE_DTable* const dtable = (FSE_DTable*)workSpace; /* normal FSE decoding mode */ - size_t const NCountLength = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize); + size_t const NCountLength = FSE_readNCount_bmi2(counting, &maxSymbolValue, &tableLog, istart, cSrcSize, bmi2); if (FSE_isError(NCountLength)) return NCountLength; - /* if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong); */ /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */ if (tableLog > maxLog) return ERROR(tableLog_tooLarge); + assert(NCountLength <= cSrcSize); ip += NCountLength; cSrcSize -= NCountLength; - CHECK_F( FSE_buildDTable (workSpace, counting, maxSymbolValue, tableLog) ); + if (FSE_DECOMPRESS_WKSP_SIZE(tableLog, maxSymbolValue) > wkspSize) return ERROR(tableLog_tooLarge); + workSpace = dtable + FSE_DTABLE_SIZE_U32(tableLog); + wkspSize -= FSE_DTABLE_SIZE(tableLog); + + CHECK_F( FSE_buildDTable_internal(dtable, counting, maxSymbolValue, tableLog, workSpace, wkspSize) ); + + { + const void* ptr = dtable; + const FSE_DTableHeader* DTableH = (const FSE_DTableHeader*)ptr; + const U32 fastMode = DTableH->fastMode; + + /* select fast mode (static) */ + if (fastMode) return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 1); + return FSE_decompress_usingDTable_generic(dst, dstCapacity, ip, cSrcSize, dtable, 0); + } +} + +/* Avoids the FORCE_INLINE of the _body() function. */ +static size_t FSE_decompress_wksp_body_default(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize) +{ + return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 0); +} + +#if DYNAMIC_BMI2 +TARGET_ATTRIBUTE("bmi2") static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize) +{ + return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 1); +} +#endif - return FSE_decompress_usingDTable (dst, dstCapacity, ip, cSrcSize, workSpace); /* always return, even if it is an error code */ +size_t FSE_decompress_wksp_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize, int bmi2) +{ +#if DYNAMIC_BMI2 + if (bmi2) { + return FSE_decompress_wksp_body_bmi2(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize); + } +#endif + (void)bmi2; + return FSE_decompress_wksp_body_default(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize); } typedef FSE_DTable DTable_max_t[FSE_DTABLE_SIZE_U32(FSE_MAX_TABLELOG)]; +#ifndef ZSTD_NO_UNUSED_FUNCTIONS +size_t FSE_buildDTable(FSE_DTable* dt, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { + U32 wksp[FSE_BUILD_DTABLE_WKSP_SIZE_U32(FSE_TABLELOG_ABSOLUTE_MAX, FSE_MAX_SYMBOL_VALUE)]; + return FSE_buildDTable_wksp(dt, normalizedCounter, maxSymbolValue, tableLog, wksp, sizeof(wksp)); +} + size_t FSE_decompress(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize) { - DTable_max_t dt; /* Static analyzer seems unable to understand this table will be properly initialized later */ - return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, dt, FSE_MAX_TABLELOG); + /* Static analyzer seems unable to understand this table will be properly initialized later */ + U32 wksp[FSE_DECOMPRESS_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)]; + return FSE_decompress_wksp(dst, dstCapacity, cSrc, cSrcSize, FSE_MAX_TABLELOG, wksp, sizeof(wksp)); } - +#endif #endif /* FSE_COMMONDEFS_ONLY */ diff --git a/thirdparty/zstd/common/huf.h b/thirdparty/zstd/common/huf.h index ef432685da..1afef90c7c 100644 --- a/thirdparty/zstd/common/huf.h +++ b/thirdparty/zstd/common/huf.h @@ -20,7 +20,7 @@ extern "C" { #define HUF_H_298734234 /* *** Dependencies *** */ -#include <stddef.h> /* size_t */ +#include "zstd_deps.h" /* size_t */ /* *** library symbols visibility *** */ @@ -111,6 +111,8 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, /* *** Dependencies *** */ #include "mem.h" /* U32 */ +#define FSE_STATIC_LINKING_ONLY +#include "fse.h" /* *** Constants *** */ @@ -133,12 +135,16 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity, #define HUF_COMPRESSBOUND(size) (HUF_CTABLEBOUND + HUF_BLOCKBOUND(size)) /* Macro version, useful for static allocation */ /* static allocation of HUF's Compression Table */ +/* this is a private definition, just exposed for allocation and strict aliasing purpose. never EVER access its members directly */ +struct HUF_CElt_s { + U16 val; + BYTE nbBits; +}; /* typedef'd to HUF_CElt */ +typedef struct HUF_CElt_s HUF_CElt; /* consider it an incomplete type */ #define HUF_CTABLE_SIZE_U32(maxSymbolValue) ((maxSymbolValue)+1) /* Use tables of U32, for proper alignment */ #define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_U32(maxSymbolValue) * sizeof(U32)) #define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \ - U32 name##hb[HUF_CTABLE_SIZE_U32(maxSymbolValue)]; \ - void* name##hv = &(name##hb); \ - HUF_CElt* name = (HUF_CElt*)(name##hv) /* no final ; */ + HUF_CElt name[HUF_CTABLE_SIZE_U32(maxSymbolValue)] /* no final ; */ /* static allocation of HUF's DTable */ typedef U32 HUF_DTable; @@ -184,7 +190,6 @@ size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, * or to save and regenerate 'CTable' using external methods. */ unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxSymbolValue); -typedef struct HUF_CElt_s HUF_CElt; /* incomplete type */ size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits); /* @return : maxNbBits; CTable and count can overlap. In which case, CTable will overwrite count content */ size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog); size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable); @@ -226,6 +231,19 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, const void* src, size_t srcSize); +/*! HUF_readStats_wksp() : + * Same as HUF_readStats() but takes an external workspace which must be + * 4-byte aligned and its size must be >= HUF_READ_STATS_WORKSPACE_SIZE. + * If the CPU has BMI2 support, pass bmi2=1, otherwise pass bmi2=0. + */ +#define HUF_READ_STATS_WORKSPACE_SIZE_U32 FSE_DECOMPRESS_WKSP_SIZE_U32(6, HUF_TABLELOG_MAX-1) +#define HUF_READ_STATS_WORKSPACE_SIZE (HUF_READ_STATS_WORKSPACE_SIZE_U32 * sizeof(unsigned)) +size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize, + U32* rankStats, U32* nbSymbolsPtr, U32* tableLogPtr, + const void* src, size_t srcSize, + void* workspace, size_t wkspSize, + int bmi2); + /** HUF_readCTable() : * Loading a CTable saved with HUF_writeCTable() */ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights); @@ -332,6 +350,9 @@ size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstS #endif size_t HUF_decompress4X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2); size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, size_t wkspSize, int bmi2); +#ifndef HUF_FORCE_DECOMPRESS_X2 +size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2); +#endif #endif /* HUF_STATIC_LINKING_ONLY */ diff --git a/thirdparty/zstd/common/mem.h b/thirdparty/zstd/common/mem.h index 89c8aea7d2..4728ef767b 100644 --- a/thirdparty/zstd/common/mem.h +++ b/thirdparty/zstd/common/mem.h @@ -18,8 +18,10 @@ extern "C" { /*-**************************************** * Dependencies ******************************************/ -#include <stddef.h> /* size_t, ptrdiff_t */ -#include <string.h> /* memcpy */ +#include <stddef.h> /* size_t, ptrdiff_t */ +#include "compiler.h" /* __has_builtin */ +#include "debug.h" /* DEBUG_STATIC_ASSERT */ +#include "zstd_deps.h" /* ZSTD_memcpy */ /*-**************************************** @@ -39,93 +41,15 @@ extern "C" { # define MEM_STATIC static /* this version may generate warnings for unused static functions; disable the relevant warning */ #endif -#ifndef __has_builtin -# define __has_builtin(x) 0 /* compat. with non-clang compilers */ -#endif - -/* code only tested on 32 and 64 bits systems */ -#define MEM_STATIC_ASSERT(c) { enum { MEM_static_assert = 1/(int)(!!(c)) }; } -MEM_STATIC void MEM_check(void) { MEM_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); } - -/* detects whether we are being compiled under msan */ -#if defined (__has_feature) -# if __has_feature(memory_sanitizer) -# define MEMORY_SANITIZER 1 -# endif -#endif - -#if defined (MEMORY_SANITIZER) -/* Not all platforms that support msan provide sanitizers/msan_interface.h. - * We therefore declare the functions we need ourselves, rather than trying to - * include the header file... */ - -#include <stdint.h> /* intptr_t */ - -/* Make memory region fully initialized (without changing its contents). */ -void __msan_unpoison(const volatile void *a, size_t size); - -/* Make memory region fully uninitialized (without changing its contents). - This is a legacy interface that does not update origin information. Use - __msan_allocated_memory() instead. */ -void __msan_poison(const volatile void *a, size_t size); - -/* Returns the offset of the first (at least partially) poisoned byte in the - memory range, or -1 if the whole range is good. */ -intptr_t __msan_test_shadow(const volatile void *x, size_t size); -#endif - -/* detects whether we are being compiled under asan */ -#if defined (__has_feature) -# if __has_feature(address_sanitizer) -# define ADDRESS_SANITIZER 1 -# endif -#elif defined(__SANITIZE_ADDRESS__) -# define ADDRESS_SANITIZER 1 -#endif - -#if defined (ADDRESS_SANITIZER) -/* Not all platforms that support asan provide sanitizers/asan_interface.h. - * We therefore declare the functions we need ourselves, rather than trying to - * include the header file... */ - -/** - * Marks a memory region (<c>[addr, addr+size)</c>) as unaddressable. - * - * This memory must be previously allocated by your program. Instrumented - * code is forbidden from accessing addresses in this region until it is - * unpoisoned. This function is not guaranteed to poison the entire region - - * it could poison only a subregion of <c>[addr, addr+size)</c> due to ASan - * alignment restrictions. - * - * \note This function is not thread-safe because no two threads can poison or - * unpoison memory in the same memory region simultaneously. - * - * \param addr Start of memory region. - * \param size Size of memory region. */ -void __asan_poison_memory_region(void const volatile *addr, size_t size); - -/** - * Marks a memory region (<c>[addr, addr+size)</c>) as addressable. - * - * This memory must be previously allocated by your program. Accessing - * addresses in this region is allowed until this region is poisoned again. - * This function could unpoison a super-region of <c>[addr, addr+size)</c> due - * to ASan alignment restrictions. - * - * \note This function is not thread-safe because no two threads can - * poison or unpoison memory in the same memory region simultaneously. - * - * \param addr Start of memory region. - * \param size Size of memory region. */ -void __asan_unpoison_memory_region(void const volatile *addr, size_t size); -#endif - - /*-************************************************************** * Basic Types *****************************************************************/ #if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include <stdint.h> +# if defined(_AIX) +# include <inttypes.h> +# else +# include <stdint.h> /* intptr_t */ +# endif typedef uint8_t BYTE; typedef uint16_t U16; typedef int16_t S16; @@ -157,7 +81,53 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size); /*-************************************************************** -* Memory I/O +* Memory I/O API +*****************************************************************/ +/*=== Static platform detection ===*/ +MEM_STATIC unsigned MEM_32bits(void); +MEM_STATIC unsigned MEM_64bits(void); +MEM_STATIC unsigned MEM_isLittleEndian(void); + +/*=== Native unaligned read/write ===*/ +MEM_STATIC U16 MEM_read16(const void* memPtr); +MEM_STATIC U32 MEM_read32(const void* memPtr); +MEM_STATIC U64 MEM_read64(const void* memPtr); +MEM_STATIC size_t MEM_readST(const void* memPtr); + +MEM_STATIC void MEM_write16(void* memPtr, U16 value); +MEM_STATIC void MEM_write32(void* memPtr, U32 value); +MEM_STATIC void MEM_write64(void* memPtr, U64 value); + +/*=== Little endian unaligned read/write ===*/ +MEM_STATIC U16 MEM_readLE16(const void* memPtr); +MEM_STATIC U32 MEM_readLE24(const void* memPtr); +MEM_STATIC U32 MEM_readLE32(const void* memPtr); +MEM_STATIC U64 MEM_readLE64(const void* memPtr); +MEM_STATIC size_t MEM_readLEST(const void* memPtr); + +MEM_STATIC void MEM_writeLE16(void* memPtr, U16 val); +MEM_STATIC void MEM_writeLE24(void* memPtr, U32 val); +MEM_STATIC void MEM_writeLE32(void* memPtr, U32 val32); +MEM_STATIC void MEM_writeLE64(void* memPtr, U64 val64); +MEM_STATIC void MEM_writeLEST(void* memPtr, size_t val); + +/*=== Big endian unaligned read/write ===*/ +MEM_STATIC U32 MEM_readBE32(const void* memPtr); +MEM_STATIC U64 MEM_readBE64(const void* memPtr); +MEM_STATIC size_t MEM_readBEST(const void* memPtr); + +MEM_STATIC void MEM_writeBE32(void* memPtr, U32 val32); +MEM_STATIC void MEM_writeBE64(void* memPtr, U64 val64); +MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val); + +/*=== Byteswap ===*/ +MEM_STATIC U32 MEM_swap32(U32 in); +MEM_STATIC U64 MEM_swap64(U64 in); +MEM_STATIC size_t MEM_swapST(size_t in); + + +/*-************************************************************** +* Memory I/O Implementation *****************************************************************/ /* MEM_FORCE_MEMORY_ACCESS : * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. @@ -236,37 +206,37 @@ MEM_STATIC void MEM_write64(void* memPtr, U64 value) { ((unalign64*)memPtr)->v = MEM_STATIC U16 MEM_read16(const void* memPtr) { - U16 val; memcpy(&val, memPtr, sizeof(val)); return val; + U16 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC U32 MEM_read32(const void* memPtr) { - U32 val; memcpy(&val, memPtr, sizeof(val)); return val; + U32 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC U64 MEM_read64(const void* memPtr) { - U64 val; memcpy(&val, memPtr, sizeof(val)); return val; + U64 val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC size_t MEM_readST(const void* memPtr) { - size_t val; memcpy(&val, memPtr, sizeof(val)); return val; + size_t val; ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } MEM_STATIC void MEM_write16(void* memPtr, U16 value) { - memcpy(memPtr, &value, sizeof(value)); + ZSTD_memcpy(memPtr, &value, sizeof(value)); } MEM_STATIC void MEM_write32(void* memPtr, U32 value) { - memcpy(memPtr, &value, sizeof(value)); + ZSTD_memcpy(memPtr, &value, sizeof(value)); } MEM_STATIC void MEM_write64(void* memPtr, U64 value) { - memcpy(memPtr, &value, sizeof(value)); + ZSTD_memcpy(memPtr, &value, sizeof(value)); } #endif /* MEM_FORCE_MEMORY_ACCESS */ @@ -445,6 +415,9 @@ MEM_STATIC void MEM_writeBEST(void* memPtr, size_t val) MEM_writeBE64(memPtr, (U64)val); } +/* code only tested on 32 and 64 bits systems */ +MEM_STATIC void MEM_check(void) { DEBUG_STATIC_ASSERT((sizeof(size_t)==4) || (sizeof(size_t)==8)); } + #if defined (__cplusplus) } diff --git a/thirdparty/zstd/common/pool.c b/thirdparty/zstd/common/pool.c index aa4b4de0d3..4c1b83376f 100644 --- a/thirdparty/zstd/common/pool.c +++ b/thirdparty/zstd/common/pool.c @@ -10,9 +10,9 @@ /* ====== Dependencies ======= */ -#include <stddef.h> /* size_t */ +#include "zstd_deps.h" /* size_t */ #include "debug.h" /* assert */ -#include "zstd_internal.h" /* ZSTD_malloc, ZSTD_free */ +#include "zstd_internal.h" /* ZSTD_customMalloc, ZSTD_customFree */ #include "pool.h" /* ====== Compiler specifics ====== */ @@ -105,6 +105,10 @@ static void* POOL_thread(void* opaque) { assert(0); /* Unreachable */ } +POOL_ctx* ZSTD_createThreadPool(size_t numThreads) { + return POOL_create (numThreads, 0); +} + POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) { return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem); } @@ -115,14 +119,14 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, /* Check parameters */ if (!numThreads) { return NULL; } /* Allocate the context and zero initialize */ - ctx = (POOL_ctx*)ZSTD_calloc(sizeof(POOL_ctx), customMem); + ctx = (POOL_ctx*)ZSTD_customCalloc(sizeof(POOL_ctx), customMem); if (!ctx) { return NULL; } /* Initialize the job queue. * It needs one extra space since one space is wasted to differentiate * empty and full queues. */ ctx->queueSize = queueSize + 1; - ctx->queue = (POOL_job*)ZSTD_malloc(ctx->queueSize * sizeof(POOL_job), customMem); + ctx->queue = (POOL_job*)ZSTD_customMalloc(ctx->queueSize * sizeof(POOL_job), customMem); ctx->queueHead = 0; ctx->queueTail = 0; ctx->numThreadsBusy = 0; @@ -136,7 +140,7 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, } ctx->shutdown = 0; /* Allocate space for the thread handles */ - ctx->threads = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), customMem); + ctx->threads = (ZSTD_pthread_t*)ZSTD_customMalloc(numThreads * sizeof(ZSTD_pthread_t), customMem); ctx->threadCapacity = 0; ctx->customMem = customMem; /* Check for errors */ @@ -179,12 +183,14 @@ void POOL_free(POOL_ctx *ctx) { ZSTD_pthread_mutex_destroy(&ctx->queueMutex); ZSTD_pthread_cond_destroy(&ctx->queuePushCond); ZSTD_pthread_cond_destroy(&ctx->queuePopCond); - ZSTD_free(ctx->queue, ctx->customMem); - ZSTD_free(ctx->threads, ctx->customMem); - ZSTD_free(ctx, ctx->customMem); + ZSTD_customFree(ctx->queue, ctx->customMem); + ZSTD_customFree(ctx->threads, ctx->customMem); + ZSTD_customFree(ctx, ctx->customMem); } - +void ZSTD_freeThreadPool (ZSTD_threadPool* pool) { + POOL_free (pool); +} size_t POOL_sizeof(POOL_ctx *ctx) { if (ctx==NULL) return 0; /* supports sizeof NULL */ @@ -203,11 +209,11 @@ static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads) return 0; } /* numThreads > threadCapacity */ - { ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_malloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem); + { ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)ZSTD_customMalloc(numThreads * sizeof(ZSTD_pthread_t), ctx->customMem); if (!threadPool) return 1; /* replace existing thread pool */ - memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool)); - ZSTD_free(ctx->threads, ctx->customMem); + ZSTD_memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool)); + ZSTD_customFree(ctx->threads, ctx->customMem); ctx->threads = threadPool; /* Initialize additional threads */ { size_t threadId; @@ -301,7 +307,7 @@ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) struct POOL_ctx_s { int dummy; }; -static POOL_ctx g_ctx; +static POOL_ctx g_poolCtx; POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) { return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem); @@ -311,11 +317,11 @@ POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customM (void)numThreads; (void)queueSize; (void)customMem; - return &g_ctx; + return &g_poolCtx; } void POOL_free(POOL_ctx* ctx) { - assert(!ctx || ctx == &g_ctx); + assert(!ctx || ctx == &g_poolCtx); (void)ctx; } @@ -337,7 +343,7 @@ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) { size_t POOL_sizeof(POOL_ctx* ctx) { if (ctx==NULL) return 0; /* supports sizeof NULL */ - assert(ctx == &g_ctx); + assert(ctx == &g_poolCtx); return sizeof(*ctx); } diff --git a/thirdparty/zstd/common/pool.h b/thirdparty/zstd/common/pool.h index 259bafc975..63954ca6ca 100644 --- a/thirdparty/zstd/common/pool.h +++ b/thirdparty/zstd/common/pool.h @@ -16,7 +16,7 @@ extern "C" { #endif -#include <stddef.h> /* size_t */ +#include "zstd_deps.h" #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_customMem */ #include "../zstd.h" diff --git a/thirdparty/zstd/common/threading.c b/thirdparty/zstd/common/threading.c index e2edb313eb..92cf57c195 100644 --- a/thirdparty/zstd/common/threading.c +++ b/thirdparty/zstd/common/threading.c @@ -78,11 +78,12 @@ int ZSTD_pthread_join(ZSTD_pthread_t thread, void **value_ptr) #if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32) -#include <stdlib.h> +#define ZSTD_DEPS_NEED_MALLOC +#include "zstd_deps.h" int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr) { - *mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t)); + *mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t)); if (!*mutex) return 1; return pthread_mutex_init(*mutex, attr); @@ -94,14 +95,14 @@ int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex) return 0; { int const ret = pthread_mutex_destroy(*mutex); - free(*mutex); + ZSTD_free(*mutex); return ret; } } int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr) { - *cond = (pthread_cond_t*)malloc(sizeof(pthread_cond_t)); + *cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t)); if (!*cond) return 1; return pthread_cond_init(*cond, attr); @@ -113,7 +114,7 @@ int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond) return 0; { int const ret = pthread_cond_destroy(*cond); - free(*cond); + ZSTD_free(*cond); return ret; } } diff --git a/thirdparty/zstd/common/xxhash.c b/thirdparty/zstd/common/xxhash.c index 597de18fc8..e708df3c33 100644 --- a/thirdparty/zstd/common/xxhash.c +++ b/thirdparty/zstd/common/xxhash.c @@ -77,14 +77,12 @@ * Includes & Memory related functions ***************************************/ /* Modify the local functions below should you wish to use some other memory routines */ -/* for malloc(), free() */ -#include <stdlib.h> -#include <stddef.h> /* size_t */ -static void* XXH_malloc(size_t s) { return malloc(s); } -static void XXH_free (void* p) { free(p); } -/* for memcpy() */ -#include <string.h> -static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } +/* for ZSTD_malloc(), ZSTD_free() */ +#define ZSTD_DEPS_NEED_MALLOC +#include "zstd_deps.h" /* size_t, ZSTD_malloc, ZSTD_free, ZSTD_memcpy */ +static void* XXH_malloc(size_t s) { return ZSTD_malloc(s); } +static void XXH_free (void* p) { ZSTD_free(p); } +static void* XXH_memcpy(void* dest, const void* src, size_t size) { return ZSTD_memcpy(dest,src,size); } #ifndef XXH_STATIC_LINKING_ONLY # define XXH_STATIC_LINKING_ONLY @@ -95,49 +93,13 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcp /* ************************************* * Compiler Specific Options ***************************************/ -#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ -# define INLINE_KEYWORD inline -#else -# define INLINE_KEYWORD -#endif - -#if defined(__GNUC__) || defined(__ICCARM__) -# define FORCE_INLINE_ATTR __attribute__((always_inline)) -#elif defined(_MSC_VER) -# define FORCE_INLINE_ATTR __forceinline -#else -# define FORCE_INLINE_ATTR -#endif - -#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR - - -#ifdef _MSC_VER -# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ -#endif +#include "compiler.h" /* ************************************* * Basic Types ***************************************/ -#ifndef MEM_MODULE -# define MEM_MODULE -# if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) -# include <stdint.h> - typedef uint8_t BYTE; - typedef uint16_t U16; - typedef uint32_t U32; - typedef int32_t S32; - typedef uint64_t U64; -# else - typedef unsigned char BYTE; - typedef unsigned short U16; - typedef unsigned int U32; - typedef signed int S32; - typedef unsigned long long U64; /* if your compiler doesn't support unsigned long long, replace by another 64-bit type here. Note that xxhash.h will also need to be updated. */ -# endif -#endif - +#include "mem.h" /* BYTE, U32, U64, size_t */ #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) @@ -163,14 +125,14 @@ static U64 XXH_read64(const void* ptr) { return ((const unalign*)ptr)->u64; } static U32 XXH_read32(const void* memPtr) { U32 val; - memcpy(&val, memPtr, sizeof(val)); + ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } static U64 XXH_read64(const void* memPtr) { U64 val; - memcpy(&val, memPtr, sizeof(val)); + ZSTD_memcpy(&val, memPtr, sizeof(val)); return val; } @@ -307,12 +269,12 @@ XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } ****************************/ XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dstState, const XXH32_state_t* restrict srcState) { - memcpy(dstState, srcState, sizeof(*dstState)); + ZSTD_memcpy(dstState, srcState, sizeof(*dstState)); } XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dstState, const XXH64_state_t* restrict srcState) { - memcpy(dstState, srcState, sizeof(*dstState)); + ZSTD_memcpy(dstState, srcState, sizeof(*dstState)); } @@ -554,12 +516,12 @@ XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed) { XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */ + ZSTD_memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */ state.v1 = seed + PRIME32_1 + PRIME32_2; state.v2 = seed + PRIME32_2; state.v3 = seed + 0; state.v4 = seed - PRIME32_1; - memcpy(statePtr, &state, sizeof(state)); + ZSTD_memcpy(statePtr, &state, sizeof(state)); return XXH_OK; } @@ -567,12 +529,12 @@ XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int s XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed) { XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */ + ZSTD_memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */ state.v1 = seed + PRIME64_1 + PRIME64_2; state.v2 = seed + PRIME64_2; state.v3 = seed + 0; state.v4 = seed - PRIME64_1; - memcpy(statePtr, &state, sizeof(state)); + ZSTD_memcpy(statePtr, &state, sizeof(state)); return XXH_OK; } @@ -843,14 +805,14 @@ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t { XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); - memcpy(dst, &hash, sizeof(*dst)); + ZSTD_memcpy(dst, &hash, sizeof(*dst)); } XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) { XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); - memcpy(dst, &hash, sizeof(*dst)); + ZSTD_memcpy(dst, &hash, sizeof(*dst)); } XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) diff --git a/thirdparty/zstd/common/xxhash.h b/thirdparty/zstd/common/xxhash.h index 4207eba832..eceb55d5e0 100644 --- a/thirdparty/zstd/common/xxhash.h +++ b/thirdparty/zstd/common/xxhash.h @@ -55,7 +55,7 @@ extern "C" { /* **************************** * Definitions ******************************/ -#include <stddef.h> /* size_t */ +#include "zstd_deps.h" typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; diff --git a/thirdparty/zstd/common/zstd_common.c b/thirdparty/zstd/common/zstd_common.c index 91fe3323a5..939e9f08fa 100644 --- a/thirdparty/zstd/common/zstd_common.c +++ b/thirdparty/zstd/common/zstd_common.c @@ -13,8 +13,8 @@ /*-************************************* * Dependencies ***************************************/ -#include <stdlib.h> /* malloc, calloc, free */ -#include <string.h> /* memset */ +#define ZSTD_DEPS_NEED_MALLOC +#include "zstd_deps.h" /* ZSTD_malloc, ZSTD_calloc, ZSTD_free, ZSTD_memset */ #include "error_private.h" #include "zstd_internal.h" @@ -53,31 +53,31 @@ const char* ZSTD_getErrorString(ZSTD_ErrorCode code) { return ERR_getErrorString /*=************************************************************** * Custom allocator ****************************************************************/ -void* ZSTD_malloc(size_t size, ZSTD_customMem customMem) +void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem) { if (customMem.customAlloc) return customMem.customAlloc(customMem.opaque, size); - return malloc(size); + return ZSTD_malloc(size); } -void* ZSTD_calloc(size_t size, ZSTD_customMem customMem) +void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem) { if (customMem.customAlloc) { /* calloc implemented as malloc+memset; * not as efficient as calloc, but next best guess for custom malloc */ void* const ptr = customMem.customAlloc(customMem.opaque, size); - memset(ptr, 0, size); + ZSTD_memset(ptr, 0, size); return ptr; } - return calloc(1, size); + return ZSTD_calloc(1, size); } -void ZSTD_free(void* ptr, ZSTD_customMem customMem) +void ZSTD_customFree(void* ptr, ZSTD_customMem customMem) { if (ptr!=NULL) { if (customMem.customFree) customMem.customFree(customMem.opaque, ptr); else - free(ptr); + ZSTD_free(ptr); } } diff --git a/thirdparty/zstd/common/zstd_deps.h b/thirdparty/zstd/common/zstd_deps.h new file mode 100644 index 0000000000..0fb8b7818b --- /dev/null +++ b/thirdparty/zstd/common/zstd_deps.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2016-2020, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +/* This file provides common libc dependencies that zstd requires. + * The purpose is to allow replacing this file with a custom implementation + * to compile zstd without libc support. + */ + +/* Need: + * NULL + * INT_MAX + * UINT_MAX + * ZSTD_memcpy() + * ZSTD_memset() + * ZSTD_memmove() + */ +#ifndef ZSTD_DEPS_COMMON +#define ZSTD_DEPS_COMMON + +#include <limits.h> +#include <stddef.h> +#include <string.h> + +#if defined(__GNUC__) && __GNUC__ >= 4 +# define ZSTD_memcpy(d,s,l) __builtin_memcpy((d),(s),(l)) +# define ZSTD_memmove(d,s,l) __builtin_memmove((d),(s),(l)) +# define ZSTD_memset(p,v,l) __builtin_memset((p),(v),(l)) +#else +# define ZSTD_memcpy(d,s,l) memcpy((d),(s),(l)) +# define ZSTD_memmove(d,s,l) memmove((d),(s),(l)) +# define ZSTD_memset(p,v,l) memset((p),(v),(l)) +#endif + +#endif /* ZSTD_DEPS_COMMON */ + +/* Need: + * ZSTD_malloc() + * ZSTD_free() + * ZSTD_calloc() + */ +#ifdef ZSTD_DEPS_NEED_MALLOC +#ifndef ZSTD_DEPS_MALLOC +#define ZSTD_DEPS_MALLOC + +#include <stdlib.h> + +#define ZSTD_malloc(s) malloc(s) +#define ZSTD_calloc(n,s) calloc((n), (s)) +#define ZSTD_free(p) free((p)) + +#endif /* ZSTD_DEPS_MALLOC */ +#endif /* ZSTD_DEPS_NEED_MALLOC */ + +/* + * Provides 64-bit math support. + * Need: + * U64 ZSTD_div64(U64 dividend, U32 divisor) + */ +#ifdef ZSTD_DEPS_NEED_MATH64 +#ifndef ZSTD_DEPS_MATH64 +#define ZSTD_DEPS_MATH64 + +#define ZSTD_div64(dividend, divisor) ((dividend) / (divisor)) + +#endif /* ZSTD_DEPS_MATH64 */ +#endif /* ZSTD_DEPS_NEED_MATH64 */ + +/* Need: + * assert() + */ +#ifdef ZSTD_DEPS_NEED_ASSERT +#ifndef ZSTD_DEPS_ASSERT +#define ZSTD_DEPS_ASSERT + +#include <assert.h> + +#endif /* ZSTD_DEPS_ASSERT */ +#endif /* ZSTD_DEPS_NEED_ASSERT */ + +/* Need: + * ZSTD_DEBUG_PRINT() + */ +#ifdef ZSTD_DEPS_NEED_IO +#ifndef ZSTD_DEPS_IO +#define ZSTD_DEPS_IO + +#include <stdio.h> +#define ZSTD_DEBUG_PRINT(...) fprintf(stderr, __VA_ARGS__) + +#endif /* ZSTD_DEPS_IO */ +#endif /* ZSTD_DEPS_NEED_IO */ + +/* Only requested when <stdint.h> is known to be present. + * Need: + * intptr_t + */ +#ifdef ZSTD_DEPS_NEED_STDINT +#ifndef ZSTD_DEPS_STDINT +#define ZSTD_DEPS_STDINT + +#include <stdint.h> + +#endif /* ZSTD_DEPS_STDINT */ +#endif /* ZSTD_DEPS_NEED_STDINT */ diff --git a/thirdparty/zstd/common/zstd_errors.h b/thirdparty/zstd/common/zstd_errors.h index 998398e7e5..6d0d003004 100644 --- a/thirdparty/zstd/common/zstd_errors.h +++ b/thirdparty/zstd/common/zstd_errors.h @@ -77,6 +77,7 @@ typedef enum { ZSTD_error_frameIndex_tooLarge = 100, ZSTD_error_seekableIO = 102, ZSTD_error_dstBuffer_wrong = 104, + ZSTD_error_srcBuffer_wrong = 105, ZSTD_error_maxCode = 120 /* never EVER use this value directly, it can change in future versions! Use ZSTD_isError() instead */ } ZSTD_ErrorCode; diff --git a/thirdparty/zstd/common/zstd_internal.h b/thirdparty/zstd/common/zstd_internal.h index 3bc7e55a0a..0991f20a08 100644 --- a/thirdparty/zstd/common/zstd_internal.h +++ b/thirdparty/zstd/common/zstd_internal.h @@ -19,7 +19,7 @@ /*-************************************* * Dependencies ***************************************/ -#ifdef __aarch64__ +#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON) #include <arm_neon.h> #endif #include "compiler.h" @@ -139,7 +139,7 @@ void _force_has_format_string(const char *format, ...) { #define ZSTD_REP_NUM 3 /* number of repcodes */ #define ZSTD_REP_MOVE (ZSTD_REP_NUM-1) -static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; +static UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; #define KB *(1 <<10) #define MB *(1 <<20) @@ -153,13 +153,13 @@ static const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 }; #define BIT0 1 #define ZSTD_WINDOWLOG_ABSOLUTEMIN 10 -static const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 }; -static const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 }; +static UNUSED_ATTR const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 }; +static UNUSED_ATTR const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 }; #define ZSTD_FRAMEIDSIZE 4 /* magic number size */ #define ZSTD_BLOCKHEADERSIZE 3 /* C standard doesn't allow `static const` variable to be init using another `static const` variable */ -static const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; +static UNUSED_ATTR const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE; typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e; #define ZSTD_FRAMECHECKSUMSIZE 4 @@ -186,61 +186,75 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy #define OffFSELog 8 #define MaxFSELog MAX(MAX(MLFSELog, LLFSELog), OffFSELog) -static const U32 LL_bits[MaxLL+1] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 3, 3, - 4, 6, 7, 8, 9,10,11,12, - 13,14,15,16 }; -static const S16 LL_defaultNorm[MaxLL+1] = { 4, 3, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, - 2, 3, 2, 1, 1, 1, 1, 1, - -1,-1,-1,-1 }; +#define ZSTD_MAX_HUF_HEADER_SIZE 128 /* header + <= 127 byte tree description */ +/* Each table cannot take more than #symbols * FSELog bits */ +#define ZSTD_MAX_FSE_HEADERS_SIZE (((MaxML + 1) * MLFSELog + (MaxLL + 1) * LLFSELog + (MaxOff + 1) * OffFSELog + 7) / 8) + +static UNUSED_ATTR const U32 LL_bits[MaxLL+1] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, + 4, 6, 7, 8, 9,10,11,12, + 13,14,15,16 +}; +static UNUSED_ATTR const S16 LL_defaultNorm[MaxLL+1] = { + 4, 3, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 2, 1, 1, 1, 1, 1, + -1,-1,-1,-1 +}; #define LL_DEFAULTNORMLOG 6 /* for static allocation */ -static const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG; - -static const U32 ML_bits[MaxML+1] = { 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 2, 2, 3, 3, - 4, 4, 5, 7, 8, 9,10,11, - 12,13,14,15,16 }; -static const S16 ML_defaultNorm[MaxML+1] = { 1, 4, 3, 2, 2, 2, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1,-1,-1, - -1,-1,-1,-1,-1 }; +static UNUSED_ATTR const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG; + +static UNUSED_ATTR const U32 ML_bits[MaxML+1] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 2, 2, 3, 3, + 4, 4, 5, 7, 8, 9,10,11, + 12,13,14,15,16 +}; +static UNUSED_ATTR const S16 ML_defaultNorm[MaxML+1] = { + 1, 4, 3, 2, 2, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1,-1,-1, + -1,-1,-1,-1,-1 +}; #define ML_DEFAULTNORMLOG 6 /* for static allocation */ -static const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG; - -static const S16 OF_defaultNorm[DefaultMaxOff+1] = { 1, 1, 1, 1, 1, 1, 2, 2, - 2, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - -1,-1,-1,-1,-1 }; +static UNUSED_ATTR const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG; + +static UNUSED_ATTR const S16 OF_defaultNorm[DefaultMaxOff+1] = { + 1, 1, 1, 1, 1, 1, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + -1,-1,-1,-1,-1 +}; #define OF_DEFAULTNORMLOG 5 /* for static allocation */ -static const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG; +static UNUSED_ATTR const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG; /*-******************************************* * Shared functions to include for inlining *********************************************/ static void ZSTD_copy8(void* dst, const void* src) { -#ifdef __aarch64__ +#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON) vst1_u8((uint8_t*)dst, vld1_u8((const uint8_t*)src)); #else - memcpy(dst, src, 8); + ZSTD_memcpy(dst, src, 8); #endif } #define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; } static void ZSTD_copy16(void* dst, const void* src) { -#ifdef __aarch64__ +#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON) vst1q_u8((uint8_t*)dst, vld1q_u8((const uint8_t*)src)); #else - memcpy(dst, src, 16); + ZSTD_memcpy(dst, src, 16); #endif } #define COPY16(d,s) { ZSTD_copy16(d,s); d+=16; s+=16; } @@ -255,13 +269,13 @@ typedef enum { } ZSTD_overlap_e; /*! ZSTD_wildcopy() : - * Custom version of memcpy(), can over read/write up to WILDCOPY_OVERLENGTH bytes (if length==0) + * Custom version of ZSTD_memcpy(), can over read/write up to WILDCOPY_OVERLENGTH bytes (if length==0) * @param ovtype controls the overlap detection * - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart. * - ZSTD_overlap_src_before_dst: The src and dst may overlap, but they MUST be at least 8 bytes apart. * The src buffer must be before the dst buffer. */ -MEM_STATIC FORCE_INLINE_ATTR +MEM_STATIC FORCE_INLINE_ATTR void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e const ovtype) { ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src; @@ -284,14 +298,16 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e * one COPY16() in the first call. Then, do two calls per loop since * at that point it is more likely to have a high trip count. */ -#ifndef __aarch64__ +#ifdef __aarch64__ do { COPY16(op, ip); } while (op < oend); #else - COPY16(op, ip); - if (op >= oend) return; + ZSTD_copy16(op, ip); + if (16 >= length) return; + op += 16; + ip += 16; do { COPY16(op, ip); COPY16(op, ip); @@ -305,7 +321,7 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, { size_t const length = MIN(dstCapacity, srcSize); if (length > 0) { - memcpy(dst, src, length); + ZSTD_memcpy(dst, src, length); } return length; } @@ -320,28 +336,39 @@ MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, * In which case, resize it down to free some memory */ #define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128 +/* Controls whether the input/output buffer is buffered or stable. */ +typedef enum { + ZSTD_bm_buffered = 0, /* Buffer the input/output */ + ZSTD_bm_stable = 1 /* ZSTD_inBuffer/ZSTD_outBuffer is stable */ +} ZSTD_bufferMode_e; + /*-******************************************* * Private declarations *********************************************/ typedef struct seqDef_s { - U32 offset; + U32 offset; /* Offset code of the sequence */ U16 litLength; U16 matchLength; } seqDef; typedef struct { seqDef* sequencesStart; - seqDef* sequences; + seqDef* sequences; /* ptr to end of sequences */ BYTE* litStart; - BYTE* lit; + BYTE* lit; /* ptr to end of literals */ BYTE* llCode; BYTE* mlCode; BYTE* ofCode; size_t maxNbSeq; size_t maxNbLit; - U32 longLengthID; /* 0 == no longLength; 1 == Lit.longLength; 2 == Match.longLength; */ - U32 longLengthPos; + + /* longLengthPos and longLengthID to allow us to represent either a single litLength or matchLength + * in the seqStore that has a value larger than U16 (if it exists). To do so, we increment + * the existing value of the litLength or matchLength by 0x10000. + */ + U32 longLengthID; /* 0 == no longLength; 1 == Represent the long literal; 2 == Represent the long match; */ + U32 longLengthPos; /* Index of the sequence to apply long length modification to */ } seqStore_t; typedef struct { @@ -384,9 +411,9 @@ const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx); /* compress & dictBu void ZSTD_seqToCodes(const seqStore_t* seqStorePtr); /* compress, dictBuilder, decodeCorpus (shouldn't get its definition from here) */ /* custom memory allocation functions */ -void* ZSTD_malloc(size_t size, ZSTD_customMem customMem); -void* ZSTD_calloc(size_t size, ZSTD_customMem customMem); -void ZSTD_free(void* ptr, ZSTD_customMem customMem); +void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem); +void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem); +void ZSTD_customFree(void* ptr, ZSTD_customMem customMem); MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */ @@ -394,8 +421,12 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus assert(val != 0); { # if defined(_MSC_VER) /* Visual */ - unsigned long r=0; - return _BitScanReverse(&r, val) ? (unsigned)r : 0; +# if STATIC_BMI2 == 1 + return _lzcnt_u32(val)^31; +# else + unsigned long r=0; + return _BitScanReverse(&r, val) ? (unsigned)r : 0; +# endif # elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */ return __builtin_clz (val) ^ 31; # elif defined(__ICCARM__) /* IAR Intrinsic */ diff --git a/thirdparty/zstd/compress/fse_compress.c b/thirdparty/zstd/compress/fse_compress.c index a42759814f..304a82b3cc 100644 --- a/thirdparty/zstd/compress/fse_compress.c +++ b/thirdparty/zstd/compress/fse_compress.c @@ -15,8 +15,6 @@ /* ************************************************************** * Includes ****************************************************************/ -#include <stdlib.h> /* malloc, free, qsort */ -#include <string.h> /* memcpy, memset */ #include "../common/compiler.h" #include "../common/mem.h" /* U32, U16, etc. */ #include "../common/debug.h" /* assert, DEBUGLOG */ @@ -25,6 +23,9 @@ #define FSE_STATIC_LINKING_ONLY #include "../common/fse.h" #include "../common/error_private.h" +#define ZSTD_DEPS_NEED_MALLOC +#define ZSTD_DEPS_NEED_MATH64 +#include "../common/zstd_deps.h" /* ZSTD_malloc, ZSTD_free, ZSTD_memcpy, ZSTD_memset */ /* ************************************************************** @@ -74,13 +75,15 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ; FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT); U32 const step = FSE_TABLESTEP(tableSize); - U32 cumul[FSE_MAX_SYMBOL_VALUE+2]; - FSE_FUNCTION_TYPE* const tableSymbol = (FSE_FUNCTION_TYPE*)workSpace; + U32* cumul = (U32*)workSpace; + FSE_FUNCTION_TYPE* tableSymbol = (FSE_FUNCTION_TYPE*)(cumul + (maxSymbolValue + 2)); + U32 highThreshold = tableSize-1; + if ((size_t)workSpace & 3) return ERROR(GENERIC); /* Must be 4 byte aligned */ + if (FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) > wkspSize) return ERROR(tableLog_tooLarge); /* CTable header */ - if (((size_t)1 << tableLog) * sizeof(FSE_FUNCTION_TYPE) > wkspSize) return ERROR(tableLog_tooLarge); tableU16[-2] = (U16) tableLog; tableU16[-1] = (U16) maxSymbolValue; assert(tableLog < 16); /* required for threshold strategy to work */ @@ -89,7 +92,7 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */ #ifdef __clang_analyzer__ - memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize); /* useless initialization, just to keep scan-build happy */ + ZSTD_memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize); /* useless initialization, just to keep scan-build happy */ #endif /* symbol start positions */ @@ -168,12 +171,13 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct, return 0; } - +#ifndef ZSTD_NO_UNUSED_FUNCTIONS size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog) { FSE_FUNCTION_TYPE tableSymbol[FSE_MAX_TABLESIZE]; /* memset() is not necessary, even if static analyzer complain about it */ return FSE_buildCTable_wksp(ct, normalizedCounter, maxSymbolValue, tableLog, tableSymbol, sizeof(tableSymbol)); } +#endif @@ -307,10 +311,10 @@ FSE_CTable* FSE_createCTable (unsigned maxSymbolValue, unsigned tableLog) size_t size; if (tableLog > FSE_TABLELOG_ABSOLUTE_MAX) tableLog = FSE_TABLELOG_ABSOLUTE_MAX; size = FSE_CTABLE_SIZE_U32 (tableLog, maxSymbolValue) * sizeof(U32); - return (FSE_CTable*)malloc(size); + return (FSE_CTable*)ZSTD_malloc(size); } -void FSE_freeCTable (FSE_CTable* ct) { free(ct); } +void FSE_freeCTable (FSE_CTable* ct) { ZSTD_free(ct); } /* provides the minimum logSize to safely represent a distribution */ static unsigned FSE_minTableLog(size_t srcSize, unsigned maxSymbolValue) @@ -341,11 +345,10 @@ unsigned FSE_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS return FSE_optimalTableLog_internal(maxTableLog, srcSize, maxSymbolValue, 2); } - /* Secondary normalization method. To be used when primary method fails. */ -static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue) +static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, size_t total, U32 maxSymbolValue, short lowProbCount) { short const NOT_YET_ASSIGNED = -2; U32 s; @@ -362,7 +365,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, continue; } if (count[s] <= lowThreshold) { - norm[s] = -1; + norm[s] = lowProbCount; distributed++; total -= count[s]; continue; @@ -414,7 +417,7 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, { U64 const vStepLog = 62 - tableLog; U64 const mid = (1ULL << (vStepLog-1)) - 1; - U64 const rStep = ((((U64)1<<vStepLog) * ToDistribute) + mid) / total; /* scale on remaining */ + U64 const rStep = ZSTD_div64((((U64)1<<vStepLog) * ToDistribute) + mid, (U32)total); /* scale on remaining */ U64 tmpTotal = mid; for (s=0; s<=maxSymbolValue; s++) { if (norm[s]==NOT_YET_ASSIGNED) { @@ -431,10 +434,9 @@ static size_t FSE_normalizeM2(short* norm, U32 tableLog, const unsigned* count, return 0; } - size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog, const unsigned* count, size_t total, - unsigned maxSymbolValue) + unsigned maxSymbolValue, unsigned useLowProbCount) { /* Sanity checks */ if (tableLog==0) tableLog = FSE_DEFAULT_TABLELOG; @@ -443,8 +445,9 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog, if (tableLog < FSE_minTableLog(total, maxSymbolValue)) return ERROR(GENERIC); /* Too small tableLog, compression potentially impossible */ { static U32 const rtbTable[] = { 0, 473195, 504333, 520860, 550000, 700000, 750000, 830000 }; + short const lowProbCount = useLowProbCount ? -1 : 1; U64 const scale = 62 - tableLog; - U64 const step = ((U64)1<<62) / total; /* <== here, one division ! */ + U64 const step = ZSTD_div64((U64)1<<62, (U32)total); /* <== here, one division ! */ U64 const vStep = 1ULL<<(scale-20); int stillToDistribute = 1<<tableLog; unsigned s; @@ -456,7 +459,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog, if (count[s] == total) return 0; /* rle special case */ if (count[s] == 0) { normalizedCounter[s]=0; continue; } if (count[s] <= lowThreshold) { - normalizedCounter[s] = -1; + normalizedCounter[s] = lowProbCount; stillToDistribute--; } else { short proba = (short)((count[s]*step) >> scale); @@ -470,7 +473,7 @@ size_t FSE_normalizeCount (short* normalizedCounter, unsigned tableLog, } } if (-stillToDistribute >= (normalizedCounter[largest] >> 1)) { /* corner case, need another normalization method */ - size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue); + size_t const errorCode = FSE_normalizeM2(normalizedCounter, tableLog, count, total, maxSymbolValue, lowProbCount); if (FSE_isError(errorCode)) return errorCode; } else normalizedCounter[largest] += (short)stillToDistribute; @@ -625,6 +628,7 @@ size_t FSE_compress_usingCTable (void* dst, size_t dstSize, size_t FSE_compressBound(size_t size) { return FSE_COMPRESSBOUND(size); } +#ifndef ZSTD_NO_UNUSED_FUNCTIONS /* FSE_compress_wksp() : * Same as FSE_compress2(), but using an externally allocated scratch buffer (`workSpace`). * `wkspSize` size must be `(1<<tableLog)`. @@ -643,7 +647,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src size_t const scratchBufferSize = wkspSize - (CTableSize * sizeof(FSE_CTable)); /* init conditions */ - if (wkspSize < FSE_WKSP_SIZE_U32(tableLog, maxSymbolValue)) return ERROR(tableLog_tooLarge); + if (wkspSize < FSE_COMPRESS_WKSP_SIZE_U32(tableLog, maxSymbolValue)) return ERROR(tableLog_tooLarge); if (srcSize <= 1) return 0; /* Not compressible */ if (!maxSymbolValue) maxSymbolValue = FSE_MAX_SYMBOL_VALUE; if (!tableLog) tableLog = FSE_DEFAULT_TABLELOG; @@ -656,7 +660,7 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src } tableLog = FSE_optimalTableLog(tableLog, srcSize, maxSymbolValue); - CHECK_F( FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue) ); + CHECK_F( FSE_normalizeCount(norm, tableLog, count, srcSize, maxSymbolValue, /* useLowProbCount */ srcSize >= 2048) ); /* Write table description header */ { CHECK_V_F(nc_err, FSE_writeNCount(op, oend-op, norm, maxSymbolValue, tableLog) ); @@ -678,13 +682,16 @@ size_t FSE_compress_wksp (void* dst, size_t dstSize, const void* src, size_t src typedef struct { FSE_CTable CTable_max[FSE_CTABLE_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)]; - BYTE scratchBuffer[1 << FSE_MAX_TABLELOG]; + union { + U32 hist_wksp[HIST_WKSP_SIZE_U32]; + BYTE scratchBuffer[1 << FSE_MAX_TABLELOG]; + } workspace; } fseWkspMax_t; size_t FSE_compress2 (void* dst, size_t dstCapacity, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog) { fseWkspMax_t scratchBuffer; - DEBUG_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */ + DEBUG_STATIC_ASSERT(sizeof(scratchBuffer) >= FSE_COMPRESS_WKSP_SIZE_U32(FSE_MAX_TABLELOG, FSE_MAX_SYMBOL_VALUE)); /* compilation failures here means scratchBuffer is not large enough */ if (tableLog > FSE_MAX_TABLELOG) return ERROR(tableLog_tooLarge); return FSE_compress_wksp(dst, dstCapacity, src, srcSize, maxSymbolValue, tableLog, &scratchBuffer, sizeof(scratchBuffer)); } @@ -693,6 +700,6 @@ size_t FSE_compress (void* dst, size_t dstCapacity, const void* src, size_t srcS { return FSE_compress2(dst, dstCapacity, src, srcSize, FSE_MAX_SYMBOL_VALUE, FSE_DEFAULT_TABLELOG); } - +#endif #endif /* FSE_COMMONDEFS_ONLY */ diff --git a/thirdparty/zstd/compress/hist.c b/thirdparty/zstd/compress/hist.c index 61e08c7968..a9659d11ad 100644 --- a/thirdparty/zstd/compress/hist.c +++ b/thirdparty/zstd/compress/hist.c @@ -34,7 +34,7 @@ unsigned HIST_count_simple(unsigned* count, unsigned* maxSymbolValuePtr, unsigned maxSymbolValue = *maxSymbolValuePtr; unsigned largestCount=0; - memset(count, 0, (maxSymbolValue+1) * sizeof(*count)); + ZSTD_memset(count, 0, (maxSymbolValue+1) * sizeof(*count)); if (srcSize==0) { *maxSymbolValuePtr = 0; return 0; } while (ip<end) { @@ -60,9 +60,9 @@ typedef enum { trustInput, checkMaxSymbolValue } HIST_checkInput_e; * this design makes better use of OoO cpus, * and is noticeably faster when some values are heavily repeated. * But it needs some additional workspace for intermediate tables. - * `workSpace` size must be a table of size >= HIST_WKSP_SIZE_U32. + * `workSpace` must be a U32 table of size >= HIST_WKSP_SIZE_U32. * @return : largest histogram frequency, - * or an error code (notably when histogram would be larger than *maxSymbolValuePtr). */ + * or an error code (notably when histogram's alphabet is larger than *maxSymbolValuePtr) */ static size_t HIST_count_parallel_wksp( unsigned* count, unsigned* maxSymbolValuePtr, const void* source, size_t sourceSize, @@ -71,22 +71,21 @@ static size_t HIST_count_parallel_wksp( { const BYTE* ip = (const BYTE*)source; const BYTE* const iend = ip+sourceSize; - unsigned maxSymbolValue = *maxSymbolValuePtr; + size_t const countSize = (*maxSymbolValuePtr + 1) * sizeof(*count); unsigned max=0; U32* const Counting1 = workSpace; U32* const Counting2 = Counting1 + 256; U32* const Counting3 = Counting2 + 256; U32* const Counting4 = Counting3 + 256; - memset(workSpace, 0, 4*256*sizeof(unsigned)); - /* safety checks */ + assert(*maxSymbolValuePtr <= 255); if (!sourceSize) { - memset(count, 0, maxSymbolValue + 1); + ZSTD_memset(count, 0, countSize); *maxSymbolValuePtr = 0; return 0; } - if (!maxSymbolValue) maxSymbolValue = 255; /* 0 == default */ + ZSTD_memset(workSpace, 0, 4*256*sizeof(unsigned)); /* by stripes of 16 bytes */ { U32 cached = MEM_read32(ip); ip += 4; @@ -118,21 +117,18 @@ static size_t HIST_count_parallel_wksp( /* finish last symbols */ while (ip<iend) Counting1[*ip++]++; - if (check) { /* verify stats will fit into destination table */ - U32 s; for (s=255; s>maxSymbolValue; s--) { - Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s]; - if (Counting1[s]) return ERROR(maxSymbolValue_tooSmall); - } } - { U32 s; - if (maxSymbolValue > 255) maxSymbolValue = 255; - for (s=0; s<=maxSymbolValue; s++) { - count[s] = Counting1[s] + Counting2[s] + Counting3[s] + Counting4[s]; - if (count[s] > max) max = count[s]; + for (s=0; s<256; s++) { + Counting1[s] += Counting2[s] + Counting3[s] + Counting4[s]; + if (Counting1[s] > max) max = Counting1[s]; } } - while (!count[maxSymbolValue]) maxSymbolValue--; - *maxSymbolValuePtr = maxSymbolValue; + { unsigned maxSymbolValue = 255; + while (!Counting1[maxSymbolValue]) maxSymbolValue--; + if (check && maxSymbolValue > *maxSymbolValuePtr) return ERROR(maxSymbolValue_tooSmall); + *maxSymbolValuePtr = maxSymbolValue; + ZSTD_memmove(count, Counting1, countSize); /* in case count & Counting1 are overlapping */ + } return (size_t)max; } @@ -152,14 +148,6 @@ size_t HIST_countFast_wksp(unsigned* count, unsigned* maxSymbolValuePtr, return HIST_count_parallel_wksp(count, maxSymbolValuePtr, source, sourceSize, trustInput, (U32*)workSpace); } -/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */ -size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr, - const void* source, size_t sourceSize) -{ - unsigned tmpCounters[HIST_WKSP_SIZE_U32]; - return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters)); -} - /* HIST_count_wksp() : * Same as HIST_count(), but using an externally provided scratch buffer. * `workSpace` size must be table of >= HIST_WKSP_SIZE_U32 unsigned */ @@ -175,9 +163,19 @@ size_t HIST_count_wksp(unsigned* count, unsigned* maxSymbolValuePtr, return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, workSpace, workSpaceSize); } +#ifndef ZSTD_NO_UNUSED_FUNCTIONS +/* fast variant (unsafe : won't check if src contains values beyond count[] limit) */ +size_t HIST_countFast(unsigned* count, unsigned* maxSymbolValuePtr, + const void* source, size_t sourceSize) +{ + unsigned tmpCounters[HIST_WKSP_SIZE_U32]; + return HIST_countFast_wksp(count, maxSymbolValuePtr, source, sourceSize, tmpCounters, sizeof(tmpCounters)); +} + size_t HIST_count(unsigned* count, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize) { unsigned tmpCounters[HIST_WKSP_SIZE_U32]; return HIST_count_wksp(count, maxSymbolValuePtr, src, srcSize, tmpCounters, sizeof(tmpCounters)); } +#endif diff --git a/thirdparty/zstd/compress/hist.h b/thirdparty/zstd/compress/hist.h index 77e3ec4fb1..fb9ead6834 100644 --- a/thirdparty/zstd/compress/hist.h +++ b/thirdparty/zstd/compress/hist.h @@ -14,7 +14,7 @@ ****************************************************************** */ /* --- dependencies --- */ -#include <stddef.h> /* size_t */ +#include "../common/zstd_deps.h" /* size_t */ /* --- simple histogram functions --- */ diff --git a/thirdparty/zstd/compress/huf_compress.c b/thirdparty/zstd/compress/huf_compress.c index 546879868a..302e08864d 100644 --- a/thirdparty/zstd/compress/huf_compress.c +++ b/thirdparty/zstd/compress/huf_compress.c @@ -23,8 +23,7 @@ /* ************************************************************** * Includes ****************************************************************/ -#include <string.h> /* memcpy, memset */ -#include <stdio.h> /* printf (debug) */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset */ #include "../common/compiler.h" #include "../common/bitstream.h" #include "hist.h" @@ -70,7 +69,7 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER; FSE_CTable CTable[FSE_CTABLE_SIZE_U32(MAX_FSE_TABLELOG_FOR_HUFF_HEADER, HUF_TABLELOG_MAX)]; - BYTE scratchBuffer[1<<MAX_FSE_TABLELOG_FOR_HUFF_HEADER]; + U32 scratchBuffer[FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(HUF_TABLELOG_MAX, MAX_FSE_TABLELOG_FOR_HUFF_HEADER)]; unsigned count[HUF_TABLELOG_MAX+1]; S16 norm[HUF_TABLELOG_MAX+1]; @@ -85,7 +84,7 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight } tableLog = FSE_optimalTableLog(tableLog, wtSize, maxSymbolValue); - CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue) ); + CHECK_F( FSE_normalizeCount(norm, tableLog, count, wtSize, maxSymbolValue, /* useLowProbCount */ 0) ); /* Write table description header */ { CHECK_V_F(hSize, FSE_writeNCount(op, (size_t)(oend-op), norm, maxSymbolValue, tableLog) ); @@ -103,11 +102,6 @@ static size_t HUF_compressWeights (void* dst, size_t dstSize, const void* weight } -struct HUF_CElt_s { - U16 val; - BYTE nbBits; -}; /* typedef'd to HUF_CElt within "huf.h" */ - /*! HUF_writeCTable() : `CTable` : Huffman tree to save, using huf representation. @return : size of saved CTable */ @@ -156,6 +150,7 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void /* get symbol weights */ CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize)); + *hasZeroWeights = (rankVal[0] > 0); /* check result */ if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); @@ -164,16 +159,14 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void /* Prepare base value per rank */ { U32 n, nextRankStart = 0; for (n=1; n<=tableLog; n++) { - U32 current = nextRankStart; + U32 curr = nextRankStart; nextRankStart += (rankVal[n] << (n-1)); - rankVal[n] = current; + rankVal[n] = curr; } } /* fill nbBits */ - *hasZeroWeights = 0; { U32 n; for (n=0; n<nbSymbols; n++) { const U32 w = huffWeight[n]; - *hasZeroWeights |= (w == 0); CTable[n].nbBits = (BYTE)(tableLog + 1 - w) & -(w != 0); } } @@ -212,32 +205,63 @@ typedef struct nodeElt_s { BYTE nbBits; } nodeElt; +/** + * HUF_setMaxHeight(): + * Enforces maxNbBits on the Huffman tree described in huffNode. + * + * It sets all nodes with nbBits > maxNbBits to be maxNbBits. Then it adjusts + * the tree to so that it is a valid canonical Huffman tree. + * + * @pre The sum of the ranks of each symbol == 2^largestBits, + * where largestBits == huffNode[lastNonNull].nbBits. + * @post The sum of the ranks of each symbol == 2^largestBits, + * where largestBits is the return value <= maxNbBits. + * + * @param huffNode The Huffman tree modified in place to enforce maxNbBits. + * @param lastNonNull The symbol with the lowest count in the Huffman tree. + * @param maxNbBits The maximum allowed number of bits, which the Huffman tree + * may not respect. After this function the Huffman tree will + * respect maxNbBits. + * @return The maximum number of bits of the Huffman tree after adjustment, + * necessarily no more than maxNbBits. + */ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) { const U32 largestBits = huffNode[lastNonNull].nbBits; - if (largestBits <= maxNbBits) return largestBits; /* early exit : no elt > maxNbBits */ + /* early exit : no elt > maxNbBits, so the tree is already valid. */ + if (largestBits <= maxNbBits) return largestBits; /* there are several too large elements (at least >= 2) */ { int totalCost = 0; const U32 baseCost = 1 << (largestBits - maxNbBits); int n = (int)lastNonNull; + /* Adjust any ranks > maxNbBits to maxNbBits. + * Compute totalCost, which is how far the sum of the ranks is + * we are over 2^largestBits after adjust the offending ranks. + */ while (huffNode[n].nbBits > maxNbBits) { totalCost += baseCost - (1 << (largestBits - huffNode[n].nbBits)); huffNode[n].nbBits = (BYTE)maxNbBits; - n --; - } /* n stops at huffNode[n].nbBits <= maxNbBits */ - while (huffNode[n].nbBits == maxNbBits) n--; /* n end at index of smallest symbol using < maxNbBits */ + n--; + } + /* n stops at huffNode[n].nbBits <= maxNbBits */ + assert(huffNode[n].nbBits <= maxNbBits); + /* n end at index of smallest symbol using < maxNbBits */ + while (huffNode[n].nbBits == maxNbBits) --n; - /* renorm totalCost */ - totalCost >>= (largestBits - maxNbBits); /* note : totalCost is necessarily a multiple of baseCost */ + /* renorm totalCost from 2^largestBits to 2^maxNbBits + * note : totalCost is necessarily a multiple of baseCost */ + assert((totalCost & (baseCost - 1)) == 0); + totalCost >>= (largestBits - maxNbBits); + assert(totalCost > 0); /* repay normalized cost */ { U32 const noSymbol = 0xF0F0F0F0; U32 rankLast[HUF_TABLELOG_MAX+2]; - /* Get pos of last (smallest) symbol per rank */ - memset(rankLast, 0xF0, sizeof(rankLast)); + /* Get pos of last (smallest = lowest cum. count) symbol per rank */ + ZSTD_memset(rankLast, 0xF0, sizeof(rankLast)); { U32 currentNbBits = maxNbBits; int pos; for (pos=n ; pos >= 0; pos--) { @@ -247,34 +271,65 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) } } while (totalCost > 0) { + /* Try to reduce the next power of 2 above totalCost because we + * gain back half the rank. + */ U32 nBitsToDecrease = BIT_highbit32((U32)totalCost) + 1; for ( ; nBitsToDecrease > 1; nBitsToDecrease--) { U32 const highPos = rankLast[nBitsToDecrease]; U32 const lowPos = rankLast[nBitsToDecrease-1]; if (highPos == noSymbol) continue; + /* Decrease highPos if no symbols of lowPos or if it is + * not cheaper to remove 2 lowPos than highPos. + */ if (lowPos == noSymbol) break; { U32 const highTotal = huffNode[highPos].count; U32 const lowTotal = 2 * huffNode[lowPos].count; if (highTotal <= lowTotal) break; } } /* only triggered when no more rank 1 symbol left => find closest one (note : there is necessarily at least one !) */ + assert(rankLast[nBitsToDecrease] != noSymbol || nBitsToDecrease == 1); /* HUF_MAX_TABLELOG test just to please gcc 5+; but it should not be necessary */ while ((nBitsToDecrease<=HUF_TABLELOG_MAX) && (rankLast[nBitsToDecrease] == noSymbol)) - nBitsToDecrease ++; + nBitsToDecrease++; + assert(rankLast[nBitsToDecrease] != noSymbol); + /* Increase the number of bits to gain back half the rank cost. */ totalCost -= 1 << (nBitsToDecrease-1); + huffNode[rankLast[nBitsToDecrease]].nbBits++; + + /* Fix up the new rank. + * If the new rank was empty, this symbol is now its smallest. + * Otherwise, this symbol will be the largest in the new rank so no adjustment. + */ if (rankLast[nBitsToDecrease-1] == noSymbol) - rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]; /* this rank is no longer empty */ - huffNode[rankLast[nBitsToDecrease]].nbBits ++; + rankLast[nBitsToDecrease-1] = rankLast[nBitsToDecrease]; + /* Fix up the old rank. + * If the symbol was at position 0, meaning it was the highest weight symbol in the tree, + * it must be the only symbol in its rank, so the old rank now has no symbols. + * Otherwise, since the Huffman nodes are sorted by count, the previous position is now + * the smallest node in the rank. If the previous position belongs to a different rank, + * then the rank is now empty. + */ if (rankLast[nBitsToDecrease] == 0) /* special case, reached largest symbol */ rankLast[nBitsToDecrease] = noSymbol; else { rankLast[nBitsToDecrease]--; if (huffNode[rankLast[nBitsToDecrease]].nbBits != maxNbBits-nBitsToDecrease) rankLast[nBitsToDecrease] = noSymbol; /* this rank is now empty */ - } } /* while (totalCost > 0) */ - + } + } /* while (totalCost > 0) */ + + /* If we've removed too much weight, then we have to add it back. + * To avoid overshooting again, we only adjust the smallest rank. + * We take the largest nodes from the lowest rank 0 and move them + * to rank 1. There's guaranteed to be enough rank 0 symbols because + * TODO. + */ while (totalCost < 0) { /* Sometimes, cost correction overshoot */ - if (rankLast[1] == noSymbol) { /* special case : no rank 1 symbol (using maxNbBits-1); let's create one from largest rank 0 (using maxNbBits) */ + /* special case : no rank 1 symbol (using maxNbBits-1); + * let's create one from largest rank 0 (using maxNbBits). + */ + if (rankLast[1] == noSymbol) { while (huffNode[n].nbBits == maxNbBits) n--; huffNode[n+1].nbBits--; assert(n >= 0); @@ -285,14 +340,16 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits) huffNode[ rankLast[1] + 1 ].nbBits--; rankLast[1]++; totalCost ++; - } } } /* there are several too large elements (at least >= 2) */ + } + } /* repay normalized cost */ + } /* there are several too large elements (at least >= 2) */ return maxNbBits; } typedef struct { U32 base; - U32 current; + U32 curr; } rankPos; typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32]; @@ -304,21 +361,45 @@ typedef struct { rankPos rankPosition[RANK_POSITION_TABLE_SIZE]; } HUF_buildCTable_wksp_tables; +/** + * HUF_sort(): + * Sorts the symbols [0, maxSymbolValue] by count[symbol] in decreasing order. + * + * @param[out] huffNode Sorted symbols by decreasing count. Only members `.count` and `.byte` are filled. + * Must have (maxSymbolValue + 1) entries. + * @param[in] count Histogram of the symbols. + * @param[in] maxSymbolValue Maximum symbol value. + * @param rankPosition This is a scratch workspace. Must have RANK_POSITION_TABLE_SIZE entries. + */ static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rankPosition) { - U32 n; - - memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE); - for (n=0; n<=maxSymbolValue; n++) { - U32 r = BIT_highbit32(count[n] + 1); - rankPosition[r].base ++; + int n; + int const maxSymbolValue1 = (int)maxSymbolValue + 1; + + /* Compute base and set curr to base. + * For symbol s let lowerRank = BIT_highbit32(count[n]+1) and rank = lowerRank + 1. + * Then 2^lowerRank <= count[n]+1 <= 2^rank. + * We attribute each symbol to lowerRank's base value, because we want to know where + * each rank begins in the output, so for rank R we want to count ranks R+1 and above. + */ + ZSTD_memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE); + for (n = 0; n < maxSymbolValue1; ++n) { + U32 lowerRank = BIT_highbit32(count[n] + 1); + rankPosition[lowerRank].base++; } - for (n=30; n>0; n--) rankPosition[n-1].base += rankPosition[n].base; - for (n=0; n<32; n++) rankPosition[n].current = rankPosition[n].base; - for (n=0; n<=maxSymbolValue; n++) { + assert(rankPosition[RANK_POSITION_TABLE_SIZE - 1].base == 0); + for (n = RANK_POSITION_TABLE_SIZE - 1; n > 0; --n) { + rankPosition[n-1].base += rankPosition[n].base; + rankPosition[n-1].curr = rankPosition[n-1].base; + } + /* Sort */ + for (n = 0; n < maxSymbolValue1; ++n) { U32 const c = count[n]; U32 const r = BIT_highbit32(c+1) + 1; - U32 pos = rankPosition[r].current++; + U32 pos = rankPosition[r].curr++; + /* Insert into the correct position in the rank. + * We have at most 256 symbols, so this insertion should be fine. + */ while ((pos > rankPosition[r].base) && (c > huffNode[pos-1].count)) { huffNode[pos] = huffNode[pos-1]; pos--; @@ -335,28 +416,20 @@ static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValu */ #define STARTNODE (HUF_SYMBOLVALUE_MAX+1) -size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize) +/* HUF_buildTree(): + * Takes the huffNode array sorted by HUF_sort() and builds an unlimited-depth Huffman tree. + * + * @param huffNode The array sorted by HUF_sort(). Builds the Huffman tree in this array. + * @param maxSymbolValue The maximum symbol value. + * @return The smallest node in the Huffman tree (by count). + */ +static int HUF_buildTree(nodeElt* huffNode, U32 maxSymbolValue) { - HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace; - nodeElt* const huffNode0 = wksp_tables->huffNodeTbl; - nodeElt* const huffNode = huffNode0+1; + nodeElt* const huffNode0 = huffNode - 1; int nonNullRank; int lowS, lowN; int nodeNb = STARTNODE; int n, nodeRoot; - - /* safety checks */ - if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ - if (wkspSize < sizeof(HUF_buildCTable_wksp_tables)) - return ERROR(workSpace_tooSmall); - if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT; - if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) - return ERROR(maxSymbolValue_tooLarge); - memset(huffNode0, 0, sizeof(huffNodeTable)); - - /* sort, decreasing order */ - HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition); - /* init for parents */ nonNullRank = (int)maxSymbolValue; while(huffNode[nonNullRank].count == 0) nonNullRank--; @@ -383,42 +456,72 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo for (n=0; n<=nonNullRank; n++) huffNode[n].nbBits = huffNode[ huffNode[n].parent ].nbBits + 1; + return nonNullRank; +} + +/** + * HUF_buildCTableFromTree(): + * Build the CTable given the Huffman tree in huffNode. + * + * @param[out] CTable The output Huffman CTable. + * @param huffNode The Huffman tree. + * @param nonNullRank The last and smallest node in the Huffman tree. + * @param maxSymbolValue The maximum symbol value. + * @param maxNbBits The exact maximum number of bits used in the Huffman tree. + */ +static void HUF_buildCTableFromTree(HUF_CElt* CTable, nodeElt const* huffNode, int nonNullRank, U32 maxSymbolValue, U32 maxNbBits) +{ + /* fill result into ctable (val, nbBits) */ + int n; + U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0}; + U16 valPerRank[HUF_TABLELOG_MAX+1] = {0}; + int const alphabetSize = (int)(maxSymbolValue + 1); + for (n=0; n<=nonNullRank; n++) + nbPerRank[huffNode[n].nbBits]++; + /* determine starting value per rank */ + { U16 min = 0; + for (n=(int)maxNbBits; n>0; n--) { + valPerRank[n] = min; /* get starting value within each rank */ + min += nbPerRank[n]; + min >>= 1; + } } + for (n=0; n<alphabetSize; n++) + CTable[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */ + for (n=0; n<alphabetSize; n++) + CTable[n].val = valPerRank[CTable[n].nbBits]++; /* assign value within rank, symbol order */ +} + +size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize) +{ + HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace; + nodeElt* const huffNode0 = wksp_tables->huffNodeTbl; + nodeElt* const huffNode = huffNode0+1; + int nonNullRank; + + /* safety checks */ + if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ + if (wkspSize < sizeof(HUF_buildCTable_wksp_tables)) + return ERROR(workSpace_tooSmall); + if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT; + if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) + return ERROR(maxSymbolValue_tooLarge); + ZSTD_memset(huffNode0, 0, sizeof(huffNodeTable)); + + /* sort, decreasing order */ + HUF_sort(huffNode, count, maxSymbolValue, wksp_tables->rankPosition); + + /* build tree */ + nonNullRank = HUF_buildTree(huffNode, maxSymbolValue); + /* enforce maxTableLog */ maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits); + if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */ - /* fill result into tree (val, nbBits) */ - { U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0}; - U16 valPerRank[HUF_TABLELOG_MAX+1] = {0}; - int const alphabetSize = (int)(maxSymbolValue + 1); - if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */ - for (n=0; n<=nonNullRank; n++) - nbPerRank[huffNode[n].nbBits]++; - /* determine stating value per rank */ - { U16 min = 0; - for (n=(int)maxNbBits; n>0; n--) { - valPerRank[n] = min; /* get starting value within each rank */ - min += nbPerRank[n]; - min >>= 1; - } } - for (n=0; n<alphabetSize; n++) - tree[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */ - for (n=0; n<alphabetSize; n++) - tree[n].val = valPerRank[tree[n].nbBits]++; /* assign value within rank, symbol order */ - } + HUF_buildCTableFromTree(tree, huffNode, nonNullRank, maxSymbolValue, maxNbBits); return maxNbBits; } -/** HUF_buildCTable() : - * @return : maxNbBits - * Note : count is used before tree is written, so they can safely overlap - */ -size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits) -{ - HUF_buildCTable_wksp_tables workspace; - return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, &workspace, sizeof(workspace)); -} - size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) { size_t nbBits = 0; @@ -633,25 +736,26 @@ typedef struct { } HUF_compress_tables_t; /* HUF_compress_internal() : - * `workSpace` must a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */ + * `workSpace_align4` must be aligned on 4-bytes boundaries, + * and occupies the same space as a table of HUF_WORKSPACE_SIZE_U32 unsigned */ static size_t HUF_compress_internal (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog, HUF_nbStreams_e nbStreams, - void* workSpace, size_t wkspSize, + void* workSpace_align4, size_t wkspSize, HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat, const int bmi2) { - HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace; + HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace_align4; BYTE* const ostart = (BYTE*)dst; BYTE* const oend = ostart + dstSize; BYTE* op = ostart; HUF_STATIC_ASSERT(sizeof(*table) <= HUF_WORKSPACE_SIZE); + assert(((size_t)workSpace_align4 & 3) == 0); /* must be aligned on 4-bytes boundaries */ /* checks & inits */ - if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */ if (wkspSize < HUF_WORKSPACE_SIZE) return ERROR(workSpace_tooSmall); if (!srcSize) return 0; /* Uncompressed */ if (!dstSize) return 0; /* cannot fit anything within dst budget */ @@ -669,7 +773,7 @@ HUF_compress_internal (void* dst, size_t dstSize, } /* Scan input and build symbol stats */ - { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace, wkspSize) ); + { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace_align4, wkspSize) ); if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */ if (largest <= (srcSize >> 7)+4) return 0; /* heuristic : probably not compressible enough */ } @@ -695,7 +799,7 @@ HUF_compress_internal (void* dst, size_t dstSize, CHECK_F(maxBits); huffLog = (U32)maxBits; /* Zero unused symbols in CTable, so we can check it for validity */ - memset(table->CTable + (maxSymbolValue + 1), 0, + ZSTD_memset(table->CTable + (maxSymbolValue + 1), 0, sizeof(table->CTable) - ((maxSymbolValue + 1) * sizeof(HUF_CElt))); } @@ -716,7 +820,7 @@ HUF_compress_internal (void* dst, size_t dstSize, op += hSize; if (repeat) { *repeat = HUF_repeat_none; } if (oldHufTable) - memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */ + ZSTD_memcpy(oldHufTable, table->CTable, sizeof(table->CTable)); /* Save new table */ } return HUF_compressCTable_internal(ostart, op, oend, src, srcSize, @@ -747,14 +851,6 @@ size_t HUF_compress1X_repeat (void* dst, size_t dstSize, repeat, preferRepeat, bmi2); } -size_t HUF_compress1X (void* dst, size_t dstSize, - const void* src, size_t srcSize, - unsigned maxSymbolValue, unsigned huffLog) -{ - unsigned workSpace[HUF_WORKSPACE_SIZE_U32]; - return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace)); -} - /* HUF_compress4X_repeat(): * compress input using 4 streams. * provide workspace to generate compression tables */ @@ -784,6 +880,25 @@ size_t HUF_compress4X_repeat (void* dst, size_t dstSize, hufTable, repeat, preferRepeat, bmi2); } +#ifndef ZSTD_NO_UNUSED_FUNCTIONS +/** HUF_buildCTable() : + * @return : maxNbBits + * Note : count is used before tree is written, so they can safely overlap + */ +size_t HUF_buildCTable (HUF_CElt* tree, const unsigned* count, unsigned maxSymbolValue, unsigned maxNbBits) +{ + HUF_buildCTable_wksp_tables workspace; + return HUF_buildCTable_wksp(tree, count, maxSymbolValue, maxNbBits, &workspace, sizeof(workspace)); +} + +size_t HUF_compress1X (void* dst, size_t dstSize, + const void* src, size_t srcSize, + unsigned maxSymbolValue, unsigned huffLog) +{ + unsigned workSpace[HUF_WORKSPACE_SIZE_U32]; + return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace)); +} + size_t HUF_compress2 (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned huffLog) @@ -796,3 +911,4 @@ size_t HUF_compress (void* dst, size_t maxDstSize, const void* src, size_t srcSi { return HUF_compress2(dst, maxDstSize, src, srcSize, 255, HUF_TABLELOG_DEFAULT); } +#endif diff --git a/thirdparty/zstd/compress/zstd_compress.c b/thirdparty/zstd/compress/zstd_compress.c index 3f963b1cff..386b051df6 100644 --- a/thirdparty/zstd/compress/zstd_compress.c +++ b/thirdparty/zstd/compress/zstd_compress.c @@ -11,8 +11,7 @@ /*-************************************* * Dependencies ***************************************/ -#include <limits.h> /* INT_MAX */ -#include <string.h> /* memset */ +#include "../common/zstd_deps.h" /* INT_MAX, ZSTD_memset, ZSTD_memcpy */ #include "../common/cpu.h" #include "../common/mem.h" #include "hist.h" /* HIST_countFast_wksp */ @@ -30,6 +29,19 @@ #include "zstd_ldm.h" #include "zstd_compress_superblock.h" +/* *************************************************************** +* Tuning parameters +*****************************************************************/ +/*! + * COMPRESS_HEAPMODE : + * Select how default decompression function ZSTD_compress() allocates its context, + * on stack (0, default), or into heap (1). + * Note that functions with explicit context such as ZSTD_compressCCtx() are unaffected. + */ +#ifndef ZSTD_COMPRESS_HEAPMODE +# define ZSTD_COMPRESS_HEAPMODE 0 +#endif + /*-************************************* * Helper functions @@ -52,6 +64,7 @@ size_t ZSTD_compressBound(size_t srcSize) { struct ZSTD_CDict_s { const void* dictContent; size_t dictContentSize; + ZSTD_dictContentType_e dictContentType; /* The dictContentType the CDict was created with */ U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */ ZSTD_cwksp workspace; ZSTD_matchState_t matchState; @@ -69,7 +82,7 @@ ZSTD_CCtx* ZSTD_createCCtx(void) static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager) { assert(cctx != NULL); - memset(cctx, 0, sizeof(*cctx)); + ZSTD_memset(cctx, 0, sizeof(*cctx)); cctx->customMem = memManager; cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); { size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters); @@ -82,8 +95,8 @@ ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem) { ZSTD_STATIC_ASSERT(zcss_init==0); ZSTD_STATIC_ASSERT(ZSTD_CONTENTSIZE_UNKNOWN==(0ULL - 1)); - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; - { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_malloc(sizeof(ZSTD_CCtx), customMem); + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; + { ZSTD_CCtx* const cctx = (ZSTD_CCtx*)ZSTD_customMalloc(sizeof(ZSTD_CCtx), customMem); if (!cctx) return NULL; ZSTD_initCCtx(cctx, customMem); return cctx; @@ -96,20 +109,20 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) ZSTD_CCtx* cctx; if (workspaceSize <= sizeof(ZSTD_CCtx)) return NULL; /* minimum size */ if ((size_t)workspace & 7) return NULL; /* must be 8-aligned */ - ZSTD_cwksp_init(&ws, workspace, workspaceSize); + ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc); cctx = (ZSTD_CCtx*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CCtx)); if (cctx == NULL) return NULL; - memset(cctx, 0, sizeof(ZSTD_CCtx)); + ZSTD_memset(cctx, 0, sizeof(ZSTD_CCtx)); ZSTD_cwksp_move(&cctx->workspace, &ws); cctx->staticSize = workspaceSize; /* statically sized space. entropyWorkspace never moves (but prev/next block swap places) */ - if (!ZSTD_cwksp_check_available(&cctx->workspace, HUF_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; + if (!ZSTD_cwksp_check_available(&cctx->workspace, ENTROPY_WORKSPACE_SIZE + 2 * sizeof(ZSTD_compressedBlockState_t))) return NULL; cctx->blockState.prevCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); cctx->blockState.nextCBlock = (ZSTD_compressedBlockState_t*)ZSTD_cwksp_reserve_object(&cctx->workspace, sizeof(ZSTD_compressedBlockState_t)); - cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, HUF_WORKSPACE_SIZE); + cctx->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cctx->workspace, ENTROPY_WORKSPACE_SIZE); cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); return cctx; } @@ -119,10 +132,10 @@ ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize) */ static void ZSTD_clearAllDicts(ZSTD_CCtx* cctx) { - ZSTD_free(cctx->localDict.dictBuffer, cctx->customMem); + ZSTD_customFree(cctx->localDict.dictBuffer, cctx->customMem); ZSTD_freeCDict(cctx->localDict.cdict); - memset(&cctx->localDict, 0, sizeof(cctx->localDict)); - memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); + ZSTD_memset(&cctx->localDict, 0, sizeof(cctx->localDict)); + ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); cctx->cdict = NULL; } @@ -153,7 +166,7 @@ size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx) int cctxInWorkspace = ZSTD_cwksp_owns_buffer(&cctx->workspace, cctx); ZSTD_freeCCtxContent(cctx); if (!cctxInWorkspace) { - ZSTD_free(cctx, cctx->customMem); + ZSTD_customFree(cctx, cctx->customMem); } } return 0; @@ -189,15 +202,32 @@ size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs) /* private API call, for dictBuilder only */ const seqStore_t* ZSTD_getSeqStore(const ZSTD_CCtx* ctx) { return &(ctx->seqStore); } +/* Returns 1 if compression parameters are such that we should + * enable long distance matching (wlog >= 27, strategy >= btopt). + * Returns 0 otherwise. + */ +static U32 ZSTD_CParams_shouldEnableLdm(const ZSTD_compressionParameters* const cParams) { + return cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27; +} + static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams( ZSTD_compressionParameters cParams) { ZSTD_CCtx_params cctxParams; - memset(&cctxParams, 0, sizeof(cctxParams)); + /* should not matter, as all cParams are presumed properly defined */ + ZSTD_CCtxParams_init(&cctxParams, ZSTD_CLEVEL_DEFAULT); cctxParams.cParams = cParams; - cctxParams.compressionLevel = ZSTD_CLEVEL_DEFAULT; /* should not matter, as all cParams are presumed properly defined */ + + if (ZSTD_CParams_shouldEnableLdm(&cParams)) { + DEBUGLOG(4, "ZSTD_makeCCtxParamsFromCParams(): Including LDM into cctx params"); + cctxParams.ldmParams.enableLdm = 1; + /* LDM is enabled by default for optimal parser and window size >= 128MB */ + ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cParams); + assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog); + assert(cctxParams.ldmParams.hashRateLog < 32); + } + assert(!ZSTD_checkCParams(cParams)); - cctxParams.fParams.contentSizeFlag = 1; return cctxParams; } @@ -205,13 +235,12 @@ static ZSTD_CCtx_params* ZSTD_createCCtxParams_advanced( ZSTD_customMem customMem) { ZSTD_CCtx_params* params; - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; - params = (ZSTD_CCtx_params*)ZSTD_calloc( + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; + params = (ZSTD_CCtx_params*)ZSTD_customCalloc( sizeof(ZSTD_CCtx_params), customMem); if (!params) { return NULL; } + ZSTD_CCtxParams_init(params, ZSTD_CLEVEL_DEFAULT); params->customMem = customMem; - params->compressionLevel = ZSTD_CLEVEL_DEFAULT; - params->fParams.contentSizeFlag = 1; return params; } @@ -223,7 +252,7 @@ ZSTD_CCtx_params* ZSTD_createCCtxParams(void) size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params) { if (params == NULL) { return 0; } - ZSTD_free(params, params->customMem); + ZSTD_customFree(params, params->customMem); return 0; } @@ -234,7 +263,7 @@ size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params) size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel) { RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); - memset(cctxParams, 0, sizeof(*cctxParams)); + ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); cctxParams->compressionLevel = compressionLevel; cctxParams->fParams.contentSizeFlag = 1; return 0; @@ -244,7 +273,7 @@ size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_paramete { RETURN_ERROR_IF(!cctxParams, GENERIC, "NULL pointer!"); FORWARD_IF_ERROR( ZSTD_checkCParams(params.cParams) , ""); - memset(cctxParams, 0, sizeof(*cctxParams)); + ZSTD_memset(cctxParams, 0, sizeof(*cctxParams)); assert(!ZSTD_checkCParams(params.cParams)); cctxParams->cParams = params.cParams; cctxParams->fParams = params.fParams; @@ -354,6 +383,11 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) #endif return bounds; + case ZSTD_c_enableDedicatedDictSearch: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + case ZSTD_c_enableLongDistanceMatching: bounds.lowerBound = 0; bounds.upperBound = 1; @@ -397,7 +431,7 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) return bounds; case ZSTD_c_forceAttachDict: - ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceCopy); + ZSTD_STATIC_ASSERT(ZSTD_dictDefaultAttach < ZSTD_dictForceLoad); bounds.lowerBound = ZSTD_dictDefaultAttach; bounds.upperBound = ZSTD_dictForceLoad; /* note : how to ensure at compile time that this is the highest value enum ? */ return bounds; @@ -418,6 +452,22 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param) bounds.upperBound = ZSTD_SRCSIZEHINT_MAX; return bounds; + case ZSTD_c_stableInBuffer: + case ZSTD_c_stableOutBuffer: + bounds.lowerBound = (int)ZSTD_bm_buffered; + bounds.upperBound = (int)ZSTD_bm_stable; + return bounds; + + case ZSTD_c_blockDelimiters: + bounds.lowerBound = (int)ZSTD_sf_noBlockDelimiters; + bounds.upperBound = (int)ZSTD_sf_explicitBlockDelimiters; + return bounds; + + case ZSTD_c_validateSequences: + bounds.lowerBound = 0; + bounds.upperBound = 1; + return bounds; + default: bounds.error = ERROR(parameter_unsupported); return bounds; @@ -465,6 +515,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) case ZSTD_c_jobSize: case ZSTD_c_overlapLog: case ZSTD_c_rsyncable: + case ZSTD_c_enableDedicatedDictSearch: case ZSTD_c_enableLongDistanceMatching: case ZSTD_c_ldmHashLog: case ZSTD_c_ldmMinMatch: @@ -474,6 +525,10 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param) case ZSTD_c_literalCompressionMode: case ZSTD_c_targetCBlockSize: case ZSTD_c_srcSizeHint: + case ZSTD_c_stableInBuffer: + case ZSTD_c_stableOutBuffer: + case ZSTD_c_blockDelimiters: + case ZSTD_c_validateSequences: default: return 0; } @@ -515,12 +570,17 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value) case ZSTD_c_jobSize: case ZSTD_c_overlapLog: case ZSTD_c_rsyncable: + case ZSTD_c_enableDedicatedDictSearch: case ZSTD_c_enableLongDistanceMatching: case ZSTD_c_ldmHashLog: case ZSTD_c_ldmMinMatch: case ZSTD_c_ldmBucketSizeLog: case ZSTD_c_targetCBlockSize: case ZSTD_c_srcSizeHint: + case ZSTD_c_stableInBuffer: + case ZSTD_c_stableOutBuffer: + case ZSTD_c_blockDelimiters: + case ZSTD_c_validateSequences: break; default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); @@ -541,9 +601,10 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, case ZSTD_c_compressionLevel : { FORWARD_IF_ERROR(ZSTD_cParam_clampBounds(param, &value), ""); - if (value) { /* 0 : does not change current level */ + if (value == 0) + CCtxParams->compressionLevel = ZSTD_CLEVEL_DEFAULT; /* 0 == default */ + else CCtxParams->compressionLevel = value; - } if (CCtxParams->compressionLevel >= 0) return (size_t)CCtxParams->compressionLevel; return 0; /* return type (size_t) cannot represent negative values */ } @@ -667,6 +728,10 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, return CCtxParams->rsyncable; #endif + case ZSTD_c_enableDedicatedDictSearch : + CCtxParams->enableDedicatedDictSearch = (value!=0); + return CCtxParams->enableDedicatedDictSearch; + case ZSTD_c_enableLongDistanceMatching : CCtxParams->ldmParams.enableLdm = (value!=0); return CCtxParams->ldmParams.enableLdm; @@ -707,6 +772,26 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams, CCtxParams->srcSizeHint = value; return CCtxParams->srcSizeHint; + case ZSTD_c_stableInBuffer: + BOUNDCHECK(ZSTD_c_stableInBuffer, value); + CCtxParams->inBufferMode = (ZSTD_bufferMode_e)value; + return CCtxParams->inBufferMode; + + case ZSTD_c_stableOutBuffer: + BOUNDCHECK(ZSTD_c_stableOutBuffer, value); + CCtxParams->outBufferMode = (ZSTD_bufferMode_e)value; + return CCtxParams->outBufferMode; + + case ZSTD_c_blockDelimiters: + BOUNDCHECK(ZSTD_c_blockDelimiters, value); + CCtxParams->blockDelimiters = (ZSTD_sequenceFormat_e)value; + return CCtxParams->blockDelimiters; + + case ZSTD_c_validateSequences: + BOUNDCHECK(ZSTD_c_validateSequences, value); + CCtxParams->validateSequences = value; + return CCtxParams->validateSequences; + default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); } } @@ -794,6 +879,9 @@ size_t ZSTD_CCtxParams_getParameter( *value = CCtxParams->rsyncable; break; #endif + case ZSTD_c_enableDedicatedDictSearch : + *value = CCtxParams->enableDedicatedDictSearch; + break; case ZSTD_c_enableLongDistanceMatching : *value = CCtxParams->ldmParams.enableLdm; break; @@ -815,6 +903,18 @@ size_t ZSTD_CCtxParams_getParameter( case ZSTD_c_srcSizeHint : *value = (int)CCtxParams->srcSizeHint; break; + case ZSTD_c_stableInBuffer : + *value = (int)CCtxParams->inBufferMode; + break; + case ZSTD_c_stableOutBuffer : + *value = (int)CCtxParams->outBufferMode; + break; + case ZSTD_c_blockDelimiters : + *value = (int)CCtxParams->blockDelimiters; + break; + case ZSTD_c_validateSequences : + *value = (int)CCtxParams->validateSequences; + break; default: RETURN_ERROR(parameter_unsupported, "unknown parameter"); } return 0; @@ -850,6 +950,14 @@ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long lo return 0; } +static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams( + int const compressionLevel, + size_t const dictSize); +static int ZSTD_dedicatedDictSearch_isSupported( + const ZSTD_compressionParameters* cParams); +static void ZSTD_dedicatedDictSearch_revertCParams( + ZSTD_compressionParameters* cParams); + /** * Initializes the local dict using the requested parameters. * NOTE: This does not use the pledged src size, because it may be used for more @@ -858,8 +966,6 @@ ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long lo static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx) { ZSTD_localDict* const dl = &cctx->localDict; - ZSTD_compressionParameters const cParams = ZSTD_getCParamsFromCCtxParams( - &cctx->requestedParams, ZSTD_CONTENTSIZE_UNKNOWN, dl->dictSize); if (dl->dict == NULL) { /* No local dictionary. */ assert(dl->dictBuffer == NULL); @@ -876,12 +982,12 @@ static size_t ZSTD_initLocalDict(ZSTD_CCtx* cctx) assert(cctx->cdict == NULL); assert(cctx->prefixDict.dict == NULL); - dl->cdict = ZSTD_createCDict_advanced( + dl->cdict = ZSTD_createCDict_advanced2( dl->dict, dl->dictSize, ZSTD_dlm_byRef, dl->dictContentType, - cParams, + &cctx->requestedParams, cctx->customMem); RETURN_ERROR_IF(!dl->cdict, memory_allocation, "ZSTD_createCDict_advanced failed"); cctx->cdict = dl->cdict; @@ -894,8 +1000,6 @@ size_t ZSTD_CCtx_loadDictionary_advanced( { RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, "Can't load a dictionary when ctx is not in init stage."); - RETURN_ERROR_IF(cctx->staticSize, memory_allocation, - "no malloc for static CCtx"); DEBUGLOG(4, "ZSTD_CCtx_loadDictionary_advanced (size: %u)", (U32)dictSize); ZSTD_clearAllDicts(cctx); /* in case one already exists */ if (dict == NULL || dictSize == 0) /* no dictionary mode */ @@ -903,9 +1007,12 @@ size_t ZSTD_CCtx_loadDictionary_advanced( if (dictLoadMethod == ZSTD_dlm_byRef) { cctx->localDict.dict = dict; } else { - void* dictBuffer = ZSTD_malloc(dictSize, cctx->customMem); + void* dictBuffer; + RETURN_ERROR_IF(cctx->staticSize, memory_allocation, + "no malloc for static CCtx"); + dictBuffer = ZSTD_customMalloc(dictSize, cctx->customMem); RETURN_ERROR_IF(!dictBuffer, memory_allocation, "NULL pointer!"); - memcpy(dictBuffer, dict, dictSize); + ZSTD_memcpy(dictBuffer, dict, dictSize); cctx->localDict.dictBuffer = dictBuffer; cctx->localDict.dict = dictBuffer; } @@ -938,6 +1045,14 @@ size_t ZSTD_CCtx_refCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict) return 0; } +size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool) +{ + RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong, + "Can't ref a pool when ctx not in init stage."); + cctx->pool = pool; + return 0; +} + size_t ZSTD_CCtx_refPrefix(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize) { return ZSTD_CCtx_refPrefix_advanced(cctx, prefix, prefixSize, ZSTD_dct_rawContent); @@ -1022,24 +1137,73 @@ U32 ZSTD_cycleLog(U32 hashLog, ZSTD_strategy strat) return hashLog - btScale; } +/** ZSTD_dictAndWindowLog() : + * Returns an adjusted window log that is large enough to fit the source and the dictionary. + * The zstd format says that the entire dictionary is valid if one byte of the dictionary + * is within the window. So the hashLog and chainLog should be large enough to reference both + * the dictionary and the window. So we must use this adjusted dictAndWindowLog when downsizing + * the hashLog and windowLog. + * NOTE: srcSize must not be ZSTD_CONTENTSIZE_UNKNOWN. + */ +static U32 ZSTD_dictAndWindowLog(U32 windowLog, U64 srcSize, U64 dictSize) +{ + const U64 maxWindowSize = 1ULL << ZSTD_WINDOWLOG_MAX; + /* No dictionary ==> No change */ + if (dictSize == 0) { + return windowLog; + } + assert(windowLog <= ZSTD_WINDOWLOG_MAX); + assert(srcSize != ZSTD_CONTENTSIZE_UNKNOWN); /* Handled in ZSTD_adjustCParams_internal() */ + { + U64 const windowSize = 1ULL << windowLog; + U64 const dictAndWindowSize = dictSize + windowSize; + /* If the window size is already large enough to fit both the source and the dictionary + * then just use the window size. Otherwise adjust so that it fits the dictionary and + * the window. + */ + if (windowSize >= dictSize + srcSize) { + return windowLog; /* Window size large enough already */ + } else if (dictAndWindowSize >= maxWindowSize) { + return ZSTD_WINDOWLOG_MAX; /* Larger than max window log */ + } else { + return ZSTD_highbit32((U32)dictAndWindowSize - 1) + 1; + } + } +} + /** ZSTD_adjustCParams_internal() : * optimize `cPar` for a specified input (`srcSize` and `dictSize`). * mostly downsize to reduce memory consumption and initialization latency. * `srcSize` can be ZSTD_CONTENTSIZE_UNKNOWN when not known. + * `mode` is the mode for parameter adjustment. See docs for `ZSTD_cParamMode_e`. * note : `srcSize==0` means 0! * condition : cPar is presumed validated (can be checked using ZSTD_checkCParams()). */ static ZSTD_compressionParameters ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, unsigned long long srcSize, - size_t dictSize) + size_t dictSize, + ZSTD_cParamMode_e mode) { - static const U64 minSrcSize = 513; /* (1<<9) + 1 */ - static const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); + const U64 minSrcSize = 513; /* (1<<9) + 1 */ + const U64 maxWindowResize = 1ULL << (ZSTD_WINDOWLOG_MAX-1); assert(ZSTD_checkCParams(cPar)==0); if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN) srcSize = minSrcSize; + switch (mode) { + case ZSTD_cpm_noAttachDict: + case ZSTD_cpm_unknown: + case ZSTD_cpm_createCDict: + break; + case ZSTD_cpm_attachDict: + dictSize = 0; + break; + default: + assert(0); + break; + } + /* resize windowLog if input is small enough, to use less memory */ if ( (srcSize < maxWindowResize) && (dictSize < maxWindowResize) ) { @@ -1049,10 +1213,11 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar, ZSTD_highbit32(tSize-1) + 1; if (cPar.windowLog > srcLog) cPar.windowLog = srcLog; } - if (cPar.hashLog > cPar.windowLog+1) cPar.hashLog = cPar.windowLog+1; - { U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy); - if (cycleLog > cPar.windowLog) - cPar.chainLog -= (cycleLog - cPar.windowLog); + { U32 const dictAndWindowLog = ZSTD_dictAndWindowLog(cPar.windowLog, (U64)srcSize, (U64)dictSize); + U32 const cycleLog = ZSTD_cycleLog(cPar.chainLog, cPar.strategy); + if (cPar.hashLog > dictAndWindowLog+1) cPar.hashLog = dictAndWindowLog+1; + if (cycleLog > dictAndWindowLog) + cPar.chainLog -= (cycleLog - dictAndWindowLog); } if (cPar.windowLog < ZSTD_WINDOWLOG_ABSOLUTEMIN) @@ -1068,31 +1233,38 @@ ZSTD_adjustCParams(ZSTD_compressionParameters cPar, { cPar = ZSTD_clampCParams(cPar); /* resulting cPar is necessarily valid (all parameters within range) */ if (srcSize == 0) srcSize = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize); + return ZSTD_adjustCParams_internal(cPar, srcSize, dictSize, ZSTD_cpm_unknown); } -static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize); -static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize); +static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode); +static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode); + +static void ZSTD_overrideCParams( + ZSTD_compressionParameters* cParams, + const ZSTD_compressionParameters* overrides) +{ + if (overrides->windowLog) cParams->windowLog = overrides->windowLog; + if (overrides->hashLog) cParams->hashLog = overrides->hashLog; + if (overrides->chainLog) cParams->chainLog = overrides->chainLog; + if (overrides->searchLog) cParams->searchLog = overrides->searchLog; + if (overrides->minMatch) cParams->minMatch = overrides->minMatch; + if (overrides->targetLength) cParams->targetLength = overrides->targetLength; + if (overrides->strategy) cParams->strategy = overrides->strategy; +} ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( - const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize) + const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) { ZSTD_compressionParameters cParams; if (srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN && CCtxParams->srcSizeHint > 0) { srcSizeHint = CCtxParams->srcSizeHint; } - cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize); + cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode); if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG; - if (CCtxParams->cParams.windowLog) cParams.windowLog = CCtxParams->cParams.windowLog; - if (CCtxParams->cParams.hashLog) cParams.hashLog = CCtxParams->cParams.hashLog; - if (CCtxParams->cParams.chainLog) cParams.chainLog = CCtxParams->cParams.chainLog; - if (CCtxParams->cParams.searchLog) cParams.searchLog = CCtxParams->cParams.searchLog; - if (CCtxParams->cParams.minMatch) cParams.minMatch = CCtxParams->cParams.minMatch; - if (CCtxParams->cParams.targetLength) cParams.targetLength = CCtxParams->cParams.targetLength; - if (CCtxParams->cParams.strategy) cParams.strategy = CCtxParams->cParams.strategy; + ZSTD_overrideCParams(&cParams, &CCtxParams->cParams); assert(!ZSTD_checkCParams(cParams)); /* srcSizeHint == 0 means 0 */ - return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize); + return ZSTD_adjustCParams_internal(cParams, srcSizeHint, dictSize, mode); } static size_t @@ -1123,45 +1295,61 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams, return tableSpace + optSpace; } -size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) +static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal( + const ZSTD_compressionParameters* cParams, + const ldmParams_t* ldmParams, + const int isStatic, + const size_t buffInSize, + const size_t buffOutSize, + const U64 pledgedSrcSize) { - RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); - { ZSTD_compressionParameters const cParams = - ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0); - size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); - U32 const divider = (cParams.minMatch==3) ? 3 : 4; - size_t const maxNbSeq = blockSize / divider; - size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) - + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef)) - + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); - size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE); - size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); - size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 1); + size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << cParams->windowLog), pledgedSrcSize)); + size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize); + U32 const divider = (cParams->minMatch==3) ? 3 : 4; + size_t const maxNbSeq = blockSize / divider; + size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) + + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef)) + + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); + size_t const entropySpace = ZSTD_cwksp_alloc_size(ENTROPY_WORKSPACE_SIZE); + size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); + size_t const matchStateSize = ZSTD_sizeof_matchState(cParams, /* forCCtx */ 1); - size_t const ldmSpace = ZSTD_ldm_getTableSize(params->ldmParams); - size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(ZSTD_ldm_getMaxNbSeq(params->ldmParams, blockSize) * sizeof(rawSeq)); + size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams); + size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize); + size_t const ldmSeqSpace = ldmParams->enableLdm ? + ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0; - /* estimateCCtxSize is for one-shot compression. So no buffers should - * be needed. However, we still allocate two 0-sized buffers, which can - * take space under ASAN. */ - size_t const bufferSpace = ZSTD_cwksp_alloc_size(0) - + ZSTD_cwksp_alloc_size(0); - size_t const cctxSpace = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)); + size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize) + + ZSTD_cwksp_alloc_size(buffOutSize); - size_t const neededSpace = - cctxSpace + - entropySpace + - blockStateSpace + - ldmSpace + - ldmSeqSpace + - matchStateSize + - tokenSpace + - bufferSpace; + size_t const cctxSpace = isStatic ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0; - DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace); - return neededSpace; - } + size_t const neededSpace = + cctxSpace + + entropySpace + + blockStateSpace + + ldmSpace + + ldmSeqSpace + + matchStateSize + + tokenSpace + + bufferSpace; + + DEBUGLOG(5, "estimate workspace : %u", (U32)neededSpace); + return neededSpace; +} + +size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params) +{ + ZSTD_compressionParameters const cParams = + ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); + + RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); + /* estimateCCtxSize is for one-shot compression. So no buffers should + * be needed. However, we still allocate two 0-sized buffers, which can + * take space under ASAN. */ + return ZSTD_estimateCCtxSize_usingCCtxParams_internal( + &cParams, ¶ms->ldmParams, 1, 0, 0, ZSTD_CONTENTSIZE_UNKNOWN); } size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) @@ -1172,7 +1360,7 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams) static size_t ZSTD_estimateCCtxSize_internal(int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); return ZSTD_estimateCCtxSize_usingCParams(cParams); } @@ -1191,15 +1379,18 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params) { RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only."); { ZSTD_compressionParameters const cParams = - ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0); - size_t const CCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(params); + ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, (size_t)1 << cParams.windowLog); - size_t const inBuffSize = ((size_t)1 << cParams.windowLog) + blockSize; - size_t const outBuffSize = ZSTD_compressBound(blockSize) + 1; - size_t const streamingSize = ZSTD_cwksp_alloc_size(inBuffSize) - + ZSTD_cwksp_alloc_size(outBuffSize); - - return CCtxSize + streamingSize; + size_t const inBuffSize = (params->inBufferMode == ZSTD_bm_buffered) + ? ((size_t)1 << cParams.windowLog) + blockSize + : 0; + size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered) + ? ZSTD_compressBound(blockSize) + 1 + : 0; + + return ZSTD_estimateCCtxSize_usingCCtxParams_internal( + &cParams, ¶ms->ldmParams, 1, inBuffSize, outBuffSize, + ZSTD_CONTENTSIZE_UNKNOWN); } } @@ -1211,7 +1402,7 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams) static size_t ZSTD_estimateCStreamSize_internal(int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); return ZSTD_estimateCStreamSize_usingCParams(cParams); } @@ -1305,16 +1496,6 @@ static void ZSTD_invalidateMatchState(ZSTD_matchState_t* ms) } /** - * Indicates whether this compression proceeds directly from user-provided - * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or - * whether the context needs to buffer the input/output (ZSTDb_buffered). - */ -typedef enum { - ZSTDb_not_buffered, - ZSTDb_buffered -} ZSTD_buffered_policy_e; - -/** * Controls, for this matchState reset, whether the tables need to be cleared / * prepared for the coming compression (ZSTDcrp_makeClean), or whether the * tables can be left unclean (ZSTDcrp_leaveDirty), because we know that a @@ -1441,45 +1622,32 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize); U32 const divider = (params.cParams.minMatch==3) ? 3 : 4; size_t const maxNbSeq = blockSize / divider; - size_t const tokenSpace = ZSTD_cwksp_alloc_size(WILDCOPY_OVERLENGTH + blockSize) - + ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(seqDef)) - + 3 * ZSTD_cwksp_alloc_size(maxNbSeq * sizeof(BYTE)); - size_t const buffOutSize = (zbuff==ZSTDb_buffered) ? ZSTD_compressBound(blockSize)+1 : 0; - size_t const buffInSize = (zbuff==ZSTDb_buffered) ? windowSize + blockSize : 0; - size_t const matchStateSize = ZSTD_sizeof_matchState(¶ms.cParams, /* forCCtx */ 1); + size_t const buffOutSize = (zbuff == ZSTDb_buffered && params.outBufferMode == ZSTD_bm_buffered) + ? ZSTD_compressBound(blockSize) + 1 + : 0; + size_t const buffInSize = (zbuff == ZSTDb_buffered && params.inBufferMode == ZSTD_bm_buffered) + ? windowSize + blockSize + : 0; size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(params.ldmParams, blockSize); - ZSTD_indexResetPolicy_e needsIndexReset = zc->initialized ? ZSTDirp_continue : ZSTDirp_reset; + int const indexTooClose = ZSTD_indexTooCloseToMax(zc->blockState.matchState.window); + ZSTD_indexResetPolicy_e needsIndexReset = + (!indexTooClose && zc->initialized) ? ZSTDirp_continue : ZSTDirp_reset; - if (ZSTD_indexTooCloseToMax(zc->blockState.matchState.window)) { - needsIndexReset = ZSTDirp_reset; - } + size_t const neededSpace = + ZSTD_estimateCCtxSize_usingCCtxParams_internal( + ¶ms.cParams, ¶ms.ldmParams, zc->staticSize != 0, + buffInSize, buffOutSize, pledgedSrcSize); + FORWARD_IF_ERROR(neededSpace, "cctx size estimate failed!"); if (!zc->staticSize) ZSTD_cwksp_bump_oversized_duration(ws, 0); /* Check if workspace is large enough, alloc a new one if needed */ - { size_t const cctxSpace = zc->staticSize ? ZSTD_cwksp_alloc_size(sizeof(ZSTD_CCtx)) : 0; - size_t const entropySpace = ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE); - size_t const blockStateSpace = 2 * ZSTD_cwksp_alloc_size(sizeof(ZSTD_compressedBlockState_t)); - size_t const bufferSpace = ZSTD_cwksp_alloc_size(buffInSize) + ZSTD_cwksp_alloc_size(buffOutSize); - size_t const ldmSpace = ZSTD_ldm_getTableSize(params.ldmParams); - size_t const ldmSeqSpace = ZSTD_cwksp_alloc_size(maxNbLdmSeq * sizeof(rawSeq)); - - size_t const neededSpace = - cctxSpace + - entropySpace + - blockStateSpace + - ldmSpace + - ldmSeqSpace + - matchStateSize + - tokenSpace + - bufferSpace; - + { int const workspaceTooSmall = ZSTD_cwksp_sizeof(ws) < neededSpace; int const workspaceWasteful = ZSTD_cwksp_check_wasteful(ws, neededSpace); - DEBUGLOG(4, "Need %zuKB workspace, including %zuKB for match state, and %zuKB for buffers", - neededSpace>>10, matchStateSize>>10, bufferSpace>>10); + DEBUGLOG(4, "Need %zu B workspace", neededSpace); DEBUGLOG(4, "windowSize: %zu - blockSize: %zu", windowSize, blockSize); if (workspaceTooSmall || workspaceWasteful) { @@ -1503,7 +1671,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, RETURN_ERROR_IF(zc->blockState.prevCBlock == NULL, memory_allocation, "couldn't allocate prevCBlock"); zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t)); RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock"); - zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, HUF_WORKSPACE_SIZE); + zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, ENTROPY_WORKSPACE_SIZE); RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace"); } } @@ -1534,6 +1702,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, zc->seqStore.maxNbLit = blockSize; /* buffers */ + zc->bufferedPolicy = zbuff; zc->inBuffSize = buffInSize; zc->inBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffInSize); zc->outBuffSize = buffOutSize; @@ -1546,7 +1715,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, ((size_t)1) << (params.ldmParams.hashLog - params.ldmParams.bucketSizeLog); zc->ldmState.bucketOffsets = ZSTD_cwksp_reserve_buffer(ws, ldmBucketSize); - memset(zc->ldmState.bucketOffsets, 0, ldmBucketSize); + ZSTD_memset(zc->ldmState.bucketOffsets, 0, ldmBucketSize); } /* sequences storage */ @@ -1570,7 +1739,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, /* TODO: avoid memset? */ size_t const ldmHSize = ((size_t)1) << params.ldmParams.hashLog; zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t)); - memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t)); + ZSTD_memset(zc->ldmState.hashTable, 0, ldmHSize * sizeof(ldmEntry_t)); zc->ldmSequences = (rawSeq*)ZSTD_cwksp_reserve_aligned(ws, maxNbLdmSeq * sizeof(rawSeq)); zc->maxNbLdmSequences = maxNbLdmSeq; @@ -1579,6 +1748,12 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc, zc->ldmState.loadedDictEnd = 0; } + /* Due to alignment, when reusing a workspace, we can actually consume + * up to 3 extra bytes for alignment. See the comments in zstd_cwksp.h + */ + assert(ZSTD_cwksp_used(ws) >= neededSpace && + ZSTD_cwksp_used(ws) <= neededSpace + 3); + DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws)); zc->initialized = 1; @@ -1618,12 +1793,14 @@ static int ZSTD_shouldAttachDict(const ZSTD_CDict* cdict, U64 pledgedSrcSize) { size_t cutoff = attachDictSizeCutoffs[cdict->matchState.cParams.strategy]; - return ( pledgedSrcSize <= cutoff - || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN - || params->attachDictPref == ZSTD_dictForceAttach ) - && params->attachDictPref != ZSTD_dictForceCopy - && !params->forceWindow; /* dictMatchState isn't correctly - * handled in _enforceMaxDist */ + int const dedicatedDictSearch = cdict->matchState.dedicatedDictSearch; + return dedicatedDictSearch + || ( ( pledgedSrcSize <= cutoff + || pledgedSrcSize == ZSTD_CONTENTSIZE_UNKNOWN + || params->attachDictPref == ZSTD_dictForceAttach ) + && params->attachDictPref != ZSTD_dictForceCopy + && !params->forceWindow ); /* dictMatchState isn't correctly + * handled in _enforceMaxDist */ } static size_t @@ -1633,17 +1810,24 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, U64 pledgedSrcSize, ZSTD_buffered_policy_e zbuff) { - { const ZSTD_compressionParameters* const cdict_cParams = &cdict->matchState.cParams; + { + ZSTD_compressionParameters adjusted_cdict_cParams = cdict->matchState.cParams; unsigned const windowLog = params.cParams.windowLog; assert(windowLog != 0); /* Resize working context table params for input only, since the dict * has its own tables. */ - /* pledgeSrcSize == 0 means 0! */ - params.cParams = ZSTD_adjustCParams_internal(*cdict_cParams, pledgedSrcSize, 0); + /* pledgedSrcSize == 0 means 0! */ + + if (cdict->matchState.dedicatedDictSearch) { + ZSTD_dedicatedDictSearch_revertCParams(&adjusted_cdict_cParams); + } + + params.cParams = ZSTD_adjustCParams_internal(adjusted_cdict_cParams, pledgedSrcSize, + cdict->dictContentSize, ZSTD_cpm_attachDict); params.cParams.windowLog = windowLog; FORWARD_IF_ERROR(ZSTD_resetCCtx_internal(cctx, params, pledgedSrcSize, ZSTDcrp_makeClean, zbuff), ""); - assert(cctx->appliedParams.cParams.strategy == cdict_cParams->strategy); + assert(cctx->appliedParams.cParams.strategy == adjusted_cdict_cParams.strategy); } { const U32 cdictEnd = (U32)( cdict->matchState.window.nextSrc @@ -1670,7 +1854,7 @@ ZSTD_resetCCtx_byAttachingCDict(ZSTD_CCtx* cctx, cctx->dictID = cdict->dictID; /* copy block state */ - memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); + ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); return 0; } @@ -1683,6 +1867,8 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, { const ZSTD_compressionParameters *cdict_cParams = &cdict->matchState.cParams; + assert(!cdict->matchState.dedicatedDictSearch); + DEBUGLOG(4, "copying dictionary into context"); { unsigned const windowLog = params.cParams.windowLog; @@ -1703,10 +1889,10 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, { size_t const chainSize = (cdict_cParams->strategy == ZSTD_fast) ? 0 : ((size_t)1 << cdict_cParams->chainLog); size_t const hSize = (size_t)1 << cdict_cParams->hashLog; - memcpy(cctx->blockState.matchState.hashTable, + ZSTD_memcpy(cctx->blockState.matchState.hashTable, cdict->matchState.hashTable, hSize * sizeof(U32)); - memcpy(cctx->blockState.matchState.chainTable, + ZSTD_memcpy(cctx->blockState.matchState.chainTable, cdict->matchState.chainTable, chainSize * sizeof(U32)); } @@ -1715,7 +1901,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, { int const h3log = cctx->blockState.matchState.hashLog3; size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0; assert(cdict->matchState.hashLog3 == 0); - memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32)); + ZSTD_memset(cctx->blockState.matchState.hashTable3, 0, h3Size * sizeof(U32)); } ZSTD_cwksp_mark_tables_clean(&cctx->workspace); @@ -1731,7 +1917,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx, cctx->dictID = cdict->dictID; /* copy block state */ - memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); + ZSTD_memcpy(cctx->blockState.prevCBlock, &cdict->cBlockState, sizeof(cdict->cBlockState)); return 0; } @@ -1775,7 +1961,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, RETURN_ERROR_IF(srcCCtx->stage!=ZSTDcs_init, stage_wrong, "Can't copy a ctx that's not in init stage."); - memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); + ZSTD_memcpy(&dstCCtx->customMem, &srcCCtx->customMem, sizeof(ZSTD_customMem)); { ZSTD_CCtx_params params = dstCCtx->requestedParams; /* Copy only compression parameters related to tables. */ params.cParams = srcCCtx->appliedParams.cParams; @@ -1797,13 +1983,13 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, int const h3log = srcCCtx->blockState.matchState.hashLog3; size_t const h3Size = h3log ? ((size_t)1 << h3log) : 0; - memcpy(dstCCtx->blockState.matchState.hashTable, + ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable, srcCCtx->blockState.matchState.hashTable, hSize * sizeof(U32)); - memcpy(dstCCtx->blockState.matchState.chainTable, + ZSTD_memcpy(dstCCtx->blockState.matchState.chainTable, srcCCtx->blockState.matchState.chainTable, chainSize * sizeof(U32)); - memcpy(dstCCtx->blockState.matchState.hashTable3, + ZSTD_memcpy(dstCCtx->blockState.matchState.hashTable3, srcCCtx->blockState.matchState.hashTable3, h3Size * sizeof(U32)); } @@ -1821,7 +2007,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, dstCCtx->dictID = srcCCtx->dictID; /* copy block state */ - memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock)); + ZSTD_memcpy(dstCCtx->blockState.prevCBlock, srcCCtx->blockState.prevCBlock, sizeof(*srcCCtx->blockState.prevCBlock)); return 0; } @@ -1834,7 +2020,7 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx, size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long long pledgedSrcSize) { ZSTD_frameParameters fParams = { 1 /*content*/, 0 /*checksum*/, 0 /*noDictID*/ }; - ZSTD_buffered_policy_e const zbuff = (ZSTD_buffered_policy_e)(srcCCtx->inBuffSize>0); + ZSTD_buffered_policy_e const zbuff = srcCCtx->bufferedPolicy; ZSTD_STATIC_ASSERT((U32)ZSTDb_buffered==1); if (pledgedSrcSize==0) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; fParams.contentSizeFlag = (pledgedSrcSize != ZSTD_CONTENTSIZE_UNKNOWN); @@ -1861,7 +2047,7 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */ assert(size < (1U<<31)); /* can be casted to int */ -#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) +#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) /* To validate that the table re-use logic is sound, and that we don't * access table space that we haven't cleaned, we re-"poison" the table * space every time we mark it dirty. @@ -1958,10 +2144,10 @@ static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams) return (cctxParams->targetCBlockSize != 0); } -/* ZSTD_compressSequences_internal(): +/* ZSTD_entropyCompressSequences_internal(): * actually compresses both literals and sequences */ MEM_STATIC size_t -ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, +ZSTD_entropyCompressSequences_internal(seqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, ZSTD_entropyCTables_t* nextEntropy, const ZSTD_CCtx_params* cctxParams, @@ -1971,7 +2157,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, { const int longOffsets = cctxParams->cParams.windowLog > STREAM_ACCUMULATOR_MIN; ZSTD_strategy const strategy = cctxParams->cParams.strategy; - unsigned count[MaxSeq+1]; + unsigned* count = (unsigned*)entropyWorkspace; FSE_CTable* CTable_LitLength = nextEntropy->fse.litlengthCTable; FSE_CTable* CTable_OffsetBits = nextEntropy->fse.offcodeCTable; FSE_CTable* CTable_MatchLength = nextEntropy->fse.matchlengthCTable; @@ -1987,8 +2173,12 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, BYTE* seqHead; BYTE* lastNCount = NULL; - DEBUGLOG(5, "ZSTD_compressSequences_internal (nbSeq=%zu)", nbSeq); + entropyWorkspace = count + (MaxSeq + 1); + entropyWkspSize -= (MaxSeq + 1) * sizeof(*count); + + DEBUGLOG(4, "ZSTD_entropyCompressSequences_internal (nbSeq=%zu)", nbSeq); ZSTD_STATIC_ASSERT(HUF_WORKSPACE_SIZE >= (1<<MAX(MLFSELog,LLFSELog))); + assert(entropyWkspSize >= HUF_WORKSPACE_SIZE); /* Compress literals */ { const BYTE* const literals = seqStorePtr->litStart; @@ -2023,7 +2213,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, assert(op <= oend); if (nbSeq==0) { /* Copy the old tables over as if we repeated them */ - memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse)); + ZSTD_memcpy(&nextEntropy->fse, &prevEntropy->fse, sizeof(prevEntropy->fse)); return (size_t)(op - ostart); } @@ -2148,7 +2338,7 @@ ZSTD_compressSequences_internal(seqStore_t* seqStorePtr, } MEM_STATIC size_t -ZSTD_compressSequences(seqStore_t* seqStorePtr, +ZSTD_entropyCompressSequences(seqStore_t* seqStorePtr, const ZSTD_entropyCTables_t* prevEntropy, ZSTD_entropyCTables_t* nextEntropy, const ZSTD_CCtx_params* cctxParams, @@ -2157,7 +2347,7 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr, void* entropyWorkspace, size_t entropyWkspSize, int bmi2) { - size_t const cSize = ZSTD_compressSequences_internal( + size_t const cSize = ZSTD_entropyCompressSequences_internal( seqStorePtr, prevEntropy, nextEntropy, cctxParams, dst, dstCapacity, entropyWorkspace, entropyWkspSize, bmi2); @@ -2167,13 +2357,13 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr, */ if ((cSize == ERROR(dstSize_tooSmall)) & (srcSize <= dstCapacity)) return 0; /* block not compressed */ - FORWARD_IF_ERROR(cSize, "ZSTD_compressSequences_internal failed"); + FORWARD_IF_ERROR(cSize, "ZSTD_entropyCompressSequences_internal failed"); /* Check compressibility */ { size_t const maxCSize = srcSize - ZSTD_minGain(srcSize, cctxParams->cParams.strategy); if (cSize >= maxCSize) return 0; /* block not compressed */ } - + DEBUGLOG(4, "ZSTD_entropyCompressSequences() cSize: %zu\n", cSize); return cSize; } @@ -2182,7 +2372,7 @@ ZSTD_compressSequences(seqStore_t* seqStorePtr, * assumption : strat is a valid strategy */ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMode_e dictMode) { - static const ZSTD_blockCompressor blockCompressor[3][ZSTD_STRATEGY_MAX+1] = { + static const ZSTD_blockCompressor blockCompressor[4][ZSTD_STRATEGY_MAX+1] = { { ZSTD_compressBlock_fast /* default for 0 */, ZSTD_compressBlock_fast, ZSTD_compressBlock_doubleFast, @@ -2212,7 +2402,17 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMo ZSTD_compressBlock_btlazy2_dictMatchState, ZSTD_compressBlock_btopt_dictMatchState, ZSTD_compressBlock_btultra_dictMatchState, - ZSTD_compressBlock_btultra_dictMatchState } + ZSTD_compressBlock_btultra_dictMatchState }, + { NULL /* default for 0 */, + NULL, + NULL, + ZSTD_compressBlock_greedy_dedicatedDictSearch, + ZSTD_compressBlock_lazy_dedicatedDictSearch, + ZSTD_compressBlock_lazy2_dedicatedDictSearch, + NULL, + NULL, + NULL, + NULL } }; ZSTD_blockCompressor selectedCompressor; ZSTD_STATIC_ASSERT((unsigned)ZSTD_fast == 1); @@ -2226,7 +2426,7 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_dictMo static void ZSTD_storeLastLiterals(seqStore_t* seqStorePtr, const BYTE* anchor, size_t lastLLSize) { - memcpy(seqStorePtr->lit, anchor, lastLLSize); + ZSTD_memcpy(seqStorePtr->lit, anchor, lastLLSize); seqStorePtr->lit += lastLLSize; } @@ -2247,7 +2447,11 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) /* Assert that we have correctly flushed the ctx params into the ms's copy */ ZSTD_assertEqualCParams(zc->appliedParams.cParams, ms->cParams); if (srcSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) { - ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch); + if (zc->appliedParams.cParams.strategy >= ZSTD_btopt) { + ZSTD_ldm_skipRawSeqStoreBytes(&zc->externSeqStore, srcSize); + } else { + ZSTD_ldm_skipSequences(&zc->externSeqStore, srcSize, zc->appliedParams.cParams.minMatch); + } return ZSTDbss_noCompress; /* don't even attempt compression below a certain srcSize */ } ZSTD_resetSeqStore(&(zc->seqStore)); @@ -2263,10 +2467,10 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) /* limited update after a very long match */ { const BYTE* const base = ms->window.base; const BYTE* const istart = (const BYTE*)src; - const U32 current = (U32)(istart-base); + const U32 curr = (U32)(istart-base); if (sizeof(ptrdiff_t)==8) assert(istart - base < (ptrdiff_t)(U32)(-1)); /* ensure no overflow */ - if (current > ms->nextToUpdate + 384) - ms->nextToUpdate = current - MIN(192, (U32)(current - ms->nextToUpdate - 384)); + if (curr > ms->nextToUpdate + 384) + ms->nextToUpdate = curr - MIN(192, (U32)(curr - ms->nextToUpdate - 384)); } /* select and store sequences */ @@ -2286,7 +2490,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) src, srcSize); assert(zc->externSeqStore.pos <= zc->externSeqStore.size); } else if (zc->appliedParams.ldmParams.enableLdm) { - rawSeqStore_t ldmSeqStore = {NULL, 0, 0, 0}; + rawSeqStore_t ldmSeqStore = kNullRawSeqStore; ldmSeqStore.seq = zc->ldmSequences; ldmSeqStore.capacity = zc->maxNbLdmSequences; @@ -2303,6 +2507,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) assert(ldmSeqStore.pos == ldmSeqStore.size); } else { /* not long range mode */ ZSTD_blockCompressor const blockCompressor = ZSTD_selectBlockCompressor(zc->appliedParams.cParams.strategy, dictMode); + ms->ldmSeqStore = NULL; lastLLSize = blockCompressor(ms, &zc->seqStore, zc->blockState.nextCBlock->rep, src, srcSize); } { const BYTE* const lastLiterals = (const BYTE*)src + srcSize - lastLLSize; @@ -2314,17 +2519,25 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize) static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc) { const seqStore_t* seqStore = ZSTD_getSeqStore(zc); - const seqDef* seqs = seqStore->sequencesStart; - size_t seqsSize = seqStore->sequences - seqs; + const seqDef* seqStoreSeqs = seqStore->sequencesStart; + size_t seqStoreSeqSize = seqStore->sequences - seqStoreSeqs; + size_t seqStoreLiteralsSize = (size_t)(seqStore->lit - seqStore->litStart); + size_t literalsRead = 0; + size_t lastLLSize; ZSTD_Sequence* outSeqs = &zc->seqCollector.seqStart[zc->seqCollector.seqIndex]; - size_t i; size_t position; int repIdx; + size_t i; + repcodes_t updatedRepcodes; assert(zc->seqCollector.seqIndex + 1 < zc->seqCollector.maxSequences); - for (i = 0, position = 0; i < seqsSize; ++i) { - outSeqs[i].offset = seqs[i].offset; - outSeqs[i].litLength = seqs[i].litLength; - outSeqs[i].matchLength = seqs[i].matchLength + MINMATCH; + /* Ensure we have enough space for last literals "sequence" */ + assert(zc->seqCollector.maxSequences >= seqStoreSeqSize + 1); + ZSTD_memcpy(updatedRepcodes.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t)); + for (i = 0; i < seqStoreSeqSize; ++i) { + U32 rawOffset = seqStoreSeqs[i].offset - ZSTD_REP_NUM; + outSeqs[i].litLength = seqStoreSeqs[i].litLength; + outSeqs[i].matchLength = seqStoreSeqs[i].matchLength + MINMATCH; + outSeqs[i].rep = 0; if (i == seqStore->longLengthPos) { if (seqStore->longLengthID == 1) { @@ -2334,39 +2547,44 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc) } } - if (outSeqs[i].offset <= ZSTD_REP_NUM) { - outSeqs[i].rep = outSeqs[i].offset; - repIdx = (unsigned int)i - outSeqs[i].offset; - - if (outSeqs[i].litLength == 0) { - if (outSeqs[i].offset < 3) { - --repIdx; + if (seqStoreSeqs[i].offset <= ZSTD_REP_NUM) { + /* Derive the correct offset corresponding to a repcode */ + outSeqs[i].rep = seqStoreSeqs[i].offset; + if (outSeqs[i].litLength != 0) { + rawOffset = updatedRepcodes.rep[outSeqs[i].rep - 1]; + } else { + if (outSeqs[i].rep == 3) { + rawOffset = updatedRepcodes.rep[0] - 1; } else { - repIdx = (unsigned int)i - 1; + rawOffset = updatedRepcodes.rep[outSeqs[i].rep]; } - ++outSeqs[i].rep; - } - assert(repIdx >= -3); - outSeqs[i].offset = repIdx >= 0 ? outSeqs[repIdx].offset : repStartValue[-repIdx - 1]; - if (outSeqs[i].rep == 4) { - --outSeqs[i].offset; } - } else { - outSeqs[i].offset -= ZSTD_REP_NUM; } - - position += outSeqs[i].litLength; - outSeqs[i].matchPos = (unsigned int)position; - position += outSeqs[i].matchLength; + outSeqs[i].offset = rawOffset; + /* seqStoreSeqs[i].offset == offCode+1, and ZSTD_updateRep() expects offCode + so we provide seqStoreSeqs[i].offset - 1 */ + updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, + seqStoreSeqs[i].offset - 1, + seqStoreSeqs[i].litLength == 0); + literalsRead += outSeqs[i].litLength; } - zc->seqCollector.seqIndex += seqsSize; + /* Insert last literals (if any exist) in the block as a sequence with ml == off == 0. + * If there are no last literals, then we'll emit (of: 0, ml: 0, ll: 0), which is a marker + * for the block boundary, according to the API. + */ + assert(seqStoreLiteralsSize >= literalsRead); + lastLLSize = seqStoreLiteralsSize - literalsRead; + outSeqs[i].litLength = (U32)lastLLSize; + outSeqs[i].matchLength = outSeqs[i].offset = outSeqs[i].rep = 0; + seqStoreSeqSize++; + zc->seqCollector.seqIndex += seqStoreSeqSize; } -size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, - size_t outSeqsSize, const void* src, size_t srcSize) +size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, + size_t outSeqsSize, const void* src, size_t srcSize) { const size_t dstCapacity = ZSTD_compressBound(srcSize); - void* dst = ZSTD_malloc(dstCapacity, ZSTD_defaultCMem); + void* dst = ZSTD_customMalloc(dstCapacity, ZSTD_defaultCMem); SeqCollector seqCollector; RETURN_ERROR_IF(dst == NULL, memory_allocation, "NULL pointer!"); @@ -2378,16 +2596,47 @@ size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, zc->seqCollector = seqCollector; ZSTD_compress2(zc, dst, dstCapacity, src, srcSize); - ZSTD_free(dst, ZSTD_defaultCMem); + ZSTD_customFree(dst, ZSTD_defaultCMem); return zc->seqCollector.seqIndex; } -/* Returns true if the given block is a RLE block */ -static int ZSTD_isRLE(const BYTE *ip, size_t length) { +size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize) { + size_t in = 0; + size_t out = 0; + for (; in < seqsSize; ++in) { + if (sequences[in].offset == 0 && sequences[in].matchLength == 0) { + if (in != seqsSize - 1) { + sequences[in+1].litLength += sequences[in].litLength; + } + } else { + sequences[out] = sequences[in]; + ++out; + } + } + return out; +} + +/* Unrolled loop to read four size_ts of input at a time. Returns 1 if is RLE, 0 if not. */ +static int ZSTD_isRLE(const BYTE* src, size_t length) { + const BYTE* ip = src; + const BYTE value = ip[0]; + const size_t valueST = (size_t)((U64)value * 0x0101010101010101ULL); + const size_t unrollSize = sizeof(size_t) * 4; + const size_t unrollMask = unrollSize - 1; + const size_t prefixLength = length & unrollMask; size_t i; - if (length < 2) return 1; - for (i = 1; i < length; ++i) { - if (ip[0] != ip[i]) return 0; + size_t u; + if (length == 1) return 1; + /* Check if prefix is RLE first before using unrolled loop */ + if (prefixLength && ZSTD_count(ip+1, ip, ip+prefixLength) != prefixLength-1) { + return 0; + } + for (i = prefixLength; i != length; i += unrollSize) { + for (u = 0; u < unrollSize; u += sizeof(size_t)) { + if (MEM_readST(ip + i + u) != valueST) { + return 0; + } + } } return 1; } @@ -2434,18 +2683,25 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc, if (zc->seqCollector.collectSequences) { ZSTD_copyBlockSequences(zc); + ZSTD_confirmRepcodesAndEntropyTables(zc); return 0; } /* encode sequences and literals */ - cSize = ZSTD_compressSequences(&zc->seqStore, + cSize = ZSTD_entropyCompressSequences(&zc->seqStore, &zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy, &zc->appliedParams, dst, dstCapacity, srcSize, - zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, zc->bmi2); + if (zc->seqCollector.collectSequences) { + ZSTD_copyBlockSequences(zc); + return 0; + } + + if (frame && /* We don't want to emit our first block as a RLE even if it qualifies because * doing so will cause the decoder (cli only) to throw a "should consume all input error." @@ -2593,7 +2849,7 @@ static size_t ZSTD_compress_frameChunk (ZSTD_CCtx* cctx, assert(cctx->appliedParams.cParams.windowLog <= ZSTD_WINDOWLOG_MAX); - DEBUGLOG(5, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); + DEBUGLOG(4, "ZSTD_compress_frameChunk (blockSize=%u)", (unsigned)blockSize); if (cctx->appliedParams.fParams.checksumFlag && srcSize) XXH64_update(&cctx->xxhState, src, srcSize); @@ -2673,7 +2929,6 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity, "dst buf is too small to fit worst-case frame header size."); DEBUGLOG(4, "ZSTD_writeFrameHeader : dictIDFlag : %u ; dictID : %u ; dictIDSizeCode : %u", !params->fParams.noDictIDFlag, (unsigned)dictID, (unsigned)dictIDSizeCode); - if (params->format == ZSTD_f_zstd1) { MEM_writeLE32(dst, ZSTD_MAGICNUMBER); pos = 4; @@ -2725,6 +2980,7 @@ size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSe cctx->externSeqStore.size = nbSeq; cctx->externSeqStore.capacity = nbSeq; cctx->externSeqStore.pos = 0; + cctx->externSeqStore.posInSequence = 0; return 0; } @@ -2862,8 +3118,12 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, case ZSTD_greedy: case ZSTD_lazy: case ZSTD_lazy2: - if (chunk >= HASH_READ_SIZE) + if (chunk >= HASH_READ_SIZE && ms->dedicatedDictSearch) { + assert(chunk == remaining); /* must load everything in one go */ + ZSTD_dedicatedDictSearch_lazy_loadDictionary(ms, ichunk-HASH_READ_SIZE); + } else if (chunk >= HASH_READ_SIZE) { ZSTD_insertAndFindFirstIndex(ms, ichunk-HASH_READ_SIZE); + } break; case ZSTD_btlazy2: /* we want the dictionary table fully sorted */ @@ -2887,22 +3147,28 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms, /* Dictionaries that assign zero probability to symbols that show up causes problems - when FSE encoding. Refuse dictionaries that assign zero probability to symbols - that we may encounter during compression. - NOTE: This behavior is not standard and could be improved in the future. */ -static size_t ZSTD_checkDictNCount(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) { + * when FSE encoding. Mark dictionaries with zero probability symbols as FSE_repeat_check + * and only dictionaries with 100% valid symbols can be assumed valid. + */ +static FSE_repeat ZSTD_dictNCountRepeat(short* normalizedCounter, unsigned dictMaxSymbolValue, unsigned maxSymbolValue) +{ U32 s; - RETURN_ERROR_IF(dictMaxSymbolValue < maxSymbolValue, dictionary_corrupted, "dict fse tables don't have all symbols"); + if (dictMaxSymbolValue < maxSymbolValue) { + return FSE_repeat_check; + } for (s = 0; s <= maxSymbolValue; ++s) { - RETURN_ERROR_IF(normalizedCounter[s] == 0, dictionary_corrupted, "dict fse tables don't have all symbols"); + if (normalizedCounter[s] == 0) { + return FSE_repeat_check; + } } - return 0; + return FSE_repeat_valid; } size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, - short* offcodeNCount, unsigned* offcodeMaxValue, const void* const dict, size_t dictSize) { + short offcodeNCount[MaxOff+1]; + unsigned offcodeMaxValue = MaxOff; const BYTE* dictPtr = (const BYTE*)dict; /* skip magic num and dict ID */ const BYTE* const dictEnd = dictPtr + dictSize; dictPtr += 8; @@ -2924,16 +3190,16 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, } { unsigned offcodeLog; - size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); + size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, ""); - /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ /* fill all offset symbols to avoid garbage at end of table */ RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( bs->entropy.fse.offcodeCTable, offcodeNCount, MaxOff, offcodeLog, workspace, HUF_WORKSPACE_SIZE)), dictionary_corrupted, ""); + /* Defer checking offcodeMaxValue because we need to know the size of the dictionary content */ dictPtr += offcodeHeaderSize; } @@ -2942,13 +3208,12 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, ""); - /* Every match length code must have non-zero probability */ - FORWARD_IF_ERROR( ZSTD_checkDictNCount(matchlengthNCount, matchlengthMaxValue, MaxML), ""); RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( bs->entropy.fse.matchlengthCTable, matchlengthNCount, matchlengthMaxValue, matchlengthLog, workspace, HUF_WORKSPACE_SIZE)), dictionary_corrupted, ""); + bs->entropy.fse.matchlength_repeatMode = ZSTD_dictNCountRepeat(matchlengthNCount, matchlengthMaxValue, MaxML); dictPtr += matchlengthHeaderSize; } @@ -2957,13 +3222,12 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, ""); - /* Every literal length code must have non-zero probability */ - FORWARD_IF_ERROR( ZSTD_checkDictNCount(litlengthNCount, litlengthMaxValue, MaxLL), ""); RETURN_ERROR_IF(FSE_isError(FSE_buildCTable_wksp( bs->entropy.fse.litlengthCTable, litlengthNCount, litlengthMaxValue, litlengthLog, workspace, HUF_WORKSPACE_SIZE)), dictionary_corrupted, ""); + bs->entropy.fse.litlength_repeatMode = ZSTD_dictNCountRepeat(litlengthNCount, litlengthMaxValue, MaxLL); dictPtr += litlengthHeaderSize; } @@ -2973,12 +3237,28 @@ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, bs->rep[2] = MEM_readLE32(dictPtr+8); dictPtr += 12; + { size_t const dictContentSize = (size_t)(dictEnd - dictPtr); + U32 offcodeMax = MaxOff; + if (dictContentSize <= ((U32)-1) - 128 KB) { + U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */ + offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */ + } + /* All offset values <= dictContentSize + 128 KB must be representable for a valid table */ + bs->entropy.fse.offcode_repeatMode = ZSTD_dictNCountRepeat(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)); + + /* All repCodes must be <= dictContentSize and != 0 */ + { U32 u; + for (u=0; u<3; u++) { + RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, ""); + RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, ""); + } } } + return dictPtr - (const BYTE*)dict; } /* Dictionary format : * See : - * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#dictionary-format + * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#dictionary-format */ /*! ZSTD_loadZstdDictionary() : * @return : dictID, or an error code @@ -2995,8 +3275,6 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, { const BYTE* dictPtr = (const BYTE*)dict; const BYTE* const dictEnd = dictPtr + dictSize; - short offcodeNCount[MaxOff+1]; - unsigned offcodeMaxValue = MaxOff; size_t dictID; size_t eSize; @@ -3005,32 +3283,16 @@ static size_t ZSTD_loadZstdDictionary(ZSTD_compressedBlockState_t* bs, assert(MEM_readLE32(dictPtr) == ZSTD_MAGIC_DICTIONARY); dictID = params->fParams.noDictIDFlag ? 0 : MEM_readLE32(dictPtr + 4 /* skip magic number */ ); - eSize = ZSTD_loadCEntropy(bs, workspace, offcodeNCount, &offcodeMaxValue, dict, dictSize); + eSize = ZSTD_loadCEntropy(bs, workspace, dict, dictSize); FORWARD_IF_ERROR(eSize, "ZSTD_loadCEntropy failed"); dictPtr += eSize; - { size_t const dictContentSize = (size_t)(dictEnd - dictPtr); - U32 offcodeMax = MaxOff; - if (dictContentSize <= ((U32)-1) - 128 KB) { - U32 const maxOffset = (U32)dictContentSize + 128 KB; /* The maximum offset that must be supported */ - offcodeMax = ZSTD_highbit32(maxOffset); /* Calculate minimum offset code required to represent maxOffset */ - } - /* All offset values <= dictContentSize + 128 KB must be representable */ - FORWARD_IF_ERROR(ZSTD_checkDictNCount(offcodeNCount, offcodeMaxValue, MIN(offcodeMax, MaxOff)), ""); - /* All repCodes must be <= dictContentSize and != 0*/ - { U32 u; - for (u=0; u<3; u++) { - RETURN_ERROR_IF(bs->rep[u] == 0, dictionary_corrupted, ""); - RETURN_ERROR_IF(bs->rep[u] > dictContentSize, dictionary_corrupted, ""); - } } - - bs->entropy.fse.offcode_repeatMode = FSE_repeat_valid; - bs->entropy.fse.matchlength_repeatMode = FSE_repeat_valid; - bs->entropy.fse.litlength_repeatMode = FSE_repeat_valid; + { + size_t const dictContentSize = (size_t)(dictEnd - dictPtr); FORWARD_IF_ERROR(ZSTD_loadDictionaryContent( ms, NULL, ws, params, dictPtr, dictContentSize, dtlm), ""); - return dictID; } + return dictID; } /** ZSTD_compress_insertDictionary() : @@ -3074,7 +3336,7 @@ ZSTD_compress_insertDictionary(ZSTD_compressedBlockState_t* bs, } #define ZSTD_USE_CDICT_PARAMS_SRCSIZE_CUTOFF (128 KB) -#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6) +#define ZSTD_USE_CDICT_PARAMS_DICTSIZE_MULTIPLIER (6ULL) /*! ZSTD_compressBegin_internal() : * @return : 0, or an error code */ @@ -3106,7 +3368,7 @@ static size_t ZSTD_compressBegin_internal(ZSTD_CCtx* cctx, ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, &cctx->ldmState, &cctx->workspace, &cctx->appliedParams, cdict->dictContent, - cdict->dictContentSize, dictContentType, dtlm, + cdict->dictContentSize, cdict->dictContentType, dtlm, cctx->entropyWorkspace) : ZSTD_compress_insertDictionary( cctx->blockState.prevCBlock, &cctx->blockState.matchState, @@ -3153,7 +3415,7 @@ size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); + ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_noAttachDict); ZSTD_CCtx_params const cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); DEBUGLOG(4, "ZSTD_compressBegin_usingDict (dictSize=%u)", (unsigned)dictSize); @@ -3234,7 +3496,6 @@ size_t ZSTD_compressEnd (ZSTD_CCtx* cctx, return cSize + endResult; } - static size_t ZSTD_compress_internal (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, @@ -3287,7 +3548,7 @@ size_t ZSTD_compress_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0); + ZSTD_parameters const params = ZSTD_getParams_internal(compressionLevel, srcSize, dict ? dictSize : 0, ZSTD_cpm_noAttachDict); ZSTD_CCtx_params cctxParams = ZSTD_assignParamsToCCtxParams(&cctx->requestedParams, ¶ms); DEBUGLOG(4, "ZSTD_compress_usingDict (srcSize=%u)", (unsigned)srcSize); assert(params.fParams.contentSizeFlag == 1); @@ -3309,10 +3570,17 @@ size_t ZSTD_compress(void* dst, size_t dstCapacity, int compressionLevel) { size_t result; +#if ZSTD_COMPRESS_HEAPMODE + ZSTD_CCtx* cctx = ZSTD_createCCtx(); + RETURN_ERROR_IF(!cctx, memory_allocation, "ZSTD_createCCtx failed"); + result = ZSTD_compressCCtx(cctx, dst, dstCapacity, src, srcSize, compressionLevel); + ZSTD_freeCCtx(cctx); +#else ZSTD_CCtx ctxBody; ZSTD_initCCtx(&ctxBody, ZSTD_defaultCMem); result = ZSTD_compressCCtx(&ctxBody, dst, dstCapacity, src, srcSize, compressionLevel); ZSTD_freeCCtxContent(&ctxBody); /* can't free ctxBody itself, as it's on stack; free only heap content */ +#endif return result; } @@ -3335,7 +3603,7 @@ size_t ZSTD_estimateCDictSize_advanced( size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); return ZSTD_estimateCDictSize_advanced(dictSize, cParams, ZSTD_dlm_byCopy); } @@ -3353,20 +3621,25 @@ static size_t ZSTD_initCDict_internal( const void* dictBuffer, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, - ZSTD_compressionParameters cParams) + ZSTD_CCtx_params params) { DEBUGLOG(3, "ZSTD_initCDict_internal (dictContentType:%u)", (unsigned)dictContentType); - assert(!ZSTD_checkCParams(cParams)); - cdict->matchState.cParams = cParams; + assert(!ZSTD_checkCParams(params.cParams)); + cdict->matchState.cParams = params.cParams; + cdict->matchState.dedicatedDictSearch = params.enableDedicatedDictSearch; + if (cdict->matchState.dedicatedDictSearch && dictSize > ZSTD_CHUNKSIZE_MAX) { + cdict->matchState.dedicatedDictSearch = 0; + } if ((dictLoadMethod == ZSTD_dlm_byRef) || (!dictBuffer) || (!dictSize)) { cdict->dictContent = dictBuffer; } else { void *internalBuffer = ZSTD_cwksp_reserve_object(&cdict->workspace, ZSTD_cwksp_align(dictSize, sizeof(void*))); RETURN_ERROR_IF(!internalBuffer, memory_allocation, "NULL pointer!"); cdict->dictContent = internalBuffer; - memcpy(internalBuffer, dictBuffer, dictSize); + ZSTD_memcpy(internalBuffer, dictBuffer, dictSize); } cdict->dictContentSize = dictSize; + cdict->dictContentType = dictContentType; cdict->entropyWorkspace = (U32*)ZSTD_cwksp_reserve_object(&cdict->workspace, HUF_WORKSPACE_SIZE); @@ -3376,18 +3649,15 @@ static size_t ZSTD_initCDict_internal( FORWARD_IF_ERROR(ZSTD_reset_matchState( &cdict->matchState, &cdict->workspace, - &cParams, + ¶ms.cParams, ZSTDcrp_makeClean, ZSTDirp_reset, ZSTD_resetTarget_CDict), ""); /* (Maybe) load the dictionary * Skips loading the dictionary if it is < 8 bytes. */ - { ZSTD_CCtx_params params; - memset(¶ms, 0, sizeof(params)); - params.compressionLevel = ZSTD_CLEVEL_DEFAULT; + { params.compressionLevel = ZSTD_CLEVEL_DEFAULT; params.fParams.contentSizeFlag = 1; - params.cParams = cParams; { size_t const dictID = ZSTD_compress_insertDictionary( &cdict->cBlockState, &cdict->matchState, NULL, &cdict->workspace, ¶ms, cdict->dictContent, cdict->dictContentSize, @@ -3401,13 +3671,11 @@ static size_t ZSTD_initCDict_internal( return 0; } -ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, +static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, - ZSTD_dictContentType_e dictContentType, ZSTD_compressionParameters cParams, ZSTD_customMem customMem) { - DEBUGLOG(3, "ZSTD_createCDict_advanced, mode %u", (unsigned)dictContentType); - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; { size_t const workspaceSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict)) + @@ -3415,16 +3683,16 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, ZSTD_sizeof_matchState(&cParams, /* forCCtx */ 0) + (dictLoadMethod == ZSTD_dlm_byRef ? 0 : ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void*)))); - void* const workspace = ZSTD_malloc(workspaceSize, customMem); + void* const workspace = ZSTD_customMalloc(workspaceSize, customMem); ZSTD_cwksp ws; ZSTD_CDict* cdict; if (!workspace) { - ZSTD_free(workspace, customMem); + ZSTD_customFree(workspace, customMem); return NULL; } - ZSTD_cwksp_init(&ws, workspace, workspaceSize); + ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_dynamic_alloc); cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict)); assert(cdict != NULL); @@ -3432,35 +3700,94 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, cdict->customMem = customMem; cdict->compressionLevel = 0; /* signals advanced API usage */ - if (ZSTD_isError( ZSTD_initCDict_internal(cdict, - dictBuffer, dictSize, - dictLoadMethod, dictContentType, - cParams) )) { - ZSTD_freeCDict(cdict); - return NULL; - } - return cdict; } } +ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + ZSTD_compressionParameters cParams, + ZSTD_customMem customMem) +{ + ZSTD_CCtx_params cctxParams; + ZSTD_memset(&cctxParams, 0, sizeof(cctxParams)); + ZSTD_CCtxParams_init(&cctxParams, 0); + cctxParams.cParams = cParams; + cctxParams.customMem = customMem; + return ZSTD_createCDict_advanced2( + dictBuffer, dictSize, + dictLoadMethod, dictContentType, + &cctxParams, customMem); +} + +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2( + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + const ZSTD_CCtx_params* originalCctxParams, + ZSTD_customMem customMem) +{ + ZSTD_CCtx_params cctxParams = *originalCctxParams; + ZSTD_compressionParameters cParams; + ZSTD_CDict* cdict; + + DEBUGLOG(3, "ZSTD_createCDict_advanced2, mode %u", (unsigned)dictContentType); + if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + + if (cctxParams.enableDedicatedDictSearch) { + cParams = ZSTD_dedicatedDictSearch_getCParams( + cctxParams.compressionLevel, dictSize); + ZSTD_overrideCParams(&cParams, &cctxParams.cParams); + } else { + cParams = ZSTD_getCParamsFromCCtxParams( + &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + } + + if (!ZSTD_dedicatedDictSearch_isSupported(&cParams)) { + /* Fall back to non-DDSS params */ + cctxParams.enableDedicatedDictSearch = 0; + cParams = ZSTD_getCParamsFromCCtxParams( + &cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + } + + cctxParams.cParams = cParams; + + cdict = ZSTD_createCDict_advanced_internal(dictSize, + dictLoadMethod, cctxParams.cParams, + customMem); + + if (ZSTD_isError( ZSTD_initCDict_internal(cdict, + dict, dictSize, + dictLoadMethod, dictContentType, + cctxParams) )) { + ZSTD_freeCDict(cdict); + return NULL; + } + + return cdict; +} + ZSTD_CDict* ZSTD_createCDict(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); - ZSTD_CDict* cdict = ZSTD_createCDict_advanced(dict, dictSize, + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); if (cdict) - cdict->compressionLevel = compressionLevel == 0 ? ZSTD_CLEVEL_DEFAULT : compressionLevel; + cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; return cdict; } ZSTD_CDict* ZSTD_createCDict_byReference(const void* dict, size_t dictSize, int compressionLevel) { - ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize); - return ZSTD_createCDict_advanced(dict, dictSize, + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, dictSize, ZSTD_cpm_createCDict); + ZSTD_CDict* const cdict = ZSTD_createCDict_advanced(dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto, cParams, ZSTD_defaultCMem); + if (cdict) + cdict->compressionLevel = (compressionLevel == 0) ? ZSTD_CLEVEL_DEFAULT : compressionLevel; + return cdict; } size_t ZSTD_freeCDict(ZSTD_CDict* cdict) @@ -3470,7 +3797,7 @@ size_t ZSTD_freeCDict(ZSTD_CDict* cdict) int cdictInWorkspace = ZSTD_cwksp_owns_buffer(&cdict->workspace, cdict); ZSTD_cwksp_free(&cdict->workspace, cMem); if (!cdictInWorkspace) { - ZSTD_free(cdict, cMem); + ZSTD_customFree(cdict, cMem); } return 0; } @@ -3503,12 +3830,13 @@ const ZSTD_CDict* ZSTD_initStaticCDict( + ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE) + matchStateSize; ZSTD_CDict* cdict; + ZSTD_CCtx_params params; if ((size_t)workspace & 7) return NULL; /* 8-aligned */ { ZSTD_cwksp ws; - ZSTD_cwksp_init(&ws, workspace, workspaceSize); + ZSTD_cwksp_init(&ws, workspace, workspaceSize, ZSTD_cwksp_static_alloc); cdict = (ZSTD_CDict*)ZSTD_cwksp_reserve_object(&ws, sizeof(ZSTD_CDict)); if (cdict == NULL) return NULL; ZSTD_cwksp_move(&cdict->workspace, &ws); @@ -3518,10 +3846,13 @@ const ZSTD_CDict* ZSTD_initStaticCDict( (unsigned)workspaceSize, (unsigned)neededSize, (unsigned)(workspaceSize < neededSize)); if (workspaceSize < neededSize) return NULL; + ZSTD_CCtxParams_init(¶ms, 0); + params.cParams = cParams; + if (ZSTD_isError( ZSTD_initCDict_internal(cdict, dict, dictSize, dictLoadMethod, dictContentType, - cParams) )) + params) )) return NULL; return cdict; @@ -3533,6 +3864,17 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCDict(const ZSTD_CDict* cdict) return cdict->matchState.cParams; } +/*! ZSTD_getDictID_fromCDict() : + * Provides the dictID of the dictionary loaded into `cdict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict) +{ + if (cdict==NULL) return 0; + return cdict->dictID; +} + + /* ZSTD_compressBegin_usingCDict_advanced() : * cdict must be != NULL */ size_t ZSTD_compressBegin_usingCDict_advanced( @@ -3640,32 +3982,12 @@ size_t ZSTD_CStreamOutSize(void) return ZSTD_compressBound(ZSTD_BLOCKSIZE_MAX) + ZSTD_blockHeaderSize + 4 /* 32-bits hash */ ; } -static size_t ZSTD_resetCStream_internal(ZSTD_CStream* cctx, - const void* const dict, size_t const dictSize, ZSTD_dictContentType_e const dictContentType, - const ZSTD_CDict* const cdict, - ZSTD_CCtx_params params, unsigned long long const pledgedSrcSize) +static ZSTD_cParamMode_e ZSTD_getCParamMode(ZSTD_CDict const* cdict, ZSTD_CCtx_params const* params, U64 pledgedSrcSize) { - DEBUGLOG(4, "ZSTD_resetCStream_internal"); - /* Finalize the compression parameters */ - params.cParams = ZSTD_getCParamsFromCCtxParams(¶ms, pledgedSrcSize, dictSize); - /* params are supposed to be fully validated at this point */ - assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); - assert(!((dict) && (cdict))); /* either dict or cdict, not both */ - - FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx, - dict, dictSize, dictContentType, ZSTD_dtlm_fast, - cdict, - ¶ms, pledgedSrcSize, - ZSTDb_buffered) , ""); - - cctx->inToCompress = 0; - cctx->inBuffPos = 0; - cctx->inBuffTarget = cctx->blockSize - + (cctx->blockSize == pledgedSrcSize); /* for small input: avoid automatic flush on reaching end of block, since it would require to add a 3-bytes null block to end frame */ - cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0; - cctx->streamStage = zcss_load; - cctx->frameEnded = 0; - return 0; /* ready to go */ + if (cdict != NULL && ZSTD_shouldAttachDict(cdict, params, pledgedSrcSize)) + return ZSTD_cpm_attachDict; + else + return ZSTD_cpm_noAttachDict; } /* ZSTD_resetCStream(): @@ -3815,12 +4137,17 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, /* check expectations */ DEBUGLOG(5, "ZSTD_compressStream_generic, flush=%u", (unsigned)flushMode); - assert(zcs->inBuff != NULL); - assert(zcs->inBuffSize > 0); - assert(zcs->outBuff != NULL); - assert(zcs->outBuffSize > 0); + if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) { + assert(zcs->inBuff != NULL); + assert(zcs->inBuffSize > 0); + } + if (zcs->appliedParams.outBufferMode == ZSTD_bm_buffered) { + assert(zcs->outBuff != NULL); + assert(zcs->outBuffSize > 0); + } assert(output->pos <= output->size); assert(input->pos <= input->size); + assert((U32)flushMode <= (U32)ZSTD_e_end); while (someMoreWork) { switch(zcs->streamStage) @@ -3830,7 +4157,8 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, case zcss_load: if ( (flushMode == ZSTD_e_end) - && ((size_t)(oend-op) >= ZSTD_compressBound(iend-ip)) /* enough dstCapacity */ + && ( (size_t)(oend-op) >= ZSTD_compressBound(iend-ip) /* Enough output space */ + || zcs->appliedParams.outBufferMode == ZSTD_bm_stable) /* OR we are allowed to return dstSizeTooSmall */ && (zcs->inBuffPos == 0) ) { /* shortcut to compression pass directly into output buffer */ size_t const cSize = ZSTD_compressEnd(zcs, @@ -3843,8 +4171,9 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); someMoreWork = 0; break; } - /* complete loading into inBuffer */ - { size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos; + /* complete loading into inBuffer in buffered mode */ + if (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered) { + size_t const toLoad = zcs->inBuffTarget - zcs->inBuffPos; size_t const loaded = ZSTD_limitCopy( zcs->inBuff + zcs->inBuffPos, toLoad, ip, iend-ip); @@ -3864,31 +4193,49 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, } /* compress current block (note : this stage cannot be stopped in the middle) */ DEBUGLOG(5, "stream compression stage (flushMode==%u)", flushMode); - { void* cDst; + { int const inputBuffered = (zcs->appliedParams.inBufferMode == ZSTD_bm_buffered); + void* cDst; size_t cSize; - size_t const iSize = zcs->inBuffPos - zcs->inToCompress; size_t oSize = oend-op; - unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend); - if (oSize >= ZSTD_compressBound(iSize)) + size_t const iSize = inputBuffered + ? zcs->inBuffPos - zcs->inToCompress + : MIN((size_t)(iend - ip), zcs->blockSize); + if (oSize >= ZSTD_compressBound(iSize) || zcs->appliedParams.outBufferMode == ZSTD_bm_stable) cDst = op; /* compress into output buffer, to skip flush stage */ else cDst = zcs->outBuff, oSize = zcs->outBuffSize; - cSize = lastBlock ? - ZSTD_compressEnd(zcs, cDst, oSize, - zcs->inBuff + zcs->inToCompress, iSize) : - ZSTD_compressContinue(zcs, cDst, oSize, - zcs->inBuff + zcs->inToCompress, iSize); - FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); - zcs->frameEnded = lastBlock; - /* prepare next block */ - zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; - if (zcs->inBuffTarget > zcs->inBuffSize) - zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; - DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u", - (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize); - if (!lastBlock) - assert(zcs->inBuffTarget <= zcs->inBuffSize); - zcs->inToCompress = zcs->inBuffPos; + if (inputBuffered) { + unsigned const lastBlock = (flushMode == ZSTD_e_end) && (ip==iend); + cSize = lastBlock ? + ZSTD_compressEnd(zcs, cDst, oSize, + zcs->inBuff + zcs->inToCompress, iSize) : + ZSTD_compressContinue(zcs, cDst, oSize, + zcs->inBuff + zcs->inToCompress, iSize); + FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); + zcs->frameEnded = lastBlock; + /* prepare next block */ + zcs->inBuffTarget = zcs->inBuffPos + zcs->blockSize; + if (zcs->inBuffTarget > zcs->inBuffSize) + zcs->inBuffPos = 0, zcs->inBuffTarget = zcs->blockSize; + DEBUGLOG(5, "inBuffTarget:%u / inBuffSize:%u", + (unsigned)zcs->inBuffTarget, (unsigned)zcs->inBuffSize); + if (!lastBlock) + assert(zcs->inBuffTarget <= zcs->inBuffSize); + zcs->inToCompress = zcs->inBuffPos; + } else { + unsigned const lastBlock = (ip + iSize == iend); + assert(flushMode == ZSTD_e_end /* Already validated */); + cSize = lastBlock ? + ZSTD_compressEnd(zcs, cDst, oSize, ip, iSize) : + ZSTD_compressContinue(zcs, cDst, oSize, ip, iSize); + /* Consume the input prior to error checking to mirror buffered mode. */ + if (iSize > 0) + ip += iSize; + FORWARD_IF_ERROR(cSize, "%s", lastBlock ? "ZSTD_compressEnd failed" : "ZSTD_compressContinue failed"); + zcs->frameEnded = lastBlock; + if (lastBlock) + assert(ip == iend); + } if (cDst == op) { /* no need to flush */ op += cSize; if (zcs->frameEnded) { @@ -3905,6 +4252,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs, /* fall-through */ case zcss_flush: DEBUGLOG(5, "flush stage"); + assert(zcs->appliedParams.outBufferMode == ZSTD_bm_buffered); { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; size_t const flushed = ZSTD_limitCopy(op, (size_t)(oend-op), zcs->outBuff + zcs->outBuffFlushedSize, toFlush); @@ -3959,6 +4307,116 @@ size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuf return ZSTD_nextInputSizeHint_MTorST(zcs); } +/* After a compression call set the expected input/output buffer. + * This is validated at the start of the next compression call. + */ +static void ZSTD_setBufferExpectations(ZSTD_CCtx* cctx, ZSTD_outBuffer const* output, ZSTD_inBuffer const* input) +{ + if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) { + cctx->expectedInBuffer = *input; + } + if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) { + cctx->expectedOutBufferSize = output->size - output->pos; + } +} + +/* Validate that the input/output buffers match the expectations set by + * ZSTD_setBufferExpectations. + */ +static size_t ZSTD_checkBufferStability(ZSTD_CCtx const* cctx, + ZSTD_outBuffer const* output, + ZSTD_inBuffer const* input, + ZSTD_EndDirective endOp) +{ + if (cctx->appliedParams.inBufferMode == ZSTD_bm_stable) { + ZSTD_inBuffer const expect = cctx->expectedInBuffer; + if (expect.src != input->src || expect.pos != input->pos || expect.size != input->size) + RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer enabled but input differs!"); + if (endOp != ZSTD_e_end) + RETURN_ERROR(srcBuffer_wrong, "ZSTD_c_stableInBuffer can only be used with ZSTD_e_end!"); + } + if (cctx->appliedParams.outBufferMode == ZSTD_bm_stable) { + size_t const outBufferSize = output->size - output->pos; + if (cctx->expectedOutBufferSize != outBufferSize) + RETURN_ERROR(dstBuffer_wrong, "ZSTD_c_stableOutBuffer enabled but output size differs!"); + } + return 0; +} + +static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx, + ZSTD_EndDirective endOp, + size_t inSize) { + ZSTD_CCtx_params params = cctx->requestedParams; + ZSTD_prefixDict const prefixDict = cctx->prefixDict; + FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */ + ZSTD_memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */ + assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */ + if (cctx->cdict) + params.compressionLevel = cctx->cdict->compressionLevel; /* let cdict take priority in terms of compression level */ + DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage"); + if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = inSize + 1; /* auto-fix pledgedSrcSize */ + { + size_t const dictSize = prefixDict.dict + ? prefixDict.dictSize + : (cctx->cdict ? cctx->cdict->dictContentSize : 0); + ZSTD_cParamMode_e const mode = ZSTD_getCParamMode(cctx->cdict, ¶ms, cctx->pledgedSrcSizePlusOne - 1); + params.cParams = ZSTD_getCParamsFromCCtxParams( + ¶ms, cctx->pledgedSrcSizePlusOne-1, + dictSize, mode); + } + + if (ZSTD_CParams_shouldEnableLdm(¶ms.cParams)) { + /* Enable LDM by default for optimal parser and window size >= 128MB */ + DEBUGLOG(4, "LDM enabled by default (window size >= 128MB, strategy >= btopt)"); + params.ldmParams.enableLdm = 1; + } + +#ifdef ZSTD_MULTITHREAD + if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) { + params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */ + } + if (params.nbWorkers > 0) { + /* mt context creation */ + if (cctx->mtctx == NULL) { + DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u", + params.nbWorkers); + cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem, cctx->pool); + RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!"); + } + /* mt compression */ + DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); + FORWARD_IF_ERROR( ZSTDMT_initCStream_internal( + cctx->mtctx, + prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, + cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , ""); + cctx->streamStage = zcss_load; + cctx->appliedParams = params; + } else +#endif + { U64 const pledgedSrcSize = cctx->pledgedSrcSizePlusOne - 1; + assert(!ZSTD_isError(ZSTD_checkCParams(params.cParams))); + FORWARD_IF_ERROR( ZSTD_compressBegin_internal(cctx, + prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, ZSTD_dtlm_fast, + cctx->cdict, + ¶ms, pledgedSrcSize, + ZSTDb_buffered) , ""); + assert(cctx->appliedParams.nbWorkers == 0); + cctx->inToCompress = 0; + cctx->inBuffPos = 0; + if (cctx->appliedParams.inBufferMode == ZSTD_bm_buffered) { + /* for small input: avoid automatic flush on reaching end of block, since + * it would require to add a 3-bytes null block to end frame + */ + cctx->inBuffTarget = cctx->blockSize + (cctx->blockSize == pledgedSrcSize); + } else { + cctx->inBuffTarget = 0; + } + cctx->outBuffContentSize = cctx->outBuffFlushedSize = 0; + cctx->streamStage = zcss_load; + cctx->frameEnded = 0; + } + return 0; +} size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, ZSTD_outBuffer* output, @@ -3967,82 +4425,65 @@ size_t ZSTD_compressStream2( ZSTD_CCtx* cctx, { DEBUGLOG(5, "ZSTD_compressStream2, endOp=%u ", (unsigned)endOp); /* check conditions */ - RETURN_ERROR_IF(output->pos > output->size, GENERIC, "invalid buffer"); - RETURN_ERROR_IF(input->pos > input->size, GENERIC, "invalid buffer"); - assert(cctx!=NULL); + RETURN_ERROR_IF(output->pos > output->size, dstSize_tooSmall, "invalid output buffer"); + RETURN_ERROR_IF(input->pos > input->size, srcSize_wrong, "invalid input buffer"); + RETURN_ERROR_IF((U32)endOp > (U32)ZSTD_e_end, parameter_outOfBound, "invalid endDirective"); + assert(cctx != NULL); /* transparent initialization stage */ if (cctx->streamStage == zcss_init) { - ZSTD_CCtx_params params = cctx->requestedParams; - ZSTD_prefixDict const prefixDict = cctx->prefixDict; - FORWARD_IF_ERROR( ZSTD_initLocalDict(cctx) , ""); /* Init the local dict if present. */ - memset(&cctx->prefixDict, 0, sizeof(cctx->prefixDict)); /* single usage */ - assert(prefixDict.dict==NULL || cctx->cdict==NULL); /* only one can be set */ - DEBUGLOG(4, "ZSTD_compressStream2 : transparent init stage"); - if (endOp == ZSTD_e_end) cctx->pledgedSrcSizePlusOne = input->size + 1; /* auto-fix pledgedSrcSize */ - params.cParams = ZSTD_getCParamsFromCCtxParams( - &cctx->requestedParams, cctx->pledgedSrcSizePlusOne-1, 0 /*dictSize*/); - - -#ifdef ZSTD_MULTITHREAD - if ((cctx->pledgedSrcSizePlusOne-1) <= ZSTDMT_JOBSIZE_MIN) { - params.nbWorkers = 0; /* do not invoke multi-threading when src size is too small */ - } - if (params.nbWorkers > 0) { - /* mt context creation */ - if (cctx->mtctx == NULL) { - DEBUGLOG(4, "ZSTD_compressStream2: creating new mtctx for nbWorkers=%u", - params.nbWorkers); - cctx->mtctx = ZSTDMT_createCCtx_advanced((U32)params.nbWorkers, cctx->customMem); - RETURN_ERROR_IF(cctx->mtctx == NULL, memory_allocation, "NULL pointer!"); - } - /* mt compression */ - DEBUGLOG(4, "call ZSTDMT_initCStream_internal as nbWorkers=%u", params.nbWorkers); - FORWARD_IF_ERROR( ZSTDMT_initCStream_internal( - cctx->mtctx, - prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, - cctx->cdict, params, cctx->pledgedSrcSizePlusOne-1) , ""); - cctx->streamStage = zcss_load; - cctx->appliedParams.nbWorkers = params.nbWorkers; - } else -#endif - { FORWARD_IF_ERROR( ZSTD_resetCStream_internal(cctx, - prefixDict.dict, prefixDict.dictSize, prefixDict.dictContentType, - cctx->cdict, - params, cctx->pledgedSrcSizePlusOne-1) , ""); - assert(cctx->streamStage == zcss_load); - assert(cctx->appliedParams.nbWorkers == 0); - } } + FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, endOp, input->size), "CompressStream2 initialization failed"); + ZSTD_setBufferExpectations(cctx, output, input); /* Set initial buffer expectations now that we've initialized */ + } /* end of transparent initialization stage */ + FORWARD_IF_ERROR(ZSTD_checkBufferStability(cctx, output, input, endOp), "invalid buffers"); /* compression stage */ #ifdef ZSTD_MULTITHREAD if (cctx->appliedParams.nbWorkers > 0) { - int const forceMaxProgress = (endOp == ZSTD_e_flush || endOp == ZSTD_e_end); size_t flushMin; - assert(forceMaxProgress || endOp == ZSTD_e_continue /* Protection for a new flush type */); if (cctx->cParamsChanged) { ZSTDMT_updateCParams_whileCompressing(cctx->mtctx, &cctx->requestedParams); cctx->cParamsChanged = 0; } - do { + for (;;) { + size_t const ipos = input->pos; + size_t const opos = output->pos; flushMin = ZSTDMT_compressStream_generic(cctx->mtctx, output, input, endOp); if ( ZSTD_isError(flushMin) || (endOp == ZSTD_e_end && flushMin == 0) ) { /* compression completed */ ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); } FORWARD_IF_ERROR(flushMin, "ZSTDMT_compressStream_generic failed"); - } while (forceMaxProgress && flushMin != 0 && output->pos < output->size); + + if (endOp == ZSTD_e_continue) { + /* We only require some progress with ZSTD_e_continue, not maximal progress. + * We're done if we've consumed or produced any bytes, or either buffer is + * full. + */ + if (input->pos != ipos || output->pos != opos || input->pos == input->size || output->pos == output->size) + break; + } else { + assert(endOp == ZSTD_e_flush || endOp == ZSTD_e_end); + /* We require maximal progress. We're done when the flush is complete or the + * output buffer is full. + */ + if (flushMin == 0 || output->pos == output->size) + break; + } + } DEBUGLOG(5, "completed ZSTD_compressStream2 delegating to ZSTDMT_compressStream_generic"); /* Either we don't require maximum forward progress, we've finished the * flush, or we are out of output space. */ - assert(!forceMaxProgress || flushMin == 0 || output->pos == output->size); + assert(endOp == ZSTD_e_continue || flushMin == 0 || output->pos == output->size); + ZSTD_setBufferExpectations(cctx, output, input); return flushMin; } #endif FORWARD_IF_ERROR( ZSTD_compressStream_generic(cctx, output, input, endOp) , ""); DEBUGLOG(5, "completed ZSTD_compressStream2"); + ZSTD_setBufferExpectations(cctx, output, input); return cctx->outBuffContentSize - cctx->outBuffFlushedSize; /* remaining to flush */ } @@ -4065,14 +4506,22 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize) { + ZSTD_bufferMode_e const originalInBufferMode = cctx->requestedParams.inBufferMode; + ZSTD_bufferMode_e const originalOutBufferMode = cctx->requestedParams.outBufferMode; DEBUGLOG(4, "ZSTD_compress2 (srcSize=%u)", (unsigned)srcSize); ZSTD_CCtx_reset(cctx, ZSTD_reset_session_only); + /* Enable stable input/output buffers. */ + cctx->requestedParams.inBufferMode = ZSTD_bm_stable; + cctx->requestedParams.outBufferMode = ZSTD_bm_stable; { size_t oPos = 0; size_t iPos = 0; size_t const result = ZSTD_compressStream2_simpleArgs(cctx, dst, dstCapacity, &oPos, src, srcSize, &iPos, ZSTD_e_end); + /* Reset to the original values. */ + cctx->requestedParams.inBufferMode = originalInBufferMode; + cctx->requestedParams.outBufferMode = originalOutBufferMode; FORWARD_IF_ERROR(result, "ZSTD_compressStream2_simpleArgs failed"); if (result != 0) { /* compression not completed, due to lack of output space */ assert(oPos == dstCapacity); @@ -4083,6 +4532,409 @@ size_t ZSTD_compress2(ZSTD_CCtx* cctx, } } +typedef struct { + U32 idx; /* Index in array of ZSTD_Sequence */ + U32 posInSequence; /* Position within sequence at idx */ + size_t posInSrc; /* Number of bytes given by sequences provided so far */ +} ZSTD_sequencePosition; + +/* Returns a ZSTD error code if sequence is not valid */ +static size_t ZSTD_validateSequence(U32 offCode, U32 matchLength, + size_t posInSrc, U32 windowLog, size_t dictSize, U32 minMatch) { + size_t offsetBound; + U32 windowSize = 1 << windowLog; + /* posInSrc represents the amount of data the the decoder would decode up to this point. + * As long as the amount of data decoded is less than or equal to window size, offsets may be + * larger than the total length of output decoded in order to reference the dict, even larger than + * window size. After output surpasses windowSize, we're limited to windowSize offsets again. + */ + offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize; + RETURN_ERROR_IF(offCode > offsetBound + ZSTD_REP_MOVE, corruption_detected, "Offset too large!"); + RETURN_ERROR_IF(matchLength < minMatch, corruption_detected, "Matchlength too small"); + return 0; +} + +/* Returns an offset code, given a sequence's raw offset, the ongoing repcode array, and whether litLength == 0 */ +static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0) { + U32 offCode = rawOffset + ZSTD_REP_MOVE; + U32 repCode = 0; + + if (!ll0 && rawOffset == rep[0]) { + repCode = 1; + } else if (rawOffset == rep[1]) { + repCode = 2 - ll0; + } else if (rawOffset == rep[2]) { + repCode = 3 - ll0; + } else if (ll0 && rawOffset == rep[0] - 1) { + repCode = 3; + } + if (repCode) { + /* ZSTD_storeSeq expects a number in the range [0, 2] to represent a repcode */ + offCode = repCode - 1; + } + return offCode; +} + +/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of + * ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter. + */ +static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize) { + U32 idx = seqPos->idx; + BYTE const* ip = (BYTE const*)(src); + const BYTE* const iend = ip + blockSize; + repcodes_t updatedRepcodes; + U32 dictSize; + U32 litLength; + U32 matchLength; + U32 ll0; + U32 offCode; + + if (cctx->cdict) { + dictSize = (U32)cctx->cdict->dictContentSize; + } else if (cctx->prefixDict.dict) { + dictSize = (U32)cctx->prefixDict.dictSize; + } else { + dictSize = 0; + } + ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t)); + for (; (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0) && idx < inSeqsSize; ++idx) { + litLength = inSeqs[idx].litLength; + matchLength = inSeqs[idx].matchLength; + ll0 = litLength == 0; + offCode = ZSTD_finalizeOffCode(inSeqs[idx].offset, updatedRepcodes.rep, ll0); + updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0); + + DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength); + if (cctx->appliedParams.validateSequences) { + seqPos->posInSrc += litLength + matchLength; + FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc, + cctx->appliedParams.cParams.windowLog, dictSize, + cctx->appliedParams.cParams.minMatch), + "Sequence validation failed"); + } + RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation, + "Not enough memory allocated. Try adjusting ZSTD_c_minMatch."); + ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH); + ip += matchLength + litLength; + } + ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t)); + + if (inSeqs[idx].litLength) { + DEBUGLOG(6, "Storing last literals of size: %u", inSeqs[idx].litLength); + ZSTD_storeLastLiterals(&cctx->seqStore, ip, inSeqs[idx].litLength); + ip += inSeqs[idx].litLength; + seqPos->posInSrc += inSeqs[idx].litLength; + } + RETURN_ERROR_IF(ip != iend, corruption_detected, "Blocksize doesn't agree with block delimiter!"); + seqPos->idx = idx+1; + return 0; +} + +/* Returns the number of bytes to move the current read position back by. Only non-zero + * if we ended up splitting a sequence. Otherwise, it may return a ZSTD error if something + * went wrong. + * + * This function will attempt to scan through blockSize bytes represented by the sequences + * in inSeqs, storing any (partial) sequences. + * + * Occasionally, we may want to change the actual number of bytes we consumed from inSeqs to + * avoid splitting a match, or to avoid splitting a match such that it would produce a match + * smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block. + */ +static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize) { + U32 idx = seqPos->idx; + U32 startPosInSequence = seqPos->posInSequence; + U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize; + size_t dictSize; + BYTE const* ip = (BYTE const*)(src); + BYTE const* iend = ip + blockSize; /* May be adjusted if we decide to process fewer than blockSize bytes */ + repcodes_t updatedRepcodes; + U32 bytesAdjustment = 0; + U32 finalMatchSplit = 0; + U32 litLength; + U32 matchLength; + U32 rawOffset; + U32 offCode; + + if (cctx->cdict) { + dictSize = cctx->cdict->dictContentSize; + } else if (cctx->prefixDict.dict) { + dictSize = cctx->prefixDict.dictSize; + } else { + dictSize = 0; + } + DEBUGLOG(5, "ZSTD_copySequencesToSeqStore: idx: %u PIS: %u blockSize: %zu", idx, startPosInSequence, blockSize); + DEBUGLOG(5, "Start seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength); + ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t)); + while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) { + const ZSTD_Sequence currSeq = inSeqs[idx]; + litLength = currSeq.litLength; + matchLength = currSeq.matchLength; + rawOffset = currSeq.offset; + + /* Modify the sequence depending on where endPosInSequence lies */ + if (endPosInSequence >= currSeq.litLength + currSeq.matchLength) { + if (startPosInSequence >= litLength) { + startPosInSequence -= litLength; + litLength = 0; + matchLength -= startPosInSequence; + } else { + litLength -= startPosInSequence; + } + /* Move to the next sequence */ + endPosInSequence -= currSeq.litLength + currSeq.matchLength; + startPosInSequence = 0; + idx++; + } else { + /* This is the final (partial) sequence we're adding from inSeqs, and endPosInSequence + does not reach the end of the match. So, we have to split the sequence */ + DEBUGLOG(6, "Require a split: diff: %u, idx: %u PIS: %u", + currSeq.litLength + currSeq.matchLength - endPosInSequence, idx, endPosInSequence); + if (endPosInSequence > litLength) { + U32 firstHalfMatchLength; + litLength = startPosInSequence >= litLength ? 0 : litLength - startPosInSequence; + firstHalfMatchLength = endPosInSequence - startPosInSequence - litLength; + if (matchLength > blockSize && firstHalfMatchLength >= cctx->appliedParams.cParams.minMatch) { + /* Only ever split the match if it is larger than the block size */ + U32 secondHalfMatchLength = currSeq.matchLength + currSeq.litLength - endPosInSequence; + if (secondHalfMatchLength < cctx->appliedParams.cParams.minMatch) { + /* Move the endPosInSequence backward so that it creates match of minMatch length */ + endPosInSequence -= cctx->appliedParams.cParams.minMatch - secondHalfMatchLength; + bytesAdjustment = cctx->appliedParams.cParams.minMatch - secondHalfMatchLength; + firstHalfMatchLength -= bytesAdjustment; + } + matchLength = firstHalfMatchLength; + /* Flag that we split the last match - after storing the sequence, exit the loop, + but keep the value of endPosInSequence */ + finalMatchSplit = 1; + } else { + /* Move the position in sequence backwards so that we don't split match, and break to store + * the last literals. We use the original currSeq.litLength as a marker for where endPosInSequence + * should go. We prefer to do this whenever it is not necessary to split the match, or if doing so + * would cause the first half of the match to be too small + */ + bytesAdjustment = endPosInSequence - currSeq.litLength; + endPosInSequence = currSeq.litLength; + break; + } + } else { + /* This sequence ends inside the literals, break to store the last literals */ + break; + } + } + /* Check if this offset can be represented with a repcode */ + { U32 ll0 = (litLength == 0); + offCode = ZSTD_finalizeOffCode(rawOffset, updatedRepcodes.rep, ll0); + updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0); + } + + if (cctx->appliedParams.validateSequences) { + seqPos->posInSrc += litLength + matchLength; + FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc, + cctx->appliedParams.cParams.windowLog, dictSize, + cctx->appliedParams.cParams.minMatch), + "Sequence validation failed"); + } + DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength); + RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation, + "Not enough memory allocated. Try adjusting ZSTD_c_minMatch."); + ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH); + ip += matchLength + litLength; + } + DEBUGLOG(5, "Ending seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength); + assert(idx == inSeqsSize || endPosInSequence <= inSeqs[idx].litLength + inSeqs[idx].matchLength); + seqPos->idx = idx; + seqPos->posInSequence = endPosInSequence; + ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t)); + + iend -= bytesAdjustment; + if (ip != iend) { + /* Store any last literals */ + U32 lastLLSize = (U32)(iend - ip); + assert(ip <= iend); + DEBUGLOG(6, "Storing last literals of size: %u", lastLLSize); + ZSTD_storeLastLiterals(&cctx->seqStore, ip, lastLLSize); + seqPos->posInSrc += lastLLSize; + } + + return bytesAdjustment; +} + +typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos, + const ZSTD_Sequence* const inSeqs, size_t inSeqsSize, + const void* src, size_t blockSize); +static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode) { + ZSTD_sequenceCopier sequenceCopier = NULL; + assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, mode)); + if (mode == ZSTD_sf_explicitBlockDelimiters) { + return ZSTD_copySequencesToSeqStoreExplicitBlockDelim; + } else if (mode == ZSTD_sf_noBlockDelimiters) { + return ZSTD_copySequencesToSeqStoreNoBlockDelim; + } + assert(sequenceCopier != NULL); + return sequenceCopier; +} + +/* Compress, block-by-block, all of the sequences given. + * + * Returns the cumulative size of all compressed blocks (including their headers), otherwise a ZSTD error. + */ +static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx, + void* dst, size_t dstCapacity, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* src, size_t srcSize) { + size_t cSize = 0; + U32 lastBlock; + size_t blockSize; + size_t compressedSeqsSize; + size_t remaining = srcSize; + ZSTD_sequencePosition seqPos = {0, 0, 0}; + + BYTE const* ip = (BYTE const*)src; + BYTE* op = (BYTE*)dst; + ZSTD_sequenceCopier sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters); + + DEBUGLOG(4, "ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu", srcSize, inSeqsSize); + /* Special case: empty frame */ + if (remaining == 0) { + U32 const cBlockHeader24 = 1 /* last block */ + (((U32)bt_raw)<<1); + RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "No room for empty frame block header"); + MEM_writeLE32(op, cBlockHeader24); + op += ZSTD_blockHeaderSize; + dstCapacity -= ZSTD_blockHeaderSize; + cSize += ZSTD_blockHeaderSize; + } + + while (remaining) { + size_t cBlockSize; + size_t additionalByteAdjustment; + lastBlock = remaining <= cctx->blockSize; + blockSize = lastBlock ? (U32)remaining : (U32)cctx->blockSize; + ZSTD_resetSeqStore(&cctx->seqStore); + DEBUGLOG(4, "Working on new block. Blocksize: %zu", blockSize); + + additionalByteAdjustment = sequenceCopier(cctx, &seqPos, inSeqs, inSeqsSize, ip, blockSize); + FORWARD_IF_ERROR(additionalByteAdjustment, "Bad sequence copy"); + blockSize -= additionalByteAdjustment; + + /* If blocks are too small, emit as a nocompress block */ + if (blockSize < MIN_CBLOCK_SIZE+ZSTD_blockHeaderSize+1) { + cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed"); + DEBUGLOG(4, "Block too small, writing out nocompress block: cSize: %zu", cBlockSize); + cSize += cBlockSize; + ip += blockSize; + op += cBlockSize; + remaining -= blockSize; + dstCapacity -= cBlockSize; + continue; + } + + compressedSeqsSize = ZSTD_entropyCompressSequences(&cctx->seqStore, + &cctx->blockState.prevCBlock->entropy, &cctx->blockState.nextCBlock->entropy, + &cctx->appliedParams, + op + ZSTD_blockHeaderSize /* Leave space for block header */, dstCapacity - ZSTD_blockHeaderSize, + blockSize, + cctx->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */, + cctx->bmi2); + FORWARD_IF_ERROR(compressedSeqsSize, "Compressing sequences of block failed"); + DEBUGLOG(4, "Compressed sequences size: %zu", compressedSeqsSize); + + if (!cctx->isFirstBlock && + ZSTD_maybeRLE(&cctx->seqStore) && + ZSTD_isRLE((BYTE const*)src, srcSize)) { + /* We don't want to emit our first block as a RLE even if it qualifies because + * doing so will cause the decoder (cli only) to throw a "should consume all input error." + * This is only an issue for zstd <= v1.4.3 + */ + compressedSeqsSize = 1; + } + + if (compressedSeqsSize == 0) { + /* ZSTD_noCompressBlock writes the block header as well */ + cBlockSize = ZSTD_noCompressBlock(op, dstCapacity, ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cBlockSize, "Nocompress block failed"); + DEBUGLOG(4, "Writing out nocompress block, size: %zu", cBlockSize); + } else if (compressedSeqsSize == 1) { + cBlockSize = ZSTD_rleCompressBlock(op, dstCapacity, *ip, blockSize, lastBlock); + FORWARD_IF_ERROR(cBlockSize, "RLE compress block failed"); + DEBUGLOG(4, "Writing out RLE block, size: %zu", cBlockSize); + } else { + U32 cBlockHeader; + /* Error checking and repcodes update */ + ZSTD_confirmRepcodesAndEntropyTables(cctx); + if (cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid) + cctx->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check; + + /* Write block header into beginning of block*/ + cBlockHeader = lastBlock + (((U32)bt_compressed)<<1) + (U32)(compressedSeqsSize << 3); + MEM_writeLE24(op, cBlockHeader); + cBlockSize = ZSTD_blockHeaderSize + compressedSeqsSize; + DEBUGLOG(4, "Writing out compressed block, size: %zu", cBlockSize); + } + + cSize += cBlockSize; + DEBUGLOG(4, "cSize running total: %zu", cSize); + + if (lastBlock) { + break; + } else { + ip += blockSize; + op += cBlockSize; + remaining -= blockSize; + dstCapacity -= cBlockSize; + cctx->isFirstBlock = 0; + } + } + + return cSize; +} + +size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstCapacity, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* src, size_t srcSize) { + BYTE* op = (BYTE*)dst; + size_t cSize = 0; + size_t compressedBlocksSize = 0; + size_t frameHeaderSize = 0; + + /* Transparent initialization stage, same as compressStream2() */ + DEBUGLOG(3, "ZSTD_compressSequences()"); + assert(cctx != NULL); + FORWARD_IF_ERROR(ZSTD_CCtx_init_compressStream2(cctx, ZSTD_e_end, srcSize), "CCtx initialization failed"); + /* Begin writing output, starting with frame header */ + frameHeaderSize = ZSTD_writeFrameHeader(op, dstCapacity, &cctx->appliedParams, srcSize, cctx->dictID); + op += frameHeaderSize; + dstCapacity -= frameHeaderSize; + cSize += frameHeaderSize; + if (cctx->appliedParams.fParams.checksumFlag && srcSize) { + XXH64_update(&cctx->xxhState, src, srcSize); + } + /* cSize includes block header size and compressed sequences size */ + compressedBlocksSize = ZSTD_compressSequences_internal(cctx, + op, dstCapacity, + inSeqs, inSeqsSize, + src, srcSize); + FORWARD_IF_ERROR(compressedBlocksSize, "Compressing blocks failed!"); + cSize += compressedBlocksSize; + dstCapacity -= compressedBlocksSize; + + if (cctx->appliedParams.fParams.checksumFlag) { + U32 const checksum = (U32) XXH64_digest(&cctx->xxhState); + RETURN_ERROR_IF(dstCapacity<4, dstSize_tooSmall, "no room for checksum"); + DEBUGLOG(4, "Write checksum : %08X", (unsigned)checksum); + MEM_writeLE32((char*)dst + cSize, checksum); + cSize += 4; + } + + DEBUGLOG(3, "Final compressed size: %zu", cSize); + return cSize; +} + /*====== Finalize ======*/ /*! ZSTD_flushStream() : @@ -4223,25 +5075,103 @@ static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEV }, }; +static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize) +{ + ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict); + switch (cParams.strategy) { + case ZSTD_fast: + case ZSTD_dfast: + break; + case ZSTD_greedy: + case ZSTD_lazy: + case ZSTD_lazy2: + cParams.hashLog += ZSTD_LAZY_DDSS_BUCKET_LOG; + break; + case ZSTD_btlazy2: + case ZSTD_btopt: + case ZSTD_btultra: + case ZSTD_btultra2: + break; + } + return cParams; +} + +static int ZSTD_dedicatedDictSearch_isSupported( + ZSTD_compressionParameters const* cParams) +{ + return (cParams->strategy >= ZSTD_greedy) && (cParams->strategy <= ZSTD_lazy2); +} + +/** + * Reverses the adjustment applied to cparams when enabling dedicated dict + * search. This is used to recover the params set to be used in the working + * context. (Otherwise, those tables would also grow.) + */ +static void ZSTD_dedicatedDictSearch_revertCParams( + ZSTD_compressionParameters* cParams) { + switch (cParams->strategy) { + case ZSTD_fast: + case ZSTD_dfast: + break; + case ZSTD_greedy: + case ZSTD_lazy: + case ZSTD_lazy2: + cParams->hashLog -= ZSTD_LAZY_DDSS_BUCKET_LOG; + break; + case ZSTD_btlazy2: + case ZSTD_btopt: + case ZSTD_btultra: + case ZSTD_btultra2: + break; + } +} + +static U64 ZSTD_getCParamRowSize(U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) +{ + switch (mode) { + case ZSTD_cpm_unknown: + case ZSTD_cpm_noAttachDict: + case ZSTD_cpm_createCDict: + break; + case ZSTD_cpm_attachDict: + dictSize = 0; + break; + default: + assert(0); + break; + } + { int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN; + size_t const addedSize = unknown && dictSize > 0 ? 500 : 0; + return unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize; + } +} + /*! ZSTD_getCParams_internal() : * @return ZSTD_compressionParameters structure for a selected compression level, srcSize and dictSize. * Note: srcSizeHint 0 means 0, use ZSTD_CONTENTSIZE_UNKNOWN for unknown. - * Use dictSize == 0 for unknown or unused. */ -static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) + * Use dictSize == 0 for unknown or unused. + * Note: `mode` controls how we treat the `dictSize`. See docs for `ZSTD_cParamMode_e`. */ +static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) { - int const unknown = srcSizeHint == ZSTD_CONTENTSIZE_UNKNOWN; - size_t const addedSize = unknown && dictSize > 0 ? 500 : 0; - U64 const rSize = unknown && dictSize == 0 ? ZSTD_CONTENTSIZE_UNKNOWN : srcSizeHint+dictSize+addedSize; + U64 const rSize = ZSTD_getCParamRowSize(srcSizeHint, dictSize, mode); U32 const tableID = (rSize <= 256 KB) + (rSize <= 128 KB) + (rSize <= 16 KB); - int row = compressionLevel; + int row; DEBUGLOG(5, "ZSTD_getCParams_internal (cLevel=%i)", compressionLevel); + + /* row */ if (compressionLevel == 0) row = ZSTD_CLEVEL_DEFAULT; /* 0 == default */ - if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */ - if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL; + else if (compressionLevel < 0) row = 0; /* entry 0 is baseline for fast mode */ + else if (compressionLevel > ZSTD_MAX_CLEVEL) row = ZSTD_MAX_CLEVEL; + else row = compressionLevel; + { ZSTD_compressionParameters cp = ZSTD_defaultCParameters[tableID][row]; - if (compressionLevel < 0) cp.targetLength = (unsigned)(-compressionLevel); /* acceleration factor */ + /* acceleration factor */ + if (compressionLevel < 0) { + int const clampedCompressionLevel = MAX(ZSTD_minCLevel(), compressionLevel); + cp.targetLength = (unsigned)(-clampedCompressionLevel); + } /* refine parameters based on srcSize & dictSize */ - return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize); + return ZSTD_adjustCParams_internal(cp, srcSizeHint, dictSize, mode); } } @@ -4251,18 +5181,18 @@ static ZSTD_compressionParameters ZSTD_getCParams_internal(int compressionLevel, ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize); + return ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown); } /*! ZSTD_getParams() : * same idea as ZSTD_getCParams() * @return a `ZSTD_parameters` structure (instead of `ZSTD_compressionParameters`). * Fields of `ZSTD_frameParameters` are set to default values */ -static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { +static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode) { ZSTD_parameters params; - ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize); + ZSTD_compressionParameters const cParams = ZSTD_getCParams_internal(compressionLevel, srcSizeHint, dictSize, mode); DEBUGLOG(5, "ZSTD_getParams (cLevel=%i)", compressionLevel); - memset(¶ms, 0, sizeof(params)); + ZSTD_memset(¶ms, 0, sizeof(params)); params.cParams = cParams; params.fParams.contentSizeFlag = 1; return params; @@ -4274,5 +5204,5 @@ static ZSTD_parameters ZSTD_getParams_internal(int compressionLevel, unsigned lo * Fields of `ZSTD_frameParameters` are set to default values */ ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long srcSizeHint, size_t dictSize) { if (srcSizeHint == 0) srcSizeHint = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize); + return ZSTD_getParams_internal(compressionLevel, srcSizeHint, dictSize, ZSTD_cpm_unknown); } diff --git a/thirdparty/zstd/compress/zstd_compress_internal.h b/thirdparty/zstd/compress/zstd_compress_internal.h index db73f6ce21..c04998b8b1 100644 --- a/thirdparty/zstd/compress/zstd_compress_internal.h +++ b/thirdparty/zstd/compress/zstd_compress_internal.h @@ -28,7 +28,6 @@ extern "C" { #endif - /*-************************************* * Constants ***************************************/ @@ -64,7 +63,7 @@ typedef struct { } ZSTD_localDict; typedef struct { - U32 CTable[HUF_CTABLE_SIZE_U32(255)]; + HUF_CElt CTable[HUF_CTABLE_SIZE_U32(255)]; HUF_repeat repeatMode; } ZSTD_hufCTables_t; @@ -83,11 +82,28 @@ typedef struct { } ZSTD_entropyCTables_t; typedef struct { - U32 off; - U32 len; + U32 off; /* Offset code (offset + ZSTD_REP_MOVE) for the match */ + U32 len; /* Raw length of match */ } ZSTD_match_t; typedef struct { + U32 offset; /* Offset of sequence */ + U32 litLength; /* Length of literals prior to match */ + U32 matchLength; /* Raw length of match */ +} rawSeq; + +typedef struct { + rawSeq* seq; /* The start of the sequences */ + size_t pos; /* The index in seq where reading stopped. pos <= size. */ + size_t posInSequence; /* The position within the sequence at seq[pos] where reading + stopped. posInSequence <= seq[pos].litLength + seq[pos].matchLength */ + size_t size; /* The number of sequences. <= capacity. */ + size_t capacity; /* The capacity starting from `seq` pointer */ +} rawSeqStore_t; + +UNUSED_ATTR static const rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0, 0}; + +typedef struct { int price; U32 off; U32 mlen; @@ -147,9 +163,13 @@ struct ZSTD_matchState_t { U32* hashTable; U32* hashTable3; U32* chainTable; + int dedicatedDictSearch; /* Indicates whether this matchState is using the + * dedicated dictionary search structure. + */ optState_t opt; /* optimal parser state */ const ZSTD_matchState_t* dictMatchState; ZSTD_compressionParameters cParams; + const rawSeqStore_t* ldmSeqStore; }; typedef struct { @@ -182,19 +202,6 @@ typedef struct { } ldmParams_t; typedef struct { - U32 offset; - U32 litLength; - U32 matchLength; -} rawSeq; - -typedef struct { - rawSeq* seq; /* The start of the sequences */ - size_t pos; /* The position where reading stopped. <= size. */ - size_t size; /* The number of sequences. <= capacity. */ - size_t capacity; /* The capacity starting from `seq` pointer */ -} rawSeqStore_t; - -typedef struct { int collectSequences; ZSTD_Sequence* seqStart; size_t seqIndex; @@ -228,10 +235,34 @@ struct ZSTD_CCtx_params_s { /* Long distance matching parameters */ ldmParams_t ldmParams; + /* Dedicated dict search algorithm trigger */ + int enableDedicatedDictSearch; + + /* Input/output buffer modes */ + ZSTD_bufferMode_e inBufferMode; + ZSTD_bufferMode_e outBufferMode; + + /* Sequence compression API */ + ZSTD_sequenceFormat_e blockDelimiters; + int validateSequences; + /* Internal use, for createCCtxParams() and freeCCtxParams() only */ ZSTD_customMem customMem; }; /* typedef'd to ZSTD_CCtx_params within "zstd.h" */ +#define COMPRESS_SEQUENCES_WORKSPACE_SIZE (sizeof(unsigned) * (MaxSeq + 2)) +#define ENTROPY_WORKSPACE_SIZE (HUF_WORKSPACE_SIZE + COMPRESS_SEQUENCES_WORKSPACE_SIZE) + +/** + * Indicates whether this compression proceeds directly from user-provided + * source buffer to user-provided destination buffer (ZSTDb_not_buffered), or + * whether the context needs to buffer the input/output (ZSTDb_buffered). + */ +typedef enum { + ZSTDb_not_buffered, + ZSTDb_buffered +} ZSTD_buffered_policy_e; + struct ZSTD_CCtx_s { ZSTD_compressionStage_e stage; int cParamsChanged; /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */ @@ -247,6 +278,7 @@ struct ZSTD_CCtx_s { unsigned long long producedCSize; XXH64_state_t xxhState; ZSTD_customMem customMem; + ZSTD_threadPool* pool; size_t staticSize; SeqCollector seqCollector; int isFirstBlock; @@ -258,7 +290,10 @@ struct ZSTD_CCtx_s { size_t maxNbLdmSequences; rawSeqStore_t externSeqStore; /* Mutable reference to external sequences */ ZSTD_blockState_t blockState; - U32* entropyWorkspace; /* entropy workspace of HUF_WORKSPACE_SIZE bytes */ + U32* entropyWorkspace; /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */ + + /* Wether we are streaming or not */ + ZSTD_buffered_policy_e bufferedPolicy; /* streaming */ char* inBuff; @@ -273,6 +308,10 @@ struct ZSTD_CCtx_s { ZSTD_cStreamStage streamStage; U32 frameEnded; + /* Stable in/out buffer verification */ + ZSTD_inBuffer expectedInBuffer; + size_t expectedOutBufferSize; + /* Dictionary */ ZSTD_localDict localDict; const ZSTD_CDict* cdict; @@ -286,8 +325,32 @@ struct ZSTD_CCtx_s { typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e; -typedef enum { ZSTD_noDict = 0, ZSTD_extDict = 1, ZSTD_dictMatchState = 2 } ZSTD_dictMode_e; - +typedef enum { + ZSTD_noDict = 0, + ZSTD_extDict = 1, + ZSTD_dictMatchState = 2, + ZSTD_dedicatedDictSearch = 3 +} ZSTD_dictMode_e; + +typedef enum { + ZSTD_cpm_noAttachDict = 0, /* Compression with ZSTD_noDict or ZSTD_extDict. + * In this mode we use both the srcSize and the dictSize + * when selecting and adjusting parameters. + */ + ZSTD_cpm_attachDict = 1, /* Compression with ZSTD_dictMatchState or ZSTD_dedicatedDictSearch. + * In this mode we only take the srcSize into account when selecting + * and adjusting parameters. + */ + ZSTD_cpm_createCDict = 2, /* Creating a CDict. + * In this mode we take both the source size and the dictionary size + * into account when selecting and adjusting the parameters. + */ + ZSTD_cpm_unknown = 3, /* ZSTD_getCParams, ZSTD_getParams, ZSTD_adjustParams. + * We don't know what these parameters are for. We default to the legacy + * behavior of taking both the source size and the dict size into account + * when selecting and adjusting parameters. + */ +} ZSTD_cParamMode_e; typedef size_t (*ZSTD_blockCompressor) ( ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], @@ -345,7 +408,7 @@ MEM_STATIC repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 con newReps.rep[1] = rep[0]; newReps.rep[0] = currentOffset; } else { /* repCode == 0 */ - memcpy(&newReps, rep, sizeof(newReps)); + ZSTD_memcpy(&newReps, rep, sizeof(newReps)); } } return newReps; @@ -372,7 +435,7 @@ MEM_STATIC size_t ZSTD_noCompressBlock (void* dst, size_t dstCapacity, const voi RETURN_ERROR_IF(srcSize + ZSTD_blockHeaderSize > dstCapacity, dstSize_tooSmall, "dst buf too small for uncompressed block"); MEM_writeLE24(dst, cBlockHeader24); - memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize); + ZSTD_memcpy((BYTE*)dst + ZSTD_blockHeaderSize, src, srcSize); return ZSTD_blockHeaderSize + srcSize; } @@ -498,8 +561,12 @@ static unsigned ZSTD_NbCommonBytes (size_t val) if (MEM_isLittleEndian()) { if (MEM_64bits()) { # if defined(_MSC_VER) && defined(_WIN64) - unsigned long r = 0; - return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0; +# if STATIC_BMI2 + return _tzcnt_u64(val) >> 3; +# else + unsigned long r = 0; + return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0; +# endif # elif defined(__GNUC__) && (__GNUC__ >= 4) return (__builtin_ctzll((U64)val) >> 3); # else @@ -530,8 +597,12 @@ static unsigned ZSTD_NbCommonBytes (size_t val) } else { /* Big Endian CPU */ if (MEM_64bits()) { # if defined(_MSC_VER) && defined(_WIN64) - unsigned long r = 0; - return _BitScanReverse64( &r, val ) ? (unsigned)(r >> 3) : 0; +# if STATIC_BMI2 + return _lzcnt_u64(val) >> 3; +# else + unsigned long r = 0; + return _BitScanReverse64(&r, (U64)val) ? (unsigned)(r >> 3) : 0; +# endif # elif defined(__GNUC__) && (__GNUC__ >= 4) return (__builtin_clzll(val) >> 3); # else @@ -626,7 +697,8 @@ static const U64 prime8bytes = 0xCF1BBCDCB7A56463ULL; static size_t ZSTD_hash8(U64 u, U32 h) { return (size_t)(((u) * prime8bytes) >> (64-h)) ; } static size_t ZSTD_hash8Ptr(const void* p, U32 h) { return ZSTD_hash8(MEM_readLE64(p), h); } -MEM_STATIC size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls) +MEM_STATIC FORCE_INLINE_ATTR +size_t ZSTD_hashPtr(const void* p, U32 hBits, U32 mls) { switch(mls) { @@ -742,7 +814,7 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms) return ZSTD_window_hasExtDict(ms->window) ? ZSTD_extDict : ms->dictMatchState != NULL ? - ZSTD_dictMatchState : + (ms->dictMatchState->dedicatedDictSearch ? ZSTD_dedicatedDictSearch : ZSTD_dictMatchState) : ZSTD_noDict; } @@ -754,8 +826,8 @@ MEM_STATIC ZSTD_dictMode_e ZSTD_matchState_dictMode(const ZSTD_matchState_t *ms) MEM_STATIC U32 ZSTD_window_needOverflowCorrection(ZSTD_window_t const window, void const* srcEnd) { - U32 const current = (U32)((BYTE const*)srcEnd - window.base); - return current > ZSTD_CURRENT_MAX; + U32 const curr = (U32)((BYTE const*)srcEnd - window.base); + return curr > ZSTD_CURRENT_MAX; } /** @@ -791,14 +863,14 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog, * windowLog <= 31 ==> 3<<29 + 1<<windowLog < 7<<29 < 1<<32. */ U32 const cycleMask = (1U << cycleLog) - 1; - U32 const current = (U32)((BYTE const*)src - window->base); - U32 const currentCycle0 = current & cycleMask; + U32 const curr = (U32)((BYTE const*)src - window->base); + U32 const currentCycle0 = curr & cycleMask; /* Exclude zero so that newCurrent - maxDist >= 1. */ U32 const currentCycle1 = currentCycle0 == 0 ? (1U << cycleLog) : currentCycle0; U32 const newCurrent = currentCycle1 + maxDist; - U32 const correction = current - newCurrent; + U32 const correction = curr - newCurrent; assert((maxDist & cycleMask) == 0); - assert(current > newCurrent); + assert(curr > newCurrent); /* Loose bound, should be around 1<<29 (see above) */ assert(correction > 1<<28); @@ -919,7 +991,7 @@ ZSTD_checkDictValidity(const ZSTD_window_t* window, } MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) { - memset(window, 0, sizeof(*window)); + ZSTD_memset(window, 0, sizeof(*window)); window->base = (BYTE const*)""; window->dictBase = (BYTE const*)""; window->dictLimit = 1; /* start from 1, so that 1st position is valid */ @@ -973,12 +1045,16 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window, /** * Returns the lowest allowed match index. It may either be in the ext-dict or the prefix. */ -MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 current, unsigned windowLog) +MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog) { U32 const maxDistance = 1U << windowLog; U32 const lowestValid = ms->window.lowLimit; - U32 const withinWindow = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid; + U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; U32 const isDictionary = (ms->loadedDictEnd != 0); + /* When using a dictionary the entire dictionary is valid if a single byte of the dictionary + * is within the window. We invalidate the dictionary (and set loadedDictEnd to 0) when it isn't + * valid for the entire block. So this check is sufficient to find the lowest valid match index. + */ U32 const matchLowest = isDictionary ? lowestValid : withinWindow; return matchLowest; } @@ -986,12 +1062,15 @@ MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 current /** * Returns the lowest allowed match index in the prefix. */ -MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 current, unsigned windowLog) +MEM_STATIC U32 ZSTD_getLowestPrefixIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog) { U32 const maxDistance = 1U << windowLog; U32 const lowestValid = ms->window.dictLimit; - U32 const withinWindow = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid; + U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; U32 const isDictionary = (ms->loadedDictEnd != 0); + /* When computing the lowest prefix index we need to take the dictionary into account to handle + * the edge case where the dictionary and the source are contiguous in memory. + */ U32 const matchLowest = isDictionary ? lowestValid : withinWindow; return matchLowest; } @@ -1045,7 +1124,6 @@ MEM_STATIC void ZSTD_debugTable(const U32* table, U32 max) * assumptions : magic number supposed already checked * and dictSize >= 8 */ size_t ZSTD_loadCEntropy(ZSTD_compressedBlockState_t* bs, void* workspace, - short* offcodeNCount, unsigned* offcodeMaxValue, const void* const dict, size_t dictSize); void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs); @@ -1061,7 +1139,7 @@ void ZSTD_reset_compressedBlockState(ZSTD_compressedBlockState_t* bs); * Note: srcSizeHint == 0 means 0! */ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams( - const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize); + const ZSTD_CCtx_params* CCtxParams, U64 srcSizeHint, size_t dictSize, ZSTD_cParamMode_e mode); /*! ZSTD_initCStream_internal() : * Private use only. Init streaming operation. diff --git a/thirdparty/zstd/compress/zstd_compress_literals.c b/thirdparty/zstd/compress/zstd_compress_literals.c index 17e7168d89..6dd1c1447a 100644 --- a/thirdparty/zstd/compress/zstd_compress_literals.c +++ b/thirdparty/zstd/compress/zstd_compress_literals.c @@ -35,7 +35,7 @@ size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src, assert(0); } - memcpy(ostart + flSize, src, srcSize); + ZSTD_memcpy(ostart + flSize, src, srcSize); DEBUGLOG(5, "Raw literals: %u -> %u", (U32)srcSize, (U32)(srcSize + flSize)); return srcSize + flSize; } @@ -86,7 +86,7 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf, disableLiteralCompression, (U32)srcSize); /* Prepare nextEntropy assuming reusing the existing table */ - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); if (disableLiteralCompression) return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); @@ -118,11 +118,11 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf, } if ((cLitSize==0) | (cLitSize >= srcSize - minGain) | ERR_isError(cLitSize)) { - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize); } if (cLitSize==1) { - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize); } diff --git a/thirdparty/zstd/compress/zstd_compress_sequences.c b/thirdparty/zstd/compress/zstd_compress_sequences.c index f9f8097c83..be30c08c6b 100644 --- a/thirdparty/zstd/compress/zstd_compress_sequences.c +++ b/thirdparty/zstd/compress/zstd_compress_sequences.c @@ -51,6 +51,19 @@ static unsigned ZSTD_getFSEMaxSymbolValue(FSE_CTable const* ctable) { } /** + * Returns true if we should use ncount=-1 else we should + * use ncount=1 for low probability symbols instead. + */ +static unsigned ZSTD_useLowProbCount(size_t const nbSeq) +{ + /* Heuristic: This should cover most blocks <= 16K and + * start to fade out after 16K to about 32K depending on + * comprssibility. + */ + return nbSeq >= 2048; +} + +/** * Returns the cost in bytes of encoding the normalized count header. * Returns an error if any of the helper functions return an error. */ @@ -60,7 +73,7 @@ static size_t ZSTD_NCountCost(unsigned const* count, unsigned const max, BYTE wksp[FSE_NCOUNTBOUND]; S16 norm[MaxSeq + 1]; const U32 tableLog = FSE_optimalTableLog(FSELog, nbSeq, max); - FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max), ""); + FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq, max, ZSTD_useLowProbCount(nbSeq)), ""); return FSE_writeNCount(wksp, sizeof(wksp), norm, max, tableLog); } @@ -239,7 +252,7 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity, *op = codeTable[0]; return 1; case set_repeat: - memcpy(nextCTable, prevCTable, prevCTableSize); + ZSTD_memcpy(nextCTable, prevCTable, prevCTableSize); return 0; case set_basic: FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, defaultNorm, defaultMax, defaultNormLog, entropyWorkspace, entropyWorkspaceSize), ""); /* note : could be pre-calculated */ @@ -253,7 +266,8 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity, nbSeq_1--; } assert(nbSeq_1 > 1); - FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max), ""); + assert(entropyWorkspaceSize >= FSE_BUILD_CTABLE_WORKSPACE_SIZE(MaxSeq, MaxFSELog)); + FORWARD_IF_ERROR(FSE_normalizeCount(norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), ""); { size_t const NCountSize = FSE_writeNCount(op, oend - op, norm, max, tableLog); /* overflow protected */ FORWARD_IF_ERROR(NCountSize, "FSE_writeNCount failed"); FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, norm, max, tableLog, entropyWorkspace, entropyWorkspaceSize), ""); diff --git a/thirdparty/zstd/compress/zstd_compress_superblock.c b/thirdparty/zstd/compress/zstd_compress_superblock.c index b693866c0a..e23e619eef 100644 --- a/thirdparty/zstd/compress/zstd_compress_superblock.c +++ b/thirdparty/zstd/compress/zstd_compress_superblock.c @@ -29,7 +29,7 @@ * This metadata is populated in ZSTD_buildSuperBlockEntropy_literal() */ typedef struct { symbolEncodingType_e hType; - BYTE hufDesBuffer[500]; /* TODO give name to this value */ + BYTE hufDesBuffer[ZSTD_MAX_HUF_HEADER_SIZE]; size_t hufDesSize; } ZSTD_hufCTablesMetadata_t; @@ -42,7 +42,7 @@ typedef struct { symbolEncodingType_e llType; symbolEncodingType_e ofType; symbolEncodingType_e mlType; - BYTE fseTablesBuffer[500]; /* TODO give name to this value */ + BYTE fseTablesBuffer[ZSTD_MAX_FSE_HEADERS_SIZE]; size_t fseTablesSize; size_t lastCountSize; /* This is to account for bug in 1.3.4. More detail in ZSTD_compressSubBlock_sequences() */ } ZSTD_fseCTablesMetadata_t; @@ -79,7 +79,7 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_literal (srcSize=%zu)", srcSize); /* Prepare nextEntropy assuming reusing the existing table */ - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); if (disableLiteralsCompression) { DEBUGLOG(5, "set_basic - disabled"); @@ -118,7 +118,7 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz } /* Build Huffman Tree */ - memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable)); + ZSTD_memset(nextHuf->CTable, 0, sizeof(nextHuf->CTable)); huffLog = HUF_optimalTableLog(huffLog, srcSize, maxSymbolValue); { size_t const maxBits = HUF_buildCTable_wksp((HUF_CElt*)nextHuf->CTable, countWksp, maxSymbolValue, huffLog, @@ -137,14 +137,14 @@ static size_t ZSTD_buildSuperBlockEntropy_literal(void* const src, size_t srcSiz (HUF_CElt const*)prevHuf->CTable, countWksp, maxSymbolValue); if (oldCSize < srcSize && (oldCSize <= hSize + newCSize || hSize + 12 >= srcSize)) { DEBUGLOG(5, "set_repeat - smaller"); - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); hufMetadata->hType = set_repeat; return 0; } } if (newCSize + hSize >= srcSize) { DEBUGLOG(5, "set_basic - no gains"); - memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); + ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf)); hufMetadata->hType = set_basic; return 0; } @@ -188,7 +188,7 @@ static size_t ZSTD_buildSuperBlockEntropy_sequences(seqStore_t* seqStorePtr, assert(cTableWkspSize >= (1 << MaxFSELog) * sizeof(FSE_FUNCTION_TYPE)); DEBUGLOG(5, "ZSTD_buildSuperBlockEntropy_sequences (nbSeq=%zu)", nbSeq); - memset(workspace, 0, wkspSize); + ZSTD_memset(workspace, 0, wkspSize); fseMetadata->lastCountSize = 0; /* convert length/distances into codes */ @@ -348,7 +348,7 @@ static size_t ZSTD_compressSubBlock_literal(const HUF_CElt* hufTable, assert(hufMetadata->hType == set_compressed || hufMetadata->hType == set_repeat); if (writeEntropy && hufMetadata->hType == set_compressed) { - memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize); + ZSTD_memcpy(op, hufMetadata->hufDesBuffer, hufMetadata->hufDesSize); op += hufMetadata->hufDesSize; cLitSize += hufMetadata->hufDesSize; DEBUGLOG(5, "ZSTD_compressSubBlock_literal (hSize=%zu)", hufMetadata->hufDesSize); @@ -474,7 +474,7 @@ static size_t ZSTD_compressSubBlock_sequences(const ZSTD_fseCTables_t* fseTables const U32 MLtype = fseMetadata->mlType; DEBUGLOG(5, "ZSTD_compressSubBlock_sequences (fseTablesSize=%zu)", fseMetadata->fseTablesSize); *seqHead = (BYTE)((LLtype<<6) + (Offtype<<4) + (MLtype<<2)); - memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize); + ZSTD_memcpy(op, fseMetadata->fseTablesBuffer, fseMetadata->fseTablesSize); op += fseMetadata->fseTablesSize; } else { const U32 repeat = set_repeat; @@ -603,7 +603,7 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type, const BYTE* codeTable, unsigned maxCode, size_t nbSeq, const FSE_CTable* fseCTable, const U32* additionalBits, - short const* defaultNorm, U32 defaultNormLog, + short const* defaultNorm, U32 defaultNormLog, U32 defaultMax, void* workspace, size_t wkspSize) { unsigned* const countWksp = (unsigned*)workspace; @@ -615,7 +615,11 @@ static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type, HIST_countFast_wksp(countWksp, &max, codeTable, nbSeq, workspace, wkspSize); /* can't fail */ if (type == set_basic) { - cSymbolTypeSizeEstimateInBits = ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max); + /* We selected this encoding type, so it must be valid. */ + assert(max <= defaultMax); + cSymbolTypeSizeEstimateInBits = max <= defaultMax + ? ZSTD_crossEntropyCost(defaultNorm, defaultNormLog, countWksp, max) + : ERROR(GENERIC); } else if (type == set_rle) { cSymbolTypeSizeEstimateInBits = 0; } else if (type == set_compressed || type == set_repeat) { @@ -643,15 +647,15 @@ static size_t ZSTD_estimateSubBlockSize_sequences(const BYTE* ofCodeTable, size_t cSeqSizeEstimate = 0; cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->ofType, ofCodeTable, MaxOff, nbSeq, fseTables->offcodeCTable, NULL, - OF_defaultNorm, OF_defaultNormLog, + OF_defaultNorm, OF_defaultNormLog, DefaultMaxOff, workspace, wkspSize); cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->llType, llCodeTable, MaxLL, nbSeq, fseTables->litlengthCTable, LL_bits, - LL_defaultNorm, LL_defaultNormLog, + LL_defaultNorm, LL_defaultNormLog, MaxLL, workspace, wkspSize); cSeqSizeEstimate += ZSTD_estimateSubBlockSize_symbolType(fseMetadata->mlType, mlCodeTable, MaxML, nbSeq, fseTables->matchlengthCTable, ML_bits, - ML_defaultNorm, ML_defaultNormLog, + ML_defaultNorm, ML_defaultNormLog, MaxML, workspace, wkspSize); if (writeEntropy) cSeqSizeEstimate += fseMetadata->fseTablesSize; return cSeqSizeEstimate + sequencesSectionHeaderSize; @@ -790,7 +794,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, } while (!lastSequence); if (writeLitEntropy) { DEBUGLOG(5, "ZSTD_compressSubBlock_multi has literal entropy tables unwritten"); - memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf)); + ZSTD_memcpy(&nextCBlock->entropy.huf, &prevCBlock->entropy.huf, sizeof(prevCBlock->entropy.huf)); } if (writeSeqEntropy && ZSTD_needSequenceEntropyTables(&entropyMetadata->fseMetadata)) { /* If we haven't written our entropy tables, then we've violated our contract and @@ -809,11 +813,11 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr, if (sp < send) { seqDef const* seq; repcodes_t rep; - memcpy(&rep, prevCBlock->rep, sizeof(rep)); + ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep)); for (seq = sstart; seq < sp; ++seq) { rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0); } - memcpy(nextCBlock->rep, &rep, sizeof(rep)); + ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep)); } } DEBUGLOG(5, "ZSTD_compressSubBlock_multi compressed"); @@ -831,7 +835,7 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, &zc->blockState.nextCBlock->entropy, &zc->appliedParams, &entropyMetadata, - zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */), ""); + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), ""); return ZSTD_compressSubBlock_multi(&zc->seqStore, zc->blockState.prevCBlock, @@ -841,5 +845,5 @@ size_t ZSTD_compressSuperBlock(ZSTD_CCtx* zc, dst, dstCapacity, src, srcSize, zc->bmi2, lastBlock, - zc->entropyWorkspace, HUF_WORKSPACE_SIZE /* statically allocated in resetCCtx */); + zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */); } diff --git a/thirdparty/zstd/compress/zstd_cwksp.h b/thirdparty/zstd/compress/zstd_cwksp.h index a25c9263b7..d65170b39c 100644 --- a/thirdparty/zstd/compress/zstd_cwksp.h +++ b/thirdparty/zstd/compress/zstd_cwksp.h @@ -45,6 +45,16 @@ typedef enum { } ZSTD_cwksp_alloc_phase_e; /** + * Used to describe whether the workspace is statically allocated (and will not + * necessarily ever be freed), or if it's dynamically allocated and we can + * expect a well-formed caller to free this. + */ +typedef enum { + ZSTD_cwksp_dynamic_alloc, + ZSTD_cwksp_static_alloc +} ZSTD_cwksp_static_alloc_e; + +/** * Zstd fits all its internal datastructures into a single continuous buffer, * so that it only needs to perform a single OS allocation (or so that a buffer * can be provided to it and it can perform no allocations at all). This buffer @@ -92,7 +102,7 @@ typedef enum { * * - Static objects: this is optionally the enclosing ZSTD_CCtx or ZSTD_CDict, * so that literally everything fits in a single buffer. Note: if present, - * this must be the first object in the workspace, since ZSTD_free{CCtx, + * this must be the first object in the workspace, since ZSTD_customFree{CCtx, * CDict}() rely on a pointer comparison to see whether one or two frees are * required. * @@ -137,9 +147,10 @@ typedef struct { void* tableValidEnd; void* allocStart; - int allocFailed; + BYTE allocFailed; int workspaceOversizedDuration; ZSTD_cwksp_alloc_phase_e phase; + ZSTD_cwksp_static_alloc_e isStatic; } ZSTD_cwksp; /*-************************************* @@ -178,7 +189,9 @@ MEM_STATIC size_t ZSTD_cwksp_align(size_t size, size_t const align) { * else is though. */ MEM_STATIC size_t ZSTD_cwksp_alloc_size(size_t size) { -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + if (size == 0) + return 0; +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) return size + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; #else return size; @@ -228,7 +241,10 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal( ZSTD_cwksp_internal_advance_phase(ws, phase); alloc = (BYTE *)ws->allocStart - bytes; -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + if (bytes == 0) + return NULL; + +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) /* over-reserve space */ alloc = (BYTE *)alloc - 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; #endif @@ -247,11 +263,13 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal( } ws->allocStart = alloc; -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on * either size. */ alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE; - __asan_unpoison_memory_region(alloc, bytes); + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { + __asan_unpoison_memory_region(alloc, bytes); + } #endif return alloc; @@ -296,8 +314,10 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) { } ws->tableEnd = end; -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - __asan_unpoison_memory_region(alloc, bytes); +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { + __asan_unpoison_memory_region(alloc, bytes); + } #endif return alloc; @@ -311,7 +331,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) { void* alloc = ws->objectEnd; void* end = (BYTE*)alloc + roundedBytes; -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) /* over-reserve space */ end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE; #endif @@ -332,11 +352,13 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) { ws->tableEnd = end; ws->tableValidEnd = end; -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) /* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on * either size. */ alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE; - __asan_unpoison_memory_region(alloc, bytes); + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { + __asan_unpoison_memory_region(alloc, bytes); + } #endif return alloc; @@ -345,7 +367,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) { MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) { DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty"); -#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) +#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) /* To validate that the table re-use logic is sound, and that we don't * access table space that we haven't cleaned, we re-"poison" the table * space every time we mark it dirty. */ @@ -380,7 +402,7 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) { assert(ws->tableValidEnd >= ws->objectEnd); assert(ws->tableValidEnd <= ws->allocStart); if (ws->tableValidEnd < ws->tableEnd) { - memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd); + ZSTD_memset(ws->tableValidEnd, 0, (BYTE*)ws->tableEnd - (BYTE*)ws->tableValidEnd); } ZSTD_cwksp_mark_tables_clean(ws); } @@ -392,8 +414,12 @@ MEM_STATIC void ZSTD_cwksp_clean_tables(ZSTD_cwksp* ws) { MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) { DEBUGLOG(4, "cwksp: clearing tables!"); -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - { +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + /* We don't do this when the workspace is statically allocated, because + * when that is the case, we have no capability to hook into the end of the + * workspace's lifecycle to unpoison the memory. + */ + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { size_t size = (BYTE*)ws->tableValidEnd - (BYTE*)ws->objectEnd; __asan_poison_memory_region(ws->objectEnd, size); } @@ -410,7 +436,7 @@ MEM_STATIC void ZSTD_cwksp_clear_tables(ZSTD_cwksp* ws) { MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) { DEBUGLOG(4, "cwksp: clearing!"); -#if defined (MEMORY_SANITIZER) && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) +#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE) /* To validate that the context re-use logic is sound, and that we don't * access stuff that this compression hasn't initialized, we re-"poison" * the workspace (or at least the non-static, non-table parts of it) @@ -421,8 +447,12 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) { } #endif -#if defined (ADDRESS_SANITIZER) && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) - { +#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE) + /* We don't do this when the workspace is statically allocated, because + * when that is the case, we have no capability to hook into the end of the + * workspace's lifecycle to unpoison the memory. + */ + if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) { size_t size = (BYTE*)ws->workspaceEnd - (BYTE*)ws->objectEnd; __asan_poison_memory_region(ws->objectEnd, size); } @@ -442,7 +472,7 @@ MEM_STATIC void ZSTD_cwksp_clear(ZSTD_cwksp* ws) { * Any existing values in the workspace are ignored (the previously managed * buffer, if present, must be separately freed). */ -MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) { +MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size, ZSTD_cwksp_static_alloc_e isStatic) { DEBUGLOG(4, "cwksp: init'ing workspace with %zd bytes", size); assert(((size_t)start & (sizeof(void*)-1)) == 0); /* ensure correct alignment */ ws->workspace = start; @@ -450,24 +480,25 @@ MEM_STATIC void ZSTD_cwksp_init(ZSTD_cwksp* ws, void* start, size_t size) { ws->objectEnd = ws->workspace; ws->tableValidEnd = ws->objectEnd; ws->phase = ZSTD_cwksp_alloc_objects; + ws->isStatic = isStatic; ZSTD_cwksp_clear(ws); ws->workspaceOversizedDuration = 0; ZSTD_cwksp_assert_internal_consistency(ws); } MEM_STATIC size_t ZSTD_cwksp_create(ZSTD_cwksp* ws, size_t size, ZSTD_customMem customMem) { - void* workspace = ZSTD_malloc(size, customMem); + void* workspace = ZSTD_customMalloc(size, customMem); DEBUGLOG(4, "cwksp: creating new workspace with %zd bytes", size); RETURN_ERROR_IF(workspace == NULL, memory_allocation, "NULL pointer!"); - ZSTD_cwksp_init(ws, workspace, size); + ZSTD_cwksp_init(ws, workspace, size, ZSTD_cwksp_dynamic_alloc); return 0; } MEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) { void *ptr = ws->workspace; DEBUGLOG(4, "cwksp: freeing workspace"); - memset(ws, 0, sizeof(ZSTD_cwksp)); - ZSTD_free(ptr, customMem); + ZSTD_memset(ws, 0, sizeof(ZSTD_cwksp)); + ZSTD_customFree(ptr, customMem); } /** @@ -476,13 +507,18 @@ MEM_STATIC void ZSTD_cwksp_free(ZSTD_cwksp* ws, ZSTD_customMem customMem) { */ MEM_STATIC void ZSTD_cwksp_move(ZSTD_cwksp* dst, ZSTD_cwksp* src) { *dst = *src; - memset(src, 0, sizeof(ZSTD_cwksp)); + ZSTD_memset(src, 0, sizeof(ZSTD_cwksp)); } MEM_STATIC size_t ZSTD_cwksp_sizeof(const ZSTD_cwksp* ws) { return (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->workspace); } +MEM_STATIC size_t ZSTD_cwksp_used(const ZSTD_cwksp* ws) { + return (size_t)((BYTE*)ws->tableEnd - (BYTE*)ws->workspace) + + (size_t)((BYTE*)ws->workspaceEnd - (BYTE*)ws->allocStart); +} + MEM_STATIC int ZSTD_cwksp_reserve_failed(const ZSTD_cwksp* ws) { return ws->allocFailed; } diff --git a/thirdparty/zstd/compress/zstd_double_fast.c b/thirdparty/zstd/compress/zstd_double_fast.c index 27eed66cfe..ef12a524f7 100644 --- a/thirdparty/zstd/compress/zstd_double_fast.c +++ b/thirdparty/zstd/compress/zstd_double_fast.c @@ -31,15 +31,15 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms, * is empty. */ for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) { - U32 const current = (U32)(ip - base); + U32 const curr = (U32)(ip - base); U32 i; for (i = 0; i < fastHashFillStep; ++i) { size_t const smHash = ZSTD_hashPtr(ip + i, hBitsS, mls); size_t const lgHash = ZSTD_hashPtr(ip + i, hBitsL, 8); if (i == 0) - hashSmall[smHash] = current + i; + hashSmall[smHash] = curr + i; if (i == 0 || hashLarge[lgHash] == 0) - hashLarge[lgHash] = current + i; + hashLarge[lgHash] = curr + i; /* Only load extra positions for ZSTD_dtlm_full */ if (dtlm == ZSTD_dtlm_fast) break; @@ -108,9 +108,9 @@ size_t ZSTD_compressBlock_doubleFast_generic( /* init */ ip += (dictAndPrefixLength == 0); if (dictMode == ZSTD_noDict) { - U32 const current = (U32)(ip - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog); - U32 const maxRep = current - windowLow; + U32 const curr = (U32)(ip - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog); + U32 const maxRep = curr - windowLow; if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0; if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0; } @@ -129,17 +129,17 @@ size_t ZSTD_compressBlock_doubleFast_generic( size_t const h = ZSTD_hashPtr(ip, hBitsS, mls); size_t const dictHL = ZSTD_hashPtr(ip, dictHBitsL, 8); size_t const dictHS = ZSTD_hashPtr(ip, dictHBitsS, mls); - U32 const current = (U32)(ip-base); + U32 const curr = (U32)(ip-base); U32 const matchIndexL = hashLong[h2]; U32 matchIndexS = hashSmall[h]; const BYTE* matchLong = base + matchIndexL; const BYTE* match = base + matchIndexS; - const U32 repIndex = current + 1 - offset_1; + const U32 repIndex = curr + 1 - offset_1; const BYTE* repMatch = (dictMode == ZSTD_dictMatchState && repIndex < prefixLowestIndex) ? dictBase + (repIndex - dictIndexDelta) : base + repIndex; - hashLong[h2] = hashSmall[h] = current; /* update hash tables */ + hashLong[h2] = hashSmall[h] = curr; /* update hash tables */ /* check dictMatchState repcode */ if (dictMode == ZSTD_dictMatchState @@ -177,7 +177,7 @@ size_t ZSTD_compressBlock_doubleFast_generic( if (dictMatchL > dictStart && MEM_read64(dictMatchL) == MEM_read64(ip)) { mLength = ZSTD_count_2segments(ip+8, dictMatchL+8, iend, dictEnd, prefixLowest) + 8; - offset = (U32)(current - dictMatchIndexL - dictIndexDelta); + offset = (U32)(curr - dictMatchIndexL - dictIndexDelta); while (((ip>anchor) & (dictMatchL>dictStart)) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } /* catch up */ goto _match_found; } } @@ -209,7 +209,7 @@ _search_next_long: size_t const dictHLNext = ZSTD_hashPtr(ip+1, dictHBitsL, 8); U32 const matchIndexL3 = hashLong[hl3]; const BYTE* matchL3 = base + matchIndexL3; - hashLong[hl3] = current + 1; + hashLong[hl3] = curr + 1; /* check prefix long +1 match */ if (matchIndexL3 > prefixLowestIndex) { @@ -228,7 +228,7 @@ _search_next_long: if (dictMatchL3 > dictStart && MEM_read64(dictMatchL3) == MEM_read64(ip+1)) { mLength = ZSTD_count_2segments(ip+1+8, dictMatchL3+8, iend, dictEnd, prefixLowest) + 8; ip++; - offset = (U32)(current + 1 - dictMatchIndexL3 - dictIndexDelta); + offset = (U32)(curr + 1 - dictMatchIndexL3 - dictIndexDelta); while (((ip>anchor) & (dictMatchL3>dictStart)) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } /* catch up */ goto _match_found; } } } @@ -236,7 +236,7 @@ _search_next_long: /* if no long +1 match, explore the short match we found */ if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) { mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4; - offset = (U32)(current - matchIndexS); + offset = (U32)(curr - matchIndexS); while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ } else { mLength = ZSTD_count(ip+4, match+4, iend) + 4; @@ -260,7 +260,7 @@ _match_stored: if (ip <= ilimit) { /* Complementary insertion */ /* done after iLimit test, as candidates could be > iend-8 */ - { U32 const indexToInsert = current+2; + { U32 const indexToInsert = curr+2; hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert; hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert; @@ -401,12 +401,12 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( const BYTE* const matchLongBase = matchLongIndex < prefixStartIndex ? dictBase : base; const BYTE* matchLong = matchLongBase + matchLongIndex; - const U32 current = (U32)(ip-base); - const U32 repIndex = current + 1 - offset_1; /* offset_1 expected <= current +1 */ + const U32 curr = (U32)(ip-base); + const U32 repIndex = curr + 1 - offset_1; /* offset_1 expected <= curr +1 */ const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; size_t mLength; - hashSmall[hSmall] = hashLong[hLong] = current; /* update hash table */ + hashSmall[hSmall] = hashLong[hLong] = curr; /* update hash table */ if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */ & (repIndex > dictStartIndex)) @@ -421,7 +421,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( const BYTE* const lowMatchPtr = matchLongIndex < prefixStartIndex ? dictStart : prefixStart; U32 offset; mLength = ZSTD_count_2segments(ip+8, matchLong+8, iend, matchEnd, prefixStart) + 8; - offset = current - matchLongIndex; + offset = curr - matchLongIndex; while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */ offset_2 = offset_1; offset_1 = offset; @@ -433,19 +433,19 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( const BYTE* const match3Base = matchIndex3 < prefixStartIndex ? dictBase : base; const BYTE* match3 = match3Base + matchIndex3; U32 offset; - hashLong[h3] = current + 1; + hashLong[h3] = curr + 1; if ( (matchIndex3 > dictStartIndex) && (MEM_read64(match3) == MEM_read64(ip+1)) ) { const BYTE* const matchEnd = matchIndex3 < prefixStartIndex ? dictEnd : iend; const BYTE* const lowMatchPtr = matchIndex3 < prefixStartIndex ? dictStart : prefixStart; mLength = ZSTD_count_2segments(ip+9, match3+8, iend, matchEnd, prefixStart) + 8; ip++; - offset = current+1 - matchIndex3; + offset = curr+1 - matchIndex3; while (((ip>anchor) & (match3>lowMatchPtr)) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } /* catch up */ } else { const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend; const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart; mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4; - offset = current - matchIndex; + offset = curr - matchIndex; while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ } offset_2 = offset_1; @@ -464,7 +464,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic( if (ip <= ilimit) { /* Complementary insertion */ /* done after iLimit test, as candidates could be > iend-8 */ - { U32 const indexToInsert = current+2; + { U32 const indexToInsert = curr+2; hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert; hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base); hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert; diff --git a/thirdparty/zstd/compress/zstd_fast.c b/thirdparty/zstd/compress/zstd_fast.c index 85a3a7a91e..db7ce83d0a 100644 --- a/thirdparty/zstd/compress/zstd_fast.c +++ b/thirdparty/zstd/compress/zstd_fast.c @@ -29,16 +29,16 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms, * Insert the other positions if their hash entry is empty. */ for ( ; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) { - U32 const current = (U32)(ip - base); + U32 const curr = (U32)(ip - base); size_t const hash0 = ZSTD_hashPtr(ip, hBits, mls); - hashTable[hash0] = current; + hashTable[hash0] = curr; if (dtlm == ZSTD_dtlm_fast) continue; /* Only load extra positions for ZSTD_dtlm_full */ { U32 p; for (p = 1; p < fastHashFillStep; ++p) { size_t const hash = ZSTD_hashPtr(ip + p, hBits, mls); if (hashTable[hash] == 0) { /* not yet filled */ - hashTable[hash] = current + p; + hashTable[hash] = curr + p; } } } } } @@ -72,9 +72,9 @@ ZSTD_compressBlock_fast_generic( DEBUGLOG(5, "ZSTD_compressBlock_fast_generic"); ip0 += (ip0 == prefixStart); ip1 = ip0 + 1; - { U32 const current = (U32)(ip0 - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog); - U32 const maxRep = current - windowLow; + { U32 const curr = (U32)(ip0 - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog); + U32 const maxRep = curr - windowLow; if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0; if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0; } @@ -258,14 +258,14 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */ size_t mLength; size_t const h = ZSTD_hashPtr(ip, hlog, mls); - U32 const current = (U32)(ip-base); + U32 const curr = (U32)(ip-base); U32 const matchIndex = hashTable[h]; const BYTE* match = base + matchIndex; - const U32 repIndex = current + 1 - offset_1; + const U32 repIndex = curr + 1 - offset_1; const BYTE* repMatch = (repIndex < prefixStartIndex) ? dictBase + (repIndex - dictIndexDelta) : base + repIndex; - hashTable[h] = current; /* update hash table */ + hashTable[h] = curr; /* update hash table */ if ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex isn't overlapping dict + prefix */ && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { @@ -284,7 +284,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( continue; } else { /* found a dict match */ - U32 const offset = (U32)(current-dictMatchIndex-dictIndexDelta); + U32 const offset = (U32)(curr-dictMatchIndex-dictIndexDelta); mLength = ZSTD_count_2segments(ip+4, dictMatch+4, iend, dictEnd, prefixStart) + 4; while (((ip>anchor) & (dictMatch>dictStart)) && (ip[-1] == dictMatch[-1])) { @@ -316,8 +316,8 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic( if (ip <= ilimit) { /* Fill Table */ - assert(base+current+2 > istart); /* check base overflow */ - hashTable[ZSTD_hashPtr(base+current+2, hlog, mls)] = current+2; /* here because current+2 could be > iend-8 */ + assert(base+curr+2 > istart); /* check base overflow */ + hashTable[ZSTD_hashPtr(base+curr+2, hlog, mls)] = curr+2; /* here because curr+2 could be > iend-8 */ hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base); /* check immediate repcode */ @@ -410,13 +410,13 @@ static size_t ZSTD_compressBlock_fast_extDict_generic( const U32 matchIndex = hashTable[h]; const BYTE* const matchBase = matchIndex < prefixStartIndex ? dictBase : base; const BYTE* match = matchBase + matchIndex; - const U32 current = (U32)(ip-base); - const U32 repIndex = current + 1 - offset_1; + const U32 curr = (U32)(ip-base); + const U32 repIndex = curr + 1 - offset_1; const BYTE* const repBase = repIndex < prefixStartIndex ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; - hashTable[h] = current; /* update hash table */ - DEBUGLOG(7, "offset_1 = %u , current = %u", offset_1, current); - assert(offset_1 <= current +1); /* check repIndex */ + hashTable[h] = curr; /* update hash table */ + DEBUGLOG(7, "offset_1 = %u , curr = %u", offset_1, curr); + assert(offset_1 <= curr +1); /* check repIndex */ if ( (((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */ & (repIndex > dictStartIndex)) && (MEM_read32(repMatch) == MEM_read32(ip+1)) ) { @@ -435,7 +435,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic( } { const BYTE* const matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend; const BYTE* const lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart; - U32 const offset = current - matchIndex; + U32 const offset = curr - matchIndex; size_t mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4; while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */ offset_2 = offset_1; offset_1 = offset; /* update offset history */ @@ -446,7 +446,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic( if (ip <= ilimit) { /* Fill Table */ - hashTable[ZSTD_hashPtr(base+current+2, hlog, mls)] = current+2; + hashTable[ZSTD_hashPtr(base+curr+2, hlog, mls)] = curr+2; hashTable[ZSTD_hashPtr(ip-2, hlog, mls)] = (U32)(ip-2-base); /* check immediate repcode */ while (ip <= ilimit) { diff --git a/thirdparty/zstd/compress/zstd_lazy.c b/thirdparty/zstd/compress/zstd_lazy.c index 4cf5c88b53..49ec1b09ef 100644 --- a/thirdparty/zstd/compress/zstd_lazy.c +++ b/thirdparty/zstd/compress/zstd_lazy.c @@ -58,11 +58,11 @@ ZSTD_updateDUBT(ZSTD_matchState_t* ms, /** ZSTD_insertDUBT1() : * sort one already inserted but unsorted position - * assumption : current >= btlow == (current - btmask) + * assumption : curr >= btlow == (curr - btmask) * doesn't fail */ static void ZSTD_insertDUBT1(ZSTD_matchState_t* ms, - U32 current, const BYTE* inputEnd, + U32 curr, const BYTE* inputEnd, U32 nbCompares, U32 btLow, const ZSTD_dictMode_e dictMode) { @@ -74,41 +74,41 @@ ZSTD_insertDUBT1(ZSTD_matchState_t* ms, const BYTE* const base = ms->window.base; const BYTE* const dictBase = ms->window.dictBase; const U32 dictLimit = ms->window.dictLimit; - const BYTE* const ip = (current>=dictLimit) ? base + current : dictBase + current; - const BYTE* const iend = (current>=dictLimit) ? inputEnd : dictBase + dictLimit; + const BYTE* const ip = (curr>=dictLimit) ? base + curr : dictBase + curr; + const BYTE* const iend = (curr>=dictLimit) ? inputEnd : dictBase + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; const BYTE* match; - U32* smallerPtr = bt + 2*(current&btMask); + U32* smallerPtr = bt + 2*(curr&btMask); U32* largerPtr = smallerPtr + 1; U32 matchIndex = *smallerPtr; /* this candidate is unsorted : next sorted candidate is reached through *smallerPtr, while *largerPtr contains previous unsorted candidate (which is already saved and can be overwritten) */ U32 dummy32; /* to be nullified at the end */ U32 const windowValid = ms->window.lowLimit; U32 const maxDistance = 1U << cParams->windowLog; - U32 const windowLow = (current - windowValid > maxDistance) ? current - maxDistance : windowValid; + U32 const windowLow = (curr - windowValid > maxDistance) ? curr - maxDistance : windowValid; DEBUGLOG(8, "ZSTD_insertDUBT1(%u) (dictLimit=%u, lowLimit=%u)", - current, dictLimit, windowLow); - assert(current >= btLow); + curr, dictLimit, windowLow); + assert(curr >= btLow); assert(ip < iend); /* condition for ZSTD_count */ while (nbCompares-- && (matchIndex > windowLow)) { U32* const nextPtr = bt + 2*(matchIndex & btMask); size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - assert(matchIndex < current); + assert(matchIndex < curr); /* note : all candidates are now supposed sorted, * but it's still possible to have nextPtr[1] == ZSTD_DUBT_UNSORTED_MARK * when a real index has the same value as ZSTD_DUBT_UNSORTED_MARK */ if ( (dictMode != ZSTD_extDict) || (matchIndex+matchLength >= dictLimit) /* both in current segment*/ - || (current < dictLimit) /* both in extDict */) { + || (curr < dictLimit) /* both in extDict */) { const BYTE* const mBase = ( (dictMode != ZSTD_extDict) || (matchIndex+matchLength >= dictLimit)) ? base : dictBase; assert( (matchIndex+matchLength >= dictLimit) /* might be wrong if extDict is incorrectly set to 0 */ - || (current < dictLimit) ); + || (curr < dictLimit) ); match = mBase + matchIndex; matchLength += ZSTD_count(ip+matchLength, match+matchLength, iend); } else { @@ -119,7 +119,7 @@ ZSTD_insertDUBT1(ZSTD_matchState_t* ms, } DEBUGLOG(8, "ZSTD_insertDUBT1: comparing %u with %u : found %u common bytes ", - current, matchIndex, (U32)matchLength); + curr, matchIndex, (U32)matchLength); if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */ break; /* drop , to guarantee consistency ; miss a bit of compression, but other solutions can corrupt tree */ @@ -168,7 +168,7 @@ ZSTD_DUBT_findBetterDictMatch ( const BYTE* const base = ms->window.base; const BYTE* const prefixStart = base + ms->window.dictLimit; - U32 const current = (U32)(ip-base); + U32 const curr = (U32)(ip-base); const BYTE* const dictBase = dms->window.base; const BYTE* const dictEnd = dms->window.nextSrc; U32 const dictHighLimit = (U32)(dms->window.nextSrc - dms->window.base); @@ -195,10 +195,10 @@ ZSTD_DUBT_findBetterDictMatch ( if (matchLength > bestLength) { U32 matchIndex = dictMatchIndex + dictIndexDelta; - if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) { + if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) { DEBUGLOG(9, "ZSTD_DUBT_findBetterDictMatch(%u) : found better match length %u -> %u and offsetCode %u -> %u (dictMatchIndex %u, matchIndex %u)", - current, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, ZSTD_REP_MOVE + current - matchIndex, dictMatchIndex, matchIndex); - bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex; + curr, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, ZSTD_REP_MOVE + curr - matchIndex, dictMatchIndex, matchIndex); + bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + curr - matchIndex; } if (ip+matchLength == iend) { /* reached end of input : ip[matchLength] is not valid, no way to know if it's larger or smaller than match */ break; /* drop, to guarantee consistency (miss a little bit of compression) */ @@ -218,9 +218,9 @@ ZSTD_DUBT_findBetterDictMatch ( } if (bestLength >= MINMATCH) { - U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex; + U32 const mIndex = curr - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex; DEBUGLOG(8, "ZSTD_DUBT_findBetterDictMatch(%u) : found match of length %u and offsetCode %u (pos %u)", - current, (U32)bestLength, (U32)*offsetPtr, mIndex); + curr, (U32)bestLength, (U32)*offsetPtr, mIndex); } return bestLength; @@ -241,13 +241,13 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, U32 matchIndex = hashTable[h]; const BYTE* const base = ms->window.base; - U32 const current = (U32)(ip-base); - U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog); + U32 const curr = (U32)(ip-base); + U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog); U32* const bt = ms->chainTable; U32 const btLog = cParams->chainLog - 1; U32 const btMask = (1 << btLog) - 1; - U32 const btLow = (btMask >= current) ? 0 : current - btMask; + U32 const btLow = (btMask >= curr) ? 0 : curr - btMask; U32 const unsortLimit = MAX(btLow, windowLow); U32* nextCandidate = bt + 2*(matchIndex&btMask); @@ -256,8 +256,9 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, U32 nbCandidates = nbCompares; U32 previousCandidate = 0; - DEBUGLOG(7, "ZSTD_DUBT_findBestMatch (%u) ", current); + DEBUGLOG(7, "ZSTD_DUBT_findBestMatch (%u) ", curr); assert(ip <= iend-8); /* required for h calculation */ + assert(dictMode != ZSTD_dedicatedDictSearch); /* reach end of unsorted candidates list */ while ( (matchIndex > unsortLimit) @@ -299,14 +300,14 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, const U32 dictLimit = ms->window.dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; - U32* smallerPtr = bt + 2*(current&btMask); - U32* largerPtr = bt + 2*(current&btMask) + 1; - U32 matchEndIdx = current + 8 + 1; + U32* smallerPtr = bt + 2*(curr&btMask); + U32* largerPtr = bt + 2*(curr&btMask) + 1; + U32 matchEndIdx = curr + 8 + 1; U32 dummy32; /* to be nullified at the end */ size_t bestLength = 0; matchIndex = hashTable[h]; - hashTable[h] = current; /* Update Hash Table */ + hashTable[h] = curr; /* Update Hash Table */ while (nbCompares-- && (matchIndex > windowLow)) { U32* const nextPtr = bt + 2*(matchIndex & btMask); @@ -326,8 +327,8 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, if (matchLength > bestLength) { if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength; - if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(current-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) - bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + current - matchIndex; + if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) + bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + curr - matchIndex; if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */ if (dictMode == ZSTD_dictMatchState) { nbCompares = 0; /* in addition to avoiding checking any @@ -363,12 +364,12 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms, mls, dictMode); } - assert(matchEndIdx > current+8); /* ensure nextToUpdate is increased */ + assert(matchEndIdx > curr+8); /* ensure nextToUpdate is increased */ ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */ if (bestLength >= MINMATCH) { - U32 const mIndex = current - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex; + U32 const mIndex = curr - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex; DEBUGLOG(8, "ZSTD_DUBT_findBestMatch(%u) : found match of length %u and offsetCode %u (pos %u)", - current, (U32)bestLength, (U32)*offsetPtr, mIndex); + curr, (U32)bestLength, (U32)*offsetPtr, mIndex); } return bestLength; } @@ -446,7 +447,7 @@ static size_t ZSTD_BtFindBestMatch_extDict_selectMLS ( /* Update chains up to ip (excluded) Assumption : always within prefix (i.e. not within extDict) */ -static U32 ZSTD_insertAndFindFirstIndex_internal( +FORCE_INLINE_TEMPLATE U32 ZSTD_insertAndFindFirstIndex_internal( ZSTD_matchState_t* ms, const ZSTD_compressionParameters* const cParams, const BYTE* ip, U32 const mls) @@ -475,6 +476,121 @@ U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) { return ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, ms->cParams.minMatch); } +void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip) +{ + const BYTE* const base = ms->window.base; + U32 const target = (U32)(ip - base); + U32* const hashTable = ms->hashTable; + U32* const chainTable = ms->chainTable; + U32 const chainSize = 1 << ms->cParams.chainLog; + U32 idx = ms->nextToUpdate; + U32 const minChain = chainSize < target ? target - chainSize : idx; + U32 const bucketSize = 1 << ZSTD_LAZY_DDSS_BUCKET_LOG; + U32 const cacheSize = bucketSize - 1; + U32 const chainAttempts = (1 << ms->cParams.searchLog) - cacheSize; + U32 const chainLimit = chainAttempts > 255 ? 255 : chainAttempts; + + /* We know the hashtable is oversized by a factor of `bucketSize`. + * We are going to temporarily pretend `bucketSize == 1`, keeping only a + * single entry. We will use the rest of the space to construct a temporary + * chaintable. + */ + U32 const hashLog = ms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG; + U32* const tmpHashTable = hashTable; + U32* const tmpChainTable = hashTable + ((size_t)1 << hashLog); + U32 const tmpChainSize = ((1 << ZSTD_LAZY_DDSS_BUCKET_LOG) - 1) << hashLog; + U32 const tmpMinChain = tmpChainSize < target ? target - tmpChainSize : idx; + + U32 hashIdx; + + assert(ms->cParams.chainLog <= 24); + assert(ms->cParams.hashLog >= ms->cParams.chainLog); + assert(idx != 0); + assert(tmpMinChain <= minChain); + + /* fill conventional hash table and conventional chain table */ + for ( ; idx < target; idx++) { + U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch); + if (idx >= tmpMinChain) { + tmpChainTable[idx - tmpMinChain] = hashTable[h]; + } + tmpHashTable[h] = idx; + } + + /* sort chains into ddss chain table */ + { + U32 chainPos = 0; + for (hashIdx = 0; hashIdx < (1U << hashLog); hashIdx++) { + U32 count; + U32 countBeyondMinChain = 0; + U32 i = tmpHashTable[hashIdx]; + for (count = 0; i >= tmpMinChain && count < cacheSize; count++) { + /* skip through the chain to the first position that won't be + * in the hash cache bucket */ + if (i < minChain) { + countBeyondMinChain++; + } + i = tmpChainTable[i - tmpMinChain]; + } + if (count == cacheSize) { + for (count = 0; count < chainLimit;) { + if (i < minChain) { + if (!i || countBeyondMinChain++ > cacheSize) { + /* only allow pulling `cacheSize` number of entries + * into the cache or chainTable beyond `minChain`, + * to replace the entries pulled out of the + * chainTable into the cache. This lets us reach + * back further without increasing the total number + * of entries in the chainTable, guaranteeing the + * DDSS chain table will fit into the space + * allocated for the regular one. */ + break; + } + } + chainTable[chainPos++] = i; + count++; + if (i < tmpMinChain) { + break; + } + i = tmpChainTable[i - tmpMinChain]; + } + } else { + count = 0; + } + if (count) { + tmpHashTable[hashIdx] = ((chainPos - count) << 8) + count; + } else { + tmpHashTable[hashIdx] = 0; + } + } + assert(chainPos <= chainSize); /* I believe this is guaranteed... */ + } + + /* move chain pointers into the last entry of each hash bucket */ + for (hashIdx = (1 << hashLog); hashIdx; ) { + U32 const bucketIdx = --hashIdx << ZSTD_LAZY_DDSS_BUCKET_LOG; + U32 const chainPackedPointer = tmpHashTable[hashIdx]; + U32 i; + for (i = 0; i < cacheSize; i++) { + hashTable[bucketIdx + i] = 0; + } + hashTable[bucketIdx + bucketSize - 1] = chainPackedPointer; + } + + /* fill the buckets of the hash table */ + for (idx = ms->nextToUpdate; idx < target; idx++) { + U32 const h = (U32)ZSTD_hashPtr(base + idx, hashLog, ms->cParams.minMatch) + << ZSTD_LAZY_DDSS_BUCKET_LOG; + U32 i; + /* Shift hash cache down 1. */ + for (i = cacheSize - 1; i; i--) + hashTable[h + i] = hashTable[h + i - 1]; + hashTable[h] = idx; + } + + ms->nextToUpdate = target; +} + /* inlining is important to hardwire a hot branch (template emulation) */ FORCE_INLINE_TEMPLATE @@ -493,20 +609,33 @@ size_t ZSTD_HcFindBestMatch_generic ( const U32 dictLimit = ms->window.dictLimit; const BYTE* const prefixStart = base + dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; - const U32 current = (U32)(ip-base); + const U32 curr = (U32)(ip-base); const U32 maxDistance = 1U << cParams->windowLog; const U32 lowestValid = ms->window.lowLimit; - const U32 withinMaxDistance = (current - lowestValid > maxDistance) ? current - maxDistance : lowestValid; + const U32 withinMaxDistance = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid; const U32 isDictionary = (ms->loadedDictEnd != 0); const U32 lowLimit = isDictionary ? lowestValid : withinMaxDistance; - const U32 minChain = current > chainSize ? current - chainSize : 0; + const U32 minChain = curr > chainSize ? curr - chainSize : 0; U32 nbAttempts = 1U << cParams->searchLog; size_t ml=4-1; + const ZSTD_matchState_t* const dms = ms->dictMatchState; + const U32 ddsHashLog = dictMode == ZSTD_dedicatedDictSearch + ? dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG : 0; + const size_t ddsIdx = dictMode == ZSTD_dedicatedDictSearch + ? ZSTD_hashPtr(ip, ddsHashLog, mls) << ZSTD_LAZY_DDSS_BUCKET_LOG : 0; + + U32 matchIndex; + + if (dictMode == ZSTD_dedicatedDictSearch) { + const U32* entry = &dms->hashTable[ddsIdx]; + PREFETCH_L1(entry); + } + /* HC4 match finder */ - U32 matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls); + matchIndex = ZSTD_insertAndFindFirstIndex_internal(ms, cParams, ip, mls); - for ( ; (matchIndex>lowLimit) & (nbAttempts>0) ; nbAttempts--) { + for ( ; (matchIndex>=lowLimit) & (nbAttempts>0) ; nbAttempts--) { size_t currentMl=0; if ((dictMode != ZSTD_extDict) || matchIndex >= dictLimit) { const BYTE* const match = base + matchIndex; @@ -523,7 +652,7 @@ size_t ZSTD_HcFindBestMatch_generic ( /* save best solution */ if (currentMl > ml) { ml = currentMl; - *offsetPtr = current - matchIndex + ZSTD_REP_MOVE; + *offsetPtr = curr - matchIndex + ZSTD_REP_MOVE; if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ } @@ -531,8 +660,92 @@ size_t ZSTD_HcFindBestMatch_generic ( matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask); } - if (dictMode == ZSTD_dictMatchState) { - const ZSTD_matchState_t* const dms = ms->dictMatchState; + if (dictMode == ZSTD_dedicatedDictSearch) { + const U32 ddsLowestIndex = dms->window.dictLimit; + const BYTE* const ddsBase = dms->window.base; + const BYTE* const ddsEnd = dms->window.nextSrc; + const U32 ddsSize = (U32)(ddsEnd - ddsBase); + const U32 ddsIndexDelta = dictLimit - ddsSize; + const U32 bucketSize = (1 << ZSTD_LAZY_DDSS_BUCKET_LOG); + const U32 bucketLimit = nbAttempts < bucketSize - 1 ? nbAttempts : bucketSize - 1; + U32 ddsAttempt; + + for (ddsAttempt = 0; ddsAttempt < bucketSize - 1; ddsAttempt++) { + PREFETCH_L1(ddsBase + dms->hashTable[ddsIdx + ddsAttempt]); + } + + { + U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1]; + U32 const chainIndex = chainPackedPointer >> 8; + + PREFETCH_L1(&dms->chainTable[chainIndex]); + } + + for (ddsAttempt = 0; ddsAttempt < bucketLimit; ddsAttempt++) { + size_t currentMl=0; + const BYTE* match; + matchIndex = dms->hashTable[ddsIdx + ddsAttempt]; + match = ddsBase + matchIndex; + + if (!matchIndex) { + return ml; + } + + /* guaranteed by table construction */ + (void)ddsLowestIndex; + assert(matchIndex >= ddsLowestIndex); + assert(match+4 <= ddsEnd); + if (MEM_read32(match) == MEM_read32(ip)) { + /* assumption : matchIndex <= dictLimit-4 (by table construction) */ + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4; + } + + /* save best solution */ + if (currentMl > ml) { + ml = currentMl; + *offsetPtr = curr - (matchIndex + ddsIndexDelta) + ZSTD_REP_MOVE; + if (ip+currentMl == iLimit) { + /* best possible, avoids read overflow on next attempt */ + return ml; + } + } + } + + { + U32 const chainPackedPointer = dms->hashTable[ddsIdx + bucketSize - 1]; + U32 chainIndex = chainPackedPointer >> 8; + U32 const chainLength = chainPackedPointer & 0xFF; + U32 const chainAttempts = nbAttempts - ddsAttempt; + U32 const chainLimit = chainAttempts > chainLength ? chainLength : chainAttempts; + U32 chainAttempt; + + for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++) { + PREFETCH_L1(ddsBase + dms->chainTable[chainIndex + chainAttempt]); + } + + for (chainAttempt = 0 ; chainAttempt < chainLimit; chainAttempt++, chainIndex++) { + size_t currentMl=0; + const BYTE* match; + matchIndex = dms->chainTable[chainIndex]; + match = ddsBase + matchIndex; + + /* guaranteed by table construction */ + assert(matchIndex >= ddsLowestIndex); + assert(match+4 <= ddsEnd); + if (MEM_read32(match) == MEM_read32(ip)) { + /* assumption : matchIndex <= dictLimit-4 (by table construction) */ + currentMl = ZSTD_count_2segments(ip+4, match+4, iLimit, ddsEnd, prefixStart) + 4; + } + + /* save best solution */ + if (currentMl > ml) { + ml = currentMl; + *offsetPtr = curr - (matchIndex + ddsIndexDelta) + ZSTD_REP_MOVE; + if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ + } + } + } + } else if (dictMode == ZSTD_dictMatchState) { const U32* const dmsChainTable = dms->chainTable; const U32 dmsChainSize = (1 << dms->cParams.chainLog); const U32 dmsChainMask = dmsChainSize - 1; @@ -545,7 +758,7 @@ size_t ZSTD_HcFindBestMatch_generic ( matchIndex = dms->hashTable[ZSTD_hashPtr(ip, dms->cParams.hashLog, mls)]; - for ( ; (matchIndex>dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) { + for ( ; (matchIndex>=dmsLowestIndex) & (nbAttempts>0) ; nbAttempts--) { size_t currentMl=0; const BYTE* const match = dmsBase + matchIndex; assert(match+4 <= dmsEnd); @@ -555,11 +768,12 @@ size_t ZSTD_HcFindBestMatch_generic ( /* save best solution */ if (currentMl > ml) { ml = currentMl; - *offsetPtr = current - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE; + *offsetPtr = curr - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE; if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */ } if (matchIndex <= dmsMinChain) break; + matchIndex = dmsChainTable[matchIndex & dmsChainMask]; } } @@ -600,6 +814,22 @@ static size_t ZSTD_HcFindBestMatch_dictMatchState_selectMLS ( } +static size_t ZSTD_HcFindBestMatch_dedicatedDictSearch_selectMLS ( + ZSTD_matchState_t* ms, + const BYTE* ip, const BYTE* const iLimit, + size_t* offsetPtr) +{ + switch(ms->cParams.minMatch) + { + default : /* includes case 3 */ + case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_dedicatedDictSearch); + case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_dedicatedDictSearch); + case 7 : + case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_dedicatedDictSearch); + } +} + + FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS ( ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* const iLimit, @@ -641,39 +871,62 @@ ZSTD_compressBlock_lazy_generic( typedef size_t (*searchMax_f)( ZSTD_matchState_t* ms, const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr); - searchMax_f const searchMax = dictMode == ZSTD_dictMatchState ? - (searchMethod==search_binaryTree ? ZSTD_BtFindBestMatch_dictMatchState_selectMLS - : ZSTD_HcFindBestMatch_dictMatchState_selectMLS) : - (searchMethod==search_binaryTree ? ZSTD_BtFindBestMatch_selectMLS - : ZSTD_HcFindBestMatch_selectMLS); + + /** + * This table is indexed first by the four ZSTD_dictMode_e values, and then + * by the two searchMethod_e values. NULLs are placed for configurations + * that should never occur (extDict modes go to the other implementation + * below and there is no DDSS for binary tree search yet). + */ + const searchMax_f searchFuncs[4][2] = { + { + ZSTD_HcFindBestMatch_selectMLS, + ZSTD_BtFindBestMatch_selectMLS + }, + { + NULL, + NULL + }, + { + ZSTD_HcFindBestMatch_dictMatchState_selectMLS, + ZSTD_BtFindBestMatch_dictMatchState_selectMLS + }, + { + ZSTD_HcFindBestMatch_dedicatedDictSearch_selectMLS, + NULL + } + }; + + searchMax_f const searchMax = searchFuncs[dictMode][searchMethod == search_binaryTree]; U32 offset_1 = rep[0], offset_2 = rep[1], savedOffset=0; + const int isDMS = dictMode == ZSTD_dictMatchState; + const int isDDS = dictMode == ZSTD_dedicatedDictSearch; + const int isDxS = isDMS || isDDS; const ZSTD_matchState_t* const dms = ms->dictMatchState; - const U32 dictLowestIndex = dictMode == ZSTD_dictMatchState ? - dms->window.dictLimit : 0; - const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ? - dms->window.base : NULL; - const BYTE* const dictLowest = dictMode == ZSTD_dictMatchState ? - dictBase + dictLowestIndex : NULL; - const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ? - dms->window.nextSrc : NULL; - const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ? + const U32 dictLowestIndex = isDxS ? dms->window.dictLimit : 0; + const BYTE* const dictBase = isDxS ? dms->window.base : NULL; + const BYTE* const dictLowest = isDxS ? dictBase + dictLowestIndex : NULL; + const BYTE* const dictEnd = isDxS ? dms->window.nextSrc : NULL; + const U32 dictIndexDelta = isDxS ? prefixLowestIndex - (U32)(dictEnd - dictBase) : 0; const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictLowest)); + assert(searchMax != NULL); + DEBUGLOG(5, "ZSTD_compressBlock_lazy_generic (dictMode=%u)", (U32)dictMode); /* init */ ip += (dictAndPrefixLength == 0); if (dictMode == ZSTD_noDict) { - U32 const current = (U32)(ip - base); - U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, ms->cParams.windowLog); - U32 const maxRep = current - windowLow; + U32 const curr = (U32)(ip - base); + U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, ms->cParams.windowLog); + U32 const maxRep = curr - windowLow; if (offset_2 > maxRep) savedOffset = offset_2, offset_2 = 0; if (offset_1 > maxRep) savedOffset = offset_1, offset_1 = 0; } - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { /* dictMatchState repCode checks don't currently handle repCode == 0 * disabling. */ assert(offset_1 <= dictAndPrefixLength); @@ -693,9 +946,9 @@ ZSTD_compressBlock_lazy_generic( const BYTE* start=ip+1; /* check repCode */ - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { const U32 repIndex = (U32)(ip - base) + 1 - offset_1; - const BYTE* repMatch = (dictMode == ZSTD_dictMatchState + const BYTE* repMatch = ((dictMode == ZSTD_dictMatchState || dictMode == ZSTD_dedicatedDictSearch) && repIndex < prefixLowestIndex) ? dictBase + (repIndex - dictIndexDelta) : base + repIndex; @@ -736,7 +989,7 @@ ZSTD_compressBlock_lazy_generic( if ((mlRep >= 4) && (gain2 > gain1)) matchLength = mlRep, offset = 0, start = ip; } - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { const U32 repIndex = (U32)(ip - base) - offset_1; const BYTE* repMatch = repIndex < prefixLowestIndex ? dictBase + (repIndex - dictIndexDelta) : @@ -771,7 +1024,7 @@ ZSTD_compressBlock_lazy_generic( if ((mlRep >= 4) && (gain2 > gain1)) matchLength = mlRep, offset = 0, start = ip; } - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { const U32 repIndex = (U32)(ip - base) - offset_1; const BYTE* repMatch = repIndex < prefixLowestIndex ? dictBase + (repIndex - dictIndexDelta) : @@ -809,7 +1062,7 @@ ZSTD_compressBlock_lazy_generic( && (start[-1] == (start-(offset-ZSTD_REP_MOVE))[-1]) ) /* only search for offset within prefix */ { start--; matchLength++; } } - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE)); const BYTE* match = (matchIndex < prefixLowestIndex) ? dictBase + matchIndex - dictIndexDelta : base + matchIndex; const BYTE* const mStart = (matchIndex < prefixLowestIndex) ? dictLowest : prefixLowest; @@ -825,12 +1078,11 @@ _storeSequence: } /* check immediate repcode */ - if (dictMode == ZSTD_dictMatchState) { + if (isDxS) { while (ip <= ilimit) { U32 const current2 = (U32)(ip-base); U32 const repIndex = current2 - offset_2; - const BYTE* repMatch = dictMode == ZSTD_dictMatchState - && repIndex < prefixLowestIndex ? + const BYTE* repMatch = repIndex < prefixLowestIndex ? dictBase - dictIndexDelta + repIndex : base + repIndex; if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex) >= 3 /* intentional overflow */) @@ -925,6 +1177,28 @@ size_t ZSTD_compressBlock_greedy_dictMatchState( } +size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 2, ZSTD_dedicatedDictSearch); +} + +size_t ZSTD_compressBlock_lazy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 1, ZSTD_dedicatedDictSearch); +} + +size_t ZSTD_compressBlock_greedy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize) +{ + return ZSTD_compressBlock_lazy_generic(ms, seqStore, rep, src, srcSize, search_hashChain, 0, ZSTD_dedicatedDictSearch); +} + + FORCE_INLINE_TEMPLATE size_t ZSTD_compressBlock_lazy_extDict_generic( ZSTD_matchState_t* ms, seqStore_t* seqStore, @@ -968,11 +1242,11 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( size_t matchLength=0; size_t offset=0; const BYTE* start=ip+1; - U32 current = (U32)(ip-base); + U32 curr = (U32)(ip-base); /* check repCode */ - { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current+1, windowLog); - const U32 repIndex = (U32)(current+1 - offset_1); + { const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr+1, windowLog); + const U32 repIndex = (U32)(curr+1 - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ @@ -999,11 +1273,11 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( if (depth>=1) while (ip<ilimit) { ip ++; - current++; + curr++; /* check repCode */ if (offset) { - const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog); - const U32 repIndex = (U32)(current - offset_1); + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog); + const U32 repIndex = (U32)(curr - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ @@ -1030,11 +1304,11 @@ size_t ZSTD_compressBlock_lazy_extDict_generic( /* let's find an even better one */ if ((depth==2) && (ip<ilimit)) { ip ++; - current++; + curr++; /* check repCode */ if (offset) { - const U32 windowLow = ZSTD_getLowestMatchIndex(ms, current, windowLog); - const U32 repIndex = (U32)(current - offset_1); + const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog); + const U32 repIndex = (U32)(curr - offset_1); const BYTE* const repBase = repIndex < dictLimit ? dictBase : base; const BYTE* const repMatch = repBase + repIndex; if (((U32)((dictLimit-1) - repIndex) >= 3) & (repIndex > windowLow)) /* intentional overflow */ diff --git a/thirdparty/zstd/compress/zstd_lazy.h b/thirdparty/zstd/compress/zstd_lazy.h index 581936f03b..d0214d5e73 100644 --- a/thirdparty/zstd/compress/zstd_lazy.h +++ b/thirdparty/zstd/compress/zstd_lazy.h @@ -17,8 +17,18 @@ extern "C" { #include "zstd_compress_internal.h" +/** + * Dedicated Dictionary Search Structure bucket log. In the + * ZSTD_dedicatedDictSearch mode, the hashTable has + * 2 ** ZSTD_LAZY_DDSS_BUCKET_LOG entries in each bucket, rather than just + * one. + */ +#define ZSTD_LAZY_DDSS_BUCKET_LOG 2 + U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip); +void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const BYTE* const ip); + void ZSTD_preserveUnsortedMark (U32* const table, U32 const size, U32 const reducerValue); /*! used in ZSTD_reduceIndex(). preemptively increase value of ZSTD_DUBT_UNSORTED_MARK */ size_t ZSTD_compressBlock_btlazy2( @@ -47,6 +57,16 @@ size_t ZSTD_compressBlock_greedy_dictMatchState( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy2_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_lazy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); +size_t ZSTD_compressBlock_greedy_dedicatedDictSearch( + ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], + void const* src, size_t srcSize); + size_t ZSTD_compressBlock_greedy_extDict( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize); diff --git a/thirdparty/zstd/compress/zstd_ldm.c b/thirdparty/zstd/compress/zstd_ldm.c index 8c47948358..3f3d7c46ab 100644 --- a/thirdparty/zstd/compress/zstd_ldm.c +++ b/thirdparty/zstd/compress/zstd_ldm.c @@ -27,13 +27,6 @@ void ZSTD_ldm_adjustParameters(ldmParams_t* params, DEBUGLOG(4, "ZSTD_ldm_adjustParameters"); if (!params->bucketSizeLog) params->bucketSizeLog = LDM_BUCKET_SIZE_LOG; if (!params->minMatchLength) params->minMatchLength = LDM_MIN_MATCH_LENGTH; - if (cParams->strategy >= ZSTD_btopt) { - /* Get out of the way of the optimal parser */ - U32 const minMatch = MAX(cParams->targetLength, params->minMatchLength); - assert(minMatch >= ZSTD_LDM_MINMATCH_MIN); - assert(minMatch <= ZSTD_LDM_MINMATCH_MAX); - params->minMatchLength = minMatch; - } if (params->hashLog == 0) { params->hashLog = MAX(ZSTD_HASHLOG_MIN, params->windowLog - LDM_HASH_RLOG); assert(params->hashLog <= ZSTD_HASHLOG_MAX); @@ -150,10 +143,10 @@ static void ZSTD_ldm_makeEntryAndInsertByTag(ldmState_t* ldmState, * We count only bytes where pMatch >= pBase and pIn >= pAnchor. */ static size_t ZSTD_ldm_countBackwardsMatch( const BYTE* pIn, const BYTE* pAnchor, - const BYTE* pMatch, const BYTE* pBase) + const BYTE* pMatch, const BYTE* pMatchBase) { size_t matchLength = 0; - while (pIn > pAnchor && pMatch > pBase && pIn[-1] == pMatch[-1]) { + while (pIn > pAnchor && pMatch > pMatchBase && pIn[-1] == pMatch[-1]) { pIn--; pMatch--; matchLength++; @@ -161,6 +154,27 @@ static size_t ZSTD_ldm_countBackwardsMatch( return matchLength; } +/** ZSTD_ldm_countBackwardsMatch_2segments() : + * Returns the number of bytes that match backwards from pMatch, + * even with the backwards match spanning 2 different segments. + * + * On reaching `pMatchBase`, start counting from mEnd */ +static size_t ZSTD_ldm_countBackwardsMatch_2segments( + const BYTE* pIn, const BYTE* pAnchor, + const BYTE* pMatch, const BYTE* pMatchBase, + const BYTE* pExtDictStart, const BYTE* pExtDictEnd) +{ + size_t matchLength = ZSTD_ldm_countBackwardsMatch(pIn, pAnchor, pMatch, pMatchBase); + if (pMatch - matchLength != pMatchBase || pMatchBase == pExtDictStart) { + /* If backwards match is entirely in the extDict or prefix, immediately return */ + return matchLength; + } + DEBUGLOG(7, "ZSTD_ldm_countBackwardsMatch_2segments: found 2-parts backwards match (length in prefix==%zu)", matchLength); + matchLength += ZSTD_ldm_countBackwardsMatch(pIn - matchLength, pAnchor, pExtDictEnd, pExtDictStart); + DEBUGLOG(7, "final backwards match length = %zu", matchLength); + return matchLength; +} + /** ZSTD_ldm_fillFastTables() : * * Fills the relevant tables for the ZSTD_fast and ZSTD_dfast strategies. @@ -246,10 +260,10 @@ void ZSTD_ldm_fillHashTable( * (after a long match, only update tables a limited amount). */ static void ZSTD_ldm_limitTableUpdate(ZSTD_matchState_t* ms, const BYTE* anchor) { - U32 const current = (U32)(anchor - ms->window.base); - if (current > ms->nextToUpdate + 1024) { + U32 const curr = (U32)(anchor - ms->window.base); + if (curr > ms->nextToUpdate + 1024) { ms->nextToUpdate = - current - MIN(512, current - ms->nextToUpdate - 1024); + curr - MIN(512, curr - ms->nextToUpdate - 1024); } } @@ -286,7 +300,7 @@ static size_t ZSTD_ldm_generateSequences_internal( while (ip <= ilimit) { size_t mLength; - U32 const current = (U32)(ip - base); + U32 const curr = (U32)(ip - base); size_t forwardMatchLength = 0, backwardMatchLength = 0; ldmEntry_t* bestEntry = NULL; if (ip != istart) { @@ -336,8 +350,9 @@ static size_t ZSTD_ldm_generateSequences_internal( continue; } curBackwardMatchLength = - ZSTD_ldm_countBackwardsMatch(ip, anchor, pMatch, - lowMatchPtr); + ZSTD_ldm_countBackwardsMatch_2segments(ip, anchor, + pMatch, lowMatchPtr, + dictStart, dictEnd); curTotalMatchLength = curForwardMatchLength + curBackwardMatchLength; } else { /* !extDict */ @@ -365,7 +380,7 @@ static size_t ZSTD_ldm_generateSequences_internal( /* No match found -- continue searching */ if (bestEntry == NULL) { ZSTD_ldm_makeEntryAndInsertByTag(ldmState, rollingHash, - hBits, current, + hBits, curr, *params); ip++; continue; @@ -377,11 +392,11 @@ static size_t ZSTD_ldm_generateSequences_internal( { /* Store the sequence: - * ip = current - backwardMatchLength + * ip = curr - backwardMatchLength * The match is at (bestEntry->offset - backwardMatchLength) */ U32 const matchIndex = bestEntry->offset; - U32 const offset = current - matchIndex; + U32 const offset = curr - matchIndex; rawSeq* const seq = rawSeqStore->seq + rawSeqStore->size; /* Out of sequence storage */ @@ -562,6 +577,23 @@ static rawSeq maybeSplitSequence(rawSeqStore_t* rawSeqStore, return sequence; } +void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) { + U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes); + while (currPos && rawSeqStore->pos < rawSeqStore->size) { + rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos]; + if (currPos >= currSeq.litLength + currSeq.matchLength) { + currPos -= currSeq.litLength + currSeq.matchLength; + rawSeqStore->pos++; + } else { + rawSeqStore->posInSequence = currPos; + break; + } + } + if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) { + rawSeqStore->posInSequence = 0; + } +} + size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], void const* src, size_t srcSize) @@ -577,6 +609,15 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, BYTE const* ip = istart; DEBUGLOG(5, "ZSTD_ldm_blockCompress: srcSize=%zu", srcSize); + /* If using opt parser, use LDMs only as candidates rather than always accepting them */ + if (cParams->strategy >= ZSTD_btopt) { + size_t lastLLSize; + ms->ldmSeqStore = rawSeqStore; + lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize); + ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore, srcSize); + return lastLLSize; + } + assert(rawSeqStore->pos <= rawSeqStore->size); assert(rawSeqStore->size <= rawSeqStore->capacity); /* Loop through each sequence and apply the block compressor to the lits */ diff --git a/thirdparty/zstd/compress/zstd_ldm.h b/thirdparty/zstd/compress/zstd_ldm.h index 229ea05a9e..6561024e4c 100644 --- a/thirdparty/zstd/compress/zstd_ldm.h +++ b/thirdparty/zstd/compress/zstd_ldm.h @@ -78,6 +78,12 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore, void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch); +/* ZSTD_ldm_skipRawSeqStoreBytes(): + * Moves forward in rawSeqStore by nbBytes, updating fields 'pos' and 'posInSequence'. + * Not to be used in conjunction with ZSTD_ldm_skipSequences(). + * Must be called for data with is not passed to ZSTD_ldm_blockCompress(). + */ +void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes); /** ZSTD_ldm_getTableSize() : * Estimate the space needed for long distance matching tables or 0 if LDM is diff --git a/thirdparty/zstd/compress/zstd_opt.c b/thirdparty/zstd/compress/zstd_opt.c index 36fff050cf..e55c459deb 100644 --- a/thirdparty/zstd/compress/zstd_opt.c +++ b/thirdparty/zstd/compress/zstd_opt.c @@ -386,32 +386,32 @@ static U32 ZSTD_insertBt1( const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; const BYTE* match; - const U32 current = (U32)(ip-base); - const U32 btLow = btMask >= current ? 0 : current - btMask; - U32* smallerPtr = bt + 2*(current&btMask); + const U32 curr = (U32)(ip-base); + const U32 btLow = btMask >= curr ? 0 : curr - btMask; + U32* smallerPtr = bt + 2*(curr&btMask); U32* largerPtr = smallerPtr + 1; U32 dummy32; /* to be nullified at the end */ U32 const windowLow = ms->window.lowLimit; - U32 matchEndIdx = current+8+1; + U32 matchEndIdx = curr+8+1; size_t bestLength = 8; U32 nbCompares = 1U << cParams->searchLog; #ifdef ZSTD_C_PREDICT - U32 predictedSmall = *(bt + 2*((current-1)&btMask) + 0); - U32 predictedLarge = *(bt + 2*((current-1)&btMask) + 1); + U32 predictedSmall = *(bt + 2*((curr-1)&btMask) + 0); + U32 predictedLarge = *(bt + 2*((curr-1)&btMask) + 1); predictedSmall += (predictedSmall>0); predictedLarge += (predictedLarge>0); #endif /* ZSTD_C_PREDICT */ - DEBUGLOG(8, "ZSTD_insertBt1 (%u)", current); + DEBUGLOG(8, "ZSTD_insertBt1 (%u)", curr); assert(ip <= iend-8); /* required for h calculation */ - hashTable[h] = current; /* Update Hash Table */ + hashTable[h] = curr; /* Update Hash Table */ assert(windowLow > 0); while (nbCompares-- && (matchIndex >= windowLow)) { U32* const nextPtr = bt + 2*(matchIndex & btMask); size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - assert(matchIndex < current); + assert(matchIndex < curr); #ifdef ZSTD_C_PREDICT /* note : can create issues when hlog small <= 11 */ const U32* predictPtr = bt + 2*((matchIndex-1) & btMask); /* written this way, as bt is a roll buffer */ @@ -474,8 +474,8 @@ static U32 ZSTD_insertBt1( *smallerPtr = *largerPtr = 0; { U32 positions = 0; if (bestLength > 384) positions = MIN(192, (U32)(bestLength - 384)); /* speed optimization */ - assert(matchEndIdx > current + 8); - return MAX(positions, matchEndIdx - (current + 8)); + assert(matchEndIdx > curr + 8); + return MAX(positions, matchEndIdx - (curr + 8)); } } @@ -519,7 +519,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( const ZSTD_compressionParameters* const cParams = &ms->cParams; U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1); const BYTE* const base = ms->window.base; - U32 const current = (U32)(ip-base); + U32 const curr = (U32)(ip-base); U32 const hashLog = cParams->hashLog; U32 const minMatch = (mls==3) ? 3 : 4; U32* const hashTable = ms->hashTable; @@ -533,12 +533,12 @@ U32 ZSTD_insertBtAndGetAllMatches ( U32 const dictLimit = ms->window.dictLimit; const BYTE* const dictEnd = dictBase + dictLimit; const BYTE* const prefixStart = base + dictLimit; - U32 const btLow = (btMask >= current) ? 0 : current - btMask; - U32 const windowLow = ZSTD_getLowestMatchIndex(ms, current, cParams->windowLog); + U32 const btLow = (btMask >= curr) ? 0 : curr - btMask; + U32 const windowLow = ZSTD_getLowestMatchIndex(ms, curr, cParams->windowLog); U32 const matchLow = windowLow ? windowLow : 1; - U32* smallerPtr = bt + 2*(current&btMask); - U32* largerPtr = bt + 2*(current&btMask) + 1; - U32 matchEndIdx = current+8+1; /* farthest referenced position of any match => detects repetitive patterns */ + U32* smallerPtr = bt + 2*(curr&btMask); + U32* largerPtr = bt + 2*(curr&btMask) + 1; + U32 matchEndIdx = curr+8+1; /* farthest referenced position of any match => detects repetitive patterns */ U32 dummy32; /* to be nullified at the end */ U32 mnum = 0; U32 nbCompares = 1U << cParams->searchLog; @@ -557,7 +557,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( U32 const dmsBtLow = dictMode == ZSTD_dictMatchState && dmsBtMask < dmsHighLimit - dmsLowLimit ? dmsHighLimit - dmsBtMask : dmsLowLimit; size_t bestLength = lengthToBeat-1; - DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", current); + DEBUGLOG(8, "ZSTD_insertBtAndGetAllMatches: current=%u", curr); /* check repCode */ assert(ll0 <= 1); /* necessarily 1 or 0 */ @@ -565,29 +565,29 @@ U32 ZSTD_insertBtAndGetAllMatches ( U32 repCode; for (repCode = ll0; repCode < lastR; repCode++) { U32 const repOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode]; - U32 const repIndex = current - repOffset; + U32 const repIndex = curr - repOffset; U32 repLen = 0; - assert(current >= dictLimit); - if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < current-dictLimit) { /* equivalent to `current > repIndex >= dictLimit` */ + assert(curr >= dictLimit); + if (repOffset-1 /* intentional overflow, discards 0 and -1 */ < curr-dictLimit) { /* equivalent to `curr > repIndex >= dictLimit` */ /* We must validate the repcode offset because when we're using a dictionary the * valid offset range shrinks when the dictionary goes out of bounds. */ if ((repIndex >= windowLow) & (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(ip - repOffset, minMatch))) { repLen = (U32)ZSTD_count(ip+minMatch, ip+minMatch-repOffset, iLimit) + minMatch; } - } else { /* repIndex < dictLimit || repIndex >= current */ + } else { /* repIndex < dictLimit || repIndex >= curr */ const BYTE* const repMatch = dictMode == ZSTD_dictMatchState ? dmsBase + repIndex - dmsIndexDelta : dictBase + repIndex; - assert(current >= windowLow); + assert(curr >= windowLow); if ( dictMode == ZSTD_extDict - && ( ((repOffset-1) /*intentional overflow*/ < current - windowLow) /* equivalent to `current > repIndex >= windowLow` */ + && ( ((repOffset-1) /*intentional overflow*/ < curr - windowLow) /* equivalent to `curr > repIndex >= windowLow` */ & (((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */) && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) { repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dictEnd, prefixStart) + minMatch; } if (dictMode == ZSTD_dictMatchState - && ( ((repOffset-1) /*intentional overflow*/ < current - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `current > repIndex >= dmsLowLimit` */ + && ( ((repOffset-1) /*intentional overflow*/ < curr - (dmsLowLimit + dmsIndexDelta)) /* equivalent to `curr > repIndex >= dmsLowLimit` */ & ((U32)((dictLimit-1) - repIndex) >= 3) ) /* intentional overflow : do not test positions overlapping 2 memory segments */ && (ZSTD_readMINMATCH(ip, minMatch) == ZSTD_readMINMATCH(repMatch, minMatch)) ) { repLen = (U32)ZSTD_count_2segments(ip+minMatch, repMatch+minMatch, iLimit, dmsEnd, prefixStart) + minMatch; @@ -609,7 +609,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( if ((mls == 3) /*static*/ && (bestLength < mls)) { U32 const matchIndex3 = ZSTD_insertAndFindFirstIndexHash3(ms, nextToUpdate3, ip); if ((matchIndex3 >= matchLow) - & (current - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) { + & (curr - matchIndex3 < (1<<18)) /*heuristic : longer distance likely too expensive*/ ) { size_t mlen; if ((dictMode == ZSTD_noDict) /*static*/ || (dictMode == ZSTD_dictMatchState) /*static*/ || (matchIndex3 >= dictLimit)) { const BYTE* const match = base + matchIndex3; @@ -624,26 +624,26 @@ U32 ZSTD_insertBtAndGetAllMatches ( DEBUGLOG(8, "found small match with hlog3, of length %u", (U32)mlen); bestLength = mlen; - assert(current > matchIndex3); + assert(curr > matchIndex3); assert(mnum==0); /* no prior solution */ - matches[0].off = (current - matchIndex3) + ZSTD_REP_MOVE; + matches[0].off = (curr - matchIndex3) + ZSTD_REP_MOVE; matches[0].len = (U32)mlen; mnum = 1; if ( (mlen > sufficient_len) | (ip+mlen == iLimit) ) { /* best possible length */ - ms->nextToUpdate = current+1; /* skip insertion */ + ms->nextToUpdate = curr+1; /* skip insertion */ return 1; } } } /* no dictMatchState lookup: dicts don't have a populated HC3 table */ } - hashTable[h] = current; /* Update Hash Table */ + hashTable[h] = curr; /* Update Hash Table */ while (nbCompares-- && (matchIndex >= matchLow)) { U32* const nextPtr = bt + 2*(matchIndex & btMask); const BYTE* match; size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */ - assert(current > matchIndex); + assert(curr > matchIndex); if ((dictMode == ZSTD_noDict) || (dictMode == ZSTD_dictMatchState) || (matchIndex+matchLength >= dictLimit)) { assert(matchIndex+matchLength >= dictLimit); /* ensure the condition is correct when !extDict */ @@ -660,12 +660,12 @@ U32 ZSTD_insertBtAndGetAllMatches ( if (matchLength > bestLength) { DEBUGLOG(8, "found match of length %u at distance %u (offCode=%u)", - (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE); + (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE); assert(matchEndIdx > matchIndex); if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength; bestLength = matchLength; - matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE; + matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE; matches[mnum].len = (U32)matchLength; mnum++; if ( (matchLength > ZSTD_OPT_NUM) @@ -708,11 +708,11 @@ U32 ZSTD_insertBtAndGetAllMatches ( if (matchLength > bestLength) { matchIndex = dictMatchIndex + dmsIndexDelta; DEBUGLOG(8, "found dms match of length %u at distance %u (offCode=%u)", - (U32)matchLength, current - matchIndex, current - matchIndex + ZSTD_REP_MOVE); + (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE); if (matchLength > matchEndIdx - matchIndex) matchEndIdx = matchIndex + (U32)matchLength; bestLength = matchLength; - matches[mnum].off = (current - matchIndex) + ZSTD_REP_MOVE; + matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE; matches[mnum].len = (U32)matchLength; mnum++; if ( (matchLength > ZSTD_OPT_NUM) @@ -733,7 +733,7 @@ U32 ZSTD_insertBtAndGetAllMatches ( } } - assert(matchEndIdx > current+8); + assert(matchEndIdx > curr+8); ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */ return mnum; } @@ -764,6 +764,140 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches ( } } +/************************* +* LDM helper functions * +*************************/ + +/* Struct containing info needed to make decision about ldm inclusion */ +typedef struct { + rawSeqStore_t seqStore; /* External match candidates store for this block */ + U32 startPosInBlock; /* Start position of the current match candidate */ + U32 endPosInBlock; /* End position of the current match candidate */ + U32 offset; /* Offset of the match candidate */ +} ZSTD_optLdm_t; + +/* ZSTD_optLdm_skipRawSeqStoreBytes(): + * Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'. + */ +static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) { + U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes); + while (currPos && rawSeqStore->pos < rawSeqStore->size) { + rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos]; + if (currPos >= currSeq.litLength + currSeq.matchLength) { + currPos -= currSeq.litLength + currSeq.matchLength; + rawSeqStore->pos++; + } else { + rawSeqStore->posInSequence = currPos; + break; + } + } + if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) { + rawSeqStore->posInSequence = 0; + } +} + +/* ZSTD_opt_getNextMatchAndUpdateSeqStore(): + * Calculates the beginning and end of the next match in the current block. + * Updates 'pos' and 'posInSequence' of the ldmSeqStore. + */ +static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock, + U32 blockBytesRemaining) { + rawSeq currSeq; + U32 currBlockEndPos; + U32 literalsBytesRemaining; + U32 matchBytesRemaining; + + /* Setting match end position to MAX to ensure we never use an LDM during this block */ + if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) { + optLdm->startPosInBlock = UINT_MAX; + optLdm->endPosInBlock = UINT_MAX; + return; + } + /* Calculate appropriate bytes left in matchLength and litLength after adjusting + based on ldmSeqStore->posInSequence */ + currSeq = optLdm->seqStore.seq[optLdm->seqStore.pos]; + assert(optLdm->seqStore.posInSequence <= currSeq.litLength + currSeq.matchLength); + currBlockEndPos = currPosInBlock + blockBytesRemaining; + literalsBytesRemaining = (optLdm->seqStore.posInSequence < currSeq.litLength) ? + currSeq.litLength - (U32)optLdm->seqStore.posInSequence : + 0; + matchBytesRemaining = (literalsBytesRemaining == 0) ? + currSeq.matchLength - ((U32)optLdm->seqStore.posInSequence - currSeq.litLength) : + currSeq.matchLength; + + /* If there are more literal bytes than bytes remaining in block, no ldm is possible */ + if (literalsBytesRemaining >= blockBytesRemaining) { + optLdm->startPosInBlock = UINT_MAX; + optLdm->endPosInBlock = UINT_MAX; + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, blockBytesRemaining); + return; + } + + /* Matches may be < MINMATCH by this process. In that case, we will reject them + when we are deciding whether or not to add the ldm */ + optLdm->startPosInBlock = currPosInBlock + literalsBytesRemaining; + optLdm->endPosInBlock = optLdm->startPosInBlock + matchBytesRemaining; + optLdm->offset = currSeq.offset; + + if (optLdm->endPosInBlock > currBlockEndPos) { + /* Match ends after the block ends, we can't use the whole match */ + optLdm->endPosInBlock = currBlockEndPos; + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, currBlockEndPos - currPosInBlock); + } else { + /* Consume nb of bytes equal to size of sequence left */ + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, literalsBytesRemaining + matchBytesRemaining); + } +} + +/* ZSTD_optLdm_maybeAddMatch(): + * Adds a match if it's long enough, based on it's 'matchStartPosInBlock' + * and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches' + */ +static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches, + ZSTD_optLdm_t* optLdm, U32 currPosInBlock) { + U32 posDiff = currPosInBlock - optLdm->startPosInBlock; + /* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */ + U32 candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff; + U32 candidateOffCode = optLdm->offset + ZSTD_REP_MOVE; + + /* Ensure that current block position is not outside of the match */ + if (currPosInBlock < optLdm->startPosInBlock + || currPosInBlock >= optLdm->endPosInBlock + || candidateMatchLength < MINMATCH) { + return; + } + + if (*nbMatches == 0 || ((candidateMatchLength > matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM)) { + DEBUGLOG(6, "ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u", + candidateOffCode, candidateMatchLength, currPosInBlock); + matches[*nbMatches].len = candidateMatchLength; + matches[*nbMatches].off = candidateOffCode; + (*nbMatches)++; + } +} + +/* ZSTD_optLdm_processMatchCandidate(): + * Wrapper function to update ldm seq store and call ldm functions as necessary. + */ +static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches, + U32 currPosInBlock, U32 remainingBytes) { + if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) { + return; + } + + if (currPosInBlock >= optLdm->endPosInBlock) { + if (currPosInBlock > optLdm->endPosInBlock) { + /* The position at which ZSTD_optLdm_processMatchCandidate() is called is not necessarily + * at the end of a match from the ldm seq store, and will often be some bytes + * over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots" + */ + U32 posOvershoot = currPosInBlock - optLdm->endPosInBlock; + ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, posOvershoot); + } + ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes); + } + ZSTD_optLdm_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock); +} /*-******************************* * Optimal parser @@ -817,6 +951,11 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, ZSTD_optimal_t* const opt = optStatePtr->priceTable; ZSTD_match_t* const matches = optStatePtr->matchTable; ZSTD_optimal_t lastSequence; + ZSTD_optLdm_t optLdm; + + optLdm.seqStore = ms->ldmSeqStore ? *ms->ldmSeqStore : kNullRawSeqStore; + optLdm.endPosInBlock = optLdm.startPosInBlock = optLdm.offset = 0; + ZSTD_opt_getNextMatchAndUpdateSeqStore(&optLdm, (U32)(ip-istart), (U32)(iend-ip)); /* init */ DEBUGLOG(5, "ZSTD_compressBlock_opt_generic: current=%u, prefix=%u, nextToUpdate=%u", @@ -832,7 +971,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, /* find first match */ { U32 const litlen = (U32)(ip - anchor); U32 const ll0 = !litlen; - U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch); + U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch); + ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches, + (U32)(ip-istart), (U32)(iend - ip)); if (!nbMatches) { ip++; continue; } /* initialize opt[0] */ @@ -925,9 +1066,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, if (opt[cur].mlen != 0) { U32 const prev = cur - opt[cur].mlen; repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0); - memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t)); + ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t)); } else { - memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t)); + ZSTD_memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t)); } /* last match must start at a minimum distance of 8 from oend */ @@ -945,8 +1086,12 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms, U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0; U32 const previousPrice = opt[cur].price; U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel); - U32 const nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch); + U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch); U32 matchNb; + + ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches, + (U32)(inr-istart), (U32)(iend-inr)); + if (!nbMatches) { DEBUGLOG(7, "rPos:%u : no match found", cur); continue; @@ -1010,9 +1155,9 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */ */ if (lastSequence.mlen != 0) { repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0); - memcpy(rep, &reps, sizeof(reps)); + ZSTD_memcpy(rep, &reps, sizeof(reps)); } else { - memcpy(rep, opt[cur].rep, sizeof(repcodes_t)); + ZSTD_memcpy(rep, opt[cur].rep, sizeof(repcodes_t)); } { U32 const storeEnd = cur + 1; @@ -1110,7 +1255,7 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms, const void* src, size_t srcSize) { U32 tmpRep[ZSTD_REP_NUM]; /* updated rep codes will sink here */ - memcpy(tmpRep, rep, sizeof(tmpRep)); + ZSTD_memcpy(tmpRep, rep, sizeof(tmpRep)); DEBUGLOG(4, "ZSTD_initStats_ultra (srcSize=%zu)", srcSize); assert(ms->opt.litLengthSum == 0); /* first block */ @@ -1143,7 +1288,7 @@ size_t ZSTD_compressBlock_btultra2( ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], const void* src, size_t srcSize) { - U32 const current = (U32)((const BYTE*)src - ms->window.base); + U32 const curr = (U32)((const BYTE*)src - ms->window.base); DEBUGLOG(5, "ZSTD_compressBlock_btultra2 (srcSize=%zu)", srcSize); /* 2-pass strategy: @@ -1158,7 +1303,7 @@ size_t ZSTD_compressBlock_btultra2( if ( (ms->opt.litLengthSum==0) /* first block */ && (seqStore->sequences == seqStore->sequencesStart) /* no ldm */ && (ms->window.dictLimit == ms->window.lowLimit) /* no dictionary */ - && (current == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */ + && (curr == ms->window.dictLimit) /* start of frame, nothing already loaded nor skipped */ && (srcSize > ZSTD_PREDEF_THRESHOLD) ) { ZSTD_initStats_ultra(ms, seqStore, rep, src, srcSize); diff --git a/thirdparty/zstd/compress/zstdmt_compress.c b/thirdparty/zstd/compress/zstdmt_compress.c index 1e3c8fdbee..50454a50b9 100644 --- a/thirdparty/zstd/compress/zstdmt_compress.c +++ b/thirdparty/zstd/compress/zstdmt_compress.c @@ -20,8 +20,7 @@ /* ====== Dependencies ====== */ -#include <string.h> /* memcpy, memset */ -#include <limits.h> /* INT_MAX, UINT_MAX */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset, INT_MAX, UINT_MAX */ #include "../common/mem.h" /* MEM_STATIC */ #include "../common/pool.h" /* threadpool */ #include "../common/threading.h" /* mutex */ @@ -106,11 +105,11 @@ typedef struct ZSTDMT_bufferPool_s { static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbWorkers, ZSTD_customMem cMem) { unsigned const maxNbBuffers = 2*nbWorkers + 3; - ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_calloc( + ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_customCalloc( sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem); if (bufPool==NULL) return NULL; if (ZSTD_pthread_mutex_init(&bufPool->poolMutex, NULL)) { - ZSTD_free(bufPool, cMem); + ZSTD_customFree(bufPool, cMem); return NULL; } bufPool->bufferSize = 64 KB; @@ -127,10 +126,10 @@ static void ZSTDMT_freeBufferPool(ZSTDMT_bufferPool* bufPool) if (!bufPool) return; /* compatibility with free on NULL */ for (u=0; u<bufPool->totalBuffers; u++) { DEBUGLOG(4, "free buffer %2u (address:%08X)", u, (U32)(size_t)bufPool->bTable[u].start); - ZSTD_free(bufPool->bTable[u].start, bufPool->cMem); + ZSTD_customFree(bufPool->bTable[u].start, bufPool->cMem); } ZSTD_pthread_mutex_destroy(&bufPool->poolMutex); - ZSTD_free(bufPool, bufPool->cMem); + ZSTD_customFree(bufPool, bufPool->cMem); } /* only works at initialization, not during compression */ @@ -201,13 +200,13 @@ static buffer_t ZSTDMT_getBuffer(ZSTDMT_bufferPool* bufPool) } /* size conditions not respected : scratch this buffer, create new one */ DEBUGLOG(5, "ZSTDMT_getBuffer: existing buffer does not meet size conditions => freeing"); - ZSTD_free(buf.start, bufPool->cMem); + ZSTD_customFree(buf.start, bufPool->cMem); } ZSTD_pthread_mutex_unlock(&bufPool->poolMutex); /* create new buffer */ DEBUGLOG(5, "ZSTDMT_getBuffer: create a new buffer"); { buffer_t buffer; - void* const start = ZSTD_malloc(bSize, bufPool->cMem); + void* const start = ZSTD_customMalloc(bSize, bufPool->cMem); buffer.start = start; /* note : start can be NULL if malloc fails ! */ buffer.capacity = (start==NULL) ? 0 : bSize; if (start==NULL) { @@ -229,13 +228,13 @@ static buffer_t ZSTDMT_resizeBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buffer) { size_t const bSize = bufPool->bufferSize; if (buffer.capacity < bSize) { - void* const start = ZSTD_malloc(bSize, bufPool->cMem); + void* const start = ZSTD_customMalloc(bSize, bufPool->cMem); buffer_t newBuffer; newBuffer.start = start; newBuffer.capacity = start == NULL ? 0 : bSize; if (start != NULL) { assert(newBuffer.capacity >= buffer.capacity); - memcpy(newBuffer.start, buffer.start, buffer.capacity); + ZSTD_memcpy(newBuffer.start, buffer.start, buffer.capacity); DEBUGLOG(5, "ZSTDMT_resizeBuffer: created buffer of size %u", (U32)bSize); return newBuffer; } @@ -261,14 +260,12 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf) ZSTD_pthread_mutex_unlock(&bufPool->poolMutex); /* Reached bufferPool capacity (should not happen) */ DEBUGLOG(5, "ZSTDMT_releaseBuffer: pool capacity reached => freeing "); - ZSTD_free(buf.start, bufPool->cMem); + ZSTD_customFree(buf.start, bufPool->cMem); } /* ===== Seq Pool Wrapper ====== */ -static rawSeqStore_t kNullRawSeqStore = {NULL, 0, 0, 0}; - typedef ZSTDMT_bufferPool ZSTDMT_seqPool; static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool) @@ -278,7 +275,7 @@ static size_t ZSTDMT_sizeof_seqPool(ZSTDMT_seqPool* seqPool) static rawSeqStore_t bufferToSeq(buffer_t buffer) { - rawSeqStore_t seq = {NULL, 0, 0, 0}; + rawSeqStore_t seq = kNullRawSeqStore; seq.seq = (rawSeq*)buffer.start; seq.capacity = buffer.capacity / sizeof(rawSeq); return seq; @@ -354,7 +351,7 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool) for (cid=0; cid<pool->totalCCtx; cid++) ZSTD_freeCCtx(pool->cctx[cid]); /* note : compatible with free on NULL */ ZSTD_pthread_mutex_destroy(&pool->poolMutex); - ZSTD_free(pool, pool->cMem); + ZSTD_customFree(pool, pool->cMem); } /* ZSTDMT_createCCtxPool() : @@ -362,12 +359,12 @@ static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool) static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers, ZSTD_customMem cMem) { - ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_calloc( + ZSTDMT_CCtxPool* const cctxPool = (ZSTDMT_CCtxPool*) ZSTD_customCalloc( sizeof(ZSTDMT_CCtxPool) + (nbWorkers-1)*sizeof(ZSTD_CCtx*), cMem); assert(nbWorkers > 0); if (!cctxPool) return NULL; if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) { - ZSTD_free(cctxPool, cMem); + ZSTD_customFree(cctxPool, cMem); return NULL; } cctxPool->cMem = cMem; @@ -478,7 +475,7 @@ ZSTDMT_serialState_reset(serialState_t* serialState, serialState->ldmState.hashPower = ZSTD_rollingHash_primePower(params.ldmParams.minMatchLength); } else { - memset(¶ms.ldmParams, 0, sizeof(params.ldmParams)); + ZSTD_memset(¶ms.ldmParams, 0, sizeof(params.ldmParams)); } serialState->nextJobID = 0; if (params.fParams.checksumFlag) @@ -499,18 +496,18 @@ ZSTDMT_serialState_reset(serialState_t* serialState, ZSTD_window_init(&serialState->ldmState.window); /* Resize tables and output space if necessary. */ if (serialState->ldmState.hashTable == NULL || serialState->params.ldmParams.hashLog < hashLog) { - ZSTD_free(serialState->ldmState.hashTable, cMem); - serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_malloc(hashSize, cMem); + ZSTD_customFree(serialState->ldmState.hashTable, cMem); + serialState->ldmState.hashTable = (ldmEntry_t*)ZSTD_customMalloc(hashSize, cMem); } if (serialState->ldmState.bucketOffsets == NULL || prevBucketLog < bucketLog) { - ZSTD_free(serialState->ldmState.bucketOffsets, cMem); - serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_malloc(bucketSize, cMem); + ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem); + serialState->ldmState.bucketOffsets = (BYTE*)ZSTD_customMalloc(bucketSize, cMem); } if (!serialState->ldmState.hashTable || !serialState->ldmState.bucketOffsets) return 1; /* Zero the tables */ - memset(serialState->ldmState.hashTable, 0, hashSize); - memset(serialState->ldmState.bucketOffsets, 0, bucketSize); + ZSTD_memset(serialState->ldmState.hashTable, 0, hashSize); + ZSTD_memset(serialState->ldmState.bucketOffsets, 0, bucketSize); /* Update window state and fill hash table with dict */ serialState->ldmState.loadedDictEnd = 0; @@ -537,7 +534,7 @@ ZSTDMT_serialState_reset(serialState_t* serialState, static int ZSTDMT_serialState_init(serialState_t* serialState) { int initError = 0; - memset(serialState, 0, sizeof(*serialState)); + ZSTD_memset(serialState, 0, sizeof(*serialState)); initError |= ZSTD_pthread_mutex_init(&serialState->mutex, NULL); initError |= ZSTD_pthread_cond_init(&serialState->cond, NULL); initError |= ZSTD_pthread_mutex_init(&serialState->ldmWindowMutex, NULL); @@ -552,8 +549,8 @@ static void ZSTDMT_serialState_free(serialState_t* serialState) ZSTD_pthread_cond_destroy(&serialState->cond); ZSTD_pthread_mutex_destroy(&serialState->ldmWindowMutex); ZSTD_pthread_cond_destroy(&serialState->ldmWindowCond); - ZSTD_free(serialState->ldmState.hashTable, cMem); - ZSTD_free(serialState->ldmState.bucketOffsets, cMem); + ZSTD_customFree(serialState->ldmState.hashTable, cMem); + ZSTD_customFree(serialState->ldmState.bucketOffsets, cMem); } static void ZSTDMT_serialState_update(serialState_t* serialState, @@ -820,7 +817,6 @@ struct ZSTDMT_CCtx_s { roundBuff_t roundBuff; serialState_t serial; rsyncState_t rsync; - unsigned singleBlockingThread; unsigned jobIDMask; unsigned doneJobID; unsigned nextJobID; @@ -832,6 +828,7 @@ struct ZSTDMT_CCtx_s { ZSTD_customMem cMem; ZSTD_CDict* cdictLocal; const ZSTD_CDict* cdict; + unsigned providedFactory: 1; }; static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZSTD_customMem cMem) @@ -842,7 +839,7 @@ static void ZSTDMT_freeJobsTable(ZSTDMT_jobDescription* jobTable, U32 nbJobs, ZS ZSTD_pthread_mutex_destroy(&jobTable[jobNb].job_mutex); ZSTD_pthread_cond_destroy(&jobTable[jobNb].job_cond); } - ZSTD_free(jobTable, cMem); + ZSTD_customFree(jobTable, cMem); } /* ZSTDMT_allocJobsTable() @@ -854,7 +851,7 @@ static ZSTDMT_jobDescription* ZSTDMT_createJobsTable(U32* nbJobsPtr, ZSTD_custom U32 const nbJobs = 1 << nbJobsLog2; U32 jobNb; ZSTDMT_jobDescription* const jobTable = (ZSTDMT_jobDescription*) - ZSTD_calloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem); + ZSTD_customCalloc(nbJobs * sizeof(ZSTDMT_jobDescription), cMem); int initError = 0; if (jobTable==NULL) return NULL; *nbJobsPtr = nbJobs; @@ -885,12 +882,12 @@ static size_t ZSTDMT_expandJobsTable (ZSTDMT_CCtx* mtctx, U32 nbWorkers) { /* ZSTDMT_CCtxParam_setNbWorkers(): * Internal use only */ -size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers) +static size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers) { return ZSTD_CCtxParams_setParameter(params, ZSTD_c_nbWorkers, (int)nbWorkers); } -MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem) +MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool) { ZSTDMT_CCtx* mtctx; U32 nbJobs = nbWorkers + 2; @@ -903,12 +900,19 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, /* invalid custom allocator */ return NULL; - mtctx = (ZSTDMT_CCtx*) ZSTD_calloc(sizeof(ZSTDMT_CCtx), cMem); + mtctx = (ZSTDMT_CCtx*) ZSTD_customCalloc(sizeof(ZSTDMT_CCtx), cMem); if (!mtctx) return NULL; ZSTDMT_CCtxParam_setNbWorkers(&mtctx->params, nbWorkers); mtctx->cMem = cMem; mtctx->allJobsCompleted = 1; - mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem); + if (pool != NULL) { + mtctx->factory = pool; + mtctx->providedFactory = 1; + } + else { + mtctx->factory = POOL_create_advanced(nbWorkers, 0, cMem); + mtctx->providedFactory = 0; + } mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, cMem); assert(nbJobs > 0); assert((nbJobs & (nbJobs - 1)) == 0); /* ensure nbJobs is a power of 2 */ mtctx->jobIDMask = nbJobs - 1; @@ -925,22 +929,18 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers, return mtctx; } -ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem) +ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, ZSTD_customMem cMem, ZSTD_threadPool* pool) { #ifdef ZSTD_MULTITHREAD - return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem); + return ZSTDMT_createCCtx_advanced_internal(nbWorkers, cMem, pool); #else (void)nbWorkers; (void)cMem; + (void)pool; return NULL; #endif } -ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers) -{ - return ZSTDMT_createCCtx_advanced(nbWorkers, ZSTD_defaultCMem); -} - /* ZSTDMT_releaseAllJobResources() : * note : ensure all workers are killed first ! */ @@ -957,7 +957,7 @@ static void ZSTDMT_releaseAllJobResources(ZSTDMT_CCtx* mtctx) ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff); /* Clear the job description, but keep the mutex/cond */ - memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID])); + ZSTD_memset(&mtctx->jobs[jobID], 0, sizeof(mtctx->jobs[jobID])); mtctx->jobs[jobID].job_mutex = mutex; mtctx->jobs[jobID].job_cond = cond; } @@ -984,7 +984,8 @@ static void ZSTDMT_waitForAllJobsCompleted(ZSTDMT_CCtx* mtctx) size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx) { if (mtctx==NULL) return 0; /* compatible with free on NULL */ - POOL_free(mtctx->factory); /* stop and free worker threads */ + if (!mtctx->providedFactory) + POOL_free(mtctx->factory); /* stop and free worker threads */ ZSTDMT_releaseAllJobResources(mtctx); /* release job resources into pools first */ ZSTDMT_freeJobsTable(mtctx->jobs, mtctx->jobIDMask+1, mtctx->cMem); ZSTDMT_freeBufferPool(mtctx->bufPool); @@ -993,8 +994,8 @@ size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx) ZSTDMT_serialState_free(&mtctx->serial); ZSTD_freeCDict(mtctx->cdictLocal); if (mtctx->roundBuff.buffer) - ZSTD_free(mtctx->roundBuff.buffer, mtctx->cMem); - ZSTD_free(mtctx, mtctx->cMem); + ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem); + ZSTD_customFree(mtctx, mtctx->cMem); return 0; } @@ -1011,65 +1012,6 @@ size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx) + mtctx->roundBuff.capacity; } -/* Internal only */ -size_t -ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params, - ZSTDMT_parameter parameter, - int value) -{ - DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter"); - switch(parameter) - { - case ZSTDMT_p_jobSize : - DEBUGLOG(4, "ZSTDMT_CCtxParam_setMTCtxParameter : set jobSize to %i", value); - return ZSTD_CCtxParams_setParameter(params, ZSTD_c_jobSize, value); - case ZSTDMT_p_overlapLog : - DEBUGLOG(4, "ZSTDMT_p_overlapLog : %i", value); - return ZSTD_CCtxParams_setParameter(params, ZSTD_c_overlapLog, value); - case ZSTDMT_p_rsyncable : - DEBUGLOG(4, "ZSTD_p_rsyncable : %i", value); - return ZSTD_CCtxParams_setParameter(params, ZSTD_c_rsyncable, value); - default : - return ERROR(parameter_unsupported); - } -} - -size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value) -{ - DEBUGLOG(4, "ZSTDMT_setMTCtxParameter"); - return ZSTDMT_CCtxParam_setMTCtxParameter(&mtctx->params, parameter, value); -} - -size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value) -{ - switch (parameter) { - case ZSTDMT_p_jobSize: - return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_jobSize, value); - case ZSTDMT_p_overlapLog: - return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_overlapLog, value); - case ZSTDMT_p_rsyncable: - return ZSTD_CCtxParams_getParameter(&mtctx->params, ZSTD_c_rsyncable, value); - default: - return ERROR(parameter_unsupported); - } -} - -/* Sets parameters relevant to the compression job, - * initializing others to default values. */ -static ZSTD_CCtx_params ZSTDMT_initJobCCtxParams(const ZSTD_CCtx_params* params) -{ - ZSTD_CCtx_params jobParams = *params; - /* Clear parameters related to multithreading */ - jobParams.forceWindow = 0; - jobParams.nbWorkers = 0; - jobParams.jobSize = 0; - jobParams.overlapLog = 0; - jobParams.rsyncable = 0; - memset(&jobParams.ldmParams, 0, sizeof(ldmParams_t)); - memset(&jobParams.customMem, 0, sizeof(ZSTD_customMem)); - return jobParams; -} - /* ZSTDMT_resize() : * @return : error code if fails, 0 on success */ @@ -1098,7 +1040,7 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p DEBUGLOG(5, "ZSTDMT_updateCParams_whileCompressing (level:%i)", compressionLevel); mtctx->params.compressionLevel = compressionLevel; - { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0); + { ZSTD_compressionParameters cParams = ZSTD_getCParamsFromCCtxParams(cctxParams, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict); cParams.windowLog = saved_wlog; mtctx->params.cParams = cParams; } @@ -1185,8 +1127,8 @@ static unsigned ZSTDMT_computeTargetJobLog(const ZSTD_CCtx_params* params) if (params->ldmParams.enableLdm) { /* In Long Range Mode, the windowLog is typically oversized. * In which case, it's preferable to determine the jobSize - * based on chainLog instead. */ - jobLog = MAX(21, params->cParams.chainLog + 4); + * based on cycleLog instead. */ + jobLog = MAX(21, ZSTD_cycleLog(params->cParams.chainLog, params->cParams.strategy) + 3); } else { jobLog = MAX(20, params->cParams.windowLog + 2); } @@ -1240,174 +1182,6 @@ static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params) return (ovLog==0) ? 0 : (size_t)1 << ovLog; } -static unsigned -ZSTDMT_computeNbJobs(const ZSTD_CCtx_params* params, size_t srcSize, unsigned nbWorkers) -{ - assert(nbWorkers>0); - { size_t const jobSizeTarget = (size_t)1 << ZSTDMT_computeTargetJobLog(params); - size_t const jobMaxSize = jobSizeTarget << 2; - size_t const passSizeMax = jobMaxSize * nbWorkers; - unsigned const multiplier = (unsigned)(srcSize / passSizeMax) + 1; - unsigned const nbJobsLarge = multiplier * nbWorkers; - unsigned const nbJobsMax = (unsigned)(srcSize / jobSizeTarget) + 1; - unsigned const nbJobsSmall = MIN(nbJobsMax, nbWorkers); - return (multiplier>1) ? nbJobsLarge : nbJobsSmall; -} } - -/* ZSTDMT_compress_advanced_internal() : - * This is a blocking function : it will only give back control to caller after finishing its compression job. - */ -static size_t -ZSTDMT_compress_advanced_internal( - ZSTDMT_CCtx* mtctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict, - ZSTD_CCtx_params params) -{ - ZSTD_CCtx_params const jobParams = ZSTDMT_initJobCCtxParams(¶ms); - size_t const overlapSize = ZSTDMT_computeOverlapSize(¶ms); - unsigned const nbJobs = ZSTDMT_computeNbJobs(¶ms, srcSize, params.nbWorkers); - size_t const proposedJobSize = (srcSize + (nbJobs-1)) / nbJobs; - size_t const avgJobSize = (((proposedJobSize-1) & 0x1FFFF) < 0x7FFF) ? proposedJobSize + 0xFFFF : proposedJobSize; /* avoid too small last block */ - const char* const srcStart = (const char*)src; - size_t remainingSrcSize = srcSize; - unsigned const compressWithinDst = (dstCapacity >= ZSTD_compressBound(srcSize)) ? nbJobs : (unsigned)(dstCapacity / ZSTD_compressBound(avgJobSize)); /* presumes avgJobSize >= 256 KB, which should be the case */ - size_t frameStartPos = 0, dstBufferPos = 0; - assert(jobParams.nbWorkers == 0); - assert(mtctx->cctxPool->totalCCtx == params.nbWorkers); - - params.jobSize = (U32)avgJobSize; - DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: nbJobs=%2u (rawSize=%u bytes; fixedSize=%u) ", - nbJobs, (U32)proposedJobSize, (U32)avgJobSize); - - if ((nbJobs==1) | (params.nbWorkers<=1)) { /* fallback to single-thread mode : this is a blocking invocation anyway */ - ZSTD_CCtx* const cctx = mtctx->cctxPool->cctx[0]; - DEBUGLOG(4, "ZSTDMT_compress_advanced_internal: fallback to single-thread mode"); - if (cdict) return ZSTD_compress_usingCDict_advanced(cctx, dst, dstCapacity, src, srcSize, cdict, jobParams.fParams); - return ZSTD_compress_advanced_internal(cctx, dst, dstCapacity, src, srcSize, NULL, 0, &jobParams); - } - - assert(avgJobSize >= 256 KB); /* condition for ZSTD_compressBound(A) + ZSTD_compressBound(B) <= ZSTD_compressBound(A+B), required to compress directly into Dst (no additional buffer) */ - ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(avgJobSize) ); - /* LDM doesn't even try to load the dictionary in single-ingestion mode */ - if (ZSTDMT_serialState_reset(&mtctx->serial, mtctx->seqPool, params, avgJobSize, NULL, 0, ZSTD_dct_auto)) - return ERROR(memory_allocation); - - FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbJobs) , ""); /* only expands if necessary */ - - { unsigned u; - for (u=0; u<nbJobs; u++) { - size_t const jobSize = MIN(remainingSrcSize, avgJobSize); - size_t const dstBufferCapacity = ZSTD_compressBound(jobSize); - buffer_t const dstAsBuffer = { (char*)dst + dstBufferPos, dstBufferCapacity }; - buffer_t const dstBuffer = u < compressWithinDst ? dstAsBuffer : g_nullBuffer; - size_t dictSize = u ? overlapSize : 0; - - mtctx->jobs[u].prefix.start = srcStart + frameStartPos - dictSize; - mtctx->jobs[u].prefix.size = dictSize; - mtctx->jobs[u].src.start = srcStart + frameStartPos; - mtctx->jobs[u].src.size = jobSize; assert(jobSize > 0); /* avoid job.src.size == 0 */ - mtctx->jobs[u].consumed = 0; - mtctx->jobs[u].cSize = 0; - mtctx->jobs[u].cdict = (u==0) ? cdict : NULL; - mtctx->jobs[u].fullFrameSize = srcSize; - mtctx->jobs[u].params = jobParams; - /* do not calculate checksum within sections, but write it in header for first section */ - mtctx->jobs[u].dstBuff = dstBuffer; - mtctx->jobs[u].cctxPool = mtctx->cctxPool; - mtctx->jobs[u].bufPool = mtctx->bufPool; - mtctx->jobs[u].seqPool = mtctx->seqPool; - mtctx->jobs[u].serial = &mtctx->serial; - mtctx->jobs[u].jobID = u; - mtctx->jobs[u].firstJob = (u==0); - mtctx->jobs[u].lastJob = (u==nbJobs-1); - - DEBUGLOG(5, "ZSTDMT_compress_advanced_internal: posting job %u (%u bytes)", u, (U32)jobSize); - DEBUG_PRINTHEX(6, mtctx->jobs[u].prefix.start, 12); - POOL_add(mtctx->factory, ZSTDMT_compressionJob, &mtctx->jobs[u]); - - frameStartPos += jobSize; - dstBufferPos += dstBufferCapacity; - remainingSrcSize -= jobSize; - } } - - /* collect result */ - { size_t error = 0, dstPos = 0; - unsigned jobID; - for (jobID=0; jobID<nbJobs; jobID++) { - DEBUGLOG(5, "waiting for job %u ", jobID); - ZSTD_PTHREAD_MUTEX_LOCK(&mtctx->jobs[jobID].job_mutex); - while (mtctx->jobs[jobID].consumed < mtctx->jobs[jobID].src.size) { - DEBUGLOG(5, "waiting for jobCompleted signal from job %u", jobID); - ZSTD_pthread_cond_wait(&mtctx->jobs[jobID].job_cond, &mtctx->jobs[jobID].job_mutex); - } - ZSTD_pthread_mutex_unlock(&mtctx->jobs[jobID].job_mutex); - DEBUGLOG(5, "ready to write job %u ", jobID); - - { size_t const cSize = mtctx->jobs[jobID].cSize; - if (ZSTD_isError(cSize)) error = cSize; - if ((!error) && (dstPos + cSize > dstCapacity)) error = ERROR(dstSize_tooSmall); - if (jobID) { /* note : job 0 is written directly at dst, which is correct position */ - if (!error) - memmove((char*)dst + dstPos, mtctx->jobs[jobID].dstBuff.start, cSize); /* may overlap when job compressed within dst */ - if (jobID >= compressWithinDst) { /* job compressed into its own buffer, which must be released */ - DEBUGLOG(5, "releasing buffer %u>=%u", jobID, compressWithinDst); - ZSTDMT_releaseBuffer(mtctx->bufPool, mtctx->jobs[jobID].dstBuff); - } } - mtctx->jobs[jobID].dstBuff = g_nullBuffer; - mtctx->jobs[jobID].cSize = 0; - dstPos += cSize ; - } - } /* for (jobID=0; jobID<nbJobs; jobID++) */ - - DEBUGLOG(4, "checksumFlag : %u ", params.fParams.checksumFlag); - if (params.fParams.checksumFlag) { - U32 const checksum = (U32)XXH64_digest(&mtctx->serial.xxhState); - if (dstPos + 4 > dstCapacity) { - error = ERROR(dstSize_tooSmall); - } else { - DEBUGLOG(4, "writing checksum : %08X \n", checksum); - MEM_writeLE32((char*)dst + dstPos, checksum); - dstPos += 4; - } } - - if (!error) DEBUGLOG(4, "compressed size : %u ", (U32)dstPos); - return error ? error : dstPos; - } -} - -size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict, - ZSTD_parameters params, - int overlapLog) -{ - ZSTD_CCtx_params cctxParams = mtctx->params; - cctxParams.cParams = params.cParams; - cctxParams.fParams = params.fParams; - assert(ZSTD_OVERLAPLOG_MIN <= overlapLog && overlapLog <= ZSTD_OVERLAPLOG_MAX); - cctxParams.overlapLog = overlapLog; - return ZSTDMT_compress_advanced_internal(mtctx, - dst, dstCapacity, - src, srcSize, - cdict, cctxParams); -} - - -size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - int compressionLevel) -{ - ZSTD_parameters params = ZSTD_getParams(compressionLevel, srcSize, 0); - int const overlapLog = ZSTDMT_overlapLog_default(params.cParams.strategy); - params.fParams.contentSizeFlag = 1; - return ZSTDMT_compress_advanced(mtctx, dst, dstCapacity, src, srcSize, NULL, params, overlapLog); -} - - /* ====================================== */ /* ======= Streaming API ======= */ /* ====================================== */ @@ -1432,16 +1206,6 @@ size_t ZSTDMT_initCStream_internal( if (params.jobSize != 0 && params.jobSize < ZSTDMT_JOBSIZE_MIN) params.jobSize = ZSTDMT_JOBSIZE_MIN; if (params.jobSize > (size_t)ZSTDMT_JOBSIZE_MAX) params.jobSize = (size_t)ZSTDMT_JOBSIZE_MAX; - mtctx->singleBlockingThread = (pledgedSrcSize <= ZSTDMT_JOBSIZE_MIN); /* do not trigger multi-threading when srcSize is too small */ - if (mtctx->singleBlockingThread) { - ZSTD_CCtx_params const singleThreadParams = ZSTDMT_initJobCCtxParams(¶ms); - DEBUGLOG(5, "ZSTDMT_initCStream_internal: switch to single blocking thread mode"); - assert(singleThreadParams.nbWorkers == 0); - return ZSTD_initCStream_internal(mtctx->cctxPool->cctx[0], - dict, dictSize, cdict, - &singleThreadParams, pledgedSrcSize); - } - DEBUGLOG(4, "ZSTDMT_initCStream_internal: %u workers", params.nbWorkers); if (mtctx->allJobsCompleted == 0) { /* previous compression not correctly finished */ @@ -1504,8 +1268,8 @@ size_t ZSTDMT_initCStream_internal( size_t const capacity = MAX(windowSize, sectionsSize) + slackSize; if (mtctx->roundBuff.capacity < capacity) { if (mtctx->roundBuff.buffer) - ZSTD_free(mtctx->roundBuff.buffer, mtctx->cMem); - mtctx->roundBuff.buffer = (BYTE*)ZSTD_malloc(capacity, mtctx->cMem); + ZSTD_customFree(mtctx->roundBuff.buffer, mtctx->cMem); + mtctx->roundBuff.buffer = (BYTE*)ZSTD_customMalloc(capacity, mtctx->cMem); if (mtctx->roundBuff.buffer == NULL) { mtctx->roundBuff.capacity = 0; return ERROR(memory_allocation); @@ -1530,53 +1294,6 @@ size_t ZSTDMT_initCStream_internal( return 0; } -size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx, - const void* dict, size_t dictSize, - ZSTD_parameters params, - unsigned long long pledgedSrcSize) -{ - ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */ - DEBUGLOG(4, "ZSTDMT_initCStream_advanced (pledgedSrcSize=%u)", (U32)pledgedSrcSize); - cctxParams.cParams = params.cParams; - cctxParams.fParams = params.fParams; - return ZSTDMT_initCStream_internal(mtctx, dict, dictSize, ZSTD_dct_auto, NULL, - cctxParams, pledgedSrcSize); -} - -size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx, - const ZSTD_CDict* cdict, - ZSTD_frameParameters fParams, - unsigned long long pledgedSrcSize) -{ - ZSTD_CCtx_params cctxParams = mtctx->params; - if (cdict==NULL) return ERROR(dictionary_wrong); /* method incompatible with NULL cdict */ - cctxParams.cParams = ZSTD_getCParamsFromCDict(cdict); - cctxParams.fParams = fParams; - return ZSTDMT_initCStream_internal(mtctx, NULL, 0 /*dictSize*/, ZSTD_dct_auto, cdict, - cctxParams, pledgedSrcSize); -} - - -/* ZSTDMT_resetCStream() : - * pledgedSrcSize can be zero == unknown (for the time being) - * prefer using ZSTD_CONTENTSIZE_UNKNOWN, - * as `0` might mean "empty" in the future */ -size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize) -{ - if (!pledgedSrcSize) pledgedSrcSize = ZSTD_CONTENTSIZE_UNKNOWN; - return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, 0, mtctx->params, - pledgedSrcSize); -} - -size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel) { - ZSTD_parameters const params = ZSTD_getParams(compressionLevel, ZSTD_CONTENTSIZE_UNKNOWN, 0); - ZSTD_CCtx_params cctxParams = mtctx->params; /* retrieve sticky params */ - DEBUGLOG(4, "ZSTDMT_initCStream (cLevel=%i)", compressionLevel); - cctxParams.cParams = params.cParams; - cctxParams.fParams = params.fParams; - return ZSTDMT_initCStream_internal(mtctx, NULL, 0, ZSTD_dct_auto, NULL, cctxParams, ZSTD_CONTENTSIZE_UNKNOWN); -} - /* ZSTDMT_writeLastEmptyBlock() * Write a single empty block with an end-of-frame to finish a frame. @@ -1740,7 +1457,7 @@ static size_t ZSTDMT_flushProduced(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, u assert(cSize >= mtctx->jobs[wJobID].dstFlushed); assert(mtctx->jobs[wJobID].dstBuff.start != NULL); if (toFlush > 0) { - memcpy((char*)output->dst + output->pos, + ZSTD_memcpy((char*)output->dst + output->pos, (const char*)mtctx->jobs[wJobID].dstBuff.start + mtctx->jobs[wJobID].dstFlushed, toFlush); } @@ -1894,7 +1611,7 @@ static int ZSTDMT_tryGetInputRange(ZSTDMT_CCtx* mtctx) return 0; } ZSTDMT_waitForLdmComplete(mtctx, buffer); - memmove(start, mtctx->inBuff.prefix.start, prefixSize); + ZSTD_memmove(start, mtctx->inBuff.prefix.start, prefixSize); mtctx->inBuff.prefix.start = start; mtctx->roundBuff.pos = prefixSize; } @@ -1968,6 +1685,16 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input) pos = 0; prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH; hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH); + if ((hash & hitMask) == hitMask) { + /* We're already at a sync point so don't load any more until + * we're able to flush this sync point. + * This likely happened because the job table was full so we + * couldn't add our job. + */ + syncPoint.toLoad = 0; + syncPoint.flush = 1; + return syncPoint; + } } else { /* We don't have enough bytes buffered to initialize the hash, but * we know we have at least RSYNC_LENGTH bytes total. @@ -2022,34 +1749,11 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, assert(output->pos <= output->size); assert(input->pos <= input->size); - if (mtctx->singleBlockingThread) { /* delegate to single-thread (synchronous) */ - return ZSTD_compressStream2(mtctx->cctxPool->cctx[0], output, input, endOp); - } - if ((mtctx->frameEnded) && (endOp==ZSTD_e_continue)) { /* current frame being ended. Only flush/end are allowed */ return ERROR(stage_wrong); } - /* single-pass shortcut (note : synchronous-mode) */ - if ( (!mtctx->params.rsyncable) /* rsyncable mode is disabled */ - && (mtctx->nextJobID == 0) /* just started */ - && (mtctx->inBuff.filled == 0) /* nothing buffered */ - && (!mtctx->jobReady) /* no job already created */ - && (endOp == ZSTD_e_end) /* end order */ - && (output->size - output->pos >= ZSTD_compressBound(input->size - input->pos)) ) { /* enough space in dst */ - size_t const cSize = ZSTDMT_compress_advanced_internal(mtctx, - (char*)output->dst + output->pos, output->size - output->pos, - (const char*)input->src + input->pos, input->size - input->pos, - mtctx->cdict, mtctx->params); - if (ZSTD_isError(cSize)) return cSize; - input->pos = input->size; - output->pos += cSize; - mtctx->allJobsCompleted = 1; - mtctx->frameEnded = 1; - return 0; - } - /* fill input buffer */ if ( (!mtctx->jobReady) && (input->size > input->pos) ) { /* support NULL input */ @@ -2072,13 +1776,21 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, assert(mtctx->inBuff.buffer.capacity >= mtctx->targetSectionSize); DEBUGLOG(5, "ZSTDMT_compressStream_generic: adding %u bytes on top of %u to buffer of size %u", (U32)syncPoint.toLoad, (U32)mtctx->inBuff.filled, (U32)mtctx->targetSectionSize); - memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad); + ZSTD_memcpy((char*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled, (const char*)input->src + input->pos, syncPoint.toLoad); input->pos += syncPoint.toLoad; mtctx->inBuff.filled += syncPoint.toLoad; forwardInputProgress = syncPoint.toLoad>0; } - if ((input->pos < input->size) && (endOp == ZSTD_e_end)) - endOp = ZSTD_e_flush; /* can't end now : not all input consumed */ + } + if ((input->pos < input->size) && (endOp == ZSTD_e_end)) { + /* Can't end yet because the input is not fully consumed. + * We are in one of these cases: + * - mtctx->inBuff is NULL & empty: we couldn't get an input buffer so don't create a new job. + * - We filled the input buffer: flush this job but don't end the frame. + * - We hit a synchronization point: flush this job but don't end the frame. + */ + assert(mtctx->inBuff.filled == 0 || mtctx->inBuff.filled == mtctx->targetSectionSize || mtctx->params.rsyncable); + endOp = ZSTD_e_flush; } if ( (mtctx->jobReady) @@ -2097,47 +1809,3 @@ size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, return remainingToFlush; } } - - -size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input) -{ - FORWARD_IF_ERROR( ZSTDMT_compressStream_generic(mtctx, output, input, ZSTD_e_continue) , ""); - - /* recommended next input size : fill current input buffer */ - return mtctx->targetSectionSize - mtctx->inBuff.filled; /* note : could be zero when input buffer is fully filled and no more availability to create new job */ -} - - -static size_t ZSTDMT_flushStream_internal(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_EndDirective endFrame) -{ - size_t const srcSize = mtctx->inBuff.filled; - DEBUGLOG(5, "ZSTDMT_flushStream_internal"); - - if ( mtctx->jobReady /* one job ready for a worker to pick up */ - || (srcSize > 0) /* still some data within input buffer */ - || ((endFrame==ZSTD_e_end) && !mtctx->frameEnded)) { /* need a last 0-size block to end frame */ - DEBUGLOG(5, "ZSTDMT_flushStream_internal : create a new job (%u bytes, end:%u)", - (U32)srcSize, (U32)endFrame); - FORWARD_IF_ERROR( ZSTDMT_createCompressionJob(mtctx, srcSize, endFrame) , ""); - } - - /* check if there is any data available to flush */ - return ZSTDMT_flushProduced(mtctx, output, 1 /* blockToFlush */, endFrame); -} - - -size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output) -{ - DEBUGLOG(5, "ZSTDMT_flushStream"); - if (mtctx->singleBlockingThread) - return ZSTD_flushStream(mtctx->cctxPool->cctx[0], output); - return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_flush); -} - -size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output) -{ - DEBUGLOG(4, "ZSTDMT_endStream"); - if (mtctx->singleBlockingThread) - return ZSTD_endStream(mtctx->cctxPool->cctx[0], output); - return ZSTDMT_flushStream_internal(mtctx, output, ZSTD_e_end); -} diff --git a/thirdparty/zstd/compress/zstdmt_compress.h b/thirdparty/zstd/compress/zstdmt_compress.h index 89914eb7f8..0a9e551c99 100644 --- a/thirdparty/zstd/compress/zstdmt_compress.h +++ b/thirdparty/zstd/compress/zstdmt_compress.h @@ -19,26 +19,14 @@ /* Note : This is an internal API. * These APIs used to be exposed with ZSTDLIB_API, * because it used to be the only way to invoke MT compression. - * Now, it's recommended to use ZSTD_compress2 and ZSTD_compressStream2() - * instead. - * - * If you depend on these APIs and can't switch, then define - * ZSTD_LEGACY_MULTITHREADED_API when making the dynamic library. - * However, we may completely remove these functions in a future - * release, so please switch soon. + * Now, you must use ZSTD_compress2 and ZSTD_compressStream2() instead. * * This API requires ZSTD_MULTITHREAD to be defined during compilation, * otherwise ZSTDMT_createCCtx*() will fail. */ -#ifdef ZSTD_LEGACY_MULTITHREADED_API -# define ZSTDMT_API ZSTDLIB_API -#else -# define ZSTDMT_API -#endif - /* === Dependencies === */ -#include <stddef.h> /* size_t */ +#include "../common/zstd_deps.h" /* size_t */ #define ZSTD_STATIC_LINKING_ONLY /* ZSTD_parameters */ #include "../zstd.h" /* ZSTD_inBuffer, ZSTD_outBuffer, ZSTDLIB_API */ @@ -54,78 +42,34 @@ #define ZSTDMT_JOBSIZE_MAX (MEM_32bits() ? (512 MB) : (1024 MB)) +/* ======================================================== + * === Private interface, for use by ZSTD_compress.c === + * === Not exposed in libzstd. Never invoke directly === + * ======================================================== */ + /* === Memory management === */ typedef struct ZSTDMT_CCtx_s ZSTDMT_CCtx; /* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */ -ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx(unsigned nbWorkers); -/* Requires ZSTD_MULTITHREAD to be defined during compilation, otherwise it will return NULL. */ -ZSTDMT_API ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, - ZSTD_customMem cMem); -ZSTDMT_API size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx); - -ZSTDMT_API size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx); - - -/* === Simple one-pass compression function === */ - -ZSTDMT_API size_t ZSTDMT_compressCCtx(ZSTDMT_CCtx* mtctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - int compressionLevel); - +ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced(unsigned nbWorkers, + ZSTD_customMem cMem, + ZSTD_threadPool *pool); +size_t ZSTDMT_freeCCtx(ZSTDMT_CCtx* mtctx); +size_t ZSTDMT_sizeof_CCtx(ZSTDMT_CCtx* mtctx); /* === Streaming functions === */ -ZSTDMT_API size_t ZSTDMT_initCStream(ZSTDMT_CCtx* mtctx, int compressionLevel); -ZSTDMT_API size_t ZSTDMT_resetCStream(ZSTDMT_CCtx* mtctx, unsigned long long pledgedSrcSize); /**< if srcSize is not known at reset time, use ZSTD_CONTENTSIZE_UNKNOWN. Note: for compatibility with older programs, 0 means the same as ZSTD_CONTENTSIZE_UNKNOWN, but it will change in the future to mean "empty" */ - -ZSTDMT_API size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx); -ZSTDMT_API size_t ZSTDMT_compressStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output, ZSTD_inBuffer* input); - -ZSTDMT_API size_t ZSTDMT_flushStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */ -ZSTDMT_API size_t ZSTDMT_endStream(ZSTDMT_CCtx* mtctx, ZSTD_outBuffer* output); /**< @return : 0 == all flushed; >0 : still some data to be flushed; or an error code (ZSTD_isError()) */ - - -/* === Advanced functions and parameters === */ - -ZSTDMT_API size_t ZSTDMT_compress_advanced(ZSTDMT_CCtx* mtctx, - void* dst, size_t dstCapacity, - const void* src, size_t srcSize, - const ZSTD_CDict* cdict, - ZSTD_parameters params, - int overlapLog); - -ZSTDMT_API size_t ZSTDMT_initCStream_advanced(ZSTDMT_CCtx* mtctx, - const void* dict, size_t dictSize, /* dict can be released after init, a local copy is preserved within zcs */ - ZSTD_parameters params, - unsigned long long pledgedSrcSize); /* pledgedSrcSize is optional and can be zero == unknown */ - -ZSTDMT_API size_t ZSTDMT_initCStream_usingCDict(ZSTDMT_CCtx* mtctx, - const ZSTD_CDict* cdict, - ZSTD_frameParameters fparams, - unsigned long long pledgedSrcSize); /* note : zero means empty */ - -/* ZSTDMT_parameter : - * List of parameters that can be set using ZSTDMT_setMTCtxParameter() */ -typedef enum { - ZSTDMT_p_jobSize, /* Each job is compressed in parallel. By default, this value is dynamically determined depending on compression parameters. Can be set explicitly here. */ - ZSTDMT_p_overlapLog, /* Each job may reload a part of previous job to enhance compression ratio; 0 == no overlap, 6(default) == use 1/8th of window, >=9 == use full window. This is a "sticky" parameter : its value will be re-used on next compression job */ - ZSTDMT_p_rsyncable /* Enables rsyncable mode. */ -} ZSTDMT_parameter; - -/* ZSTDMT_setMTCtxParameter() : - * allow setting individual parameters, one at a time, among a list of enums defined in ZSTDMT_parameter. - * The function must be called typically after ZSTD_createCCtx() but __before ZSTDMT_init*() !__ - * Parameters not explicitly reset by ZSTDMT_init*() remain the same in consecutive compression sessions. - * @return : 0, or an error code (which can be tested using ZSTD_isError()) */ -ZSTDMT_API size_t ZSTDMT_setMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int value); - -/* ZSTDMT_getMTCtxParameter() : - * Query the ZSTDMT_CCtx for a parameter value. - * @return : 0, or an error code (which can be tested using ZSTD_isError()) */ -ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter parameter, int* value); +size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx); +/*! ZSTDMT_initCStream_internal() : + * Private use only. Init streaming operation. + * expects params to be valid. + * must receive dict, or cdict, or none, but not both. + * @return : 0, or an error code */ +size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs, + const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, + const ZSTD_CDict* cdict, + ZSTD_CCtx_params params, unsigned long long pledgedSrcSize); /*! ZSTDMT_compressStream_generic() : * Combines ZSTDMT_compressStream() with optional ZSTDMT_flushStream() or ZSTDMT_endStream() @@ -134,16 +78,10 @@ ZSTDMT_API size_t ZSTDMT_getMTCtxParameter(ZSTDMT_CCtx* mtctx, ZSTDMT_parameter * 0 if fully flushed * or an error code * note : needs to be init using any ZSTD_initCStream*() variant */ -ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, - ZSTD_outBuffer* output, - ZSTD_inBuffer* input, - ZSTD_EndDirective endOp); - - -/* ======================================================== - * === Private interface, for use by ZSTD_compress.c === - * === Not exposed in libzstd. Never invoke directly === - * ======================================================== */ +size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, + ZSTD_outBuffer* output, + ZSTD_inBuffer* input, + ZSTD_EndDirective endOp); /*! ZSTDMT_toFlushNow() * Tell how many bytes are ready to be flushed immediately. @@ -153,15 +91,6 @@ ZSTDMT_API size_t ZSTDMT_compressStream_generic(ZSTDMT_CCtx* mtctx, * therefore flushing is limited by speed of oldest job. */ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx); -/*! ZSTDMT_CCtxParam_setMTCtxParameter() - * like ZSTDMT_setMTCtxParameter(), but into a ZSTD_CCtx_Params */ -size_t ZSTDMT_CCtxParam_setMTCtxParameter(ZSTD_CCtx_params* params, ZSTDMT_parameter parameter, int value); - -/*! ZSTDMT_CCtxParam_setNbWorkers() - * Set nbWorkers, and clamp it. - * Also reset jobSize and overlapLog */ -size_t ZSTDMT_CCtxParam_setNbWorkers(ZSTD_CCtx_params* params, unsigned nbWorkers); - /*! ZSTDMT_updateCParams_whileCompressing() : * Updates only a selected set of compression parameters, to remain compatible with current frame. * New parameters will be applied to next compression job. */ @@ -174,17 +103,6 @@ void ZSTDMT_updateCParams_whileCompressing(ZSTDMT_CCtx* mtctx, const ZSTD_CCtx_p ZSTD_frameProgression ZSTDMT_getFrameProgression(ZSTDMT_CCtx* mtctx); -/*! ZSTDMT_initCStream_internal() : - * Private use only. Init streaming operation. - * expects params to be valid. - * must receive dict, or cdict, or none, but not both. - * @return : 0, or an error code */ -size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs, - const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, - const ZSTD_CDict* cdict, - ZSTD_CCtx_params params, unsigned long long pledgedSrcSize); - - #if defined (__cplusplus) } #endif diff --git a/thirdparty/zstd/decompress/huf_decompress.c b/thirdparty/zstd/decompress/huf_decompress.c index 68293a1309..1418206718 100644 --- a/thirdparty/zstd/decompress/huf_decompress.c +++ b/thirdparty/zstd/decompress/huf_decompress.c @@ -15,7 +15,7 @@ /* ************************************************************** * Dependencies ****************************************************************/ -#include <string.h> /* memcpy, memset */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memset */ #include "../common/compiler.h" #include "../common/bitstream.h" /* BIT_* */ #include "../common/fse.h" /* to compress headers */ @@ -103,7 +103,7 @@ typedef struct { BYTE maxTableLog; BYTE tableType; BYTE tableLog; BYTE reserved; static DTableDesc HUF_getDTableDesc(const HUF_DTable* table) { DTableDesc dtd; - memcpy(&dtd, table, sizeof(dtd)); + ZSTD_memcpy(&dtd, table, sizeof(dtd)); return dtd; } @@ -115,29 +115,51 @@ static DTableDesc HUF_getDTableDesc(const HUF_DTable* table) /*-***************************/ typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX1; /* single-symbol decoding */ +/** + * Packs 4 HUF_DEltX1 structs into a U64. This is used to lay down 4 entries at + * a time. + */ +static U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) { + U64 D4; + if (MEM_isLittleEndian()) { + D4 = symbol + (nbBits << 8); + } else { + D4 = (symbol << 8) + nbBits; + } + D4 *= 0x0001000100010001ULL; + return D4; +} + +typedef struct { + U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; + U32 rankStart[HUF_TABLELOG_ABSOLUTEMAX + 1]; + U32 statsWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32]; + BYTE symbols[HUF_SYMBOLVALUE_MAX + 1]; + BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1]; +} HUF_ReadDTableX1_Workspace; + + size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize) { + return HUF_readDTableX1_wksp_bmi2(DTable, src, srcSize, workSpace, wkspSize, /* bmi2 */ 0); +} + +size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2) +{ U32 tableLog = 0; U32 nbSymbols = 0; size_t iSize; void* const dtPtr = DTable + 1; HUF_DEltX1* const dt = (HUF_DEltX1*)dtPtr; + HUF_ReadDTableX1_Workspace* wksp = (HUF_ReadDTableX1_Workspace*)workSpace; - U32* rankVal; - BYTE* huffWeight; - size_t spaceUsed32 = 0; - - rankVal = (U32 *)workSpace + spaceUsed32; - spaceUsed32 += HUF_TABLELOG_ABSOLUTEMAX + 1; - huffWeight = (BYTE *)((U32 *)workSpace + spaceUsed32); - spaceUsed32 += HUF_ALIGN(HUF_SYMBOLVALUE_MAX + 1, sizeof(U32)) >> 2; - - if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge); + DEBUG_STATIC_ASSERT(HUF_DECOMPRESS_WORKSPACE_SIZE >= sizeof(*wksp)); + if (sizeof(*wksp) > wkspSize) return ERROR(tableLog_tooLarge); DEBUG_STATIC_ASSERT(sizeof(DTableDesc) == sizeof(HUF_DTable)); - /* memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */ + /* ZSTD_memset(huffWeight, 0, sizeof(huffWeight)); */ /* is not necessary, even though some analyzer complain ... */ - iSize = HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX + 1, rankVal, &nbSymbols, &tableLog, src, srcSize); + iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), bmi2); if (HUF_isError(iSize)) return iSize; /* Table header */ @@ -145,52 +167,117 @@ size_t HUF_readDTableX1_wksp(HUF_DTable* DTable, const void* src, size_t srcSize if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */ dtd.tableType = 0; dtd.tableLog = (BYTE)tableLog; - memcpy(DTable, &dtd, sizeof(dtd)); + ZSTD_memcpy(DTable, &dtd, sizeof(dtd)); } - /* Calculate starting value for each rank */ - { U32 n, nextRankStart = 0; - for (n=1; n<tableLog+1; n++) { - U32 const current = nextRankStart; - nextRankStart += (rankVal[n] << (n-1)); - rankVal[n] = current; - } } + /* Compute symbols and rankStart given rankVal: + * + * rankVal already contains the number of values of each weight. + * + * symbols contains the symbols ordered by weight. First are the rankVal[0] + * weight 0 symbols, followed by the rankVal[1] weight 1 symbols, and so on. + * symbols[0] is filled (but unused) to avoid a branch. + * + * rankStart contains the offset where each rank belongs in the DTable. + * rankStart[0] is not filled because there are no entries in the table for + * weight 0. + */ + { + int n; + int nextRankStart = 0; + int const unroll = 4; + int const nLimit = (int)nbSymbols - unroll + 1; + for (n=0; n<(int)tableLog+1; n++) { + U32 const curr = nextRankStart; + nextRankStart += wksp->rankVal[n]; + wksp->rankStart[n] = curr; + } + for (n=0; n < nLimit; n += unroll) { + int u; + for (u=0; u < unroll; ++u) { + size_t const w = wksp->huffWeight[n+u]; + wksp->symbols[wksp->rankStart[w]++] = (BYTE)(n+u); + } + } + for (; n < (int)nbSymbols; ++n) { + size_t const w = wksp->huffWeight[n]; + wksp->symbols[wksp->rankStart[w]++] = (BYTE)n; + } + } - /* fill DTable */ - { U32 n; - size_t const nEnd = nbSymbols; - for (n=0; n<nEnd; n++) { - size_t const w = huffWeight[n]; - size_t const length = (1 << w) >> 1; - size_t const uStart = rankVal[w]; - size_t const uEnd = uStart + length; - size_t u; - HUF_DEltX1 D; - D.byte = (BYTE)n; - D.nbBits = (BYTE)(tableLog + 1 - w); - rankVal[w] = (U32)uEnd; - if (length < 4) { - /* Use length in the loop bound so the compiler knows it is short. */ - for (u = 0; u < length; ++u) - dt[uStart + u] = D; - } else { - /* Unroll the loop 4 times, we know it is a power of 2. */ - for (u = uStart; u < uEnd; u += 4) { - dt[u + 0] = D; - dt[u + 1] = D; - dt[u + 2] = D; - dt[u + 3] = D; - } } } } + /* fill DTable + * We fill all entries of each weight in order. + * That way length is a constant for each iteration of the outter loop. + * We can switch based on the length to a different inner loop which is + * optimized for that particular case. + */ + { + U32 w; + int symbol=wksp->rankVal[0]; + int rankStart=0; + for (w=1; w<tableLog+1; ++w) { + int const symbolCount = wksp->rankVal[w]; + int const length = (1 << w) >> 1; + int uStart = rankStart; + BYTE const nbBits = (BYTE)(tableLog + 1 - w); + int s; + int u; + switch (length) { + case 1: + for (s=0; s<symbolCount; ++s) { + HUF_DEltX1 D; + D.byte = wksp->symbols[symbol + s]; + D.nbBits = nbBits; + dt[uStart] = D; + uStart += 1; + } + break; + case 2: + for (s=0; s<symbolCount; ++s) { + HUF_DEltX1 D; + D.byte = wksp->symbols[symbol + s]; + D.nbBits = nbBits; + dt[uStart+0] = D; + dt[uStart+1] = D; + uStart += 2; + } + break; + case 4: + for (s=0; s<symbolCount; ++s) { + U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits); + MEM_write64(dt + uStart, D4); + uStart += 4; + } + break; + case 8: + for (s=0; s<symbolCount; ++s) { + U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits); + MEM_write64(dt + uStart, D4); + MEM_write64(dt + uStart + 4, D4); + uStart += 8; + } + break; + default: + for (s=0; s<symbolCount; ++s) { + U64 const D4 = HUF_DEltX1_set4(wksp->symbols[symbol + s], nbBits); + for (u=0; u < length; u += 16) { + MEM_write64(dt + uStart + u + 0, D4); + MEM_write64(dt + uStart + u + 4, D4); + MEM_write64(dt + uStart + u + 8, D4); + MEM_write64(dt + uStart + u + 12, D4); + } + assert(u == length); + uStart += length; + } + break; + } + symbol += symbolCount; + rankStart += symbolCount * length; + } + } return iSize; } -size_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_readDTableX1_wksp(DTable, src, srcSize, - workSpace, sizeof(workSpace)); -} - FORCE_INLINE_TEMPLATE BYTE HUF_decodeSymbolX1(BIT_DStream_t* Dstream, const HUF_DEltX1* dt, const U32 dtLog) { @@ -389,20 +476,6 @@ size_t HUF_decompress1X1_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize, } -size_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - -size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); - return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize); -} - size_t HUF_decompress4X1_usingDTable( void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, @@ -419,8 +492,7 @@ static size_t HUF_decompress4X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size { const BYTE* ip = (const BYTE*) cSrc; - size_t const hSize = HUF_readDTableX1_wksp (dctx, cSrc, cSrcSize, - workSpace, wkspSize); + size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2); if (HUF_isError(hSize)) return hSize; if (hSize >= cSrcSize) return ERROR(srcSize_wrong); ip += hSize; cSrcSize -= hSize; @@ -436,18 +508,6 @@ size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, } -size_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} -size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); - return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - #endif /* HUF_FORCE_DECOMPRESS_X2 */ @@ -474,7 +534,7 @@ static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 co U32 rankVal[HUF_TABLELOG_MAX + 1]; /* get pre-calculated rankVal */ - memcpy(rankVal, rankValOrigin, sizeof(rankVal)); + ZSTD_memcpy(rankVal, rankValOrigin, sizeof(rankVal)); /* fill skipped values */ if (minWeight>1) { @@ -516,7 +576,7 @@ static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog, const U32 minBits = nbBitsBaseline - maxWeight; U32 s; - memcpy(rankVal, rankValOrigin, sizeof(rankVal)); + ZSTD_memcpy(rankVal, rankValOrigin, sizeof(rankVal)); /* fill DTable */ for (s=0; s<sortedListSize; s++) { @@ -581,11 +641,11 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, if ((spaceUsed32 << 2) > wkspSize) return ERROR(tableLog_tooLarge); rankStart = rankStart0 + 1; - memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1)); + ZSTD_memset(rankStats, 0, sizeof(U32) * (2 * HUF_TABLELOG_MAX + 2 + 1)); DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(HUF_DTable)); /* if compiler fails here, assertion is wrong */ if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge); - /* memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */ + /* ZSTD_memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */ iSize = HUF_readStats(weightList, HUF_SYMBOLVALUE_MAX + 1, rankStats, &nbSymbols, &tableLog, src, srcSize); if (HUF_isError(iSize)) return iSize; @@ -599,9 +659,9 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, /* Get start index of each weight */ { U32 w, nextRankStart = 0; for (w=1; w<maxW+1; w++) { - U32 current = nextRankStart; + U32 curr = nextRankStart; nextRankStart += rankStats[w]; - rankStart[w] = current; + rankStart[w] = curr; } rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/ sizeOfSort = nextRankStart; @@ -624,9 +684,9 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, U32 nextRankVal = 0; U32 w; for (w=1; w<maxW+1; w++) { - U32 current = nextRankVal; + U32 curr = nextRankVal; nextRankVal += rankStats[w] << (w+rescale); - rankVal0[w] = current; + rankVal0[w] = curr; } } { U32 const minBits = tableLog+1 - maxW; U32 consumed; @@ -644,23 +704,16 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable, dtd.tableLog = (BYTE)maxTableLog; dtd.tableType = 1; - memcpy(DTable, &dtd, sizeof(dtd)); + ZSTD_memcpy(DTable, &dtd, sizeof(dtd)); return iSize; } -size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_readDTableX2_wksp(DTable, src, srcSize, - workSpace, sizeof(workSpace)); -} - FORCE_INLINE_TEMPLATE U32 HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog) { size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ - memcpy(op, dt+val, 2); + ZSTD_memcpy(op, dt+val, 2); BIT_skipBits(DStream, dt[val].nbBits); return dt[val].length; } @@ -669,7 +722,7 @@ FORCE_INLINE_TEMPLATE U32 HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog) { size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */ - memcpy(op, dt+val, 1); + ZSTD_memcpy(op, dt+val, 1); if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits); else { if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) { @@ -890,20 +943,6 @@ size_t HUF_decompress1X2_DCtx_wksp(HUF_DTable* DCtx, void* dst, size_t dstSize, } -size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - -size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); - return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - size_t HUF_decompress4X2_usingDTable( void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, @@ -937,20 +976,6 @@ size_t HUF_decompress4X2_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, } -size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - -size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); - return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); -} - #endif /* HUF_FORCE_DECOMPRESS_X1 */ @@ -1051,67 +1076,6 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize) } -typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); - -size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ -#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2) - static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 }; -#endif - - /* validation checks */ - if (dstSize == 0) return ERROR(dstSize_tooSmall); - if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ - if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ - - { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)algoNb; - assert(algoNb == 0); - return HUF_decompress4X1(dst, dstSize, cSrc, cSrcSize); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)algoNb; - assert(algoNb == 1); - return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize); -#else - return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); -#endif - } -} - -size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - /* validation checks */ - if (dstSize == 0) return ERROR(dstSize_tooSmall); - if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ - if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ - - { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); -#if defined(HUF_FORCE_DECOMPRESS_X1) - (void)algoNb; - assert(algoNb == 0); - return HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); -#elif defined(HUF_FORCE_DECOMPRESS_X2) - (void)algoNb; - assert(algoNb == 1); - return HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); -#else - return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) : - HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ; -#endif - } -} - -size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress4X_hufOnly_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - - size_t HUF_decompress4X_hufOnly_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize, void* workSpace, @@ -1145,8 +1109,8 @@ size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, /* validation checks */ if (dstSize == 0) return ERROR(dstSize_tooSmall); if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ - if (cSrcSize == dstSize) { memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ - if (cSrcSize == 1) { memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ + if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ + if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); #if defined(HUF_FORCE_DECOMPRESS_X1) @@ -1168,14 +1132,6 @@ size_t HUF_decompress1X_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize, } } -size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, - const void* cSrc, size_t cSrcSize) -{ - U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; - return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, - workSpace, sizeof(workSpace)); -} - size_t HUF_decompress1X_usingDTable_bmi2(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize, const HUF_DTable* DTable, int bmi2) { @@ -1199,7 +1155,7 @@ size_t HUF_decompress1X1_DCtx_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t dstS { const BYTE* ip = (const BYTE*) cSrc; - size_t const hSize = HUF_readDTableX1_wksp(dctx, cSrc, cSrcSize, workSpace, wkspSize); + size_t const hSize = HUF_readDTableX1_wksp_bmi2(dctx, cSrc, cSrcSize, workSpace, wkspSize, bmi2); if (HUF_isError(hSize)) return hSize; if (hSize >= cSrcSize) return ERROR(srcSize_wrong); ip += hSize; cSrcSize -= hSize; @@ -1246,3 +1202,149 @@ size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t ds #endif } } + +#ifndef ZSTD_NO_UNUSED_FUNCTIONS +#ifndef HUF_FORCE_DECOMPRESS_X2 +size_t HUF_readDTableX1(HUF_DTable* DTable, const void* src, size_t srcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_readDTableX1_wksp(DTable, src, srcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X1_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress1X1_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); + return HUF_decompress1X1_DCtx (DTable, dst, dstSize, cSrc, cSrcSize); +} +#endif + +#ifndef HUF_FORCE_DECOMPRESS_X1 +size_t HUF_readDTableX2(HUF_DTable* DTable, const void* src, size_t srcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_readDTableX2_wksp(DTable, src, srcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X2_DCtx(HUF_DTable* DCtx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress1X2_DCtx_wksp(DCtx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); + return HUF_decompress1X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); +} +#endif + +#ifndef HUF_FORCE_DECOMPRESS_X2 +size_t HUF_decompress4X1_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress4X1_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} +size_t HUF_decompress4X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX1(DTable, HUF_TABLELOG_MAX); + return HUF_decompress4X1_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); +} +#endif + +#ifndef HUF_FORCE_DECOMPRESS_X1 +size_t HUF_decompress4X2_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress4X2_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress4X2 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + HUF_CREATE_STATIC_DTABLEX2(DTable, HUF_TABLELOG_MAX); + return HUF_decompress4X2_DCtx(DTable, dst, dstSize, cSrc, cSrcSize); +} +#endif + +typedef size_t (*decompressionAlgo)(void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); + +size_t HUF_decompress (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ +#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2) + static const decompressionAlgo decompress[2] = { HUF_decompress4X1, HUF_decompress4X2 }; +#endif + + /* validation checks */ + if (dstSize == 0) return ERROR(dstSize_tooSmall); + if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ + if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ + if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ + + { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); +#if defined(HUF_FORCE_DECOMPRESS_X1) + (void)algoNb; + assert(algoNb == 0); + return HUF_decompress4X1(dst, dstSize, cSrc, cSrcSize); +#elif defined(HUF_FORCE_DECOMPRESS_X2) + (void)algoNb; + assert(algoNb == 1); + return HUF_decompress4X2(dst, dstSize, cSrc, cSrcSize); +#else + return decompress[algoNb](dst, dstSize, cSrc, cSrcSize); +#endif + } +} + +size_t HUF_decompress4X_DCtx (HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + /* validation checks */ + if (dstSize == 0) return ERROR(dstSize_tooSmall); + if (cSrcSize > dstSize) return ERROR(corruption_detected); /* invalid */ + if (cSrcSize == dstSize) { ZSTD_memcpy(dst, cSrc, dstSize); return dstSize; } /* not compressed */ + if (cSrcSize == 1) { ZSTD_memset(dst, *(const BYTE*)cSrc, dstSize); return dstSize; } /* RLE */ + + { U32 const algoNb = HUF_selectDecoder(dstSize, cSrcSize); +#if defined(HUF_FORCE_DECOMPRESS_X1) + (void)algoNb; + assert(algoNb == 0); + return HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); +#elif defined(HUF_FORCE_DECOMPRESS_X2) + (void)algoNb; + assert(algoNb == 1); + return HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize); +#else + return algoNb ? HUF_decompress4X2_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) : + HUF_decompress4X1_DCtx(dctx, dst, dstSize, cSrc, cSrcSize) ; +#endif + } +} + +size_t HUF_decompress4X_hufOnly(HUF_DTable* dctx, void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress4X_hufOnly_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} + +size_t HUF_decompress1X_DCtx(HUF_DTable* dctx, void* dst, size_t dstSize, + const void* cSrc, size_t cSrcSize) +{ + U32 workSpace[HUF_DECOMPRESS_WORKSPACE_SIZE_U32]; + return HUF_decompress1X_DCtx_wksp(dctx, dst, dstSize, cSrc, cSrcSize, + workSpace, sizeof(workSpace)); +} +#endif diff --git a/thirdparty/zstd/decompress/zstd_ddict.c b/thirdparty/zstd/decompress/zstd_ddict.c index c8cb8ecc95..f5cc23b387 100644 --- a/thirdparty/zstd/decompress/zstd_ddict.c +++ b/thirdparty/zstd/decompress/zstd_ddict.c @@ -14,7 +14,7 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include <string.h> /* memcpy, memmove, memset */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */ #include "../common/cpu.h" /* bmi2 */ #include "../common/mem.h" /* low level memory routines */ #define FSE_STATIC_LINKING_ONLY @@ -127,11 +127,11 @@ static size_t ZSTD_initDDict_internal(ZSTD_DDict* ddict, ddict->dictContent = dict; if (!dict) dictSize = 0; } else { - void* const internalBuffer = ZSTD_malloc(dictSize, ddict->cMem); + void* const internalBuffer = ZSTD_customMalloc(dictSize, ddict->cMem); ddict->dictBuffer = internalBuffer; ddict->dictContent = internalBuffer; if (!internalBuffer) return ERROR(memory_allocation); - memcpy(internalBuffer, dict, dictSize); + ZSTD_memcpy(internalBuffer, dict, dictSize); } ddict->dictSize = dictSize; ddict->entropy.hufTable[0] = (HUF_DTable)((HufLog)*0x1000001); /* cover both little and big endian */ @@ -147,9 +147,9 @@ ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType, ZSTD_customMem customMem) { - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; - { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_malloc(sizeof(ZSTD_DDict), customMem); + { ZSTD_DDict* const ddict = (ZSTD_DDict*) ZSTD_customMalloc(sizeof(ZSTD_DDict), customMem); if (ddict == NULL) return NULL; ddict->cMem = customMem; { size_t const initResult = ZSTD_initDDict_internal(ddict, @@ -198,7 +198,7 @@ const ZSTD_DDict* ZSTD_initStaticDDict( if ((size_t)sBuffer & 7) return NULL; /* 8-aligned */ if (sBufferSize < neededSpace) return NULL; if (dictLoadMethod == ZSTD_dlm_byCopy) { - memcpy(ddict+1, dict, dictSize); /* local copy */ + ZSTD_memcpy(ddict+1, dict, dictSize); /* local copy */ dict = ddict+1; } if (ZSTD_isError( ZSTD_initDDict_internal(ddict, @@ -213,8 +213,8 @@ size_t ZSTD_freeDDict(ZSTD_DDict* ddict) { if (ddict==NULL) return 0; /* support free on NULL */ { ZSTD_customMem const cMem = ddict->cMem; - ZSTD_free(ddict->dictBuffer, cMem); - ZSTD_free(ddict, cMem); + ZSTD_customFree(ddict->dictBuffer, cMem); + ZSTD_customFree(ddict, cMem); return 0; } } diff --git a/thirdparty/zstd/decompress/zstd_ddict.h b/thirdparty/zstd/decompress/zstd_ddict.h index af307efd3d..8906a71c94 100644 --- a/thirdparty/zstd/decompress/zstd_ddict.h +++ b/thirdparty/zstd/decompress/zstd_ddict.h @@ -15,7 +15,7 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include <stddef.h> /* size_t */ +#include "../common/zstd_deps.h" /* size_t */ #include "../zstd.h" /* ZSTD_DDict, and several public functions */ diff --git a/thirdparty/zstd/decompress/zstd_decompress.c b/thirdparty/zstd/decompress/zstd_decompress.c index be5c7cfc33..21f846bc77 100644 --- a/thirdparty/zstd/decompress/zstd_decompress.c +++ b/thirdparty/zstd/decompress/zstd_decompress.c @@ -55,7 +55,7 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include <string.h> /* memcpy, memmove, memset */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */ #include "../common/cpu.h" /* bmi2 */ #include "../common/mem.h" /* low level memory routines */ #define FSE_STATIC_LINKING_ONLY @@ -94,11 +94,18 @@ static size_t ZSTD_startingInputLength(ZSTD_format_e format) return startingInputLength; } +static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx) +{ + assert(dctx->streamStage == zdss_init); + dctx->format = ZSTD_f_zstd1; + dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; + dctx->outBufferMode = ZSTD_bm_buffered; + dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum; +} + static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) { - dctx->format = ZSTD_f_zstd1; /* ZSTD_decompressBegin() invokes ZSTD_startingInputLength() with argument dctx->format */ dctx->staticSize = 0; - dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; dctx->ddict = NULL; dctx->ddictLocal = NULL; dctx->dictEnd = NULL; @@ -113,7 +120,8 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx) dctx->noForwardProgress = 0; dctx->oversizedDuration = 0; dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid()); - dctx->outBufferMode = ZSTD_obm_buffered; + ZSTD_DCtx_resetParameters(dctx); + dctx->validateChecksum = 1; #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION dctx->dictContentEndForFuzzing = NULL; #endif @@ -134,9 +142,9 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize) ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem) { - if (!customMem.customAlloc ^ !customMem.customFree) return NULL; + if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL; - { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_malloc(sizeof(*dctx), customMem); + { ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem); if (!dctx) return NULL; dctx->customMem = customMem; ZSTD_initDCtx_internal(dctx); @@ -164,13 +172,13 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx) RETURN_ERROR_IF(dctx->staticSize, memory_allocation, "not compatible with static DCtx"); { ZSTD_customMem const cMem = dctx->customMem; ZSTD_clearDict(dctx); - ZSTD_free(dctx->inBuff, cMem); + ZSTD_customFree(dctx->inBuff, cMem); dctx->inBuff = NULL; #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) if (dctx->legacyContext) ZSTD_freeLegacyStreamContext(dctx->legacyContext, dctx->previousLegacyVersion); #endif - ZSTD_free(dctx, cMem); + ZSTD_customFree(dctx, cMem); return 0; } } @@ -179,7 +187,7 @@ size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx) void ZSTD_copyDCtx(ZSTD_DCtx* dstDCtx, const ZSTD_DCtx* srcDCtx) { size_t const toCopy = (size_t)((char*)(&dstDCtx->inBuff) - (char*)dstDCtx); - memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */ + ZSTD_memcpy(dstDCtx, srcDCtx, toCopy); /* no need to copy workspace */ } @@ -246,7 +254,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s const BYTE* ip = (const BYTE*)src; size_t const minInputSize = ZSTD_startingInputLength(format); - memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */ + ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); /* not strictly necessary, but static analyzer do not understand that zfhPtr is only going to be read only if return value is zero, since they are 2 different signals */ if (srcSize < minInputSize) return minInputSize; RETURN_ERROR_IF(src==NULL, GENERIC, "invalid parameter"); @@ -256,7 +264,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s /* skippable frame */ if (srcSize < ZSTD_SKIPPABLEHEADERSIZE) return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */ - memset(zfhPtr, 0, sizeof(*zfhPtr)); + ZSTD_memset(zfhPtr, 0, sizeof(*zfhPtr)); zfhPtr->frameContentSize = MEM_readLE32((const char *)src + ZSTD_FRAMEIDSIZE); zfhPtr->frameType = ZSTD_skippableFrame; return 0; @@ -446,7 +454,8 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he RETURN_ERROR_IF(dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID), dictionary_wrong, ""); #endif - if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0); + dctx->validateChecksum = (dctx->fParams.checksumFlag && !dctx->forceIgnoreChecksum) ? 1 : 0; + if (dctx->validateChecksum) XXH64_reset(&dctx->xxhState, 0); return 0; } @@ -461,7 +470,7 @@ static ZSTD_frameSizeInfo ZSTD_errorFrameSizeInfo(size_t ret) static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize) { ZSTD_frameSizeInfo frameSizeInfo; - memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo)); + ZSTD_memset(&frameSizeInfo, 0, sizeof(ZSTD_frameSizeInfo)); #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) if (ZSTD_isLegacy(src, srcSize)) @@ -516,7 +525,7 @@ static ZSTD_frameSizeInfo ZSTD_findFrameSizeInfo(const void* src, size_t srcSize ip += 4; } - frameSizeInfo.compressedSize = ip - ipstart; + frameSizeInfo.compressedSize = (size_t)(ip - ipstart); frameSizeInfo.decompressedBound = (zfh.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN) ? zfh.frameContentSize : nbBlocks * zfh.blockSizeMax; @@ -579,12 +588,12 @@ static size_t ZSTD_copyRawBlock(void* dst, size_t dstCapacity, const void* src, size_t srcSize) { DEBUGLOG(5, "ZSTD_copyRawBlock"); + RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, ""); if (dst == NULL) { if (srcSize == 0) return 0; RETURN_ERROR(dstBuffer_null, ""); } - RETURN_ERROR_IF(srcSize > dstCapacity, dstSize_tooSmall, ""); - memcpy(dst, src, srcSize); + ZSTD_memcpy(dst, src, srcSize); return srcSize; } @@ -592,12 +601,12 @@ static size_t ZSTD_setRleBlock(void* dst, size_t dstCapacity, BYTE b, size_t regenSize) { + RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, ""); if (dst == NULL) { if (regenSize == 0) return 0; RETURN_ERROR(dstBuffer_null, ""); } - RETURN_ERROR_IF(regenSize > dstCapacity, dstSize_tooSmall, ""); - memset(dst, b, regenSize); + ZSTD_memset(dst, b, regenSize); return regenSize; } @@ -647,13 +656,13 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, switch(blockProperties.blockType) { case bt_compressed: - decodedSize = ZSTD_decompressBlock_internal(dctx, op, oend-op, ip, cBlockSize, /* frame */ 1); + decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1); break; case bt_raw : - decodedSize = ZSTD_copyRawBlock(op, oend-op, ip, cBlockSize); + decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize); break; case bt_rle : - decodedSize = ZSTD_setRleBlock(op, oend-op, *ip, blockProperties.origSize); + decodedSize = ZSTD_setRleBlock(op, (size_t)(oend-op), *ip, blockProperties.origSize); break; case bt_reserved : default: @@ -661,7 +670,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, } if (ZSTD_isError(decodedSize)) return decodedSize; - if (dctx->fParams.checksumFlag) + if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, op, decodedSize); if (decodedSize != 0) op += decodedSize; @@ -676,11 +685,13 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, corruption_detected, ""); } if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */ - U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); - U32 checkRead; RETURN_ERROR_IF(remainingSrcSize<4, checksum_wrong, ""); - checkRead = MEM_readLE32(ip); - RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, ""); + if (!dctx->forceIgnoreChecksum) { + U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); + U32 checkRead; + checkRead = MEM_readLE32(ip); + RETURN_ERROR_IF(checkRead != checkCalc, checksum_wrong, ""); + } ip += 4; remainingSrcSize -= 4; } @@ -688,7 +699,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, /* Allow caller to get size read */ *srcPtr = ip; *srcSizePtr = remainingSrcSize; - return op-ostart; + return (size_t)(op-ostart); } static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, @@ -721,7 +732,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, decodedSize = ZSTD_decompressLegacy(dst, dstCapacity, src, frameSize, dict, dictSize); if (ZSTD_isError(decodedSize)) return decodedSize; - assert(decodedSize <=- dstCapacity); + assert(decodedSize <= dstCapacity); dst = (BYTE*)dst + decodedSize; dstCapacity -= decodedSize; @@ -761,15 +772,13 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, (ZSTD_getErrorCode(res) == ZSTD_error_prefix_unknown) && (moreThan1Frame==1), srcSize_wrong, - "at least one frame successfully completed, but following " - "bytes are garbage: it's more likely to be a srcSize error, " - "specifying more bytes than compressed size of frame(s). This " - "error message replaces ERROR(prefix_unknown), which would be " - "confusing, as the first header is actually correct. Note that " - "one could be unlucky, it might be a corruption error instead, " - "happening right at the place where we expect zstd magic " - "bytes. But this is _much_ less likely than a srcSize field " - "error."); + "At least one frame successfully completed, " + "but following bytes are garbage: " + "it's more likely to be a srcSize error, " + "specifying more input bytes than size of frame(s). " + "Note: one could be unlucky, it might be a corruption error instead, " + "happening right at the place where we expect zstd magic bytes. " + "But this is _much_ less likely than a srcSize field error."); if (ZSTD_isError(res)) return res; assert(res <= dstCapacity); if (res != 0) @@ -781,7 +790,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, RETURN_ERROR_IF(srcSize, srcSize_wrong, "input not entirely consumed"); - return (BYTE*)dst - (BYTE*)dststart; + return (size_t)((BYTE*)dst - (BYTE*)dststart); } size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx, @@ -899,21 +908,21 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c if (dctx->format == ZSTD_f_zstd1) { /* allows header */ assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */ if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ - memcpy(dctx->headerBuffer, src, srcSize); + ZSTD_memcpy(dctx->headerBuffer, src, srcSize); dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */ dctx->stage = ZSTDds_decodeSkippableHeader; return 0; } } dctx->headerSize = ZSTD_frameHeaderSize_internal(src, srcSize, dctx->format); if (ZSTD_isError(dctx->headerSize)) return dctx->headerSize; - memcpy(dctx->headerBuffer, src, srcSize); + ZSTD_memcpy(dctx->headerBuffer, src, srcSize); dctx->expected = dctx->headerSize - srcSize; dctx->stage = ZSTDds_decodeFrameHeader; return 0; case ZSTDds_decodeFrameHeader: assert(src != NULL); - memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize); + ZSTD_memcpy(dctx->headerBuffer + (dctx->headerSize - srcSize), src, srcSize); FORWARD_IF_ERROR(ZSTD_decodeFrameHeader(dctx, dctx->headerBuffer, dctx->headerSize), ""); dctx->expected = ZSTD_blockHeaderSize; dctx->stage = ZSTDds_decodeBlockHeader; @@ -977,7 +986,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c RETURN_ERROR_IF(rSize > dctx->fParams.blockSizeMax, corruption_detected, "Decompressed Block Size Exceeds Maximum"); DEBUGLOG(5, "ZSTD_decompressContinue: decoded size from block : %u", (unsigned)rSize); dctx->decodedSize += rSize; - if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize); + if (dctx->validateChecksum) XXH64_update(&dctx->xxhState, dst, rSize); dctx->previousDstEnd = (char*)dst + rSize; /* Stay on the same stage until we are finished streaming the block. */ @@ -1007,10 +1016,13 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c case ZSTDds_checkChecksum: assert(srcSize == 4); /* guaranteed by dctx->expected */ - { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); - U32 const check32 = MEM_readLE32(src); - DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32); - RETURN_ERROR_IF(check32 != h32, checksum_wrong, ""); + { + if (dctx->validateChecksum) { + U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); + U32 const check32 = MEM_readLE32(src); + DEBUGLOG(4, "ZSTD_decompressContinue: checksum : calculated %08X :: %08X read", (unsigned)h32, (unsigned)check32); + RETURN_ERROR_IF(check32 != h32, checksum_wrong, ""); + } dctx->expected = 0; dctx->stage = ZSTDds_getFrameHeaderSize; return 0; @@ -1019,7 +1031,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c case ZSTDds_decodeSkippableHeader: assert(src != NULL); assert(srcSize <= ZSTD_SKIPPABLEHEADERSIZE); - memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */ + ZSTD_memcpy(dctx->headerBuffer + (ZSTD_SKIPPABLEHEADERSIZE - srcSize), src, srcSize); /* complete skippable header */ dctx->expected = MEM_readLE32(dctx->headerBuffer + ZSTD_FRAMEIDSIZE); /* note : dctx->expected can grow seriously large, beyond local buffer size */ dctx->stage = ZSTDds_skipFrame; return 0; @@ -1075,7 +1087,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, workspace, workspaceSize); #else size_t const hSize = HUF_readDTableX2_wksp(entropy->hufTable, - dictPtr, dictEnd - dictPtr, + dictPtr, (size_t)(dictEnd - dictPtr), workspace, workspaceSize); #endif RETURN_ERROR_IF(HUF_isError(hSize), dictionary_corrupted, ""); @@ -1084,40 +1096,46 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, { short offcodeNCount[MaxOff+1]; unsigned offcodeMaxValue = MaxOff, offcodeLog; - size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, dictEnd-dictPtr); + size_t const offcodeHeaderSize = FSE_readNCount(offcodeNCount, &offcodeMaxValue, &offcodeLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(offcodeHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(offcodeMaxValue > MaxOff, dictionary_corrupted, ""); RETURN_ERROR_IF(offcodeLog > OffFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->OFTable, offcodeNCount, offcodeMaxValue, OF_base, OF_bits, - offcodeLog); + offcodeLog, + entropy->workspace, sizeof(entropy->workspace), + /* bmi2 */0); dictPtr += offcodeHeaderSize; } { short matchlengthNCount[MaxML+1]; unsigned matchlengthMaxValue = MaxML, matchlengthLog; - size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, dictEnd-dictPtr); + size_t const matchlengthHeaderSize = FSE_readNCount(matchlengthNCount, &matchlengthMaxValue, &matchlengthLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(matchlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(matchlengthMaxValue > MaxML, dictionary_corrupted, ""); RETURN_ERROR_IF(matchlengthLog > MLFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->MLTable, matchlengthNCount, matchlengthMaxValue, ML_base, ML_bits, - matchlengthLog); + matchlengthLog, + entropy->workspace, sizeof(entropy->workspace), + /* bmi2 */ 0); dictPtr += matchlengthHeaderSize; } { short litlengthNCount[MaxLL+1]; unsigned litlengthMaxValue = MaxLL, litlengthLog; - size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, dictEnd-dictPtr); + size_t const litlengthHeaderSize = FSE_readNCount(litlengthNCount, &litlengthMaxValue, &litlengthLog, dictPtr, (size_t)(dictEnd-dictPtr)); RETURN_ERROR_IF(FSE_isError(litlengthHeaderSize), dictionary_corrupted, ""); RETURN_ERROR_IF(litlengthMaxValue > MaxLL, dictionary_corrupted, ""); RETURN_ERROR_IF(litlengthLog > LLFSELog, dictionary_corrupted, ""); ZSTD_buildFSETable( entropy->LLTable, litlengthNCount, litlengthMaxValue, LL_base, LL_bits, - litlengthLog); + litlengthLog, + entropy->workspace, sizeof(entropy->workspace), + /* bmi2 */ 0); dictPtr += litlengthHeaderSize; } @@ -1131,7 +1149,7 @@ ZSTD_loadDEntropy(ZSTD_entropyDTables_t* entropy, entropy->rep[i] = rep; } } - return dictPtr - (const BYTE*)dict; + return (size_t)(dictPtr - (const BYTE*)dict); } static size_t ZSTD_decompress_insertDictionary(ZSTD_DCtx* dctx, const void* dict, size_t dictSize) @@ -1170,7 +1188,7 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx) dctx->dictID = 0; dctx->bType = bt_reserved; ZSTD_STATIC_ASSERT(sizeof(dctx->entropy.rep) == sizeof(repStartValue)); - memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */ + ZSTD_memcpy(dctx->entropy.rep, repStartValue, sizeof(repStartValue)); /* initial repcodes */ dctx->LLTptr = dctx->entropy.LLTable; dctx->MLTptr = dctx->entropy.MLTable; dctx->OFTptr = dctx->entropy.OFTable; @@ -1394,7 +1412,7 @@ size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize) size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format) { - return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, format); + return ZSTD_DCtx_setParameter(dctx, ZSTD_d_format, (int)format); } ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam) @@ -1411,8 +1429,12 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam) ZSTD_STATIC_ASSERT(ZSTD_f_zstd1 < ZSTD_f_zstd1_magicless); return bounds; case ZSTD_d_stableOutBuffer: - bounds.lowerBound = (int)ZSTD_obm_buffered; - bounds.upperBound = (int)ZSTD_obm_stable; + bounds.lowerBound = (int)ZSTD_bm_buffered; + bounds.upperBound = (int)ZSTD_bm_stable; + return bounds; + case ZSTD_d_forceIgnoreChecksum: + bounds.lowerBound = (int)ZSTD_d_validateChecksum; + bounds.upperBound = (int)ZSTD_d_ignoreChecksum; return bounds; default:; } @@ -1436,6 +1458,26 @@ static int ZSTD_dParam_withinBounds(ZSTD_dParameter dParam, int value) RETURN_ERROR_IF(!ZSTD_dParam_withinBounds(p, v), parameter_outOfBound, ""); \ } +size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value) +{ + switch (param) { + case ZSTD_d_windowLogMax: + *value = (int)ZSTD_highbit32((U32)dctx->maxWindowSize); + return 0; + case ZSTD_d_format: + *value = (int)dctx->format; + return 0; + case ZSTD_d_stableOutBuffer: + *value = (int)dctx->outBufferMode; + return 0; + case ZSTD_d_forceIgnoreChecksum: + *value = (int)dctx->forceIgnoreChecksum; + return 0; + default:; + } + RETURN_ERROR(parameter_unsupported, ""); +} + size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value) { RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); @@ -1451,7 +1493,11 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value return 0; case ZSTD_d_stableOutBuffer: CHECK_DBOUNDS(ZSTD_d_stableOutBuffer, value); - dctx->outBufferMode = (ZSTD_outBufferMode_e)value; + dctx->outBufferMode = (ZSTD_bufferMode_e)value; + return 0; + case ZSTD_d_forceIgnoreChecksum: + CHECK_DBOUNDS(ZSTD_d_forceIgnoreChecksum, value); + dctx->forceIgnoreChecksum = (ZSTD_forceIgnoreChecksum_e)value; return 0; default:; } @@ -1469,8 +1515,7 @@ size_t ZSTD_DCtx_reset(ZSTD_DCtx* dctx, ZSTD_ResetDirective reset) || (reset == ZSTD_reset_session_and_parameters) ) { RETURN_ERROR_IF(dctx->streamStage != zdss_init, stage_wrong, ""); ZSTD_clearDict(dctx); - dctx->format = ZSTD_f_zstd1; - dctx->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT; + ZSTD_DCtx_resetParameters(dctx); } return 0; } @@ -1524,7 +1569,7 @@ static void ZSTD_DCtx_updateOversizedDuration(ZSTD_DStream* zds, size_t const ne { if (ZSTD_DCtx_isOverflow(zds, neededInBuffSize, neededOutBuffSize)) zds->oversizedDuration++; - else + else zds->oversizedDuration = 0; } @@ -1538,7 +1583,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* { ZSTD_outBuffer const expect = zds->expectedOutBuffer; /* No requirement when ZSTD_obm_stable is not enabled. */ - if (zds->outBufferMode != ZSTD_obm_stable) + if (zds->outBufferMode != ZSTD_bm_stable) return 0; /* Any buffer is allowed in zdss_init, this must be the same for every other call until * the context is reset. @@ -1548,7 +1593,7 @@ static size_t ZSTD_checkOutBuffer(ZSTD_DStream const* zds, ZSTD_outBuffer const* /* The buffer must match our expectation exactly. */ if (expect.dst == output->dst && expect.pos == output->pos && expect.size == output->size) return 0; - RETURN_ERROR(dstBuffer_wrong, "ZSTD_obm_stable enabled but output differs!"); + RETURN_ERROR(dstBuffer_wrong, "ZSTD_d_stableOutBuffer enabled but output differs!"); } /* Calls ZSTD_decompressContinue() with the right parameters for ZSTD_decompressStream() @@ -1560,7 +1605,7 @@ static size_t ZSTD_decompressContinueStream( ZSTD_DStream* zds, char** op, char* oend, void const* src, size_t srcSize) { int const isSkipFrame = ZSTD_isSkipFrame(zds); - if (zds->outBufferMode == ZSTD_obm_buffered) { + if (zds->outBufferMode == ZSTD_bm_buffered) { size_t const dstSize = isSkipFrame ? 0 : zds->outBuffSize - zds->outStart; size_t const decodedSize = ZSTD_decompressContinue(zds, zds->outBuff + zds->outStart, dstSize, src, srcSize); @@ -1573,14 +1618,14 @@ static size_t ZSTD_decompressContinueStream( } } else { /* Write directly into the output buffer */ - size_t const dstSize = isSkipFrame ? 0 : oend - *op; + size_t const dstSize = isSkipFrame ? 0 : (size_t)(oend - *op); size_t const decodedSize = ZSTD_decompressContinue(zds, *op, dstSize, src, srcSize); FORWARD_IF_ERROR(decodedSize, ""); *op += decodedSize; /* Flushing is not needed. */ zds->streamStage = zdss_read; assert(*op <= oend); - assert(zds->outBufferMode == ZSTD_obm_stable); + assert(zds->outBufferMode == ZSTD_bm_stable); } return 0; } @@ -1663,14 +1708,14 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB assert(iend >= ip); if (toLoad > remainingInput) { /* not enough input to load full header */ if (remainingInput > 0) { - memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput); + ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, remainingInput); zds->lhSize += remainingInput; } input->pos = input->size; return (MAX((size_t)ZSTD_FRAMEHEADERSIZE_MIN(zds->format), hSize) - zds->lhSize) + ZSTD_blockHeaderSize; /* remaining header bytes + next block header */ } assert(ip != NULL); - memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad; + ZSTD_memcpy(zds->headerBuffer + zds->lhSize, ip, toLoad); zds->lhSize = hSize; ip += toLoad; break; } } @@ -1678,10 +1723,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB if (zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN && zds->fParams.frameType != ZSTD_skippableFrame && (U64)(size_t)(oend-op) >= zds->fParams.frameContentSize) { - size_t const cSize = ZSTD_findFrameCompressedSize(istart, iend-istart); + size_t const cSize = ZSTD_findFrameCompressedSize(istart, (size_t)(iend-istart)); if (cSize <= (size_t)(iend-istart)) { /* shortcut : using single-pass mode */ - size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, oend-op, istart, cSize, ZSTD_getDDict(zds)); + size_t const decompressedSize = ZSTD_decompress_usingDDict(zds, op, (size_t)(oend-op), istart, cSize, ZSTD_getDDict(zds)); if (ZSTD_isError(decompressedSize)) return decompressedSize; DEBUGLOG(4, "shortcut to single-pass ZSTD_decompress_usingDDict()") ip = istart + cSize; @@ -1693,7 +1738,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB } } /* Check output buffer is large enough for ZSTD_odm_stable. */ - if (zds->outBufferMode == ZSTD_obm_stable + if (zds->outBufferMode == ZSTD_bm_stable && zds->fParams.frameType != ZSTD_skippableFrame && zds->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN && (U64)(size_t)(oend-op) < zds->fParams.frameContentSize) { @@ -1723,7 +1768,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB /* Adapt buffer sizes to frame header instructions */ { size_t const neededInBuffSize = MAX(zds->fParams.blockSizeMax, 4 /* frame checksum */); - size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_obm_buffered + size_t const neededOutBuffSize = zds->outBufferMode == ZSTD_bm_buffered ? ZSTD_decodingBufferSize_min(zds->fParams.windowSize, zds->fParams.frameContentSize) : 0; @@ -1731,7 +1776,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB { int const tooSmall = (zds->inBuffSize < neededInBuffSize) || (zds->outBuffSize < neededOutBuffSize); int const tooLarge = ZSTD_DCtx_isOversizedTooLong(zds); - + if (tooSmall || tooLarge) { size_t const bufferSize = neededInBuffSize + neededOutBuffSize; DEBUGLOG(4, "inBuff : from %u to %u", @@ -1745,10 +1790,10 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB bufferSize > zds->staticSize - sizeof(ZSTD_DCtx), memory_allocation, ""); } else { - ZSTD_free(zds->inBuff, zds->customMem); + ZSTD_customFree(zds->inBuff, zds->customMem); zds->inBuffSize = 0; zds->outBuffSize = 0; - zds->inBuff = (char*)ZSTD_malloc(bufferSize, zds->customMem); + zds->inBuff = (char*)ZSTD_customMalloc(bufferSize, zds->customMem); RETURN_ERROR_IF(zds->inBuff == NULL, memory_allocation, ""); } zds->inBuffSize = neededInBuffSize; @@ -1760,7 +1805,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB case zdss_read: DEBUGLOG(5, "stage zdss_read"); - { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, iend - ip); + { size_t const neededInSize = ZSTD_nextSrcSizeToDecompressWithInputSize(zds, (size_t)(iend - ip)); DEBUGLOG(5, "neededInSize = %u", (U32)neededInSize); if (neededInSize==0) { /* end of frame */ zds->streamStage = zdss_init; @@ -1790,7 +1835,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB RETURN_ERROR_IF(toLoad > zds->inBuffSize - zds->inPos, corruption_detected, "should never happen"); - loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, iend-ip); + loadedSize = ZSTD_limitCopy(zds->inBuff + zds->inPos, toLoad, ip, (size_t)(iend-ip)); } ip += loadedSize; zds->inPos += loadedSize; @@ -1804,7 +1849,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB } case zdss_flush: { size_t const toFlushSize = zds->outEnd - zds->outStart; - size_t const flushedSize = ZSTD_limitCopy(op, oend-op, zds->outBuff + zds->outStart, toFlushSize); + size_t const flushedSize = ZSTD_limitCopy(op, (size_t)(oend-op), zds->outBuff + zds->outStart, toFlushSize); op += flushedSize; zds->outStart += flushedSize; if (flushedSize == toFlushSize) { /* flush completed */ diff --git a/thirdparty/zstd/decompress/zstd_decompress_block.c b/thirdparty/zstd/decompress/zstd_decompress_block.c index ad3b3d8dbd..19cbdc5c16 100644 --- a/thirdparty/zstd/decompress/zstd_decompress_block.c +++ b/thirdparty/zstd/decompress/zstd_decompress_block.c @@ -14,7 +14,7 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include <string.h> /* memcpy, memmove, memset */ +#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */ #include "../common/compiler.h" /* prefetch */ #include "../common/cpu.h" /* bmi2 */ #include "../common/mem.h" /* low level memory routines */ @@ -44,7 +44,7 @@ /*_******************************************************* * Memory operations **********************************************************/ -static void ZSTD_copy4(void* dst, const void* src) { memcpy(dst, src, 4); } +static void ZSTD_copy4(void* dst, const void* src) { ZSTD_memcpy(dst, src, 4); } /*-************************************************************* @@ -166,7 +166,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, dctx->litSize = litSize; dctx->litEntropy = 1; if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable; - memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); + ZSTD_memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); return litCSize + lhSize; } @@ -191,10 +191,10 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */ RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected, ""); - memcpy(dctx->litBuffer, istart+lhSize, litSize); + ZSTD_memcpy(dctx->litBuffer, istart+lhSize, litSize); dctx->litPtr = dctx->litBuffer; dctx->litSize = litSize; - memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); + ZSTD_memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH); return lhSize+litSize; } /* direct reference into compressed stream */ @@ -223,7 +223,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, break; } RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, ""); - memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH); + ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH); dctx->litPtr = dctx->litBuffer; dctx->litSize = litSize; return lhSize+1; @@ -236,7 +236,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx, /* Default FSE distribution tables. * These are pre-calculated FSE decoding tables using default distributions as defined in specification : - * https://github.com/facebook/zstd/blob/master/doc/zstd_compression_format.md#default-distributions + * https://github.com/facebook/zstd/blob/release/doc/zstd_compression_format.md#default-distributions * They were generated programmatically with following method : * - start from default distributions, present in /lib/common/zstd_internal.h * - generate tables normally, using ZSTD_buildFSETable() @@ -364,23 +364,26 @@ static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U32 nbAddB * generate FSE decoding table for one symbol (ll, ml or off) * cannot fail if input is valid => * all inputs are presumed validated at this stage */ -void -ZSTD_buildFSETable(ZSTD_seqSymbol* dt, +FORCE_INLINE_TEMPLATE +void ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt, const short* normalizedCounter, unsigned maxSymbolValue, const U32* baseValue, const U32* nbAdditionalBits, - unsigned tableLog) + unsigned tableLog, void* wksp, size_t wkspSize) { ZSTD_seqSymbol* const tableDecode = dt+1; - U16 symbolNext[MaxSeq+1]; - U32 const maxSV1 = maxSymbolValue + 1; U32 const tableSize = 1 << tableLog; - U32 highThreshold = tableSize-1; + + U16* symbolNext = (U16*)wksp; + BYTE* spread = (BYTE*)(symbolNext + MaxSeq + 1); + U32 highThreshold = tableSize - 1; + /* Sanity Checks */ assert(maxSymbolValue <= MaxSeq); assert(tableLog <= MaxFSELog); - + assert(wkspSize >= ZSTD_BUILD_FSE_TABLE_WKSP_SIZE); + (void)wkspSize; /* Init, lay down lowprob symbols */ { ZSTD_seqSymbol_header DTableH; DTableH.tableLog = tableLog; @@ -396,16 +399,69 @@ ZSTD_buildFSETable(ZSTD_seqSymbol* dt, assert(normalizedCounter[s]>=0); symbolNext[s] = (U16)normalizedCounter[s]; } } } - memcpy(dt, &DTableH, sizeof(DTableH)); + ZSTD_memcpy(dt, &DTableH, sizeof(DTableH)); } /* Spread symbols */ - { U32 const tableMask = tableSize-1; + assert(tableSize <= 512); + /* Specialized symbol spreading for the case when there are + * no low probability (-1 count) symbols. When compressing + * small blocks we avoid low probability symbols to hit this + * case, since header decoding speed matters more. + */ + if (highThreshold == tableSize - 1) { + size_t const tableMask = tableSize-1; + size_t const step = FSE_TABLESTEP(tableSize); + /* First lay down the symbols in order. + * We use a uint64_t to lay down 8 bytes at a time. This reduces branch + * misses since small blocks generally have small table logs, so nearly + * all symbols have counts <= 8. We ensure we have 8 bytes at the end of + * our buffer to handle the over-write. + */ + { + U64 const add = 0x0101010101010101ull; + size_t pos = 0; + U64 sv = 0; + U32 s; + for (s=0; s<maxSV1; ++s, sv += add) { + int i; + int const n = normalizedCounter[s]; + MEM_write64(spread + pos, sv); + for (i = 8; i < n; i += 8) { + MEM_write64(spread + pos + i, sv); + } + pos += n; + } + } + /* Now we spread those positions across the table. + * The benefit of doing it in two stages is that we avoid the the + * variable size inner loop, which caused lots of branch misses. + * Now we can run through all the positions without any branch misses. + * We unroll the loop twice, since that is what emperically worked best. + */ + { + size_t position = 0; + size_t s; + size_t const unroll = 2; + assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */ + for (s = 0; s < (size_t)tableSize; s += unroll) { + size_t u; + for (u = 0; u < unroll; ++u) { + size_t const uPosition = (position + (u * step)) & tableMask; + tableDecode[uPosition].baseValue = spread[s + u]; + } + position = (position + (unroll * step)) & tableMask; + } + assert(position == 0); + } + } else { + U32 const tableMask = tableSize-1; U32 const step = FSE_TABLESTEP(tableSize); U32 s, position = 0; for (s=0; s<maxSV1; s++) { int i; - for (i=0; i<normalizedCounter[s]; i++) { + int const n = normalizedCounter[s]; + for (i=0; i<n; i++) { tableDecode[position].baseValue = s; position = (position + step) & tableMask; while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */ @@ -414,7 +470,8 @@ ZSTD_buildFSETable(ZSTD_seqSymbol* dt, } /* Build Decoding table */ - { U32 u; + { + U32 u; for (u=0; u<tableSize; u++) { U32 const symbol = tableDecode[u].baseValue; U32 const nextState = symbolNext[symbol]++; @@ -423,7 +480,46 @@ ZSTD_buildFSETable(ZSTD_seqSymbol* dt, assert(nbAdditionalBits[symbol] < 255); tableDecode[u].nbAdditionalBits = (BYTE)nbAdditionalBits[symbol]; tableDecode[u].baseValue = baseValue[symbol]; - } } + } + } +} + +/* Avoids the FORCE_INLINE of the _body() function. */ +static void ZSTD_buildFSETable_body_default(ZSTD_seqSymbol* dt, + const short* normalizedCounter, unsigned maxSymbolValue, + const U32* baseValue, const U32* nbAdditionalBits, + unsigned tableLog, void* wksp, size_t wkspSize) +{ + ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue, + baseValue, nbAdditionalBits, tableLog, wksp, wkspSize); +} + +#if DYNAMIC_BMI2 +TARGET_ATTRIBUTE("bmi2") static void ZSTD_buildFSETable_body_bmi2(ZSTD_seqSymbol* dt, + const short* normalizedCounter, unsigned maxSymbolValue, + const U32* baseValue, const U32* nbAdditionalBits, + unsigned tableLog, void* wksp, size_t wkspSize) +{ + ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue, + baseValue, nbAdditionalBits, tableLog, wksp, wkspSize); +} +#endif + +void ZSTD_buildFSETable(ZSTD_seqSymbol* dt, + const short* normalizedCounter, unsigned maxSymbolValue, + const U32* baseValue, const U32* nbAdditionalBits, + unsigned tableLog, void* wksp, size_t wkspSize, int bmi2) +{ +#if DYNAMIC_BMI2 + if (bmi2) { + ZSTD_buildFSETable_body_bmi2(dt, normalizedCounter, maxSymbolValue, + baseValue, nbAdditionalBits, tableLog, wksp, wkspSize); + return; + } +#endif + (void)bmi2; + ZSTD_buildFSETable_body_default(dt, normalizedCounter, maxSymbolValue, + baseValue, nbAdditionalBits, tableLog, wksp, wkspSize); } @@ -435,7 +531,8 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb const void* src, size_t srcSize, const U32* baseValue, const U32* nbAdditionalBits, const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable, - int ddictIsCold, int nbSeq) + int ddictIsCold, int nbSeq, U32* wksp, size_t wkspSize, + int bmi2) { switch(type) { @@ -467,7 +564,7 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb size_t const headerSize = FSE_readNCount(norm, &max, &tableLog, src, srcSize); RETURN_ERROR_IF(FSE_isError(headerSize), corruption_detected, ""); RETURN_ERROR_IF(tableLog > maxLog, corruption_detected, ""); - ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog); + ZSTD_buildFSETable(DTableSpace, norm, max, baseValue, nbAdditionalBits, tableLog, wksp, wkspSize, bmi2); *DTablePtr = DTableSpace; return headerSize; } @@ -499,7 +596,8 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, if (nbSeq > 0x7F) { if (nbSeq == 0xFF) { RETURN_ERROR_IF(ip+2 > iend, srcSize_wrong, ""); - nbSeq = MEM_readLE16(ip) + LONGNBSEQ, ip+=2; + nbSeq = MEM_readLE16(ip) + LONGNBSEQ; + ip+=2; } else { RETURN_ERROR_IF(ip >= iend, srcSize_wrong, ""); nbSeq = ((nbSeq-0x80)<<8) + *ip++; @@ -520,7 +618,9 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, ip, iend-ip, LL_base, LL_bits, LL_defaultDTable, dctx->fseEntropy, - dctx->ddictIsCold, nbSeq); + dctx->ddictIsCold, nbSeq, + dctx->workspace, sizeof(dctx->workspace), + dctx->bmi2); RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected, "ZSTD_buildSeqTable failed"); ip += llhSize; } @@ -530,7 +630,9 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, ip, iend-ip, OF_base, OF_bits, OF_defaultDTable, dctx->fseEntropy, - dctx->ddictIsCold, nbSeq); + dctx->ddictIsCold, nbSeq, + dctx->workspace, sizeof(dctx->workspace), + dctx->bmi2); RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected, "ZSTD_buildSeqTable failed"); ip += ofhSize; } @@ -540,7 +642,9 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr, ip, iend-ip, ML_base, ML_bits, ML_defaultDTable, dctx->fseEntropy, - dctx->ddictIsCold, nbSeq); + dctx->ddictIsCold, nbSeq, + dctx->workspace, sizeof(dctx->workspace), + dctx->bmi2); RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected, "ZSTD_buildSeqTable failed"); ip += mlhSize; } @@ -686,12 +790,12 @@ size_t ZSTD_execSequenceEnd(BYTE* op, RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, ""); match = dictEnd - (prefixStart-match); if (match + sequence.matchLength <= dictEnd) { - memmove(oLitEnd, match, sequence.matchLength); + ZSTD_memmove(oLitEnd, match, sequence.matchLength); return sequenceLength; } /* span extDict & currentPrefixSegment */ { size_t const length1 = dictEnd - match; - memmove(oLitEnd, match, length1); + ZSTD_memmove(oLitEnd, match, length1); op = oLitEnd + length1; sequence.matchLength -= length1; match = prefixStart; @@ -752,12 +856,12 @@ size_t ZSTD_execSequence(BYTE* op, RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, ""); match = dictEnd + (match - prefixStart); if (match + sequence.matchLength <= dictEnd) { - memmove(oLitEnd, match, sequence.matchLength); + ZSTD_memmove(oLitEnd, match, sequence.matchLength); return sequenceLength; } /* span extDict & currentPrefixSegment */ { size_t const length1 = dictEnd - match; - memmove(oLitEnd, match, length1); + ZSTD_memmove(oLitEnd, match, length1); op = oLitEnd + length1; sequence.matchLength -= length1; match = prefixStart; @@ -948,7 +1052,7 @@ ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets, c } #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -static int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd) +MEM_STATIC int ZSTD_dictionaryIsActive(ZSTD_DCtx const* dctx, BYTE const* prefixStart, BYTE const* oLitEnd) { size_t const windowSize = dctx->fParams.windowSize; /* No dictionary used. */ @@ -969,6 +1073,7 @@ MEM_STATIC void ZSTD_assertValidSequence( seq_t const seq, BYTE const* prefixStart, BYTE const* virtualStart) { +#if DEBUGLEVEL >= 1 size_t const windowSize = dctx->fParams.windowSize; size_t const sequenceSize = seq.litLength + seq.matchLength; BYTE const* const oLitEnd = op + seq.litLength; @@ -986,6 +1091,9 @@ MEM_STATIC void ZSTD_assertValidSequence( /* Offset must be within our window. */ assert(seq.offset <= windowSize); } +#else + (void)dctx, (void)op, (void)oend, (void)seq, (void)prefixStart, (void)virtualStart; +#endif } #endif @@ -1080,14 +1188,14 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, #endif DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize); BIT_reloadDStream(&(seqState.DStream)); + op += oneSeqSize; /* gcc and clang both don't like early returns in this loop. - * gcc doesn't like early breaks either. - * Instead save an error and report it at the end. - * When there is an error, don't increment op, so we don't - * overwrite. + * Instead break and check for an error at the end of the loop. */ - if (UNLIKELY(ZSTD_isError(oneSeqSize))) error = oneSeqSize; - else op += oneSeqSize; + if (UNLIKELY(ZSTD_isError(oneSeqSize))) { + error = oneSeqSize; + break; + } if (UNLIKELY(!--nbSeq)) break; } @@ -1104,7 +1212,7 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx, { size_t const lastLLSize = litEnd - litPtr; RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); if (op != NULL) { - memcpy(op, litPtr, lastLLSize); + ZSTD_memcpy(op, litPtr, lastLLSize); op += lastLLSize; } } @@ -1209,7 +1317,7 @@ ZSTD_decompressSequencesLong_body( { size_t const lastLLSize = litEnd - litPtr; RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, ""); if (op != NULL) { - memcpy(op, litPtr, lastLLSize); + ZSTD_memcpy(op, litPtr, lastLLSize); op += lastLLSize; } } diff --git a/thirdparty/zstd/decompress/zstd_decompress_block.h b/thirdparty/zstd/decompress/zstd_decompress_block.h index bf39b7350c..b5715c168e 100644 --- a/thirdparty/zstd/decompress/zstd_decompress_block.h +++ b/thirdparty/zstd/decompress/zstd_decompress_block.h @@ -15,7 +15,7 @@ /*-******************************************************* * Dependencies *********************************************************/ -#include <stddef.h> /* size_t */ +#include "../common/zstd_deps.h" /* size_t */ #include "../zstd.h" /* DCtx, and some public functions */ #include "../common/zstd_internal.h" /* blockProperties_t, and some public functions */ #include "zstd_decompress_internal.h" /* ZSTD_seqSymbol */ @@ -48,12 +48,15 @@ size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx, * this function must be called with valid parameters only * (dt is large enough, normalizedCounter distribution total is a power of 2, max is within range, etc.) * in which case it cannot fail. + * The workspace must be 4-byte aligned and at least ZSTD_BUILD_FSE_TABLE_WKSP_SIZE bytes, which is + * defined in zstd_decompress_internal.h. * Internal use only. */ void ZSTD_buildFSETable(ZSTD_seqSymbol* dt, const short* normalizedCounter, unsigned maxSymbolValue, const U32* baseValue, const U32* nbAdditionalBits, - unsigned tableLog); + unsigned tableLog, void* wksp, size_t wkspSize, + int bmi2); #endif /* ZSTD_DEC_BLOCK_H */ diff --git a/thirdparty/zstd/decompress/zstd_decompress_internal.h b/thirdparty/zstd/decompress/zstd_decompress_internal.h index 9ad96c5548..f80b471e99 100644 --- a/thirdparty/zstd/decompress/zstd_decompress_internal.h +++ b/thirdparty/zstd/decompress/zstd_decompress_internal.h @@ -27,26 +27,26 @@ /*-******************************************************* * Constants *********************************************************/ -static const U32 LL_base[MaxLL+1] = { +static UNUSED_ATTR const U32 LL_base[MaxLL+1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 28, 32, 40, 48, 64, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000, 0x10000 }; -static const U32 OF_base[MaxOff+1] = { +static UNUSED_ATTR const U32 OF_base[MaxOff+1] = { 0, 1, 1, 5, 0xD, 0x1D, 0x3D, 0x7D, 0xFD, 0x1FD, 0x3FD, 0x7FD, 0xFFD, 0x1FFD, 0x3FFD, 0x7FFD, 0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD, 0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD }; -static const U32 OF_bits[MaxOff+1] = { +static UNUSED_ATTR const U32 OF_bits[MaxOff+1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }; -static const U32 ML_base[MaxML+1] = { +static UNUSED_ATTR const U32 ML_base[MaxML+1] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, @@ -73,12 +73,16 @@ static const U32 ML_base[MaxML+1] = { #define SEQSYMBOL_TABLE_SIZE(log) (1 + (1 << (log))) +#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE (sizeof(S16) * (MaxSeq + 1) + (1u << MaxFSELog) + sizeof(U64)) +#define ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32 ((ZSTD_BUILD_FSE_TABLE_WKSP_SIZE + sizeof(U32) - 1) / sizeof(U32)) + typedef struct { ZSTD_seqSymbol LLTable[SEQSYMBOL_TABLE_SIZE(LLFSELog)]; /* Note : Space reserved for FSE Tables */ ZSTD_seqSymbol OFTable[SEQSYMBOL_TABLE_SIZE(OffFSELog)]; /* is also used as temporary workspace while building hufTable during DDict creation */ ZSTD_seqSymbol MLTable[SEQSYMBOL_TABLE_SIZE(MLFSELog)]; /* and therefore must be at least HUF_DECOMPRESS_WORKSPACE_SIZE large */ HUF_DTable hufTable[HUF_DTABLE_SIZE(HufLog)]; /* can accommodate HUF_decompress4X */ U32 rep[ZSTD_REP_NUM]; + U32 workspace[ZSTD_BUILD_FSE_TABLE_WKSP_SIZE_U32]; } ZSTD_entropyDTables_t; typedef enum { ZSTDds_getFrameHeaderSize, ZSTDds_decodeFrameHeader, @@ -95,11 +99,6 @@ typedef enum { ZSTD_use_once = 1 /* Use the dictionary once and set to ZSTD_dont_use */ } ZSTD_dictUses_e; -typedef enum { - ZSTD_obm_buffered = 0, /* Buffer the output */ - ZSTD_obm_stable = 1 /* ZSTD_outBuffer is stable */ -} ZSTD_outBufferMode_e; - struct ZSTD_DCtx_s { const ZSTD_seqSymbol* LLTptr; @@ -122,6 +121,8 @@ struct ZSTD_DCtx_s XXH64_state_t xxhState; size_t headerSize; ZSTD_format_e format; + ZSTD_forceIgnoreChecksum_e forceIgnoreChecksum; /* User specified: if == 1, will ignore checksums in compressed frame. Default == 0 */ + U32 validateChecksum; /* if == 1, will validate checksum. Is == 1 if (fParams.checksumFlag == 1) and (forceIgnoreChecksum == 0). */ const BYTE* litPtr; ZSTD_customMem customMem; size_t litSize; @@ -152,7 +153,7 @@ struct ZSTD_DCtx_s U32 legacyVersion; U32 hostageByte; int noForwardProgress; - ZSTD_outBufferMode_e outBufferMode; + ZSTD_bufferMode_e outBufferMode; ZSTD_outBuffer expectedOutBuffer; /* workspace */ diff --git a/thirdparty/zstd/zstd.h b/thirdparty/zstd/zstd.h index 8c6fc6ae90..b0ecdf5538 100644 --- a/thirdparty/zstd/zstd.h +++ b/thirdparty/zstd/zstd.h @@ -72,16 +72,21 @@ extern "C" { /*------ Version ------*/ #define ZSTD_VERSION_MAJOR 1 #define ZSTD_VERSION_MINOR 4 -#define ZSTD_VERSION_RELEASE 5 - +#define ZSTD_VERSION_RELEASE 8 #define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE) -ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< to check runtime library version */ + +/*! ZSTD_versionNumber() : + * Return runtime library version, the value is (MAJOR*100*100 + MINOR*100 + RELEASE). */ +ZSTDLIB_API unsigned ZSTD_versionNumber(void); #define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE #define ZSTD_QUOTE(str) #str #define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str) #define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION) -ZSTDLIB_API const char* ZSTD_versionString(void); /* requires v1.3.0+ */ + +/*! ZSTD_versionString() : + * Return runtime library version, like "1.4.5". Requires v1.3.0+. */ +ZSTDLIB_API const char* ZSTD_versionString(void); /* ************************************* * Default constant @@ -334,7 +339,9 @@ typedef enum { * for large inputs, by finding large matches at long distance. * It increases memory usage and window size. * Note: enabling this parameter increases default ZSTD_c_windowLog to 128 MB - * except when expressly set to a different value. */ + * except when expressly set to a different value. + * Note: will be enabled by default if ZSTD_c_windowLog >= 128 MB and + * compression strategy >= ZSTD_btopt (== compression level 16+) */ ZSTD_c_ldmHashLog=161, /* Size of the table for long distance matching, as a power of 2. * Larger values increase memory usage and compression ratio, * but decrease compression speed. @@ -365,16 +372,20 @@ typedef enum { ZSTD_c_dictIDFlag=202, /* When applicable, dictionary's ID is written into frame header (default:1) */ /* multi-threading parameters */ - /* These parameters are only useful if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD). - * They return an error otherwise. */ + /* These parameters are only active if multi-threading is enabled (compiled with build macro ZSTD_MULTITHREAD). + * Otherwise, trying to set any other value than default (0) will be a no-op and return an error. + * In a situation where it's unknown if the linked library supports multi-threading or not, + * setting ZSTD_c_nbWorkers to any value >= 1 and consulting the return value provides a quick way to check this property. + */ ZSTD_c_nbWorkers=400, /* Select how many threads will be spawned to compress in parallel. - * When nbWorkers >= 1, triggers asynchronous mode when used with ZSTD_compressStream*() : + * When nbWorkers >= 1, triggers asynchronous mode when invoking ZSTD_compressStream*() : * ZSTD_compressStream*() consumes input and flush output if possible, but immediately gives back control to caller, - * while compression work is performed in parallel, within worker threads. + * while compression is performed in parallel, within worker thread(s). * (note : a strong exception to this rule is when first invocation of ZSTD_compressStream2() sets ZSTD_e_end : * in which case, ZSTD_compressStream2() delegates to ZSTD_compress2(), which is always a blocking call). * More workers improve speed, but also increase memory usage. - * Default value is `0`, aka "single-threaded mode" : no worker is spawned, compression is performed inside Caller's thread, all invocations are blocking */ + * Default value is `0`, aka "single-threaded mode" : no worker is spawned, + * compression is performed inside Caller's thread, and all invocations are blocking */ ZSTD_c_jobSize=401, /* Size of a compression job. This value is enforced only when nbWorkers >= 1. * Each compression job is completed in parallel, so this value can indirectly impact the nb of active threads. * 0 means default, which is dynamically determined based on compression parameters. @@ -403,6 +414,11 @@ typedef enum { * ZSTD_c_literalCompressionMode * ZSTD_c_targetCBlockSize * ZSTD_c_srcSizeHint + * ZSTD_c_enableDedicatedDictSearch + * ZSTD_c_stableInBuffer + * ZSTD_c_stableOutBuffer + * ZSTD_c_blockDelimiters + * ZSTD_c_validateSequences * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * note : never ever use experimentalParam? names directly; * also, the enums values themselves are unstable and can still change. @@ -413,7 +429,12 @@ typedef enum { ZSTD_c_experimentalParam4=1001, ZSTD_c_experimentalParam5=1002, ZSTD_c_experimentalParam6=1003, - ZSTD_c_experimentalParam7=1004 + ZSTD_c_experimentalParam7=1004, + ZSTD_c_experimentalParam8=1005, + ZSTD_c_experimentalParam9=1006, + ZSTD_c_experimentalParam10=1007, + ZSTD_c_experimentalParam11=1008, + ZSTD_c_experimentalParam12=1009 } ZSTD_cParameter; typedef struct { @@ -524,11 +545,13 @@ typedef enum { * At the time of this writing, they include : * ZSTD_d_format * ZSTD_d_stableOutBuffer + * ZSTD_d_forceIgnoreChecksum * Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them. * note : never ever use experimentalParam? names directly */ ZSTD_d_experimentalParam1=1000, - ZSTD_d_experimentalParam2=1001 + ZSTD_d_experimentalParam2=1001, + ZSTD_d_experimentalParam3=1002 } ZSTD_dParameter; @@ -664,8 +687,9 @@ typedef enum { * - Compression parameters cannot be changed once compression is started (save a list of exceptions in multi-threading mode) * - output->pos must be <= dstCapacity, input->pos must be <= srcSize * - output->pos and input->pos will be updated. They are guaranteed to remain below their respective limit. + * - endOp must be a valid directive * - When nbWorkers==0 (default), function is blocking : it completes its job before returning to caller. - * - When nbWorkers>=1, function is non-blocking : it just acquires a copy of input, and distributes jobs to internal worker threads, flush whatever is available, + * - When nbWorkers>=1, function is non-blocking : it copies a portion of input, distributes jobs to internal worker threads, flush to output whatever is available, * and then immediately returns, just indicating that there is some data remaining to be flushed. * The function nonetheless guarantees forward progress : it will return only after it reads or write at least 1+ byte. * - Exception : if the first call requests a ZSTD_e_end directive and provides enough dstCapacity, the function delegates to ZSTD_compress2() which is always blocking. @@ -1100,21 +1124,40 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict); typedef struct ZSTD_CCtx_params_s ZSTD_CCtx_params; typedef struct { - unsigned int matchPos; /* Match pos in dst */ - /* If seqDef.offset > 3, then this is seqDef.offset - 3 - * If seqDef.offset < 3, then this is the corresponding repeat offset - * But if seqDef.offset < 3 and litLength == 0, this is the - * repeat offset before the corresponding repeat offset - * And if seqDef.offset == 3 and litLength == 0, this is the - * most recent repeat offset - 1 - */ - unsigned int offset; - unsigned int litLength; /* Literal length */ - unsigned int matchLength; /* Match length */ - /* 0 when seq not rep and seqDef.offset otherwise - * when litLength == 0 this will be <= 4, otherwise <= 3 like normal - */ - unsigned int rep; + unsigned int offset; /* The offset of the match. (NOT the same as the offset code) + * If offset == 0 and matchLength == 0, this sequence represents the last + * literals in the block of litLength size. + */ + + unsigned int litLength; /* Literal length of the sequence. */ + unsigned int matchLength; /* Match length of the sequence. */ + + /* Note: Users of this API may provide a sequence with matchLength == litLength == offset == 0. + * In this case, we will treat the sequence as a marker for a block boundary. + */ + + unsigned int rep; /* Represents which repeat offset is represented by the field 'offset'. + * Ranges from [0, 3]. + * + * Repeat offsets are essentially previous offsets from previous sequences sorted in + * recency order. For more detail, see doc/zstd_compression_format.md + * + * If rep == 0, then 'offset' does not contain a repeat offset. + * If rep > 0: + * If litLength != 0: + * rep == 1 --> offset == repeat_offset_1 + * rep == 2 --> offset == repeat_offset_2 + * rep == 3 --> offset == repeat_offset_3 + * If litLength == 0: + * rep == 1 --> offset == repeat_offset_2 + * rep == 2 --> offset == repeat_offset_3 + * rep == 3 --> offset == repeat_offset_1 - 1 + * + * Note: This field is optional. ZSTD_generateSequences() will calculate the value of + * 'rep', but repeat offsets do not necessarily need to be calculated from an external + * sequence provider's perspective. For example, ZSTD_compressSequences() does not + * use this 'rep' field at all (as of now). + */ } ZSTD_Sequence; typedef struct { @@ -1157,6 +1200,12 @@ typedef enum { } ZSTD_format_e; typedef enum { + /* Note: this enum controls ZSTD_d_forceIgnoreChecksum */ + ZSTD_d_validateChecksum = 0, + ZSTD_d_ignoreChecksum = 1 +} ZSTD_forceIgnoreChecksum_e; + +typedef enum { /* Note: this enum and the behavior it controls are effectively internal * implementation details of the compressor. They are expected to continue * to evolve and should be considered only in the context of extremely @@ -1253,14 +1302,74 @@ ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcS * or an error code (if srcSize is too small) */ ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize); -/*! ZSTD_getSequences() : - * Extract sequences from the sequence store +typedef enum { + ZSTD_sf_noBlockDelimiters = 0, /* Representation of ZSTD_Sequence has no block delimiters, sequences only */ + ZSTD_sf_explicitBlockDelimiters = 1 /* Representation of ZSTD_Sequence contains explicit block delimiters */ +} ZSTD_sequenceFormat_e; + +/*! ZSTD_generateSequences() : + * Generate sequences using ZSTD_compress2, given a source buffer. + * + * Each block will end with a dummy sequence + * with offset == 0, matchLength == 0, and litLength == length of last literals. + * litLength may be == 0, and if so, then the sequence of (of: 0 ml: 0 ll: 0) + * simply acts as a block delimiter. + * * zc can be used to insert custom compression params. * This function invokes ZSTD_compress2 - * @return : number of sequences extracted + * + * The output of this function can be fed into ZSTD_compressSequences() with CCtx + * setting of ZSTD_c_blockDelimiters as ZSTD_sf_explicitBlockDelimiters + * @return : number of sequences generated + */ + +ZSTDLIB_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, + size_t outSeqsSize, const void* src, size_t srcSize); + +/*! ZSTD_mergeBlockDelimiters() : + * Given an array of ZSTD_Sequence, remove all sequences that represent block delimiters/last literals + * by merging them into into the literals of the next sequence. + * + * As such, the final generated result has no explicit representation of block boundaries, + * and the final last literals segment is not represented in the sequences. + * + * The output of this function can be fed into ZSTD_compressSequences() with CCtx + * setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters + * @return : number of sequences left after merging + */ +ZSTDLIB_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize); + +/*! ZSTD_compressSequences() : + * Compress an array of ZSTD_Sequence, generated from the original source buffer, into dst. + * If a dictionary is included, then the cctx should reference the dict. (see: ZSTD_CCtx_refCDict(), ZSTD_CCtx_loadDictionary(), etc.) + * The entire source is compressed into a single frame. + * + * The compression behavior changes based on cctx params. In particular: + * If ZSTD_c_blockDelimiters == ZSTD_sf_noBlockDelimiters, the array of ZSTD_Sequence is expected to contain + * no block delimiters (defined in ZSTD_Sequence). Block boundaries are roughly determined based on + * the block size derived from the cctx, and sequences may be split. This is the default setting. + * + * If ZSTD_c_blockDelimiters == ZSTD_sf_explicitBlockDelimiters, the array of ZSTD_Sequence is expected to contain + * block delimiters (defined in ZSTD_Sequence). Behavior is undefined if no block delimiters are provided. + * + * If ZSTD_c_validateSequences == 0, this function will blindly accept the sequences provided. Invalid sequences cause undefined + * behavior. If ZSTD_c_validateSequences == 1, then if sequence is invalid (see doc/zstd_compression_format.md for + * specifics regarding offset/matchlength requirements) then the function will bail out and return an error. + * + * In addition to the two adjustable experimental params, there are other important cctx params. + * - ZSTD_c_minMatch MUST be set as less than or equal to the smallest match generated by the match finder. It has a minimum value of ZSTD_MINMATCH_MIN. + * - ZSTD_c_compressionLevel accordingly adjusts the strength of the entropy coder, as it would in typical compression. + * - ZSTD_c_windowLog affects offset validation: this function will return an error at higher debug levels if a provided offset + * is larger than what the spec allows for a given window log and dictionary (if present). See: doc/zstd_compression_format.md + * + * Note: Repcodes are, as of now, always re-calculated within this function, so ZSTD_Sequence::rep is unused. + * Note 2: Once we integrate ability to ingest repcodes, the explicit block delims mode must respect those repcodes exactly, + * and cannot emit an RLE block that disagrees with the repcode history + * @return : final compressed size or a ZSTD error. */ -ZSTDLIB_API size_t ZSTD_getSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs, - size_t outSeqsSize, const void* src, size_t srcSize); +ZSTDLIB_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstSize, + const ZSTD_Sequence* inSeqs, size_t inSeqsSize, + const void* src, size_t srcSize); /*************************************** @@ -1372,7 +1481,11 @@ ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict( typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size); typedef void (*ZSTD_freeFunction) (void* opaque, void* address); typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem; -static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ +static +#ifdef __GNUC__ +__attribute__((__unused__)) +#endif +ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */ ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem); ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem); @@ -1385,13 +1498,36 @@ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictS ZSTD_compressionParameters cParams, ZSTD_customMem customMem); +/* ! Thread pool : + * These prototypes make it possible to share a thread pool among multiple compression contexts. + * This can limit resources for applications with multiple threads where each one uses + * a threaded compression mode (via ZSTD_c_nbWorkers parameter). + * ZSTD_createThreadPool creates a new thread pool with a given number of threads. + * Note that the lifetime of such pool must exist while being used. + * ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value + * to use an internal thread pool). + * ZSTD_freeThreadPool frees a thread pool. + */ +typedef struct POOL_ctx_s ZSTD_threadPool; +ZSTDLIB_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads); +ZSTDLIB_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); +ZSTDLIB_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool); + +/* + * This API is temporary and is expected to change or disappear in the future! + */ +ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2( + const void* dict, size_t dictSize, + ZSTD_dictLoadMethod_e dictLoadMethod, + ZSTD_dictContentType_e dictContentType, + const ZSTD_CCtx_params* cctxParams, + ZSTD_customMem customMem); + ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType, ZSTD_customMem customMem); - - /*************************************** * Advanced compression functions ***************************************/ @@ -1404,6 +1540,12 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictS * note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */ ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel); +/*! ZSTD_getDictID_fromCDict() : + * Provides the dictID of the dictionary loaded into `cdict`. + * If @return == 0, the dictionary is not conformant to Zstandard specification, or empty. + * Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */ +ZSTDLIB_API unsigned ZSTD_getDictID_fromCDict(const ZSTD_CDict* cdict); + /*! ZSTD_getCParams() : * @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize. * `estimatedSrcSize` value is optional, select 0 if not known */ @@ -1518,6 +1660,143 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre * but compression ratio may regress significantly if guess considerably underestimates */ #define ZSTD_c_srcSizeHint ZSTD_c_experimentalParam7 +/* Controls whether the new and experimental "dedicated dictionary search + * structure" can be used. This feature is still rough around the edges, be + * prepared for surprising behavior! + * + * How to use it: + * + * When using a CDict, whether to use this feature or not is controlled at + * CDict creation, and it must be set in a CCtxParams set passed into that + * construction (via ZSTD_createCDict_advanced2()). A compression will then + * use the feature or not based on how the CDict was constructed; the value of + * this param, set in the CCtx, will have no effect. + * + * However, when a dictionary buffer is passed into a CCtx, such as via + * ZSTD_CCtx_loadDictionary(), this param can be set on the CCtx to control + * whether the CDict that is created internally can use the feature or not. + * + * What it does: + * + * Normally, the internal data structures of the CDict are analogous to what + * would be stored in a CCtx after compressing the contents of a dictionary. + * To an approximation, a compression using a dictionary can then use those + * data structures to simply continue what is effectively a streaming + * compression where the simulated compression of the dictionary left off. + * Which is to say, the search structures in the CDict are normally the same + * format as in the CCtx. + * + * It is possible to do better, since the CDict is not like a CCtx: the search + * structures are written once during CDict creation, and then are only read + * after that, while the search structures in the CCtx are both read and + * written as the compression goes along. This means we can choose a search + * structure for the dictionary that is read-optimized. + * + * This feature enables the use of that different structure. + * + * Note that some of the members of the ZSTD_compressionParameters struct have + * different semantics and constraints in the dedicated search structure. It is + * highly recommended that you simply set a compression level in the CCtxParams + * you pass into the CDict creation call, and avoid messing with the cParams + * directly. + * + * Effects: + * + * This will only have any effect when the selected ZSTD_strategy + * implementation supports this feature. Currently, that's limited to + * ZSTD_greedy, ZSTD_lazy, and ZSTD_lazy2. + * + * Note that this means that the CDict tables can no longer be copied into the + * CCtx, so the dict attachment mode ZSTD_dictForceCopy will no longer be + * useable. The dictionary can only be attached or reloaded. + * + * In general, you should expect compression to be faster--sometimes very much + * so--and CDict creation to be slightly slower. Eventually, we will probably + * make this mode the default. + */ +#define ZSTD_c_enableDedicatedDictSearch ZSTD_c_experimentalParam8 + +/* ZSTD_c_stableInBuffer + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable. + * + * Tells the compressor that the ZSTD_inBuffer will ALWAYS be the same + * between calls, except for the modifications that zstd makes to pos (the + * caller must not modify pos). This is checked by the compressor, and + * compression will fail if it ever changes. This means the only flush + * mode that makes sense is ZSTD_e_end, so zstd will error if ZSTD_e_end + * is not used. The data in the ZSTD_inBuffer in the range [src, src + pos) + * MUST not be modified during compression or you will get data corruption. + * + * When this flag is enabled zstd won't allocate an input window buffer, + * because the user guarantees it can reference the ZSTD_inBuffer until + * the frame is complete. But, it will still allocate an output buffer + * large enough to fit a block (see ZSTD_c_stableOutBuffer). This will also + * avoid the memcpy() from the input buffer to the input window buffer. + * + * NOTE: ZSTD_compressStream2() will error if ZSTD_e_end is not used. + * That means this flag cannot be used with ZSTD_compressStream(). + * + * NOTE: So long as the ZSTD_inBuffer always points to valid memory, using + * this flag is ALWAYS memory safe, and will never access out-of-bounds + * memory. However, compression WILL fail if you violate the preconditions. + * + * WARNING: The data in the ZSTD_inBuffer in the range [dst, dst + pos) MUST + * not be modified during compression or you will get data corruption. This + * is because zstd needs to reference data in the ZSTD_inBuffer to find + * matches. Normally zstd maintains its own window buffer for this purpose, + * but passing this flag tells zstd to use the user provided buffer. + */ +#define ZSTD_c_stableInBuffer ZSTD_c_experimentalParam9 + +/* ZSTD_c_stableOutBuffer + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable. + * + * Tells he compressor that the ZSTD_outBuffer will not be resized between + * calls. Specifically: (out.size - out.pos) will never grow. This gives the + * compressor the freedom to say: If the compressed data doesn't fit in the + * output buffer then return ZSTD_error_dstSizeTooSmall. This allows us to + * always decompress directly into the output buffer, instead of decompressing + * into an internal buffer and copying to the output buffer. + * + * When this flag is enabled zstd won't allocate an output buffer, because + * it can write directly to the ZSTD_outBuffer. It will still allocate the + * input window buffer (see ZSTD_c_stableInBuffer). + * + * Zstd will check that (out.size - out.pos) never grows and return an error + * if it does. While not strictly necessary, this should prevent surprises. + */ +#define ZSTD_c_stableOutBuffer ZSTD_c_experimentalParam10 + +/* ZSTD_c_blockDelimiters + * Default is 0 == ZSTD_sf_noBlockDelimiters. + * + * For use with sequence compression API: ZSTD_compressSequences(). + * + * Designates whether or not the given array of ZSTD_Sequence contains block delimiters + * and last literals, which are defined as sequences with offset == 0 and matchLength == 0. + * See the definition of ZSTD_Sequence for more specifics. + */ +#define ZSTD_c_blockDelimiters ZSTD_c_experimentalParam11 + +/* ZSTD_c_validateSequences + * Default is 0 == disabled. Set to 1 to enable sequence validation. + * + * For use with sequence compression API: ZSTD_compressSequences(). + * Designates whether or not we validate sequences provided to ZSTD_compressSequences() + * during function execution. + * + * Without validation, providing a sequence that does not conform to the zstd spec will cause + * undefined behavior, and may produce a corrupted block. + * + * With validation enabled, a if sequence is invalid (see doc/zstd_compression_format.md for + * specifics regarding offset/matchlength requirements) then the function will bail out and + * return an error. + * + */ +#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12 + /*! ZSTD_CCtx_getParameter() : * Get the requested compression parameter value, selected by enum ZSTD_cParameter, * and store it into int* value. @@ -1566,8 +1845,10 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, Z /*! ZSTD_CCtxParams_setParameter() : * Similar to ZSTD_CCtx_setParameter. * Set one compression parameter, selected by enum ZSTD_cParameter. - * Parameters must be applied to a ZSTD_CCtx using ZSTD_CCtx_setParametersUsingCCtxParams(). - * @result : 0, or an error code (which can be tested with ZSTD_isError()). + * Parameters must be applied to a ZSTD_CCtx using + * ZSTD_CCtx_setParametersUsingCCtxParams(). + * @result : a code representing success or failure (which can be tested with + * ZSTD_isError()). */ ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value); @@ -1647,6 +1928,13 @@ ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* pre */ ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize); +/*! ZSTD_DCtx_getParameter() : + * Get the requested decompression parameter value, selected by enum ZSTD_dParameter, + * and store it into int* value. + * @return : 0, or an error code (which can be tested with ZSTD_isError()). + */ +ZSTDLIB_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value); + /* ZSTD_d_format * experimental parameter, * allowing selection between ZSTD_format_e input compression formats @@ -1684,6 +1972,17 @@ ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowS */ #define ZSTD_d_stableOutBuffer ZSTD_d_experimentalParam2 +/* ZSTD_d_forceIgnoreChecksum + * Experimental parameter. + * Default is 0 == disabled. Set to 1 to enable + * + * Tells the decompressor to skip checksum validation during decompression, regardless + * of whether checksumming was specified during compression. This offers some + * slight performance benefits, and may be useful for debugging. + * Param has values of type ZSTD_forceIgnoreChecksum_e + */ +#define ZSTD_d_forceIgnoreChecksum ZSTD_d_experimentalParam3 + /*! ZSTD_DCtx_setFormat() : * Instruct the decoder context about what kind of data to decode next. * This instruction is mandatory to decode data without a fully-formed header, @@ -1711,7 +2010,8 @@ ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs ( ********************************************************************/ /*===== Advanced Streaming compression functions =====*/ -/**! ZSTD_initCStream_srcSize() : + +/*! ZSTD_initCStream_srcSize() : * This function is deprecated, and equivalent to: * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); * ZSTD_CCtx_refCDict(zcs, NULL); // clear the dictionary (if any) @@ -1728,7 +2028,7 @@ ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); -/**! ZSTD_initCStream_usingDict() : +/*! ZSTD_initCStream_usingDict() : * This function is deprecated, and is equivalent to: * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); * ZSTD_CCtx_setParameter(zcs, ZSTD_c_compressionLevel, compressionLevel); @@ -1745,7 +2045,7 @@ ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); -/**! ZSTD_initCStream_advanced() : +/*! ZSTD_initCStream_advanced() : * This function is deprecated, and is approximately equivalent to: * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); * // Pseudocode: Set each zstd parameter and leave the rest as-is. @@ -1766,7 +2066,7 @@ ZSTD_initCStream_advanced(ZSTD_CStream* zcs, ZSTD_parameters params, unsigned long long pledgedSrcSize); -/**! ZSTD_initCStream_usingCDict() : +/*! ZSTD_initCStream_usingCDict() : * This function is deprecated, and equivalent to: * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); * ZSTD_CCtx_refCDict(zcs, cdict); @@ -1776,7 +2076,7 @@ ZSTD_initCStream_advanced(ZSTD_CStream* zcs, */ ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); -/**! ZSTD_initCStream_usingCDict_advanced() : +/*! ZSTD_initCStream_usingCDict_advanced() : * This function is DEPRECATED, and is approximately equivalent to: * ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only); * // Pseudocode: Set each zstd frame parameter and leave the rest as-is. @@ -1849,7 +2149,8 @@ ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx); /*===== Advanced Streaming decompression functions =====*/ -/** + +/*! * This function is deprecated, and is equivalent to: * * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); @@ -1860,7 +2161,7 @@ ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx); */ ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize); -/** +/*! * This function is deprecated, and is equivalent to: * * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); @@ -1871,7 +2172,7 @@ ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dic */ ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); -/** +/*! * This function is deprecated, and is equivalent to: * * ZSTD_DCtx_reset(zds, ZSTD_reset_session_only); @@ -1933,7 +2234,7 @@ ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstC ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize); -/*- +/** Buffer-less streaming decompression (synchronous mode) A ZSTD_DCtx object is required to track streaming operations. |