From 073f6e85e4ab191f0cfc9c62e78fdcc14390f005 Mon Sep 17 00:00:00 2001 From: kobalicek Date: Tue, 26 Dec 2023 18:48:24 +0100 Subject: [PATCH] [ABI] Improvements to avoid UB and warnings, clean build with MSAN * Added more clang compilers on CI (CI) * Added memory sanitizer to build matrix (CI) * Use problem matcher in all builds (CI) * Fixed the use of some constructs in tests * Fixed warnings about unused functions in tests * Fixed warnings about unused variables caused by some build options * Fixed tests to be clean with MSAN (zeroing memory filled by JIT code) * Removed -Wclass-memaccess (gcc) from ignored warnings * Removed -Wconstant-logical-operand (clang) from ignored warnings * Removed -Wunnamed-type-template-args (clang) from ignored warnings * Reworked InstData and InstExData to not cause UB (ABI break) Unfortunately the existing InstData and InstExData was not good for static analysis and in general compilers emitted warnings regarding accessing InstNode::_opArray. The reason was that InstExNode added one or two more operands which extended InstData::_opArray, but there was no way to tell the C++ compiler about this layout. It has been changed to InstNode having no operands and InstNodeWithOperands being templatized for the right number of operands. Nodes that need to inherit InstNode would just inherit InstNodeWithOperands. It works the same way as before, just the class hierarchy changed a little. --- .github/workflows/build-config.json | 3 +- .github/workflows/build.yml | 191 +++++++++++++++------------- src/asmjit/arm/a64assembler.cpp | 2 - src/asmjit/arm/a64compiler.h | 21 ++- src/asmjit/arm/a64emithelper.cpp | 4 +- src/asmjit/arm/armformatter.cpp | 3 +- src/asmjit/core/api-config.h | 134 +++++++------------ src/asmjit/core/builder.h | 95 +++++++------- src/asmjit/core/compiler.h | 19 +-- src/asmjit/core/cpuinfo.h | 60 +++++---- src/asmjit/core/emitter.h | 1 + src/asmjit/core/formatter.cpp | 4 +- src/asmjit/core/inst.h | 3 +- src/asmjit/core/jitallocator.cpp | 7 +- src/asmjit/core/operand.h | 26 ++-- src/asmjit/core/rapass.cpp | 19 ++- src/asmjit/core/support.h | 59 +++++---- src/asmjit/core/zonevector.h | 67 +++++++--- src/asmjit/x86/x86assembler.cpp | 3 +- src/asmjit/x86/x86formatter.cpp | 14 +- src/asmjit/x86/x86instapi.cpp | 31 +++-- src/asmjit/x86/x86rapass.cpp | 10 +- test/asmjit_test_compiler_x86.cpp | 41 +++--- test/asmjit_test_emitters.cpp | 15 ++- test/asmjit_test_instinfo.cpp | 8 +- test/asmjit_test_unit.cpp | 3 +- test/asmjitutils.h | 8 +- tools/configure-sanitizers.sh | 4 + 28 files changed, 458 insertions(+), 397 deletions(-) diff --git a/.github/workflows/build-config.json b/.github/workflows/build-config.json index 08022ef..f33a8f3 100644 --- a/.github/workflows/build-config.json +++ b/.github/workflows/build-config.json @@ -1,7 +1,8 @@ { "diagnostics": { "asan": { "definitions": ["ASMJIT_SANITIZE=address"] }, - "ubsan": { "definitions": ["ASMJIT_SANITIZE=undefined"] } + "ubsan": { "definitions": ["ASMJIT_SANITIZE=undefined"] }, + "msan": { "definitions": ["ASMJIT_SANITIZE=memory"] } }, "valgrind_arguments": [ diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0fea3bc..fac52c0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,90 +31,107 @@ jobs: fail-fast: false matrix: include: - - { title: "linux-lib" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , problem_matcher: "cpp" } - - { title: "macos-lib" , os: "macos-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , problem_matcher: "cpp" } - - { title: "windows-lib" , os: "windows-latest", cc: "vs2022" , arch: "x64", build_type: "Debug" , problem_matcher: "cpp" } + - { title: "linux-lib" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", conf: "Debug" } + - { title: "macos-lib" , os: "macos-latest" , cc: "clang" , arch: "x64", conf: "Debug" } + - { title: "windows-lib" , os: "windows-latest", cc: "vs2022" , arch: "x64", conf: "Debug" } - - { title: "diag-asan" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", diagnostics: "address" , defs: "ASMJIT_TEST=1" } - - { title: "diag-ubsan" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", diagnostics: "undefined", defs: "ASMJIT_TEST=1" } - - { title: "diag-valgrind" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", diagnostics: "valgrind" , defs: "ASMJIT_TEST=1" } - - { title: "diag-scan-build" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , diagnostics: "scan-build" } + - { title: "diag-analyze" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Debug" , diagnostics: "analyze-build" } + - { title: "diag-asan" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", diagnostics: "asan", defs: "ASMJIT_TEST=1" } + - { title: "diag-msan" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", diagnostics: "msan", defs: "ASMJIT_TEST=1" } + - { title: "diag-ubsan" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", diagnostics: "ubsan", defs: "ASMJIT_TEST=1" } + - { title: "diag-valgrind" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", diagnostics: "valgrind", defs: "ASMJIT_TEST=1" } - - { title: "no-deprecated" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_DEPRECATED=1" } - - { title: "no-intrinsics" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_INTRINSICS=1" } - - { title: "no-logging" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_LOGGING=1" } - - { title: "no-logging-text" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_LOGGING=1,ASMJIT_NO_TEXT=1" } - - { title: "no-builder" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_BUILDER=1" } - - { title: "no-compiler" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_COMPILER=1" } - - { title: "no-jit" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_JIT=1" } - - { title: "no-introspection", os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_INTROSPECTION=1" } - - { title: "no-validation" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_VALIDATION=1" } - - { title: "no-x86" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_X86=1" } - - { title: "no-aarch64" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_AARCH64=1" } + - { title: "no-deprecated" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_DEPRECATED=1" } + - { title: "no-intrinsics" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_INTRINSICS=1" } + - { title: "no-logging" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_LOGGING=1" } + - { title: "no-logging-text" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_LOGGING=1,ASMJIT_NO_TEXT=1" } + - { title: "no-builder" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_BUILDER=1" } + - { title: "no-compiler" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_COMPILER=1" } + - { title: "no-introspection", os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_COMPILER=1,ASMJIT_NO_INTROSPECTION=1" } + - { title: "no-jit" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_JIT=1" } + - { title: "no-validation" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_VALIDATION=1" } + - { title: "no-x86" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_X86=1" } + - { title: "no-aarch64" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_AARCH64=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "macos" , os: "macos-12" , cc: "gcc-11" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "macos" , os: "macos-12" , cc: "gcc-11" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "macos" , os: "macos-12" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "macos" , os: "macos-12" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" } - - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-7" , arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "gcc-8" , arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-9" , arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-10" , arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-11" , arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-12" , arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-13" , arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-13" , arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-13" , arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "gcc-13" , arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-20.04" , cc: "clang-10", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-11", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-12", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-15", arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-15", arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-15", arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-15", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-16", arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-16", arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-16", arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-16", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-17", arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-17", arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-17", arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "linux" , os: "ubuntu-22.04" , cc: "clang-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "macos" , os: "macos-12" , cc: "gcc-11" , arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "macos" , os: "macos-12" , cc: "gcc-11" , arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "macos" , os: "macos-12" , cc: "clang" , arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "macos" , os: "macos-12" , cc: "clang" , arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" } + - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" } + - { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" } - - { host: "macos-12" , os: "freebsd", osver: "13.2", cc: "clang", arch: "x86-64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { host: "macos-12" , os: "netbsd" , osver: "9.3" , cc: "clang", arch: "x86-64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { host: "macos-12" , os: "openbsd", osver: "7.3" , cc: "clang", arch: "x86-64", build_type: "Release", defs: "ASMJIT_TEST=ON" } - - { host: "ubuntu-latest" , os: "openbsd", osver: "7.3" , cc: "clang", arch: "arm64" , build_type: "Release", defs: "ASMJIT_TEST=ON" } + - { host: "macos-12" , os: "freebsd", osver: "13.2", cc: "clang", arch: "x86-64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { host: "macos-12" , os: "netbsd" , osver: "9.3" , cc: "clang", arch: "x86-64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { host: "macos-12" , os: "openbsd", osver: "7.3" , cc: "clang", arch: "x86-64", conf: "Release", defs: "ASMJIT_TEST=1" } + - { host: "ubuntu-latest" , os: "openbsd", osver: "7.3" , cc: "clang", arch: "arm64" , conf: "Release", defs: "ASMJIT_TEST=1" } - name: "${{matrix.title || format('{0}-{1}', matrix.os, matrix.osver)}} (${{matrix.cc}}, ${{matrix.arch}}, ${{matrix.build_type}})" + name: "${{matrix.title || format('{0}-{1}', matrix.os, matrix.osver)}} (${{matrix.cc}}, ${{matrix.arch}}, ${{matrix.conf}})" runs-on: "${{matrix.host || matrix.os}}" steps: @@ -138,11 +155,13 @@ jobs: if: ${{!matrix.host}} run: python build-actions/action.py --step=all - --compiler=${{matrix.cc}} - --architecture=${{matrix.arch}} --source-dir=source --config=source/.github/workflows/build-config.json - --build-type=${{matrix.build_type}} + --compiler=${{matrix.cc}} + --diagnostics=${{matrix.diagnostics}} + --architecture=${{matrix.arch}} + --problem-matcher=auto + --build-type=${{matrix.conf}} --build-defs=${{matrix.defs}} - name: "Build & Test in VM" @@ -165,9 +184,11 @@ jobs: sh ./build-actions/prepare-environment.sh python3 build-actions/action.py \ --step=all \ - --compiler=${{matrix.cc}} \ - --architecture=${{matrix.arch}} \ --source-dir=source \ --config=source/.github/workflows/build-config.json \ - --build-type=${{matrix.build_type}} \ + --compiler=${{matrix.cc}} \ + --diagnostics=${{matrix.diagnostics}} \ + --architecture=${{matrix.arch}} \ + --problem-matcher=auto \ + --build-type=${{matrix.conf}} \ --build-defs=${{matrix.defs}} diff --git a/src/asmjit/arm/a64assembler.cpp b/src/asmjit/arm/a64assembler.cpp index 444bb1f..3dfd4a5 100644 --- a/src/asmjit/arm/a64assembler.cpp +++ b/src/asmjit/arm/a64assembler.cpp @@ -4114,7 +4114,6 @@ Case_BaseLdurStur: if (inverted) { imm8 = ~imm8 & 0xFFu; - inverted = 0; } cmode = B(3) | B(2) | B(1); @@ -4147,7 +4146,6 @@ Case_BaseLdurStur: case 3: if (inverted) { imm8 = ~imm8 & 0xFFu; - inverted = 0; } op = 1; diff --git a/src/asmjit/arm/a64compiler.h b/src/asmjit/arm/a64compiler.h index c0b3867..64f82f6 100644 --- a/src/asmjit/arm/a64compiler.h +++ b/src/asmjit/arm/a64compiler.h @@ -45,20 +45,27 @@ public: return reg; } + template + ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type, const char* s) { +#ifndef ASMJIT_NO_LOGGING + RegT reg(Globals::NoInit); + _newReg(®, type, s); + return reg; +#else + DebugUtils::unused(s); + return _newRegInternal(type); +#endif + } + template ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type, const char* s, Args&&... args) { #ifndef ASMJIT_NO_LOGGING RegT reg(Globals::NoInit); - if (sizeof...(Args) == 0) - _newReg(®, type, s); - else - _newRegFmt(®, type, s, std::forward(args)...); + _newRegFmt(®, type, s, std::forward(args)...); return reg; #else DebugUtils::unused(s, std::forward(args)...); - RegT reg(Globals::NoInit); - _newReg(®, type, nullptr); - return reg; + return _newRegInternal(type); #endif } //! \endcond diff --git a/src/asmjit/arm/a64emithelper.cpp b/src/asmjit/arm/a64emithelper.cpp index f57a9e1..fd041a4 100644 --- a/src/asmjit/arm/a64emithelper.cpp +++ b/src/asmjit/arm/a64emithelper.cpp @@ -169,7 +169,7 @@ Error EmitHelper::emitArgMove( if (TypeUtils::isInt(dstTypeId)) { if (TypeUtils::isInt(srcTypeId)) { - uint32_t x = dstSize == 8; + uint32_t x = uint32_t(dstSize == 8); dst.setSignature(OperandSignature{x ? uint32_t(GpX::kSignature) : uint32_t(GpW::kSignature)}); _emitter->setInlineComment(comment); @@ -186,7 +186,7 @@ Error EmitHelper::emitArgMove( case TypeId::kInt16: instId = Inst::kIdLdrsh; break; case TypeId::kUInt16: instId = Inst::kIdLdrh; break; case TypeId::kInt32: instId = x ? Inst::kIdLdrsw : Inst::kIdLdr; break; - case TypeId::kUInt32: instId = Inst::kIdLdr; x = 0; break; + case TypeId::kUInt32: instId = Inst::kIdLdr; break; case TypeId::kInt64: instId = Inst::kIdLdr; break; case TypeId::kUInt64: instId = Inst::kIdLdr; break; default: diff --git a/src/asmjit/arm/armformatter.cpp b/src/asmjit/arm/armformatter.cpp index 86eb24b..52b1e0a 100644 --- a/src/asmjit/arm/armformatter.cpp +++ b/src/asmjit/arm/armformatter.cpp @@ -185,7 +185,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatCondCode(String& sb, CondCode c } ASMJIT_FAVOR_SIZE Error FormatterInternal::formatShiftOp(String& sb, ShiftOp shiftOp) noexcept { - const char* str = ""; + const char* str = nullptr; switch (shiftOp) { case ShiftOp::kLSL: str = "lsl"; break; case ShiftOp::kLSR: str = "lsr"; break; @@ -201,6 +201,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatShiftOp(String& sb, ShiftOp shi case ShiftOp::kSXTH: str = "sxth"; break; case ShiftOp::kSXTW: str = "sxtw"; break; case ShiftOp::kSXTX: str = "sxtx"; break; + default: str = ""; break; } return sb.append(str); } diff --git a/src/asmjit/core/api-config.h b/src/asmjit/core/api-config.h index dd50475..ab24e27 100644 --- a/src/asmjit/core/api-config.h +++ b/src/asmjit/core/api-config.h @@ -16,7 +16,7 @@ #define ASMJIT_LIBRARY_MAKE_VERSION(major, minor, patch) ((major << 16) | (minor << 8) | (patch)) //! AsmJit library version, see \ref ASMJIT_LIBRARY_MAKE_VERSION for a version format reference. -#define ASMJIT_LIBRARY_VERSION ASMJIT_LIBRARY_MAKE_VERSION(1, 11, 0) +#define ASMJIT_LIBRARY_VERSION ASMJIT_LIBRARY_MAKE_VERSION(1, 12, 0) //! \def ASMJIT_ABI_NAMESPACE //! @@ -27,7 +27,7 @@ //! AsmJit default, which makes it possible to use multiple AsmJit libraries within a single project, totally //! controlled by users. This is useful especially in cases in which some of such library comes from third party. #if !defined(ASMJIT_ABI_NAMESPACE) - #define ASMJIT_ABI_NAMESPACE _abi_1_11 + #define ASMJIT_ABI_NAMESPACE _abi_1_12 #endif // !ASMJIT_ABI_NAMESPACE //! \} @@ -221,45 +221,11 @@ namespace asmjit { // C++ Compiler and Features Detection // =================================== -#define ASMJIT_CXX_GNU 0 -#define ASMJIT_CXX_MAKE_VER(MAJOR, MINOR) ((MAJOR) * 1000 + (MINOR)) - -// Intel Compiler [pretends to be GNU or MSC, so it must be checked first]: -// - https://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler -// - https://software.intel.com/en-us/articles/c14-features-supported-by-intel-c-compiler -// - https://software.intel.com/en-us/articles/c17-features-supported-by-intel-c-compiler -#if defined(__INTEL_COMPILER) - -// MSC Compiler: -// - https://msdn.microsoft.com/en-us/library/hh567368.aspx -// -// Version List: -// - 16.00.0 == VS2010 -// - 17.00.0 == VS2012 -// - 18.00.0 == VS2013 -// - 19.00.0 == VS2015 -// - 19.10.0 == VS2017 -#elif defined(_MSC_VER) && defined(_MSC_FULL_VER) - -// Clang Compiler [Pretends to be GNU, so it must be checked before]: -// - https://clang.llvm.org/cxx_status.html -#elif defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) - -// GNU Compiler: -// - https://gcc.gnu.org/projects/cxx-status.html -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) - - #undef ASMJIT_CXX_GNU - #define ASMJIT_CXX_GNU ASMJIT_CXX_MAKE_VER(__GNUC__, __GNUC_MINOR__) - -#endif - -// Compiler features detection macros. -#if defined(__clang__) && defined(__has_attribute) +#if defined(__GNUC__) && defined(__has_attribute) #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (__has_attribute(NAME)) #else #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (!(!(CHECK))) -#endif +#endif // !ASMJIT_CXX_HAS_ATTRIBUTE // API Decorators & C++ Extensions // =============================== @@ -301,7 +267,7 @@ namespace asmjit { //! is unwanted in most projects. MSVC automatically exports typeinfo and vtable if at least one symbol of the class //! is exported. However, GCC has some strange behavior that even if one or more symbol is exported it doesn't export //! typeinfo unless the class itself is decorated with "visibility(default)" (i.e. ASMJIT_API). -#if !defined(_WIN32) && defined(__GNUC__) +#if defined(__GNUC__) && !defined(_WIN32) #define ASMJIT_VIRTAPI ASMJIT_API #else #define ASMJIT_VIRTAPI @@ -477,66 +443,60 @@ namespace asmjit { #if ASMJIT_CXX_HAS_ATTRIBUTE(no_sanitize, 0) #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize__("undefined"))) -#elif ASMJIT_CXX_GNU >= ASMJIT_CXX_MAKE_VER(4, 9) +#elif defined(__GNUC__) && __GNUC__ >= 5 #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize_undefined__)) #else #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF #endif -// Begin-Namespace & End-Namespace Macros +// Diagnostic Macros // ====================================== -#if defined _DOXYGEN - #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { - #define ASMJIT_END_NAMESPACE } -#elif defined(__clang__) - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wconstant-logical-operand\"") \ - _Pragma("clang diagnostic ignored \"-Wunnamed-type-template-args\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("clang diagnostic pop") \ - }} -#elif defined(__GNUC__) && __GNUC__ == 4 - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ +#if !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(_DOXYGEN) + #if defined(__GNUC__) && __GNUC__ == 4 + // There is a bug in GCC 4.X that has been fixed in GCC 5+, so just silence the warning. + #define ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("GCC diagnostic pop") \ - }} -#elif defined(__GNUC__) && __GNUC__ >= 8 - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("GCC diagnostic pop") \ - }} -#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ + #define ASMJIT_END_DIAGNOSTIC_SCOPE \ + _Pragma("GCC diagnostic pop") + #elif defined(_MSC_VER) + #define ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ __pragma(warning(push)) \ __pragma(warning(disable: 4127)) /* conditional expression is const */ \ __pragma(warning(disable: 4201)) /* nameless struct/union */ + #define ASMJIT_END_DIAGNOSTIC_SCOPE \ + __pragma(warning(pop)) + #endif +#endif + +#if !defined(ASMJIT_BEGIN_DIAGNOSTIC_SCOPE) && !defined(ASMJIT_END_DIAGNOSTIC_SCOPE) + #define ASMJIT_BEGIN_DIAGNOSTIC_SCOPE + #define ASMJIT_END_DIAGNOSTIC_SCOPE +#endif + +// Begin-Namespace & End-Namespace Macros +// ====================================== + +#if !defined(ASMJIT_NO_ABI_NAMESPACE) && !defined(_DOXYGEN) + #define ASMJIT_BEGIN_NAMESPACE \ + ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ + namespace asmjit { \ + inline namespace ASMJIT_ABI_NAMESPACE { #define ASMJIT_END_NAMESPACE \ - __pragma(warning(pop)) \ - }} + }} \ + ASMJIT_END_DIAGNOSTIC_SCOPE +#else + #define ASMJIT_BEGIN_NAMESPACE \ + ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \ + namespace asmjit { + #define ASMJIT_END_NAMESPACE \ + } \ + ASMJIT_END_DIAGNOSTIC_SCOPE #endif -#if !defined(ASMJIT_BEGIN_NAMESPACE) && !defined(ASMJIT_END_NAMESPACE) - #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { - #define ASMJIT_END_NAMESPACE }} -#endif - -#define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) \ - ASMJIT_BEGIN_NAMESPACE \ - namespace NAMESPACE { - -#define ASMJIT_END_SUB_NAMESPACE \ - } \ - ASMJIT_END_NAMESPACE +#define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) ASMJIT_BEGIN_NAMESPACE namespace NAMESPACE { +#define ASMJIT_END_SUB_NAMESPACE } ASMJIT_END_NAMESPACE // C++ Utilities // ============= @@ -612,10 +572,4 @@ namespace asmjit { } #endif -// Cleanup Api-Config Specific Macros -// ================================== - -#undef ASMJIT_CXX_GNU -#undef ASMJIT_CXX_MAKE_VER - #endif // ASMJIT_CORE_API_CONFIG_H_INCLUDED diff --git a/src/asmjit/core/builder.h b/src/asmjit/core/builder.h index 3bf530c..2c6dc77 100644 --- a/src/asmjit/core/builder.h +++ b/src/asmjit/core/builder.h @@ -48,7 +48,7 @@ enum class NodeType : uint8_t { // [BaseBuilder] - //! Node is \ref InstNode or \ref InstExNode. + //! Node is \ref InstNode. kInst = 1, //! Node is \ref SectionNode. kSection = 2, @@ -748,12 +748,15 @@ public: //! \name Constants //! \{ - enum : uint32_t { - //! Count of embedded operands per `InstNode` that are always allocated as a part of the instruction. Minimum - //! embedded operands is 4, but in 32-bit more pointers are smaller and we can embed 5. The rest (up to 6 operands) - //! is always stored in `InstExNode`. - kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_)) - }; + //! The number of embedded operands for a default \ref InstNode instance that are always allocated as a part of + //! the instruction itself. Minimum embedded operands is 4, but in 32-bit more pointers are smaller and we can + //! embed 5. The rest (up to 6 operands) is considered extended. + //! + //! The number of operands InstNode holds is decided when \ref InstNode is created. + static constexpr uint32_t kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_)); + + //! Count of maximum number of operands \ref InstNode can hold. + static constexpr uint32_t kFullOpCapacity = Globals::kMaxOpCount; //! \} @@ -762,8 +765,6 @@ public: //! Base instruction data. BaseInst _baseInst; - //! First 4 or 5 operands (indexed from 0). - Operand_ _opArray[kBaseOpCapacity]; //! \} @@ -851,38 +852,52 @@ public: ASMJIT_INLINE_NODEBUG void setOpCount(uint32_t opCount) noexcept { _inst._opCount = uint8_t(opCount); } //! Returns operands array. - ASMJIT_INLINE_NODEBUG Operand* operands() noexcept { return (Operand*)_opArray; } + ASMJIT_INLINE_NODEBUG Operand* operands() noexcept { + return reinterpret_cast(reinterpret_cast(this) + sizeof(InstNode)); + } + //! Returns operands array (const). - ASMJIT_INLINE_NODEBUG const Operand* operands() const noexcept { return (const Operand*)_opArray; } + ASMJIT_INLINE_NODEBUG const Operand* operands() const noexcept { + return reinterpret_cast(reinterpret_cast(this) + sizeof(InstNode)); + } //! Returns operand at the given `index`. inline Operand& op(uint32_t index) noexcept { ASMJIT_ASSERT(index < opCapacity()); - return _opArray[index].as(); + + Operand* ops = operands(); + return ops[index].as(); } //! Returns operand at the given `index` (const). inline const Operand& op(uint32_t index) const noexcept { ASMJIT_ASSERT(index < opCapacity()); - return _opArray[index].as(); + + const Operand* ops = operands(); + return ops[index].as(); } //! Sets operand at the given `index` to `op`. inline void setOp(uint32_t index, const Operand_& op) noexcept { ASMJIT_ASSERT(index < opCapacity()); - _opArray[index].copyFrom(op); + + Operand* ops = operands(); + ops[index].copyFrom(op); } //! Resets operand at the given `index` to none. inline void resetOp(uint32_t index) noexcept { ASMJIT_ASSERT(index < opCapacity()); - _opArray[index].reset(); + + Operand* ops = operands(); + ops[index].reset(); } //! Resets operands at `[start, end)` range. inline void resetOpRange(uint32_t start, uint32_t end) noexcept { + Operand* ops = operands(); for (uint32_t i = start; i < end; i++) - _opArray[i].reset(); + ops[i].reset(); } //! \} @@ -891,8 +906,9 @@ public: //! \{ inline bool hasOpType(OperandType opType) const noexcept { + const Operand* ops = operands(); for (uint32_t i = 0, count = opCount(); i < count; i++) - if (_opArray[i].opType() == opType) + if (ops[i].opType() == opType) return true; return false; } @@ -905,9 +921,10 @@ public: inline uint32_t indexOfOpType(OperandType opType) const noexcept { uint32_t i = 0; uint32_t count = opCount(); + const Operand* ops = operands(); while (i < count) { - if (_opArray[i].opType() == opType) + if (ops[i].opType() == opType) break; i++; } @@ -950,43 +967,31 @@ public: //! \{ //! \cond INTERNAL - static ASMJIT_INLINE_NODEBUG uint32_t capacityOfOpCount(uint32_t opCount) noexcept { + static ASMJIT_INLINE_NODEBUG constexpr uint32_t capacityOfOpCount(uint32_t opCount) noexcept { return opCount <= kBaseOpCapacity ? kBaseOpCapacity : Globals::kMaxOpCount; } - static ASMJIT_INLINE_NODEBUG size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept { - size_t base = sizeof(InstNode) - kBaseOpCapacity * sizeof(Operand); - return base + opCapacity * sizeof(Operand); + static ASMJIT_INLINE_NODEBUG constexpr size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept { + return sizeof(InstNode) + opCapacity * sizeof(Operand); } //! \endcond //! \} }; -//! Instruction node with maximum number of operands. +//! Instruction node with embedded operands following \ref InstNode layout. //! -//! This node is created automatically by Builder/Compiler in case that the required number of operands exceeds -//! the default capacity of `InstNode`. -class InstExNode : public InstNode { +//! \note This is used to make tools such as static analysis and compilers happy about the layout. There were two +//! instruction nodes in the past, having the second extend the operand array of the first, but that has caused +//! undefined behavior and made recent tools unhappy about that. +template +class InstNodeWithOperands : public InstNode { public: - ASMJIT_NONCOPYABLE(InstExNode) + Operand_ _operands[kN]; - //! \name Members - //! \{ - - //! Continued `_opArray[]` to hold up to `kMaxOpCount` operands. - Operand_ _opArrayEx[Globals::kMaxOpCount - kBaseOpCapacity]; - - //! \} - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `InstExNode` instance. - ASMJIT_INLINE_NODEBUG InstExNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCapacity = Globals::kMaxOpCount) noexcept - : InstNode(cb, instId, options, opCapacity) {} - - //! \} + //! Creates a new `InstNodeWithOperands` instance. + ASMJIT_INLINE_NODEBUG InstNodeWithOperands(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCount) noexcept + : InstNode(cb, instId, options, opCount, kN) {} }; //! Section node. @@ -1013,9 +1018,9 @@ public: //! \{ //! Creates a new `SectionNode` instance. - ASMJIT_INLINE_NODEBUG SectionNode(BaseBuilder* cb, uint32_t secionId = 0) noexcept + ASMJIT_INLINE_NODEBUG SectionNode(BaseBuilder* cb, uint32_t sectionId = 0) noexcept : BaseNode(cb, NodeType::kSection, NodeFlags::kHasNoEffect), - _id(secionId), + _id(sectionId), _nextSection(nullptr) {} //! \} diff --git a/src/asmjit/core/compiler.h b/src/asmjit/core/compiler.h index 5897a1b..e6b24bb 100644 --- a/src/asmjit/core/compiler.h +++ b/src/asmjit/core/compiler.h @@ -325,7 +325,7 @@ public: //! \note This node should be only used to represent jump where the jump target cannot be deduced by examining //! instruction operands. For example if the jump target is register or memory location. This pattern is often //! used to perform indirect jumps that use jump table, e.g. to implement `switch{}` statement. -class JumpNode : public InstNode { +class JumpNode : public InstNodeWithOperands { public: ASMJIT_NONCOPYABLE(JumpNode) @@ -340,7 +340,7 @@ public: //! \{ inline JumpNode(BaseCompiler* ASMJIT_NONNULL(cc), InstId instId, InstOptions options, uint32_t opCount, JumpAnnotation* annotation) noexcept - : InstNode(cc, instId, options, opCount, kBaseOpCapacity), + : InstNodeWithOperands(cc, instId, options, opCount), _annotation(annotation) { setType(NodeType::kJump); } @@ -531,7 +531,7 @@ public: }; //! Function return, used by \ref BaseCompiler. -class FuncRetNode : public InstNode { +class FuncRetNode : public InstNodeWithOperands { public: ASMJIT_NONCOPYABLE(FuncRetNode) @@ -539,7 +539,8 @@ public: //! \{ //! Creates a new `FuncRetNode` instance. - inline FuncRetNode(BaseBuilder* ASMJIT_NONNULL(cb)) noexcept : InstNode(cb, BaseInst::kIdAbstract, InstOptions::kNone, 0) { + inline FuncRetNode(BaseBuilder* ASMJIT_NONNULL(cb)) noexcept + : InstNodeWithOperands(cb, BaseInst::kIdAbstract, InstOptions::kNone, 0) { _any._nodeType = NodeType::kFuncRet; } @@ -547,12 +548,12 @@ public: }; //! Function invocation, used by \ref BaseCompiler. -class InvokeNode : public InstNode { +class InvokeNode : public InstNodeWithOperands { public: ASMJIT_NONCOPYABLE(InvokeNode) //! Operand pack provides multiple operands that can be associated with a single return value of function - //! argument. Sometims this is necessary to express an argument or return value that requires multiple + //! argument. Sometimes this is necessary to express an argument or return value that requires multiple //! registers, for example 64-bit value in 32-bit mode or passing / returning homogeneous data structures. struct OperandPack { //! Operands. @@ -594,7 +595,7 @@ public: //! Creates a new `InvokeNode` instance. inline InvokeNode(BaseBuilder* ASMJIT_NONNULL(cb), InstId instId, InstOptions options) noexcept - : InstNode(cb, instId, options, kBaseOpCapacity), + : InstNodeWithOperands(cb, instId, options, 0), _funcDetail(), _args(nullptr) { setType(NodeType::kInvoke); @@ -619,9 +620,9 @@ public: ASMJIT_INLINE_NODEBUG const FuncDetail& detail() const noexcept { return _funcDetail; } //! Returns the target operand. - ASMJIT_INLINE_NODEBUG Operand& target() noexcept { return _opArray[0].as(); } + ASMJIT_INLINE_NODEBUG Operand& target() noexcept { return op(0); } //! \overload - ASMJIT_INLINE_NODEBUG const Operand& target() const noexcept { return _opArray[0].as(); } + ASMJIT_INLINE_NODEBUG const Operand& target() const noexcept { return op(0); } //! Returns the number of function return values. ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _funcDetail.hasRet(); } diff --git a/src/asmjit/core/cpuinfo.h b/src/asmjit/core/cpuinfo.h index 8ddc1e1..3e514ef 100644 --- a/src/asmjit/core/cpuinfo.h +++ b/src/asmjit/core/cpuinfo.h @@ -876,59 +876,58 @@ public: //! \{ //! Architecture. - Arch _arch; + Arch _arch {}; //! Sub-architecture. - SubArch _subArch; + SubArch _subArch {}; //! True if the CPU was detected, false if the detection failed or it's not available. - bool _wasDetected; + bool _wasDetected {}; //! Reserved for future use. - uint8_t _reserved; + uint8_t _reserved {}; //! CPU family ID. - uint32_t _familyId; + uint32_t _familyId {}; //! CPU model ID. - uint32_t _modelId; + uint32_t _modelId {}; //! CPU brand ID. - uint32_t _brandId; + uint32_t _brandId {}; //! CPU stepping. - uint32_t _stepping; + uint32_t _stepping {}; //! Processor type. - uint32_t _processorType; + uint32_t _processorType {}; //! Maximum number of addressable IDs for logical processors. - uint32_t _maxLogicalProcessors; + uint32_t _maxLogicalProcessors {}; //! Cache line size (in bytes). - uint32_t _cacheLineSize; + uint32_t _cacheLineSize {}; //! Number of hardware threads. - uint32_t _hwThreadCount; + uint32_t _hwThreadCount {}; //! CPU vendor string. - FixedString<16> _vendor; + FixedString<16> _vendor {}; //! CPU brand string. - FixedString<64> _brand; + FixedString<64> _brand {}; //! CPU features. - CpuFeatures _features; + CpuFeatures _features {}; //! \} //! \name Construction & Destruction //! \{ - ASMJIT_INLINE_NODEBUG CpuInfo() noexcept { reset(); } + ASMJIT_INLINE_NODEBUG CpuInfo() noexcept {} ASMJIT_INLINE_NODEBUG CpuInfo(const CpuInfo& other) noexcept = default; ASMJIT_INLINE_NODEBUG explicit CpuInfo(Globals::NoInit_) noexcept : _features(Globals::NoInit) {}; + //! \} + + //! \name CPU Information Detection + //! \{ + //! Returns the host CPU information. + //! + //! \note The returned reference is global - it's setup only once and then shared. ASMJIT_API static const CpuInfo& host() noexcept; - //! Initializes CpuInfo architecture and sub-architecture members to `arch` and `subArch`, respectively. - ASMJIT_INLINE_NODEBUG void initArch(Arch arch, SubArch subArch = SubArch::kUnknown) noexcept { - _arch = arch; - _subArch = subArch; - } - - ASMJIT_INLINE_NODEBUG void reset() noexcept { memset(this, 0, sizeof(*this)); } - //! \} //! \name Overloaded Operators @@ -938,6 +937,19 @@ public: //! \} + //! \name Init & Reset + //! \{ + + //! Initializes CpuInfo architecture and sub-architecture members to `arch` and `subArch`, respectively. + ASMJIT_INLINE_NODEBUG void initArch(Arch arch, SubArch subArch = SubArch::kUnknown) noexcept { + _arch = arch; + _subArch = subArch; + } + + ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = CpuInfo{}; } + + //! \} + //! \name Accessors //! \{ diff --git a/src/asmjit/core/emitter.h b/src/asmjit/core/emitter.h index a836790..e7cdc49 100644 --- a/src/asmjit/core/emitter.h +++ b/src/asmjit/core/emitter.h @@ -194,6 +194,7 @@ ASMJIT_DEFINE_ENUM_FLAGS(DiagnosticOptions) class ASMJIT_VIRTAPI BaseEmitter { public: ASMJIT_BASE_CLASS(BaseEmitter) + ASMJIT_NONCOPYABLE(BaseEmitter) //! \name Members //! \{ diff --git a/src/asmjit/core/formatter.cpp b/src/asmjit/core/formatter.cpp index 3fd5137..9ccfd1c 100644 --- a/src/asmjit/core/formatter.cpp +++ b/src/asmjit/core/formatter.cpp @@ -57,7 +57,7 @@ Error formatTypeId(String& sb, TypeId typeId) noexcept { if (!TypeUtils::isValid(typeId)) return sb.append("unknown"); - const char* typeName = "unknown"; + const char* typeName = nullptr; uint32_t typeSize = TypeUtils::sizeOf(typeId); TypeId scalarType = TypeUtils::scalarOf(typeId); @@ -514,7 +514,7 @@ Error formatNode( ASMJIT_PROPAGATE(sb.append("[FuncRet]")); for (uint32_t i = 0; i < 2; i++) { - const Operand_& op = retNode->_opArray[i]; + const Operand_& op = retNode->op(i); if (!op.isNone()) { ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", ")); ASMJIT_PROPAGATE(formatOperand(sb, formatOptions.flags(), builder, builder->arch(), op)); diff --git a/src/asmjit/core/inst.h b/src/asmjit/core/inst.h index d0ddd8e..a0fcce9 100644 --- a/src/asmjit/core/inst.h +++ b/src/asmjit/core/inst.h @@ -499,7 +499,8 @@ struct OpRWInfo { _consecutiveLeadCount = 0; _resetReserved(); - uint64_t mask = Support::lsbMask(regSize); + uint64_t mask = Support::lsbMask(Support::min(regSize, 64)); + _readByteMask = Support::test(opFlags, OpRWFlags::kRead) ? mask : uint64_t(0); _writeByteMask = Support::test(opFlags, OpRWFlags::kWrite) ? mask : uint64_t(0); _extendByteMask = 0; diff --git a/src/asmjit/core/jitallocator.cpp b/src/asmjit/core/jitallocator.cpp index 3aef8c5..7b80c30 100644 --- a/src/asmjit/core/jitallocator.cpp +++ b/src/asmjit/core/jitallocator.cpp @@ -37,12 +37,13 @@ static constexpr uint32_t kJitAllocatorMaxBlockSize = 1024 * 1024 * 64; // =========================== static inline uint32_t JitAllocator_defaultFillPattern() noexcept { +#if ASMJIT_ARCH_X86 // X86 and X86_64 - 4x 'int3' instruction. - if (ASMJIT_ARCH_X86) - return 0xCCCCCCCCu; - + return 0xCCCCCCCCu; +#else // Unknown... return 0u; +#endif } // JitAllocator - BitVectorRangeIterator diff --git a/src/asmjit/core/operand.h b/src/asmjit/core/operand.h index 6ffde24..3478208 100644 --- a/src/asmjit/core/operand.h +++ b/src/asmjit/core/operand.h @@ -331,25 +331,25 @@ struct OperandSignature { ASMJIT_INLINE_NODEBUG constexpr uint32_t bits() const noexcept { return _bits; } ASMJIT_INLINE_NODEBUG void setBits(uint32_t bits) noexcept { _bits = bits; } - template::value> + template ASMJIT_INLINE_NODEBUG constexpr bool hasField() const noexcept { return (_bits & kFieldMask) != 0; } - template::value> + template ASMJIT_INLINE_NODEBUG constexpr bool hasField(uint32_t value) const noexcept { - return (_bits & kFieldMask) != value << kFieldShift; + return (_bits & kFieldMask) != value << Support::ConstCTZ::value; } - template::value> + template ASMJIT_INLINE_NODEBUG constexpr uint32_t getField() const noexcept { - return (_bits >> kFieldShift) & (kFieldMask >> kFieldShift); + return (_bits >> Support::ConstCTZ::value) & (kFieldMask >> Support::ConstCTZ::value); } - template::value> + template ASMJIT_INLINE_NODEBUG void setField(uint32_t value) noexcept { - ASMJIT_ASSERT((value & ~(kFieldMask >> kFieldShift)) == 0); - _bits = (_bits & ~kFieldMask) | (value << kFieldShift); + ASMJIT_ASSERT(((value << Support::ConstCTZ::value) & ~kFieldMask) == 0); + _bits = (_bits & ~kFieldMask) | (value << Support::ConstCTZ::value); } ASMJIT_INLINE_NODEBUG constexpr OperandSignature subset(uint32_t mask) const noexcept { return OperandSignature{_bits & mask}; } @@ -643,10 +643,10 @@ struct Operand_ { //! \note This basically performs a binary comparison, if aby bit is //! different the operands are not equal. ASMJIT_INLINE_NODEBUG constexpr bool equals(const Operand_& other) const noexcept { - return (_signature == other._signature) & - (_baseId == other._baseId ) & - (_data[0] == other._data[0] ) & - (_data[1] == other._data[1] ) ; + return bool(unsigned(_signature == other._signature) & + unsigned(_baseId == other._baseId ) & + unsigned(_data[0] == other._data[0] ) & + unsigned(_data[1] == other._data[1] )); } //! Tests whether the operand is a register matching the given register `type`. @@ -712,7 +712,7 @@ public: //! Creates an operand initialized to raw `[u0, u1, u2, u3]` values. ASMJIT_INLINE_NODEBUG constexpr Operand(Globals::Init_, const Signature& u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept - : Operand_{ u0, u1, { u2, u3 }} {} + : Operand_{{u0._bits}, u1, {u2, u3}} {} //! Creates an uninitialized operand (dangerous). ASMJIT_INLINE_NODEBUG explicit Operand(Globals::NoInit_) noexcept {} diff --git a/src/asmjit/core/rapass.cpp b/src/asmjit/core/rapass.cpp index d47b0d3..6aab715 100644 --- a/src/asmjit/core/rapass.cpp +++ b/src/asmjit/core/rapass.cpp @@ -476,12 +476,18 @@ Error BaseRAPass::buildCFGDominators() noexcept { entryBlock->setIDom(entryBlock); bool changed = true; - uint32_t nIters = 0; + +#ifndef ASMJIT_NO_LOGGING + uint32_t numIters = 0; +#endif while (changed) { - nIters++; changed = false; +#ifndef ASMJIT_NO_LOGGING + numIters++; +#endif + uint32_t i = _pov.size(); while (i) { RABlock* block = _pov[--i]; @@ -508,7 +514,7 @@ Error BaseRAPass::buildCFGDominators() noexcept { } } - ASMJIT_RA_LOG_FORMAT(" Done (%u iterations)\n", nIters); + ASMJIT_RA_LOG_FORMAT(" Done (%u iterations)\n", numIters); return kErrorOk; } @@ -798,7 +804,6 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { uint32_t numAllBlocks = blockCount(); uint32_t numReachableBlocks = reachableBlockCount(); - uint32_t numVisits = numReachableBlocks; uint32_t numWorkRegs = workRegCount(); uint32_t numBitWords = ZoneBitVector::_wordsPerBits(numWorkRegs); @@ -888,6 +893,10 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { // Calculate IN/OUT of Each Block // ------------------------------ +#ifndef ASMJIT_NO_LOGGING + uint32_t numVisits = numReachableBlocks; +#endif + { ZoneStack workList; ZoneBitVector workBits; @@ -918,7 +927,9 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept { } } } +#ifndef ASMJIT_NO_LOGGING numVisits++; +#endif } workList.reset(); diff --git a/src/asmjit/core/support.h b/src/asmjit/core/support.h index ca5d17a..2250e9c 100644 --- a/src/asmjit/core/support.h +++ b/src/asmjit/core/support.h @@ -230,7 +230,7 @@ static ASMJIT_INLINE_NODEBUG constexpr T lsbMask(const CountT& n) noexcept { : n ? T(shr(allOnes(), bitSizeOf() - size_t(n))) : T(0); } -//! Generats a leading bit-mask that has `n` most significant (leading) bits set. +//! Generates a leading bit-mask that has `n` most significant (leading) bits set. template static ASMJIT_INLINE_NODEBUG constexpr T msbMask(const CountT& n) noexcept { typedef typename std::make_unsigned::type U; @@ -321,12 +321,12 @@ struct BitScanCalc { }; template -constexpr ASMJIT_INLINE_NODEBUG uint32_t clzFallback(const T& x) noexcept { +ASMJIT_INLINE_NODEBUG constexpr uint32_t clzFallback(const T& x) noexcept { return BitScanCalc() / 2u>::clz(BitScanData{x, 1}).n; } template -constexpr ASMJIT_INLINE_NODEBUG uint32_t ctzFallback(const T& x) noexcept { +ASMJIT_INLINE_NODEBUG constexpr uint32_t ctzFallback(const T& x) noexcept { return BitScanCalc() / 2u>::ctz(BitScanData{x, 1}).n; } @@ -457,31 +457,30 @@ namespace Internal { } static ASMJIT_INLINE_NODEBUG uint32_t constPopcntImpl(uint64_t x) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - x = x - ((x >> 1) & 0x5555555555555555u); - x = (x & 0x3333333333333333u) + ((x >> 2) & 0x3333333333333333u); - return uint32_t((((x + (x >> 4)) & 0x0F0F0F0F0F0F0F0Fu) * 0x0101010101010101u) >> 56); - } - else { - return constPopcntImpl(uint32_t(x >> 32)) + - constPopcntImpl(uint32_t(x & 0xFFFFFFFFu)); - } +#if ASMJIT_ARCH_BITS >= 64 + x = x - ((x >> 1) & 0x5555555555555555u); + x = (x & 0x3333333333333333u) + ((x >> 2) & 0x3333333333333333u); + return uint32_t((((x + (x >> 4)) & 0x0F0F0F0F0F0F0F0Fu) * 0x0101010101010101u) >> 56); +#else + return constPopcntImpl(uint32_t(x >> 32)) + + constPopcntImpl(uint32_t(x & 0xFFFFFFFFu)); +#endif } static ASMJIT_INLINE_NODEBUG uint32_t popcntImpl(uint32_t x) noexcept { - #if defined(__GNUC__) +#if defined(__GNUC__) return uint32_t(__builtin_popcount(x)); - #else +#else return constPopcntImpl(asUInt(x)); - #endif +#endif } static ASMJIT_INLINE_NODEBUG uint32_t popcntImpl(uint64_t x) noexcept { - #if defined(__GNUC__) +#if defined(__GNUC__) return uint32_t(__builtin_popcountll(x)); - #else +#else return constPopcntImpl(asUInt(x)); - #endif +#endif } } //! \endcond @@ -596,9 +595,9 @@ namespace Internal { template inline T subOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return subOverflowFallback(x, y, of); } template inline T mulOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return mulOverflowFallback(x, y, of); } - #if defined(__GNUC__) && !defined(ASMJIT_NO_INTRINSICS) - #if defined(__clang__) || __GNUC__ >= 5 - #define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, RESULT_T, BUILTIN) \ +#if defined(__GNUC__) && !defined(ASMJIT_NO_INTRINSICS) +#if defined(__clang__) || __GNUC__ >= 5 +#define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, RESULT_T, BUILTIN) \ template<> \ inline T FUNC(const T& x, const T& y, FastUInt8* of) noexcept { \ RESULT_T result; \ @@ -617,13 +616,13 @@ namespace Internal { ASMJIT_ARITH_OVERFLOW_SPECIALIZE(mulOverflowImpl, uint32_t, unsigned int , __builtin_umul_overflow ) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(mulOverflowImpl, int64_t , long long , __builtin_smulll_overflow) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(mulOverflowImpl, uint64_t, unsigned long long, __builtin_umulll_overflow) - #undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE - #endif - #endif +#undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE +#endif +#endif // There is a bug in MSVC that makes these specializations unusable, maybe in the future... - #if defined(_MSC_VER) && 0 - #define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, ALT_T, BUILTIN) \ +#if defined(_MSC_VER) && 0 +#define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, ALT_T, BUILTIN) \ template<> \ inline T FUNC(T x, T y, FastUInt8* of) noexcept { \ ALT_T result; \ @@ -632,12 +631,12 @@ namespace Internal { } ASMJIT_ARITH_OVERFLOW_SPECIALIZE(addOverflowImpl, uint32_t, unsigned int , _addcarry_u32 ) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(subOverflowImpl, uint32_t, unsigned int , _subborrow_u32) - #if ARCH_BITS >= 64 +#if ARCH_BITS >= 64 ASMJIT_ARITH_OVERFLOW_SPECIALIZE(addOverflowImpl, uint64_t, unsigned __int64 , _addcarry_u64 ) ASMJIT_ARITH_OVERFLOW_SPECIALIZE(subOverflowImpl, uint64_t, unsigned __int64 , _subborrow_u64) - #endif - #undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE - #endif +#endif +#undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE +#endif } // {Internal} //! \endcond diff --git a/src/asmjit/core/zonevector.h b/src/asmjit/core/zonevector.h index afb4f75..2008c81 100644 --- a/src/asmjit/core/zonevector.h +++ b/src/asmjit/core/zonevector.h @@ -194,8 +194,13 @@ public: if (ASMJIT_UNLIKELY(_size == _capacity)) ASMJIT_PROPAGATE(grow(allocator, 1)); - ::memmove(static_cast(_data) + 1, _data, size_t(_size) * sizeof(T)); - memcpy(_data, &item, sizeof(T)); + memmove(static_cast(static_cast(_data) + 1), + static_cast(_data), + size_t(_size) * sizeof(T)); + + memcpy(static_cast(_data), + static_cast(&item), + sizeof(T)); _size++; return kErrorOk; @@ -209,10 +214,15 @@ public: ASMJIT_PROPAGATE(grow(allocator, 1)); T* dst = static_cast(_data) + index; - ::memmove(dst + 1, dst, size_t(_size - index) * sizeof(T)); - memcpy(dst, &item, sizeof(T)); - _size++; + memmove(static_cast(dst + 1), + static_cast(dst), + size_t(_size - index) * sizeof(T)); + memcpy(static_cast(dst), + static_cast(&item), + sizeof(T)); + + _size++; return kErrorOk; } @@ -221,9 +231,11 @@ public: if (ASMJIT_UNLIKELY(_size == _capacity)) ASMJIT_PROPAGATE(grow(allocator, 1)); - memcpy(static_cast(_data) + _size, &item, sizeof(T)); - _size++; + memcpy(static_cast(static_cast(_data) + _size), + static_cast(&item), + sizeof(T)); + _size++; return kErrorOk; } @@ -234,7 +246,9 @@ public: ASMJIT_PROPAGATE(grow(allocator, size)); if (size) { - memcpy(static_cast(_data) + _size, other._data, size_t(size) * sizeof(T)); + memcpy(static_cast(static_cast(_data) + _size), + static_cast(other._data), + size_t(size) * sizeof(T)); _size += size; } @@ -249,10 +263,15 @@ public: ASMJIT_ASSERT(_size < _capacity); T* data = static_cast(_data); - if (_size) - ::memmove(data + 1, data, size_t(_size) * sizeof(T)); + if (_size) { + memmove(static_cast(data + 1), + static_cast(data), + size_t(_size) * sizeof(T)); + } - memcpy(data, &item, sizeof(T)); + memcpy(static_cast(data), + static_cast(&item), + sizeof(T)); _size++; } @@ -263,7 +282,9 @@ public: ASMJIT_FORCE_INLINE void appendUnsafe(const T& item) noexcept { ASMJIT_ASSERT(_size < _capacity); - memcpy(static_cast(_data) + _size, &item, sizeof(T)); + memcpy(static_cast(static_cast(_data) + _size), + static_cast(&item), + sizeof(T)); _size++; } @@ -273,17 +294,26 @@ public: ASMJIT_ASSERT(index <= _size); T* dst = static_cast(_data) + index; - ::memmove(dst + 1, dst, size_t(_size - index) * sizeof(T)); - memcpy(dst, &item, sizeof(T)); + memmove(static_cast(dst + 1), + static_cast(dst), + size_t(_size - index) * sizeof(T)); + + memcpy(static_cast(dst), + static_cast(&item), + sizeof(T)); + _size++; } + //! Concatenates all items of `other` at the end of the vector. ASMJIT_FORCE_INLINE void concatUnsafe(const ZoneVector& other) noexcept { uint32_t size = other._size; ASMJIT_ASSERT(_capacity - _size >= size); if (size) { - memcpy(static_cast(_data) + _size, other._data, size_t(size) * sizeof(T)); + memcpy(static_cast(static_cast(_data) + _size), + static_cast(other._data), + size_t(size) * sizeof(T)); _size += size; } } @@ -311,8 +341,11 @@ public: T* data = static_cast(_data) + i; size_t size = --_size - i; - if (size) - ::memmove(data, data + 1, size_t(size) * sizeof(T)); + if (size) { + memmove(static_cast(data), + static_cast(data + 1), + size_t(size) * sizeof(T)); + } } //! Pops the last element from the vector and returns it. diff --git a/src/asmjit/x86/x86assembler.cpp b/src/asmjit/x86/x86assembler.cpp index dc24abc..25112cf 100644 --- a/src/asmjit/x86/x86assembler.cpp +++ b/src/asmjit/x86/x86assembler.cpp @@ -560,7 +560,7 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(InstId instId, const Operand_& o0, con const Operand_* rmRel; // Memory operand or operand that holds Label|Imm. uint32_t rmInfo; // Memory operand's info based on x86MemInfo. - uint32_t rbReg; // Memory base or modRM register. + uint32_t rbReg = 0; // Memory base or modRM register. uint32_t rxReg; // Memory index register. uint32_t opReg; // ModR/M opcode or register id. @@ -653,7 +653,6 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(InstId instId, const Operand_& o0, con // This sequence seems to be the fastest. opcode = InstDB::_mainOpcodeTable[instInfo->_mainOpcodeIndex]; opReg = opcode.extractModO(); - rbReg = 0; opcode |= instInfo->_mainOpcodeValue; // Encoding Scope diff --git a/src/asmjit/x86/x86formatter.cpp b/src/asmjit/x86/x86formatter.cpp index e8e8c43..1d0b3fb 100644 --- a/src/asmjit/x86/x86formatter.cpp +++ b/src/asmjit/x86/x86formatter.cpp @@ -514,8 +514,8 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( // ===================================================== static constexpr char kImmCharStart = '{'; -static constexpr char kImmCharEnd = '}'; -static constexpr char kImmCharOr = '|'; +static constexpr char kImmCharEnd = '}'; +static constexpr char kImmCharOr = '|'; struct ImmBits { enum Mode : uint32_t { @@ -539,8 +539,7 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmShuf(String& sb, uint3 ASMJIT_PROPAGATE(sb.appendUInt(index)); } - if (kImmCharEnd) - ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); + ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); return kErrorOk; } @@ -576,7 +575,7 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmBits(String& sb, uint3 ASMJIT_PROPAGATE(sb.append(str)); } - if (n && kImmCharEnd) + if (n) ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); return kErrorOk; @@ -592,10 +591,7 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmText(String& sb, uint3 ASMJIT_PROPAGATE(sb.append(Support::findPackedString(text, value))); } - if (kImmCharEnd) - ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); - - return kErrorOk; + return sb.append(kImmCharEnd); } ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( diff --git a/src/asmjit/x86/x86instapi.cpp b/src/asmjit/x86/x86instapi.cpp index 1c015dc..58ff1ad 100644 --- a/src/asmjit/x86/x86instapi.cpp +++ b/src/asmjit/x86/x86instapi.cpp @@ -1711,18 +1711,6 @@ Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand // ========================= #if defined(ASMJIT_TEST) -template -static Error queryRWInfoInline(InstRWInfo* out, Arch arch, BaseInst inst, Args&&... args) { - Operand_ opArray[] = { std::forward(args)... }; - return InstInternal::queryRWInfo(arch, inst, opArray, sizeof...(args), out); -} - -template -static Error queryFeaturesInline(CpuFeatures* out, Arch arch, BaseInst inst, Args&&... args) { - Operand_ opArray[] = { std::forward(args)... }; - return InstInternal::queryFeatures(arch, inst, opArray, sizeof...(args), out); -} - #ifndef ASMJIT_NO_TEXT UNIT(x86_inst_api_text) { // All known instructions should be matched. @@ -1741,6 +1729,13 @@ UNIT(x86_inst_api_text) { } #endif // !ASMJIT_NO_TEXT +#ifndef ASMJIT_NO_INTROSPECTION +template +static Error queryFeaturesInline(CpuFeatures* out, Arch arch, BaseInst inst, Args&&... args) { + Operand_ opArray[] = { std::forward(args)... }; + return InstInternal::queryFeatures(arch, inst, opArray, sizeof...(args), out); +} + UNIT(x86_inst_api_cpu_features) { INFO("Verifying whether SSE2+ features are reported correctly for legacy instructions"); { @@ -1815,6 +1810,14 @@ UNIT(x86_inst_api_cpu_features) { EXPECT_TRUE(f.x86().hasAVX512_F()); } } +#endif // !ASMJIT_NO_INTROSPECTION + +#ifndef ASMJIT_NO_INTROSPECTION +template +static Error queryRWInfoInline(InstRWInfo* out, Arch arch, BaseInst inst, Args&&... args) { + Operand_ opArray[] = { std::forward(args)... }; + return InstInternal::queryRWInfo(arch, inst, opArray, sizeof...(args), out); +} UNIT(x86_inst_api_rm_features) { INFO("Verifying whether RM/feature is reported correctly for PEXTRW instruction"); @@ -1869,7 +1872,9 @@ UNIT(x86_inst_api_rm_features) { EXPECT_EQ(rwi.rmFeature(), 0u); } } -#endif +#endif // !ASMJIT_NO_INTROSPECTION + +#endif // ASMJIT_TEST ASMJIT_END_SUB_NAMESPACE diff --git a/src/asmjit/x86/x86rapass.cpp b/src/asmjit/x86/x86rapass.cpp index 98d4f75..88a8b39 100644 --- a/src/asmjit/x86/x86rapass.cpp +++ b/src/asmjit/x86/x86rapass.cpp @@ -823,7 +823,7 @@ Error RACFGBuilder::moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& a stackPtr.setSize(4); imm[0] = imm_; - uint32_t nMovs = 0; + uint32_t movCount = 0; // One stack entry has the same size as the native register size. That means that if we want to move a 32-bit // integer on the stack in 64-bit mode, we need to extend it to a 64-bit integer first. In 32-bit mode, pushing @@ -839,7 +839,7 @@ Error RACFGBuilder::moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& a case TypeId::kFloat32: MovU32: imm[0].zeroExtend32Bits(); - nMovs = 1; + movCount = 1; break; case TypeId::kInt64: @@ -849,20 +849,20 @@ MovU32: case TypeId::kMmx64: if (_is64Bit && imm[0].isInt32()) { stackPtr.setSize(8); - nMovs = 1; + movCount = 1; break; } imm[1].setValue(imm[0].uint32Hi()); imm[0].zeroExtend32Bits(); - nMovs = 2; + movCount = 2; break; default: return DebugUtils::errored(kErrorInvalidAssignment); } - for (uint32_t i = 0; i < nMovs; i++) { + for (uint32_t i = 0; i < movCount; i++) { ASMJIT_PROPAGATE(cc()->mov(stackPtr, imm[i])); stackPtr.addOffsetLo32(int32_t(stackPtr.size())); } diff --git a/test/asmjit_test_compiler_x86.cpp b/test/asmjit_test_compiler_x86.cpp index 0854f38..23aa37b 100644 --- a/test/asmjit_test_compiler_x86.cpp +++ b/test/asmjit_test_compiler_x86.cpp @@ -971,8 +971,8 @@ public: typedef void (*Func)(int*, int*); Func func = ptr_as_func(_func); - int resultX; - int resultY; + int resultX = 0; + int resultY = 0; int expectX = 36; int expectY = -36; @@ -1026,8 +1026,8 @@ public: Func func = ptr_as_func(_func); uint32_t i; - uint32_t resultBuf[32]; - uint32_t expectBuf[32]; + uint32_t resultBuf[32] {}; + uint32_t expectBuf[32] {}; for (i = 0; i < ASMJIT_ARRAY_SIZE(resultBuf); i++) expectBuf[i] = i * 32; @@ -1085,8 +1085,8 @@ public: int v0 = 4; int v1 = 4; - int resultHi; - int resultLo; + int resultHi = 0; + int resultLo = 0; int expectHi = 0; int expectLo = v0 * v1; @@ -1227,7 +1227,7 @@ public: typedef void (*Func)(int, int, char*); Func func = ptr_as_func(_func); - char resultBuf[4]; + char resultBuf[4] {}; char expectBuf[4] = { 1, 0, 0, 1 }; func(0, 0, &resultBuf[0]); // We are expecting 1 (0 == 0). @@ -1280,7 +1280,7 @@ public: int v0 = 0x000000FF; - int resultRet; + int resultRet = 0; int expectRet = 0x0000FF00; func(&resultRet, v0, 16, 8); @@ -1347,10 +1347,9 @@ public: uint32_t i; uint32_t buf[kCount]; - uint32_t resultRet; - uint32_t expectRet; + uint32_t resultRet = 0; + uint32_t expectRet = 0; - expectRet = 0; for (i = 0; i < kCount; i++) { buf[i] = 1; } @@ -1700,7 +1699,7 @@ public: x86::Gp x = cc.newInt8("x"); x86::Gp y = cc.newInt32("y"); - FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); + FuncNode* funcNode = cc.addFunc(FuncSignatureT(CallConvId::kHost)); funcNode->setArg(0, x); cc.movsx(y, x); @@ -1710,10 +1709,10 @@ public: } virtual bool run(void* _func, String& result, String& expect) { - typedef int (*Func)(char); + typedef int (*Func)(int8_t); Func func = ptr_as_func(_func); - int resultRet = func(-13); + int resultRet = func(int8_t(-13)); int expectRet = -13; result.assignFormat("ret=%d", resultRet); @@ -1853,7 +1852,7 @@ public: typedef void (*Func)(float, float, float, float, float, float, float, float*); Func func = ptr_as_func(_func); - float resultRet; + float resultRet = 0; float expectRet = 1.0f + 2.0f + 3.0f + 4.0f + 5.0f + 6.0f + 7.0f; func(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, &resultRet); @@ -1904,7 +1903,7 @@ public: typedef void (*Func)(double, double, double, double, double, double, double, double*); Func func = ptr_as_func(_func); - double resultRet; + double resultRet = 0; double expectRet = 1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0; func(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, &resultRet); @@ -1954,7 +1953,7 @@ public: uint8_t aData[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; uint8_t bData[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; - uint8_t rData[16]; + uint8_t rData[16] {}; uint8_t eData[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 }; __m128i aVec = _mm_loadu_si128(reinterpret_cast(aData)); @@ -2714,7 +2713,7 @@ public: uint8_t aData[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; uint8_t bData[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; - uint8_t rData[16]; + uint8_t rData[16] {}; uint8_t eData[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 }; func(rData, aData, bData); @@ -2823,7 +2822,7 @@ public: int16_t c[8] = { 1, 3, 9, 7, 5, 4, 2, 1 }; int16_t d[8] = { 2, 0,-6,-4,-2,-1, 1, 2 }; - int16_t o[8]; + int16_t o[8] {}; int oExp = 7 * 3; func(a, b, c, d, o); @@ -4066,8 +4065,8 @@ public: static const uint32_t aData[8] = { 1, 2, 3, 4, 5, 6, 7, 8 }; static const uint32_t bData[8] = { 6, 3, 5, 9, 1, 8, 7, 2 }; - uint32_t resultData[8]; - uint32_t expectData[8]; + uint32_t resultData[8] {}; + uint32_t expectData[8] {}; for (i = 0; i < 8; i++) expectData[i] = aData[i] * 8 + bData[i] + 1; diff --git a/test/asmjit_test_emitters.cpp b/test/asmjit_test_emitters.cpp index 7436bf5..c5ac0b2 100644 --- a/test/asmjit_test_emitters.cpp +++ b/test/asmjit_test_emitters.cpp @@ -98,10 +98,6 @@ static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept { Error err = kErrorOk; switch (emitterType) { - case EmitterType::kNone: { - break; - } - case EmitterType::kAssembler: { printf("Using x86::Assembler:\n"); x86::Assembler a(&code); @@ -138,6 +134,11 @@ static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept { break; } #endif + + default: { + printf("** FAILURE: No emitter to use **\n"); + return 1; + } } // Add the code generated to the runtime. @@ -150,9 +151,9 @@ static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept { } // Execute the generated function. - int inA[4] = { 4, 3, 2, 1 }; - int inB[4] = { 1, 5, 2, 8 }; - int out[4]; + static const int inA[4] = { 4, 3, 2, 1 }; + static const int inB[4] = { 1, 5, 2, 8 }; + int out[4] {}; fn(out, inA, inB); // Should print {5 8 4 9}. diff --git a/test/asmjit_test_instinfo.cpp b/test/asmjit_test_instinfo.cpp index 3d51edc..466d8a5 100644 --- a/test/asmjit_test_instinfo.cpp +++ b/test/asmjit_test_instinfo.cpp @@ -13,6 +13,9 @@ using namespace asmjit; +namespace { + +#if !defined(ASMJIT_NO_X86) static char accessLetter(bool r, bool w) noexcept { return r && w ? 'X' : r ? 'R' : w ? 'W' : '_'; } @@ -140,6 +143,7 @@ static void printInfoExtra(Arch arch, InstId instId, InstOptions options, const Operand_ opArray[] = { std::forward(args)... }; printInfo(arch, inst, opArray, sizeof...(args)); } +#endif // !ASMJIT_NO_X86 static void testX86Arch() { #if !defined(ASMJIT_NO_X86) @@ -165,9 +169,11 @@ static void testX86Arch() { printInfoExtra(arch, Inst::kIdVaddpd, InstOptions::kNone, k1, zmm0, zmm1, zmm2); printInfoExtra(arch, Inst::kIdVaddpd, InstOptions::kX86_ZMask, k1, zmm0, zmm1, zmm2); -#endif +#endif // !ASMJIT_NO_X86 } +} // {anonymous} + int main() { printf("AsmJit Instruction Info Test-Suite v%u.%u.%u\n", unsigned((ASMJIT_LIBRARY_VERSION >> 16) ), diff --git a/test/asmjit_test_unit.cpp b/test/asmjit_test_unit.cpp index 5658ebc..86d1f1a 100644 --- a/test/asmjit_test_unit.cpp +++ b/test/asmjit_test_unit.cpp @@ -109,7 +109,8 @@ static void dumpSizeOf(void) noexcept { DUMP_TYPE(BaseBuilder); DUMP_TYPE(BaseNode); DUMP_TYPE(InstNode); - DUMP_TYPE(InstExNode); + DUMP_TYPE(InstNodeWithOperands); + DUMP_TYPE(InstNodeWithOperands); DUMP_TYPE(AlignNode); DUMP_TYPE(LabelNode); DUMP_TYPE(EmbedDataNode); diff --git a/test/asmjitutils.h b/test/asmjitutils.h index 525227e..8fede0f 100644 --- a/test/asmjitutils.h +++ b/test/asmjitutils.h @@ -8,8 +8,10 @@ #include +namespace { + ASMJIT_MAYBE_UNUSED -static const char* asmjitArchAsString(asmjit::Arch arch) noexcept { +const char* asmjitArchAsString(asmjit::Arch arch) noexcept { switch (arch) { case asmjit::Arch::kX86 : return "X86"; case asmjit::Arch::kX64 : return "X64"; @@ -37,7 +39,7 @@ static const char* asmjitArchAsString(asmjit::Arch arch) noexcept { } ASMJIT_MAYBE_UNUSED -static void printIndented(const char* str, size_t indent) noexcept { +void printIndented(const char* str, size_t indent) noexcept { const char* start = str; while (*str) { if (*str == '\n') { @@ -53,4 +55,6 @@ static void printIndented(const char* str, size_t indent) noexcept { printf("%*s%.*s\n", int(indent), "", int(size), start); } +} // {anonymous} + #endif // ASMJITUTILS_H_INCLUDED diff --git a/tools/configure-sanitizers.sh b/tools/configure-sanitizers.sh index a9f6496..d35b9a4 100755 --- a/tools/configure-sanitizers.sh +++ b/tools/configure-sanitizers.sh @@ -11,3 +11,7 @@ echo "" echo "== [Configuring Build - Release_UBSAN] ==" eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Release_UBSAN" ${BUILD_OPTIONS} -DCMAKE_BUILD_TYPE=Release -DASMJIT_SANITIZE=undefined echo "" + +echo "== [Configuring Build - Release_MSAN] ==" +eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Release_MSAN" ${BUILD_OPTIONS} -DCMAKE_BUILD_TYPE=Release -DASMJIT_SANITIZE=memory +echo ""