mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 04:24:37 +03:00
[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<N>. It works the same way as before, just the class hierarchy changed a little.
This commit is contained in:
3
.github/workflows/build-config.json
vendored
3
.github/workflows/build-config.json
vendored
@@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"diagnostics": {
|
"diagnostics": {
|
||||||
"asan": { "definitions": ["ASMJIT_SANITIZE=address"] },
|
"asan": { "definitions": ["ASMJIT_SANITIZE=address"] },
|
||||||
"ubsan": { "definitions": ["ASMJIT_SANITIZE=undefined"] }
|
"ubsan": { "definitions": ["ASMJIT_SANITIZE=undefined"] },
|
||||||
|
"msan": { "definitions": ["ASMJIT_SANITIZE=memory"] }
|
||||||
},
|
},
|
||||||
|
|
||||||
"valgrind_arguments": [
|
"valgrind_arguments": [
|
||||||
|
|||||||
191
.github/workflows/build.yml
vendored
191
.github/workflows/build.yml
vendored
@@ -31,90 +31,107 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- { title: "linux-lib" , os: "ubuntu-latest" , cc: "clang" , 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", build_type: "Debug" , problem_matcher: "cpp" }
|
- { title: "macos-lib" , os: "macos-latest" , cc: "clang" , arch: "x64", conf: "Debug" }
|
||||||
- { title: "windows-lib" , os: "windows-latest", cc: "vs2022" , arch: "x64", build_type: "Debug" , problem_matcher: "cpp" }
|
- { 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-analyze" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Debug" , diagnostics: "analyze-build" }
|
||||||
- { title: "diag-ubsan" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", diagnostics: "undefined", defs: "ASMJIT_TEST=1" }
|
- { title: "diag-asan" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", diagnostics: "asan", 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-msan" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "Release", diagnostics: "msan", defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "diag-scan-build" , os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Debug" , diagnostics: "scan-build" }
|
- { 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-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" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_INTRINSICS=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" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_LOGGING=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" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_LOGGING=1,ASMJIT_NO_TEXT=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" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_BUILDER=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" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_COMPILER=1" }
|
- { title: "no-compiler" , os: "ubuntu-latest" , cc: "clang-17", arch: "x64", conf: "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-17", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_COMPILER=1,ASMJIT_NO_INTROSPECTION=1" }
|
||||||
- { title: "no-introspection", os: "ubuntu-latest" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=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" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_VALIDATION=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" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_X86=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" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1,ASMJIT_NO_AARCH64=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", conf: "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: "x86", conf: "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", conf: "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-7" , arch: "x64", conf: "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", conf: "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: "x86", conf: "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", conf: "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-20.04" , cc: "gcc-8" , arch: "x64", conf: "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", conf: "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: "x86", conf: "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", conf: "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-9" , arch: "x64", conf: "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", conf: "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: "x86", conf: "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", conf: "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-10" , arch: "x64", conf: "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", conf: "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: "x86", conf: "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", conf: "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-11" , arch: "x64", conf: "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", conf: "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: "x86", conf: "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", conf: "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-22.04" , cc: "gcc-12" , arch: "x64", conf: "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-22.04" , cc: "gcc-13" , arch: "x86", conf: "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-22.04" , cc: "gcc-13" , arch: "x86", conf: "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-22.04" , cc: "gcc-13" , arch: "x64", conf: "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: "gcc-13" , arch: "x64", conf: "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-20.04" , cc: "clang-10", arch: "x86", conf: "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-20.04" , cc: "clang-10", arch: "x86", conf: "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-20.04" , cc: "clang-10", arch: "x64", conf: "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-20.04" , cc: "clang-10", arch: "x64", conf: "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-11", arch: "x86", conf: "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-11", arch: "x86", conf: "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-11", arch: "x64", conf: "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-11", arch: "x64", conf: "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-12", arch: "x86", conf: "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-12", arch: "x86", conf: "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-12", arch: "x64", conf: "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-12", arch: "x64", conf: "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-13", arch: "x86", conf: "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-13", arch: "x86", conf: "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-13", arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-13", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "macos" , os: "macos-12" , cc: "gcc-11" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "macos" , os: "macos-12" , cc: "gcc-11" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "macos" , os: "macos-12" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "macos" , os: "macos-12" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-14", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-15", arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-15", arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-15", arch: "x64", conf: "Debug" , defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "windows" , os: "windows-2019" , cc: "vs2019" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-15", arch: "x64", conf: "Release", defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-16", arch: "x86", conf: "Debug" , defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-16", arch: "x86", conf: "Release", defs: "ASMJIT_TEST=1" }
|
||||||
- { title: "windows" , os: "windows-2022" , cc: "vs2022" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=1" }
|
- { title: "linux" , os: "ubuntu-22.04" , cc: "clang-16", arch: "x64", conf: "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-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: "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", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
- { 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", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
- { 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" , build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
- { 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}}"
|
runs-on: "${{matrix.host || matrix.os}}"
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -138,11 +155,13 @@ jobs:
|
|||||||
if: ${{!matrix.host}}
|
if: ${{!matrix.host}}
|
||||||
run: python build-actions/action.py
|
run: python build-actions/action.py
|
||||||
--step=all
|
--step=all
|
||||||
--compiler=${{matrix.cc}}
|
|
||||||
--architecture=${{matrix.arch}}
|
|
||||||
--source-dir=source
|
--source-dir=source
|
||||||
--config=source/.github/workflows/build-config.json
|
--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}}
|
--build-defs=${{matrix.defs}}
|
||||||
|
|
||||||
- name: "Build & Test in VM"
|
- name: "Build & Test in VM"
|
||||||
@@ -165,9 +184,11 @@ jobs:
|
|||||||
sh ./build-actions/prepare-environment.sh
|
sh ./build-actions/prepare-environment.sh
|
||||||
python3 build-actions/action.py \
|
python3 build-actions/action.py \
|
||||||
--step=all \
|
--step=all \
|
||||||
--compiler=${{matrix.cc}} \
|
|
||||||
--architecture=${{matrix.arch}} \
|
|
||||||
--source-dir=source \
|
--source-dir=source \
|
||||||
--config=source/.github/workflows/build-config.json \
|
--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}}
|
--build-defs=${{matrix.defs}}
|
||||||
|
|||||||
@@ -4114,7 +4114,6 @@ Case_BaseLdurStur:
|
|||||||
|
|
||||||
if (inverted) {
|
if (inverted) {
|
||||||
imm8 = ~imm8 & 0xFFu;
|
imm8 = ~imm8 & 0xFFu;
|
||||||
inverted = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmode = B(3) | B(2) | B(1);
|
cmode = B(3) | B(2) | B(1);
|
||||||
@@ -4147,7 +4146,6 @@ Case_BaseLdurStur:
|
|||||||
case 3:
|
case 3:
|
||||||
if (inverted) {
|
if (inverted) {
|
||||||
imm8 = ~imm8 & 0xFFu;
|
imm8 = ~imm8 & 0xFFu;
|
||||||
inverted = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
op = 1;
|
op = 1;
|
||||||
|
|||||||
@@ -45,20 +45,27 @@ public:
|
|||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename RegT, typename Type>
|
||||||
|
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<RegT>(type);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
template<typename RegT, typename Type, typename... Args>
|
template<typename RegT, typename Type, typename... Args>
|
||||||
ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type, const char* s, Args&&... args) {
|
ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type, const char* s, Args&&... args) {
|
||||||
#ifndef ASMJIT_NO_LOGGING
|
#ifndef ASMJIT_NO_LOGGING
|
||||||
RegT reg(Globals::NoInit);
|
RegT reg(Globals::NoInit);
|
||||||
if (sizeof...(Args) == 0)
|
_newRegFmt(®, type, s, std::forward<Args>(args)...);
|
||||||
_newReg(®, type, s);
|
|
||||||
else
|
|
||||||
_newRegFmt(®, type, s, std::forward<Args>(args)...);
|
|
||||||
return reg;
|
return reg;
|
||||||
#else
|
#else
|
||||||
DebugUtils::unused(s, std::forward<Args>(args)...);
|
DebugUtils::unused(s, std::forward<Args>(args)...);
|
||||||
RegT reg(Globals::NoInit);
|
return _newRegInternal<RegT>(type);
|
||||||
_newReg(®, type, nullptr);
|
|
||||||
return reg;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
//! \endcond
|
//! \endcond
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ Error EmitHelper::emitArgMove(
|
|||||||
|
|
||||||
if (TypeUtils::isInt(dstTypeId)) {
|
if (TypeUtils::isInt(dstTypeId)) {
|
||||||
if (TypeUtils::isInt(srcTypeId)) {
|
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)});
|
dst.setSignature(OperandSignature{x ? uint32_t(GpX::kSignature) : uint32_t(GpW::kSignature)});
|
||||||
_emitter->setInlineComment(comment);
|
_emitter->setInlineComment(comment);
|
||||||
@@ -186,7 +186,7 @@ Error EmitHelper::emitArgMove(
|
|||||||
case TypeId::kInt16: instId = Inst::kIdLdrsh; break;
|
case TypeId::kInt16: instId = Inst::kIdLdrsh; break;
|
||||||
case TypeId::kUInt16: instId = Inst::kIdLdrh; break;
|
case TypeId::kUInt16: instId = Inst::kIdLdrh; break;
|
||||||
case TypeId::kInt32: instId = x ? Inst::kIdLdrsw : Inst::kIdLdr; 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::kInt64: instId = Inst::kIdLdr; break;
|
||||||
case TypeId::kUInt64: instId = Inst::kIdLdr; break;
|
case TypeId::kUInt64: instId = Inst::kIdLdr; break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -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 {
|
ASMJIT_FAVOR_SIZE Error FormatterInternal::formatShiftOp(String& sb, ShiftOp shiftOp) noexcept {
|
||||||
const char* str = "<Unknown>";
|
const char* str = nullptr;
|
||||||
switch (shiftOp) {
|
switch (shiftOp) {
|
||||||
case ShiftOp::kLSL: str = "lsl"; break;
|
case ShiftOp::kLSL: str = "lsl"; break;
|
||||||
case ShiftOp::kLSR: str = "lsr"; 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::kSXTH: str = "sxth"; break;
|
||||||
case ShiftOp::kSXTW: str = "sxtw"; break;
|
case ShiftOp::kSXTW: str = "sxtw"; break;
|
||||||
case ShiftOp::kSXTX: str = "sxtx"; break;
|
case ShiftOp::kSXTX: str = "sxtx"; break;
|
||||||
|
default: str = "<Unknown>"; break;
|
||||||
}
|
}
|
||||||
return sb.append(str);
|
return sb.append(str);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
#define ASMJIT_LIBRARY_MAKE_VERSION(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
|
#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.
|
//! 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
|
//! \def ASMJIT_ABI_NAMESPACE
|
||||||
//!
|
//!
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
//! AsmJit default, which makes it possible to use multiple AsmJit libraries within a single project, totally
|
//! 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.
|
//! controlled by users. This is useful especially in cases in which some of such library comes from third party.
|
||||||
#if !defined(ASMJIT_ABI_NAMESPACE)
|
#if !defined(ASMJIT_ABI_NAMESPACE)
|
||||||
#define ASMJIT_ABI_NAMESPACE _abi_1_11
|
#define ASMJIT_ABI_NAMESPACE _abi_1_12
|
||||||
#endif // !ASMJIT_ABI_NAMESPACE
|
#endif // !ASMJIT_ABI_NAMESPACE
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
@@ -221,45 +221,11 @@ namespace asmjit {
|
|||||||
// C++ Compiler and Features Detection
|
// C++ Compiler and Features Detection
|
||||||
// ===================================
|
// ===================================
|
||||||
|
|
||||||
#define ASMJIT_CXX_GNU 0
|
#if defined(__GNUC__) && defined(__has_attribute)
|
||||||
#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)
|
|
||||||
#define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (__has_attribute(NAME))
|
#define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (__has_attribute(NAME))
|
||||||
#else
|
#else
|
||||||
#define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (!(!(CHECK)))
|
#define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (!(!(CHECK)))
|
||||||
#endif
|
#endif // !ASMJIT_CXX_HAS_ATTRIBUTE
|
||||||
|
|
||||||
// API Decorators & C++ Extensions
|
// 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 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
|
//! 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).
|
//! 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
|
#define ASMJIT_VIRTAPI ASMJIT_API
|
||||||
#else
|
#else
|
||||||
#define ASMJIT_VIRTAPI
|
#define ASMJIT_VIRTAPI
|
||||||
@@ -477,66 +443,60 @@ namespace asmjit {
|
|||||||
|
|
||||||
#if ASMJIT_CXX_HAS_ATTRIBUTE(no_sanitize, 0)
|
#if ASMJIT_CXX_HAS_ATTRIBUTE(no_sanitize, 0)
|
||||||
#define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize__("undefined")))
|
#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__))
|
#define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize_undefined__))
|
||||||
#else
|
#else
|
||||||
#define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF
|
#define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Begin-Namespace & End-Namespace Macros
|
// Diagnostic Macros
|
||||||
// ======================================
|
// ======================================
|
||||||
|
|
||||||
#if defined _DOXYGEN
|
#if !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(_DOXYGEN)
|
||||||
#define ASMJIT_BEGIN_NAMESPACE namespace asmjit {
|
#if defined(__GNUC__) && __GNUC__ == 4
|
||||||
#define ASMJIT_END_NAMESPACE }
|
// There is a bug in GCC 4.X that has been fixed in GCC 5+, so just silence the warning.
|
||||||
#elif defined(__clang__)
|
#define ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \
|
||||||
#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 { \
|
|
||||||
_Pragma("GCC diagnostic push") \
|
_Pragma("GCC diagnostic push") \
|
||||||
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
|
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
|
||||||
#define ASMJIT_END_NAMESPACE \
|
#define ASMJIT_END_DIAGNOSTIC_SCOPE \
|
||||||
_Pragma("GCC diagnostic pop") \
|
_Pragma("GCC diagnostic pop")
|
||||||
}}
|
#elif defined(_MSC_VER)
|
||||||
#elif defined(__GNUC__) && __GNUC__ >= 8
|
#define ASMJIT_BEGIN_DIAGNOSTIC_SCOPE \
|
||||||
#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 { \
|
|
||||||
__pragma(warning(push)) \
|
__pragma(warning(push)) \
|
||||||
__pragma(warning(disable: 4127)) /* conditional expression is const */ \
|
__pragma(warning(disable: 4127)) /* conditional expression is const */ \
|
||||||
__pragma(warning(disable: 4201)) /* nameless struct/union */
|
__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 \
|
#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
|
#endif
|
||||||
|
|
||||||
#if !defined(ASMJIT_BEGIN_NAMESPACE) && !defined(ASMJIT_END_NAMESPACE)
|
#define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) ASMJIT_BEGIN_NAMESPACE namespace NAMESPACE {
|
||||||
#define ASMJIT_BEGIN_NAMESPACE namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE {
|
#define ASMJIT_END_SUB_NAMESPACE } ASMJIT_END_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
|
|
||||||
|
|
||||||
// C++ Utilities
|
// C++ Utilities
|
||||||
// =============
|
// =============
|
||||||
@@ -612,10 +572,4 @@ namespace asmjit {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Cleanup Api-Config Specific Macros
|
|
||||||
// ==================================
|
|
||||||
|
|
||||||
#undef ASMJIT_CXX_GNU
|
|
||||||
#undef ASMJIT_CXX_MAKE_VER
|
|
||||||
|
|
||||||
#endif // ASMJIT_CORE_API_CONFIG_H_INCLUDED
|
#endif // ASMJIT_CORE_API_CONFIG_H_INCLUDED
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ enum class NodeType : uint8_t {
|
|||||||
|
|
||||||
// [BaseBuilder]
|
// [BaseBuilder]
|
||||||
|
|
||||||
//! Node is \ref InstNode or \ref InstExNode.
|
//! Node is \ref InstNode.
|
||||||
kInst = 1,
|
kInst = 1,
|
||||||
//! Node is \ref SectionNode.
|
//! Node is \ref SectionNode.
|
||||||
kSection = 2,
|
kSection = 2,
|
||||||
@@ -748,12 +748,15 @@ public:
|
|||||||
//! \name Constants
|
//! \name Constants
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
enum : uint32_t {
|
//! The number of embedded operands for a default \ref InstNode instance that are always allocated as a part of
|
||||||
//! Count of embedded operands per `InstNode` that are always allocated as a part of the instruction. Minimum
|
//! the instruction itself. Minimum embedded operands is 4, but in 32-bit more pointers are smaller and we can
|
||||||
//! embedded operands is 4, but in 32-bit more pointers are smaller and we can embed 5. The rest (up to 6 operands)
|
//! embed 5. The rest (up to 6 operands) is considered extended.
|
||||||
//! is always stored in `InstExNode`.
|
//!
|
||||||
kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_))
|
//! 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.
|
//! Base instruction data.
|
||||||
BaseInst _baseInst;
|
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); }
|
ASMJIT_INLINE_NODEBUG void setOpCount(uint32_t opCount) noexcept { _inst._opCount = uint8_t(opCount); }
|
||||||
|
|
||||||
//! Returns operands array.
|
//! Returns operands array.
|
||||||
ASMJIT_INLINE_NODEBUG Operand* operands() noexcept { return (Operand*)_opArray; }
|
ASMJIT_INLINE_NODEBUG Operand* operands() noexcept {
|
||||||
|
return reinterpret_cast<Operand*>(reinterpret_cast<uint8_t*>(this) + sizeof(InstNode));
|
||||||
|
}
|
||||||
|
|
||||||
//! Returns operands array (const).
|
//! 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<const Operand*>(reinterpret_cast<const uint8_t*>(this) + sizeof(InstNode));
|
||||||
|
}
|
||||||
|
|
||||||
//! Returns operand at the given `index`.
|
//! Returns operand at the given `index`.
|
||||||
inline Operand& op(uint32_t index) noexcept {
|
inline Operand& op(uint32_t index) noexcept {
|
||||||
ASMJIT_ASSERT(index < opCapacity());
|
ASMJIT_ASSERT(index < opCapacity());
|
||||||
return _opArray[index].as<Operand>();
|
|
||||||
|
Operand* ops = operands();
|
||||||
|
return ops[index].as<Operand>();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Returns operand at the given `index` (const).
|
//! Returns operand at the given `index` (const).
|
||||||
inline const Operand& op(uint32_t index) const noexcept {
|
inline const Operand& op(uint32_t index) const noexcept {
|
||||||
ASMJIT_ASSERT(index < opCapacity());
|
ASMJIT_ASSERT(index < opCapacity());
|
||||||
return _opArray[index].as<Operand>();
|
|
||||||
|
const Operand* ops = operands();
|
||||||
|
return ops[index].as<Operand>();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Sets operand at the given `index` to `op`.
|
//! Sets operand at the given `index` to `op`.
|
||||||
inline void setOp(uint32_t index, const Operand_& op) noexcept {
|
inline void setOp(uint32_t index, const Operand_& op) noexcept {
|
||||||
ASMJIT_ASSERT(index < opCapacity());
|
ASMJIT_ASSERT(index < opCapacity());
|
||||||
_opArray[index].copyFrom(op);
|
|
||||||
|
Operand* ops = operands();
|
||||||
|
ops[index].copyFrom(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Resets operand at the given `index` to none.
|
//! Resets operand at the given `index` to none.
|
||||||
inline void resetOp(uint32_t index) noexcept {
|
inline void resetOp(uint32_t index) noexcept {
|
||||||
ASMJIT_ASSERT(index < opCapacity());
|
ASMJIT_ASSERT(index < opCapacity());
|
||||||
_opArray[index].reset();
|
|
||||||
|
Operand* ops = operands();
|
||||||
|
ops[index].reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Resets operands at `[start, end)` range.
|
//! Resets operands at `[start, end)` range.
|
||||||
inline void resetOpRange(uint32_t start, uint32_t end) noexcept {
|
inline void resetOpRange(uint32_t start, uint32_t end) noexcept {
|
||||||
|
Operand* ops = operands();
|
||||||
for (uint32_t i = start; i < end; i++)
|
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 {
|
inline bool hasOpType(OperandType opType) const noexcept {
|
||||||
|
const Operand* ops = operands();
|
||||||
for (uint32_t i = 0, count = opCount(); i < count; i++)
|
for (uint32_t i = 0, count = opCount(); i < count; i++)
|
||||||
if (_opArray[i].opType() == opType)
|
if (ops[i].opType() == opType)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -905,9 +921,10 @@ public:
|
|||||||
inline uint32_t indexOfOpType(OperandType opType) const noexcept {
|
inline uint32_t indexOfOpType(OperandType opType) const noexcept {
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
uint32_t count = opCount();
|
uint32_t count = opCount();
|
||||||
|
const Operand* ops = operands();
|
||||||
|
|
||||||
while (i < count) {
|
while (i < count) {
|
||||||
if (_opArray[i].opType() == opType)
|
if (ops[i].opType() == opType)
|
||||||
break;
|
break;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -950,43 +967,31 @@ public:
|
|||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
//! \cond INTERNAL
|
//! \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;
|
return opCount <= kBaseOpCapacity ? kBaseOpCapacity : Globals::kMaxOpCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ASMJIT_INLINE_NODEBUG size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept {
|
static ASMJIT_INLINE_NODEBUG constexpr size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept {
|
||||||
size_t base = sizeof(InstNode) - kBaseOpCapacity * sizeof(Operand);
|
return sizeof(InstNode) + opCapacity * sizeof(Operand);
|
||||||
return base + opCapacity * sizeof(Operand);
|
|
||||||
}
|
}
|
||||||
//! \endcond
|
//! \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
|
//! \note This is used to make tools such as static analysis and compilers happy about the layout. There were two
|
||||||
//! the default capacity of `InstNode`.
|
//! instruction nodes in the past, having the second extend the operand array of the first, but that has caused
|
||||||
class InstExNode : public InstNode {
|
//! undefined behavior and made recent tools unhappy about that.
|
||||||
|
template<uint32_t kN>
|
||||||
|
class InstNodeWithOperands : public InstNode {
|
||||||
public:
|
public:
|
||||||
ASMJIT_NONCOPYABLE(InstExNode)
|
Operand_ _operands[kN];
|
||||||
|
|
||||||
//! \name Members
|
//! 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) {}
|
||||||
//! 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) {}
|
|
||||||
|
|
||||||
//! \}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Section node.
|
//! Section node.
|
||||||
@@ -1013,9 +1018,9 @@ public:
|
|||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
//! Creates a new `SectionNode` instance.
|
//! 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),
|
: BaseNode(cb, NodeType::kSection, NodeFlags::kHasNoEffect),
|
||||||
_id(secionId),
|
_id(sectionId),
|
||||||
_nextSection(nullptr) {}
|
_nextSection(nullptr) {}
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ public:
|
|||||||
//! \note This node should be only used to represent jump where the jump target cannot be deduced by examining
|
//! \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
|
//! 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.
|
//! used to perform indirect jumps that use jump table, e.g. to implement `switch{}` statement.
|
||||||
class JumpNode : public InstNode {
|
class JumpNode : public InstNodeWithOperands<InstNode::kBaseOpCapacity> {
|
||||||
public:
|
public:
|
||||||
ASMJIT_NONCOPYABLE(JumpNode)
|
ASMJIT_NONCOPYABLE(JumpNode)
|
||||||
|
|
||||||
@@ -340,7 +340,7 @@ public:
|
|||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
inline JumpNode(BaseCompiler* ASMJIT_NONNULL(cc), InstId instId, InstOptions options, uint32_t opCount, JumpAnnotation* annotation) noexcept
|
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) {
|
_annotation(annotation) {
|
||||||
setType(NodeType::kJump);
|
setType(NodeType::kJump);
|
||||||
}
|
}
|
||||||
@@ -531,7 +531,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! Function return, used by \ref BaseCompiler.
|
//! Function return, used by \ref BaseCompiler.
|
||||||
class FuncRetNode : public InstNode {
|
class FuncRetNode : public InstNodeWithOperands<InstNode::kBaseOpCapacity> {
|
||||||
public:
|
public:
|
||||||
ASMJIT_NONCOPYABLE(FuncRetNode)
|
ASMJIT_NONCOPYABLE(FuncRetNode)
|
||||||
|
|
||||||
@@ -539,7 +539,8 @@ public:
|
|||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
//! Creates a new `FuncRetNode` instance.
|
//! 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;
|
_any._nodeType = NodeType::kFuncRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,12 +548,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! Function invocation, used by \ref BaseCompiler.
|
//! Function invocation, used by \ref BaseCompiler.
|
||||||
class InvokeNode : public InstNode {
|
class InvokeNode : public InstNodeWithOperands<InstNode::kBaseOpCapacity> {
|
||||||
public:
|
public:
|
||||||
ASMJIT_NONCOPYABLE(InvokeNode)
|
ASMJIT_NONCOPYABLE(InvokeNode)
|
||||||
|
|
||||||
//! Operand pack provides multiple operands that can be associated with a single return value of function
|
//! 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.
|
//! registers, for example 64-bit value in 32-bit mode or passing / returning homogeneous data structures.
|
||||||
struct OperandPack {
|
struct OperandPack {
|
||||||
//! Operands.
|
//! Operands.
|
||||||
@@ -594,7 +595,7 @@ public:
|
|||||||
|
|
||||||
//! Creates a new `InvokeNode` instance.
|
//! Creates a new `InvokeNode` instance.
|
||||||
inline InvokeNode(BaseBuilder* ASMJIT_NONNULL(cb), InstId instId, InstOptions options) noexcept
|
inline InvokeNode(BaseBuilder* ASMJIT_NONNULL(cb), InstId instId, InstOptions options) noexcept
|
||||||
: InstNode(cb, instId, options, kBaseOpCapacity),
|
: InstNodeWithOperands(cb, instId, options, 0),
|
||||||
_funcDetail(),
|
_funcDetail(),
|
||||||
_args(nullptr) {
|
_args(nullptr) {
|
||||||
setType(NodeType::kInvoke);
|
setType(NodeType::kInvoke);
|
||||||
@@ -619,9 +620,9 @@ public:
|
|||||||
ASMJIT_INLINE_NODEBUG const FuncDetail& detail() const noexcept { return _funcDetail; }
|
ASMJIT_INLINE_NODEBUG const FuncDetail& detail() const noexcept { return _funcDetail; }
|
||||||
|
|
||||||
//! Returns the target operand.
|
//! Returns the target operand.
|
||||||
ASMJIT_INLINE_NODEBUG Operand& target() noexcept { return _opArray[0].as<Operand>(); }
|
ASMJIT_INLINE_NODEBUG Operand& target() noexcept { return op(0); }
|
||||||
//! \overload
|
//! \overload
|
||||||
ASMJIT_INLINE_NODEBUG const Operand& target() const noexcept { return _opArray[0].as<Operand>(); }
|
ASMJIT_INLINE_NODEBUG const Operand& target() const noexcept { return op(0); }
|
||||||
|
|
||||||
//! Returns the number of function return values.
|
//! Returns the number of function return values.
|
||||||
ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _funcDetail.hasRet(); }
|
ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _funcDetail.hasRet(); }
|
||||||
|
|||||||
@@ -876,59 +876,58 @@ public:
|
|||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
//! Architecture.
|
//! Architecture.
|
||||||
Arch _arch;
|
Arch _arch {};
|
||||||
//! Sub-architecture.
|
//! Sub-architecture.
|
||||||
SubArch _subArch;
|
SubArch _subArch {};
|
||||||
//! True if the CPU was detected, false if the detection failed or it's not available.
|
//! True if the CPU was detected, false if the detection failed or it's not available.
|
||||||
bool _wasDetected;
|
bool _wasDetected {};
|
||||||
//! Reserved for future use.
|
//! Reserved for future use.
|
||||||
uint8_t _reserved;
|
uint8_t _reserved {};
|
||||||
//! CPU family ID.
|
//! CPU family ID.
|
||||||
uint32_t _familyId;
|
uint32_t _familyId {};
|
||||||
//! CPU model ID.
|
//! CPU model ID.
|
||||||
uint32_t _modelId;
|
uint32_t _modelId {};
|
||||||
//! CPU brand ID.
|
//! CPU brand ID.
|
||||||
uint32_t _brandId;
|
uint32_t _brandId {};
|
||||||
//! CPU stepping.
|
//! CPU stepping.
|
||||||
uint32_t _stepping;
|
uint32_t _stepping {};
|
||||||
//! Processor type.
|
//! Processor type.
|
||||||
uint32_t _processorType;
|
uint32_t _processorType {};
|
||||||
//! Maximum number of addressable IDs for logical processors.
|
//! Maximum number of addressable IDs for logical processors.
|
||||||
uint32_t _maxLogicalProcessors;
|
uint32_t _maxLogicalProcessors {};
|
||||||
//! Cache line size (in bytes).
|
//! Cache line size (in bytes).
|
||||||
uint32_t _cacheLineSize;
|
uint32_t _cacheLineSize {};
|
||||||
//! Number of hardware threads.
|
//! Number of hardware threads.
|
||||||
uint32_t _hwThreadCount;
|
uint32_t _hwThreadCount {};
|
||||||
|
|
||||||
//! CPU vendor string.
|
//! CPU vendor string.
|
||||||
FixedString<16> _vendor;
|
FixedString<16> _vendor {};
|
||||||
//! CPU brand string.
|
//! CPU brand string.
|
||||||
FixedString<64> _brand;
|
FixedString<64> _brand {};
|
||||||
//! CPU features.
|
//! CPU features.
|
||||||
CpuFeatures _features;
|
CpuFeatures _features {};
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
//! \name Construction & Destruction
|
//! \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 CpuInfo(const CpuInfo& other) noexcept = default;
|
||||||
|
|
||||||
ASMJIT_INLINE_NODEBUG explicit CpuInfo(Globals::NoInit_) noexcept
|
ASMJIT_INLINE_NODEBUG explicit CpuInfo(Globals::NoInit_) noexcept
|
||||||
: _features(Globals::NoInit) {};
|
: _features(Globals::NoInit) {};
|
||||||
|
|
||||||
|
//! \}
|
||||||
|
|
||||||
|
//! \name CPU Information Detection
|
||||||
|
//! \{
|
||||||
|
|
||||||
//! Returns the host CPU information.
|
//! 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;
|
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
|
//! \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
|
//! \name Accessors
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
|
|||||||
@@ -194,6 +194,7 @@ ASMJIT_DEFINE_ENUM_FLAGS(DiagnosticOptions)
|
|||||||
class ASMJIT_VIRTAPI BaseEmitter {
|
class ASMJIT_VIRTAPI BaseEmitter {
|
||||||
public:
|
public:
|
||||||
ASMJIT_BASE_CLASS(BaseEmitter)
|
ASMJIT_BASE_CLASS(BaseEmitter)
|
||||||
|
ASMJIT_NONCOPYABLE(BaseEmitter)
|
||||||
|
|
||||||
//! \name Members
|
//! \name Members
|
||||||
//! \{
|
//! \{
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ Error formatTypeId(String& sb, TypeId typeId) noexcept {
|
|||||||
if (!TypeUtils::isValid(typeId))
|
if (!TypeUtils::isValid(typeId))
|
||||||
return sb.append("unknown");
|
return sb.append("unknown");
|
||||||
|
|
||||||
const char* typeName = "unknown";
|
const char* typeName = nullptr;
|
||||||
uint32_t typeSize = TypeUtils::sizeOf(typeId);
|
uint32_t typeSize = TypeUtils::sizeOf(typeId);
|
||||||
TypeId scalarType = TypeUtils::scalarOf(typeId);
|
TypeId scalarType = TypeUtils::scalarOf(typeId);
|
||||||
|
|
||||||
@@ -514,7 +514,7 @@ Error formatNode(
|
|||||||
ASMJIT_PROPAGATE(sb.append("[FuncRet]"));
|
ASMJIT_PROPAGATE(sb.append("[FuncRet]"));
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 2; i++) {
|
for (uint32_t i = 0; i < 2; i++) {
|
||||||
const Operand_& op = retNode->_opArray[i];
|
const Operand_& op = retNode->op(i);
|
||||||
if (!op.isNone()) {
|
if (!op.isNone()) {
|
||||||
ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", "));
|
ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", "));
|
||||||
ASMJIT_PROPAGATE(formatOperand(sb, formatOptions.flags(), builder, builder->arch(), op));
|
ASMJIT_PROPAGATE(formatOperand(sb, formatOptions.flags(), builder, builder->arch(), op));
|
||||||
|
|||||||
@@ -499,7 +499,8 @@ struct OpRWInfo {
|
|||||||
_consecutiveLeadCount = 0;
|
_consecutiveLeadCount = 0;
|
||||||
_resetReserved();
|
_resetReserved();
|
||||||
|
|
||||||
uint64_t mask = Support::lsbMask<uint64_t>(regSize);
|
uint64_t mask = Support::lsbMask<uint64_t>(Support::min<uint32_t>(regSize, 64));
|
||||||
|
|
||||||
_readByteMask = Support::test(opFlags, OpRWFlags::kRead) ? mask : uint64_t(0);
|
_readByteMask = Support::test(opFlags, OpRWFlags::kRead) ? mask : uint64_t(0);
|
||||||
_writeByteMask = Support::test(opFlags, OpRWFlags::kWrite) ? mask : uint64_t(0);
|
_writeByteMask = Support::test(opFlags, OpRWFlags::kWrite) ? mask : uint64_t(0);
|
||||||
_extendByteMask = 0;
|
_extendByteMask = 0;
|
||||||
|
|||||||
@@ -37,12 +37,13 @@ static constexpr uint32_t kJitAllocatorMaxBlockSize = 1024 * 1024 * 64;
|
|||||||
// ===========================
|
// ===========================
|
||||||
|
|
||||||
static inline uint32_t JitAllocator_defaultFillPattern() noexcept {
|
static inline uint32_t JitAllocator_defaultFillPattern() noexcept {
|
||||||
|
#if ASMJIT_ARCH_X86
|
||||||
// X86 and X86_64 - 4x 'int3' instruction.
|
// X86 and X86_64 - 4x 'int3' instruction.
|
||||||
if (ASMJIT_ARCH_X86)
|
return 0xCCCCCCCCu;
|
||||||
return 0xCCCCCCCCu;
|
#else
|
||||||
|
|
||||||
// Unknown...
|
// Unknown...
|
||||||
return 0u;
|
return 0u;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// JitAllocator - BitVectorRangeIterator
|
// JitAllocator - BitVectorRangeIterator
|
||||||
|
|||||||
@@ -331,25 +331,25 @@ struct OperandSignature {
|
|||||||
ASMJIT_INLINE_NODEBUG constexpr uint32_t bits() const noexcept { return _bits; }
|
ASMJIT_INLINE_NODEBUG constexpr uint32_t bits() const noexcept { return _bits; }
|
||||||
ASMJIT_INLINE_NODEBUG void setBits(uint32_t bits) noexcept { _bits = bits; }
|
ASMJIT_INLINE_NODEBUG void setBits(uint32_t bits) noexcept { _bits = bits; }
|
||||||
|
|
||||||
template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
|
template<uint32_t kFieldMask>
|
||||||
ASMJIT_INLINE_NODEBUG constexpr bool hasField() const noexcept {
|
ASMJIT_INLINE_NODEBUG constexpr bool hasField() const noexcept {
|
||||||
return (_bits & kFieldMask) != 0;
|
return (_bits & kFieldMask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
|
template<uint32_t kFieldMask>
|
||||||
ASMJIT_INLINE_NODEBUG constexpr bool hasField(uint32_t value) const noexcept {
|
ASMJIT_INLINE_NODEBUG constexpr bool hasField(uint32_t value) const noexcept {
|
||||||
return (_bits & kFieldMask) != value << kFieldShift;
|
return (_bits & kFieldMask) != value << Support::ConstCTZ<kFieldMask>::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
|
template<uint32_t kFieldMask>
|
||||||
ASMJIT_INLINE_NODEBUG constexpr uint32_t getField() const noexcept {
|
ASMJIT_INLINE_NODEBUG constexpr uint32_t getField() const noexcept {
|
||||||
return (_bits >> kFieldShift) & (kFieldMask >> kFieldShift);
|
return (_bits >> Support::ConstCTZ<kFieldMask>::value) & (kFieldMask >> Support::ConstCTZ<kFieldMask>::value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
|
template<uint32_t kFieldMask>
|
||||||
ASMJIT_INLINE_NODEBUG void setField(uint32_t value) noexcept {
|
ASMJIT_INLINE_NODEBUG void setField(uint32_t value) noexcept {
|
||||||
ASMJIT_ASSERT((value & ~(kFieldMask >> kFieldShift)) == 0);
|
ASMJIT_ASSERT(((value << Support::ConstCTZ<kFieldMask>::value) & ~kFieldMask) == 0);
|
||||||
_bits = (_bits & ~kFieldMask) | (value << kFieldShift);
|
_bits = (_bits & ~kFieldMask) | (value << Support::ConstCTZ<kFieldMask>::value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMJIT_INLINE_NODEBUG constexpr OperandSignature subset(uint32_t mask) const noexcept { return OperandSignature{_bits & mask}; }
|
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
|
//! \note This basically performs a binary comparison, if aby bit is
|
||||||
//! different the operands are not equal.
|
//! different the operands are not equal.
|
||||||
ASMJIT_INLINE_NODEBUG constexpr bool equals(const Operand_& other) const noexcept {
|
ASMJIT_INLINE_NODEBUG constexpr bool equals(const Operand_& other) const noexcept {
|
||||||
return (_signature == other._signature) &
|
return bool(unsigned(_signature == other._signature) &
|
||||||
(_baseId == other._baseId ) &
|
unsigned(_baseId == other._baseId ) &
|
||||||
(_data[0] == other._data[0] ) &
|
unsigned(_data[0] == other._data[0] ) &
|
||||||
(_data[1] == other._data[1] ) ;
|
unsigned(_data[1] == other._data[1] ));
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Tests whether the operand is a register matching the given register `type`.
|
//! 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.
|
//! 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
|
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).
|
//! Creates an uninitialized operand (dangerous).
|
||||||
ASMJIT_INLINE_NODEBUG explicit Operand(Globals::NoInit_) noexcept {}
|
ASMJIT_INLINE_NODEBUG explicit Operand(Globals::NoInit_) noexcept {}
|
||||||
|
|||||||
@@ -476,12 +476,18 @@ Error BaseRAPass::buildCFGDominators() noexcept {
|
|||||||
entryBlock->setIDom(entryBlock);
|
entryBlock->setIDom(entryBlock);
|
||||||
|
|
||||||
bool changed = true;
|
bool changed = true;
|
||||||
uint32_t nIters = 0;
|
|
||||||
|
#ifndef ASMJIT_NO_LOGGING
|
||||||
|
uint32_t numIters = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
while (changed) {
|
while (changed) {
|
||||||
nIters++;
|
|
||||||
changed = false;
|
changed = false;
|
||||||
|
|
||||||
|
#ifndef ASMJIT_NO_LOGGING
|
||||||
|
numIters++;
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t i = _pov.size();
|
uint32_t i = _pov.size();
|
||||||
while (i) {
|
while (i) {
|
||||||
RABlock* block = _pov[--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;
|
return kErrorOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,7 +804,6 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept {
|
|||||||
uint32_t numAllBlocks = blockCount();
|
uint32_t numAllBlocks = blockCount();
|
||||||
uint32_t numReachableBlocks = reachableBlockCount();
|
uint32_t numReachableBlocks = reachableBlockCount();
|
||||||
|
|
||||||
uint32_t numVisits = numReachableBlocks;
|
|
||||||
uint32_t numWorkRegs = workRegCount();
|
uint32_t numWorkRegs = workRegCount();
|
||||||
uint32_t numBitWords = ZoneBitVector::_wordsPerBits(numWorkRegs);
|
uint32_t numBitWords = ZoneBitVector::_wordsPerBits(numWorkRegs);
|
||||||
|
|
||||||
@@ -888,6 +893,10 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept {
|
|||||||
// Calculate IN/OUT of Each Block
|
// Calculate IN/OUT of Each Block
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
|
|
||||||
|
#ifndef ASMJIT_NO_LOGGING
|
||||||
|
uint32_t numVisits = numReachableBlocks;
|
||||||
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
ZoneStack<RABlock*> workList;
|
ZoneStack<RABlock*> workList;
|
||||||
ZoneBitVector workBits;
|
ZoneBitVector workBits;
|
||||||
@@ -918,7 +927,9 @@ ASMJIT_FAVOR_SPEED Error BaseRAPass::buildLiveness() noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifndef ASMJIT_NO_LOGGING
|
||||||
numVisits++;
|
numVisits++;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
workList.reset();
|
workList.reset();
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ static ASMJIT_INLINE_NODEBUG constexpr T lsbMask(const CountT& n) noexcept {
|
|||||||
: n ? T(shr(allOnes<T>(), bitSizeOf<T>() - size_t(n))) : T(0);
|
: n ? T(shr(allOnes<T>(), bitSizeOf<T>() - 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<typename T, typename CountT>
|
template<typename T, typename CountT>
|
||||||
static ASMJIT_INLINE_NODEBUG constexpr T msbMask(const CountT& n) noexcept {
|
static ASMJIT_INLINE_NODEBUG constexpr T msbMask(const CountT& n) noexcept {
|
||||||
typedef typename std::make_unsigned<T>::type U;
|
typedef typename std::make_unsigned<T>::type U;
|
||||||
@@ -321,12 +321,12 @@ struct BitScanCalc<T, 0> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr ASMJIT_INLINE_NODEBUG uint32_t clzFallback(const T& x) noexcept {
|
ASMJIT_INLINE_NODEBUG constexpr uint32_t clzFallback(const T& x) noexcept {
|
||||||
return BitScanCalc<T, bitSizeOf<T>() / 2u>::clz(BitScanData<T>{x, 1}).n;
|
return BitScanCalc<T, bitSizeOf<T>() / 2u>::clz(BitScanData<T>{x, 1}).n;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr ASMJIT_INLINE_NODEBUG uint32_t ctzFallback(const T& x) noexcept {
|
ASMJIT_INLINE_NODEBUG constexpr uint32_t ctzFallback(const T& x) noexcept {
|
||||||
return BitScanCalc<T, bitSizeOf<T>() / 2u>::ctz(BitScanData<T>{x, 1}).n;
|
return BitScanCalc<T, bitSizeOf<T>() / 2u>::ctz(BitScanData<T>{x, 1}).n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,31 +457,30 @@ namespace Internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ASMJIT_INLINE_NODEBUG uint32_t constPopcntImpl(uint64_t x) noexcept {
|
static ASMJIT_INLINE_NODEBUG uint32_t constPopcntImpl(uint64_t x) noexcept {
|
||||||
if (ASMJIT_ARCH_BITS >= 64) {
|
#if ASMJIT_ARCH_BITS >= 64
|
||||||
x = x - ((x >> 1) & 0x5555555555555555u);
|
x = x - ((x >> 1) & 0x5555555555555555u);
|
||||||
x = (x & 0x3333333333333333u) + ((x >> 2) & 0x3333333333333333u);
|
x = (x & 0x3333333333333333u) + ((x >> 2) & 0x3333333333333333u);
|
||||||
return uint32_t((((x + (x >> 4)) & 0x0F0F0F0F0F0F0F0Fu) * 0x0101010101010101u) >> 56);
|
return uint32_t((((x + (x >> 4)) & 0x0F0F0F0F0F0F0F0Fu) * 0x0101010101010101u) >> 56);
|
||||||
}
|
#else
|
||||||
else {
|
return constPopcntImpl(uint32_t(x >> 32)) +
|
||||||
return constPopcntImpl(uint32_t(x >> 32)) +
|
constPopcntImpl(uint32_t(x & 0xFFFFFFFFu));
|
||||||
constPopcntImpl(uint32_t(x & 0xFFFFFFFFu));
|
#endif
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ASMJIT_INLINE_NODEBUG uint32_t popcntImpl(uint32_t x) noexcept {
|
static ASMJIT_INLINE_NODEBUG uint32_t popcntImpl(uint32_t x) noexcept {
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
return uint32_t(__builtin_popcount(x));
|
return uint32_t(__builtin_popcount(x));
|
||||||
#else
|
#else
|
||||||
return constPopcntImpl(asUInt(x));
|
return constPopcntImpl(asUInt(x));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static ASMJIT_INLINE_NODEBUG uint32_t popcntImpl(uint64_t x) noexcept {
|
static ASMJIT_INLINE_NODEBUG uint32_t popcntImpl(uint64_t x) noexcept {
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
return uint32_t(__builtin_popcountll(x));
|
return uint32_t(__builtin_popcountll(x));
|
||||||
#else
|
#else
|
||||||
return constPopcntImpl(asUInt(x));
|
return constPopcntImpl(asUInt(x));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//! \endcond
|
//! \endcond
|
||||||
@@ -596,9 +595,9 @@ namespace Internal {
|
|||||||
template<typename T> inline T subOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return subOverflowFallback(x, y, of); }
|
template<typename T> inline T subOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return subOverflowFallback(x, y, of); }
|
||||||
template<typename T> inline T mulOverflowImpl(const T& x, const T& y, FastUInt8* of) noexcept { return mulOverflowFallback(x, y, of); }
|
template<typename T> 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(__GNUC__) && !defined(ASMJIT_NO_INTRINSICS)
|
||||||
#if defined(__clang__) || __GNUC__ >= 5
|
#if defined(__clang__) || __GNUC__ >= 5
|
||||||
#define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, RESULT_T, BUILTIN) \
|
#define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, RESULT_T, BUILTIN) \
|
||||||
template<> \
|
template<> \
|
||||||
inline T FUNC(const T& x, const T& y, FastUInt8* of) noexcept { \
|
inline T FUNC(const T& x, const T& y, FastUInt8* of) noexcept { \
|
||||||
RESULT_T result; \
|
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, uint32_t, unsigned int , __builtin_umul_overflow )
|
||||||
ASMJIT_ARITH_OVERFLOW_SPECIALIZE(mulOverflowImpl, int64_t , long long , __builtin_smulll_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)
|
ASMJIT_ARITH_OVERFLOW_SPECIALIZE(mulOverflowImpl, uint64_t, unsigned long long, __builtin_umulll_overflow)
|
||||||
#undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE
|
#undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// There is a bug in MSVC that makes these specializations unusable, maybe in the future...
|
// There is a bug in MSVC that makes these specializations unusable, maybe in the future...
|
||||||
#if defined(_MSC_VER) && 0
|
#if defined(_MSC_VER) && 0
|
||||||
#define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, ALT_T, BUILTIN) \
|
#define ASMJIT_ARITH_OVERFLOW_SPECIALIZE(FUNC, T, ALT_T, BUILTIN) \
|
||||||
template<> \
|
template<> \
|
||||||
inline T FUNC(T x, T y, FastUInt8* of) noexcept { \
|
inline T FUNC(T x, T y, FastUInt8* of) noexcept { \
|
||||||
ALT_T result; \
|
ALT_T result; \
|
||||||
@@ -632,12 +631,12 @@ namespace Internal {
|
|||||||
}
|
}
|
||||||
ASMJIT_ARITH_OVERFLOW_SPECIALIZE(addOverflowImpl, uint32_t, unsigned int , _addcarry_u32 )
|
ASMJIT_ARITH_OVERFLOW_SPECIALIZE(addOverflowImpl, uint32_t, unsigned int , _addcarry_u32 )
|
||||||
ASMJIT_ARITH_OVERFLOW_SPECIALIZE(subOverflowImpl, uint32_t, unsigned int , _subborrow_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(addOverflowImpl, uint64_t, unsigned __int64 , _addcarry_u64 )
|
||||||
ASMJIT_ARITH_OVERFLOW_SPECIALIZE(subOverflowImpl, uint64_t, unsigned __int64 , _subborrow_u64)
|
ASMJIT_ARITH_OVERFLOW_SPECIALIZE(subOverflowImpl, uint64_t, unsigned __int64 , _subborrow_u64)
|
||||||
#endif
|
#endif
|
||||||
#undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE
|
#undef ASMJIT_ARITH_OVERFLOW_SPECIALIZE
|
||||||
#endif
|
#endif
|
||||||
} // {Internal}
|
} // {Internal}
|
||||||
//! \endcond
|
//! \endcond
|
||||||
|
|
||||||
|
|||||||
@@ -194,8 +194,13 @@ public:
|
|||||||
if (ASMJIT_UNLIKELY(_size == _capacity))
|
if (ASMJIT_UNLIKELY(_size == _capacity))
|
||||||
ASMJIT_PROPAGATE(grow(allocator, 1));
|
ASMJIT_PROPAGATE(grow(allocator, 1));
|
||||||
|
|
||||||
::memmove(static_cast<T*>(_data) + 1, _data, size_t(_size) * sizeof(T));
|
memmove(static_cast<void*>(static_cast<T*>(_data) + 1),
|
||||||
memcpy(_data, &item, sizeof(T));
|
static_cast<const void*>(_data),
|
||||||
|
size_t(_size) * sizeof(T));
|
||||||
|
|
||||||
|
memcpy(static_cast<void*>(_data),
|
||||||
|
static_cast<const void*>(&item),
|
||||||
|
sizeof(T));
|
||||||
|
|
||||||
_size++;
|
_size++;
|
||||||
return kErrorOk;
|
return kErrorOk;
|
||||||
@@ -209,10 +214,15 @@ public:
|
|||||||
ASMJIT_PROPAGATE(grow(allocator, 1));
|
ASMJIT_PROPAGATE(grow(allocator, 1));
|
||||||
|
|
||||||
T* dst = static_cast<T*>(_data) + index;
|
T* dst = static_cast<T*>(_data) + index;
|
||||||
::memmove(dst + 1, dst, size_t(_size - index) * sizeof(T));
|
memmove(static_cast<void*>(dst + 1),
|
||||||
memcpy(dst, &item, sizeof(T));
|
static_cast<const void*>(dst),
|
||||||
_size++;
|
size_t(_size - index) * sizeof(T));
|
||||||
|
|
||||||
|
memcpy(static_cast<void*>(dst),
|
||||||
|
static_cast<const void*>(&item),
|
||||||
|
sizeof(T));
|
||||||
|
|
||||||
|
_size++;
|
||||||
return kErrorOk;
|
return kErrorOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,9 +231,11 @@ public:
|
|||||||
if (ASMJIT_UNLIKELY(_size == _capacity))
|
if (ASMJIT_UNLIKELY(_size == _capacity))
|
||||||
ASMJIT_PROPAGATE(grow(allocator, 1));
|
ASMJIT_PROPAGATE(grow(allocator, 1));
|
||||||
|
|
||||||
memcpy(static_cast<T*>(_data) + _size, &item, sizeof(T));
|
memcpy(static_cast<void*>(static_cast<T*>(_data) + _size),
|
||||||
_size++;
|
static_cast<const void*>(&item),
|
||||||
|
sizeof(T));
|
||||||
|
|
||||||
|
_size++;
|
||||||
return kErrorOk;
|
return kErrorOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +246,9 @@ public:
|
|||||||
ASMJIT_PROPAGATE(grow(allocator, size));
|
ASMJIT_PROPAGATE(grow(allocator, size));
|
||||||
|
|
||||||
if (size) {
|
if (size) {
|
||||||
memcpy(static_cast<T*>(_data) + _size, other._data, size_t(size) * sizeof(T));
|
memcpy(static_cast<void*>(static_cast<T*>(_data) + _size),
|
||||||
|
static_cast<const void*>(other._data),
|
||||||
|
size_t(size) * sizeof(T));
|
||||||
_size += size;
|
_size += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,10 +263,15 @@ public:
|
|||||||
ASMJIT_ASSERT(_size < _capacity);
|
ASMJIT_ASSERT(_size < _capacity);
|
||||||
T* data = static_cast<T*>(_data);
|
T* data = static_cast<T*>(_data);
|
||||||
|
|
||||||
if (_size)
|
if (_size) {
|
||||||
::memmove(data + 1, data, size_t(_size) * sizeof(T));
|
memmove(static_cast<void*>(data + 1),
|
||||||
|
static_cast<const void*>(data),
|
||||||
|
size_t(_size) * sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(data, &item, sizeof(T));
|
memcpy(static_cast<void*>(data),
|
||||||
|
static_cast<const void*>(&item),
|
||||||
|
sizeof(T));
|
||||||
_size++;
|
_size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +282,9 @@ public:
|
|||||||
ASMJIT_FORCE_INLINE void appendUnsafe(const T& item) noexcept {
|
ASMJIT_FORCE_INLINE void appendUnsafe(const T& item) noexcept {
|
||||||
ASMJIT_ASSERT(_size < _capacity);
|
ASMJIT_ASSERT(_size < _capacity);
|
||||||
|
|
||||||
memcpy(static_cast<T*>(_data) + _size, &item, sizeof(T));
|
memcpy(static_cast<void*>(static_cast<T*>(_data) + _size),
|
||||||
|
static_cast<const void*>(&item),
|
||||||
|
sizeof(T));
|
||||||
_size++;
|
_size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,17 +294,26 @@ public:
|
|||||||
ASMJIT_ASSERT(index <= _size);
|
ASMJIT_ASSERT(index <= _size);
|
||||||
|
|
||||||
T* dst = static_cast<T*>(_data) + index;
|
T* dst = static_cast<T*>(_data) + index;
|
||||||
::memmove(dst + 1, dst, size_t(_size - index) * sizeof(T));
|
memmove(static_cast<void*>(dst + 1),
|
||||||
memcpy(dst, &item, sizeof(T));
|
static_cast<const void*>(dst),
|
||||||
|
size_t(_size - index) * sizeof(T));
|
||||||
|
|
||||||
|
memcpy(static_cast<void*>(dst),
|
||||||
|
static_cast<const void*>(&item),
|
||||||
|
sizeof(T));
|
||||||
|
|
||||||
_size++;
|
_size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Concatenates all items of `other` at the end of the vector.
|
//! Concatenates all items of `other` at the end of the vector.
|
||||||
ASMJIT_FORCE_INLINE void concatUnsafe(const ZoneVector<T>& other) noexcept {
|
ASMJIT_FORCE_INLINE void concatUnsafe(const ZoneVector<T>& other) noexcept {
|
||||||
uint32_t size = other._size;
|
uint32_t size = other._size;
|
||||||
ASMJIT_ASSERT(_capacity - _size >= size);
|
ASMJIT_ASSERT(_capacity - _size >= size);
|
||||||
|
|
||||||
if (size) {
|
if (size) {
|
||||||
memcpy(static_cast<T*>(_data) + _size, other._data, size_t(size) * sizeof(T));
|
memcpy(static_cast<void*>(static_cast<T*>(_data) + _size),
|
||||||
|
static_cast<const void*>(other._data),
|
||||||
|
size_t(size) * sizeof(T));
|
||||||
_size += size;
|
_size += size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,8 +341,11 @@ public:
|
|||||||
T* data = static_cast<T*>(_data) + i;
|
T* data = static_cast<T*>(_data) + i;
|
||||||
size_t size = --_size - i;
|
size_t size = --_size - i;
|
||||||
|
|
||||||
if (size)
|
if (size) {
|
||||||
::memmove(data, data + 1, size_t(size) * sizeof(T));
|
memmove(static_cast<void*>(data),
|
||||||
|
static_cast<const void*>(data + 1),
|
||||||
|
size_t(size) * sizeof(T));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Pops the last element from the vector and returns it.
|
//! Pops the last element from the vector and returns it.
|
||||||
|
|||||||
@@ -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.
|
const Operand_* rmRel; // Memory operand or operand that holds Label|Imm.
|
||||||
uint32_t rmInfo; // Memory operand's info based on x86MemInfo.
|
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 rxReg; // Memory index register.
|
||||||
uint32_t opReg; // ModR/M opcode or register id.
|
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.
|
// This sequence seems to be the fastest.
|
||||||
opcode = InstDB::_mainOpcodeTable[instInfo->_mainOpcodeIndex];
|
opcode = InstDB::_mainOpcodeTable[instInfo->_mainOpcodeIndex];
|
||||||
opReg = opcode.extractModO();
|
opReg = opcode.extractModO();
|
||||||
rbReg = 0;
|
|
||||||
opcode |= instInfo->_mainOpcodeValue;
|
opcode |= instInfo->_mainOpcodeValue;
|
||||||
|
|
||||||
// Encoding Scope
|
// Encoding Scope
|
||||||
|
|||||||
@@ -514,8 +514,8 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand(
|
|||||||
// =====================================================
|
// =====================================================
|
||||||
|
|
||||||
static constexpr char kImmCharStart = '{';
|
static constexpr char kImmCharStart = '{';
|
||||||
static constexpr char kImmCharEnd = '}';
|
static constexpr char kImmCharEnd = '}';
|
||||||
static constexpr char kImmCharOr = '|';
|
static constexpr char kImmCharOr = '|';
|
||||||
|
|
||||||
struct ImmBits {
|
struct ImmBits {
|
||||||
enum Mode : uint32_t {
|
enum Mode : uint32_t {
|
||||||
@@ -539,8 +539,7 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmShuf(String& sb, uint3
|
|||||||
ASMJIT_PROPAGATE(sb.appendUInt(index));
|
ASMJIT_PROPAGATE(sb.appendUInt(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kImmCharEnd)
|
ASMJIT_PROPAGATE(sb.append(kImmCharEnd));
|
||||||
ASMJIT_PROPAGATE(sb.append(kImmCharEnd));
|
|
||||||
|
|
||||||
return kErrorOk;
|
return kErrorOk;
|
||||||
}
|
}
|
||||||
@@ -576,7 +575,7 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmBits(String& sb, uint3
|
|||||||
ASMJIT_PROPAGATE(sb.append(str));
|
ASMJIT_PROPAGATE(sb.append(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n && kImmCharEnd)
|
if (n)
|
||||||
ASMJIT_PROPAGATE(sb.append(kImmCharEnd));
|
ASMJIT_PROPAGATE(sb.append(kImmCharEnd));
|
||||||
|
|
||||||
return kErrorOk;
|
return kErrorOk;
|
||||||
@@ -592,10 +591,7 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmText(String& sb, uint3
|
|||||||
ASMJIT_PROPAGATE(sb.append(Support::findPackedString(text, value)));
|
ASMJIT_PROPAGATE(sb.append(Support::findPackedString(text, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kImmCharEnd)
|
return sb.append(kImmCharEnd);
|
||||||
ASMJIT_PROPAGATE(sb.append(kImmCharEnd));
|
|
||||||
|
|
||||||
return kErrorOk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst(
|
ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst(
|
||||||
|
|||||||
@@ -1711,18 +1711,6 @@ Error InstInternal::queryFeatures(Arch arch, const BaseInst& inst, const Operand
|
|||||||
// =========================
|
// =========================
|
||||||
|
|
||||||
#if defined(ASMJIT_TEST)
|
#if defined(ASMJIT_TEST)
|
||||||
template<typename... Args>
|
|
||||||
static Error queryRWInfoInline(InstRWInfo* out, Arch arch, BaseInst inst, Args&&... args) {
|
|
||||||
Operand_ opArray[] = { std::forward<Args>(args)... };
|
|
||||||
return InstInternal::queryRWInfo(arch, inst, opArray, sizeof...(args), out);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
static Error queryFeaturesInline(CpuFeatures* out, Arch arch, BaseInst inst, Args&&... args) {
|
|
||||||
Operand_ opArray[] = { std::forward<Args>(args)... };
|
|
||||||
return InstInternal::queryFeatures(arch, inst, opArray, sizeof...(args), out);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ASMJIT_NO_TEXT
|
#ifndef ASMJIT_NO_TEXT
|
||||||
UNIT(x86_inst_api_text) {
|
UNIT(x86_inst_api_text) {
|
||||||
// All known instructions should be matched.
|
// All known instructions should be matched.
|
||||||
@@ -1741,6 +1729,13 @@ UNIT(x86_inst_api_text) {
|
|||||||
}
|
}
|
||||||
#endif // !ASMJIT_NO_TEXT
|
#endif // !ASMJIT_NO_TEXT
|
||||||
|
|
||||||
|
#ifndef ASMJIT_NO_INTROSPECTION
|
||||||
|
template<typename... Args>
|
||||||
|
static Error queryFeaturesInline(CpuFeatures* out, Arch arch, BaseInst inst, Args&&... args) {
|
||||||
|
Operand_ opArray[] = { std::forward<Args>(args)... };
|
||||||
|
return InstInternal::queryFeatures(arch, inst, opArray, sizeof...(args), out);
|
||||||
|
}
|
||||||
|
|
||||||
UNIT(x86_inst_api_cpu_features) {
|
UNIT(x86_inst_api_cpu_features) {
|
||||||
INFO("Verifying whether SSE2+ features are reported correctly for legacy instructions");
|
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());
|
EXPECT_TRUE(f.x86().hasAVX512_F());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // !ASMJIT_NO_INTROSPECTION
|
||||||
|
|
||||||
|
#ifndef ASMJIT_NO_INTROSPECTION
|
||||||
|
template<typename... Args>
|
||||||
|
static Error queryRWInfoInline(InstRWInfo* out, Arch arch, BaseInst inst, Args&&... args) {
|
||||||
|
Operand_ opArray[] = { std::forward<Args>(args)... };
|
||||||
|
return InstInternal::queryRWInfo(arch, inst, opArray, sizeof...(args), out);
|
||||||
|
}
|
||||||
|
|
||||||
UNIT(x86_inst_api_rm_features) {
|
UNIT(x86_inst_api_rm_features) {
|
||||||
INFO("Verifying whether RM/feature is reported correctly for PEXTRW instruction");
|
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);
|
EXPECT_EQ(rwi.rmFeature(), 0u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif // !ASMJIT_NO_INTROSPECTION
|
||||||
|
|
||||||
|
#endif // ASMJIT_TEST
|
||||||
|
|
||||||
ASMJIT_END_SUB_NAMESPACE
|
ASMJIT_END_SUB_NAMESPACE
|
||||||
|
|
||||||
|
|||||||
@@ -823,7 +823,7 @@ Error RACFGBuilder::moveImmToStackArg(InvokeNode* invokeNode, const FuncValue& a
|
|||||||
|
|
||||||
stackPtr.setSize(4);
|
stackPtr.setSize(4);
|
||||||
imm[0] = imm_;
|
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
|
// 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
|
// 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:
|
case TypeId::kFloat32:
|
||||||
MovU32:
|
MovU32:
|
||||||
imm[0].zeroExtend32Bits();
|
imm[0].zeroExtend32Bits();
|
||||||
nMovs = 1;
|
movCount = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TypeId::kInt64:
|
case TypeId::kInt64:
|
||||||
@@ -849,20 +849,20 @@ MovU32:
|
|||||||
case TypeId::kMmx64:
|
case TypeId::kMmx64:
|
||||||
if (_is64Bit && imm[0].isInt32()) {
|
if (_is64Bit && imm[0].isInt32()) {
|
||||||
stackPtr.setSize(8);
|
stackPtr.setSize(8);
|
||||||
nMovs = 1;
|
movCount = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
imm[1].setValue(imm[0].uint32Hi());
|
imm[1].setValue(imm[0].uint32Hi());
|
||||||
imm[0].zeroExtend32Bits();
|
imm[0].zeroExtend32Bits();
|
||||||
nMovs = 2;
|
movCount = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return DebugUtils::errored(kErrorInvalidAssignment);
|
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]));
|
ASMJIT_PROPAGATE(cc()->mov(stackPtr, imm[i]));
|
||||||
stackPtr.addOffsetLo32(int32_t(stackPtr.size()));
|
stackPtr.addOffsetLo32(int32_t(stackPtr.size()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -971,8 +971,8 @@ public:
|
|||||||
typedef void (*Func)(int*, int*);
|
typedef void (*Func)(int*, int*);
|
||||||
Func func = ptr_as_func<Func>(_func);
|
Func func = ptr_as_func<Func>(_func);
|
||||||
|
|
||||||
int resultX;
|
int resultX = 0;
|
||||||
int resultY;
|
int resultY = 0;
|
||||||
|
|
||||||
int expectX = 36;
|
int expectX = 36;
|
||||||
int expectY = -36;
|
int expectY = -36;
|
||||||
@@ -1026,8 +1026,8 @@ public:
|
|||||||
Func func = ptr_as_func<Func>(_func);
|
Func func = ptr_as_func<Func>(_func);
|
||||||
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t resultBuf[32];
|
uint32_t resultBuf[32] {};
|
||||||
uint32_t expectBuf[32];
|
uint32_t expectBuf[32] {};
|
||||||
|
|
||||||
for (i = 0; i < ASMJIT_ARRAY_SIZE(resultBuf); i++)
|
for (i = 0; i < ASMJIT_ARRAY_SIZE(resultBuf); i++)
|
||||||
expectBuf[i] = i * 32;
|
expectBuf[i] = i * 32;
|
||||||
@@ -1085,8 +1085,8 @@ public:
|
|||||||
int v0 = 4;
|
int v0 = 4;
|
||||||
int v1 = 4;
|
int v1 = 4;
|
||||||
|
|
||||||
int resultHi;
|
int resultHi = 0;
|
||||||
int resultLo;
|
int resultLo = 0;
|
||||||
|
|
||||||
int expectHi = 0;
|
int expectHi = 0;
|
||||||
int expectLo = v0 * v1;
|
int expectLo = v0 * v1;
|
||||||
@@ -1227,7 +1227,7 @@ public:
|
|||||||
typedef void (*Func)(int, int, char*);
|
typedef void (*Func)(int, int, char*);
|
||||||
Func func = ptr_as_func<Func>(_func);
|
Func func = ptr_as_func<Func>(_func);
|
||||||
|
|
||||||
char resultBuf[4];
|
char resultBuf[4] {};
|
||||||
char expectBuf[4] = { 1, 0, 0, 1 };
|
char expectBuf[4] = { 1, 0, 0, 1 };
|
||||||
|
|
||||||
func(0, 0, &resultBuf[0]); // We are expecting 1 (0 == 0).
|
func(0, 0, &resultBuf[0]); // We are expecting 1 (0 == 0).
|
||||||
@@ -1280,7 +1280,7 @@ public:
|
|||||||
|
|
||||||
int v0 = 0x000000FF;
|
int v0 = 0x000000FF;
|
||||||
|
|
||||||
int resultRet;
|
int resultRet = 0;
|
||||||
int expectRet = 0x0000FF00;
|
int expectRet = 0x0000FF00;
|
||||||
|
|
||||||
func(&resultRet, v0, 16, 8);
|
func(&resultRet, v0, 16, 8);
|
||||||
@@ -1347,10 +1347,9 @@ public:
|
|||||||
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t buf[kCount];
|
uint32_t buf[kCount];
|
||||||
uint32_t resultRet;
|
uint32_t resultRet = 0;
|
||||||
uint32_t expectRet;
|
uint32_t expectRet = 0;
|
||||||
|
|
||||||
expectRet = 0;
|
|
||||||
for (i = 0; i < kCount; i++) {
|
for (i = 0; i < kCount; i++) {
|
||||||
buf[i] = 1;
|
buf[i] = 1;
|
||||||
}
|
}
|
||||||
@@ -1700,7 +1699,7 @@ public:
|
|||||||
x86::Gp x = cc.newInt8("x");
|
x86::Gp x = cc.newInt8("x");
|
||||||
x86::Gp y = cc.newInt32("y");
|
x86::Gp y = cc.newInt32("y");
|
||||||
|
|
||||||
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, char>(CallConvId::kHost));
|
FuncNode* funcNode = cc.addFunc(FuncSignatureT<int, int8_t>(CallConvId::kHost));
|
||||||
funcNode->setArg(0, x);
|
funcNode->setArg(0, x);
|
||||||
|
|
||||||
cc.movsx(y, x);
|
cc.movsx(y, x);
|
||||||
@@ -1710,10 +1709,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual bool run(void* _func, String& result, String& expect) {
|
virtual bool run(void* _func, String& result, String& expect) {
|
||||||
typedef int (*Func)(char);
|
typedef int (*Func)(int8_t);
|
||||||
Func func = ptr_as_func<Func>(_func);
|
Func func = ptr_as_func<Func>(_func);
|
||||||
|
|
||||||
int resultRet = func(-13);
|
int resultRet = func(int8_t(-13));
|
||||||
int expectRet = -13;
|
int expectRet = -13;
|
||||||
|
|
||||||
result.assignFormat("ret=%d", resultRet);
|
result.assignFormat("ret=%d", resultRet);
|
||||||
@@ -1853,7 +1852,7 @@ public:
|
|||||||
typedef void (*Func)(float, float, float, float, float, float, float, float*);
|
typedef void (*Func)(float, float, float, float, float, float, float, float*);
|
||||||
Func func = ptr_as_func<Func>(_func);
|
Func func = ptr_as_func<Func>(_func);
|
||||||
|
|
||||||
float resultRet;
|
float resultRet = 0;
|
||||||
float expectRet = 1.0f + 2.0f + 3.0f + 4.0f + 5.0f + 6.0f + 7.0f;
|
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);
|
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*);
|
typedef void (*Func)(double, double, double, double, double, double, double, double*);
|
||||||
Func func = ptr_as_func<Func>(_func);
|
Func func = ptr_as_func<Func>(_func);
|
||||||
|
|
||||||
double resultRet;
|
double resultRet = 0;
|
||||||
double expectRet = 1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.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);
|
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 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 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 };
|
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<const __m128i*>(aData));
|
__m128i aVec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(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 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 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 };
|
uint8_t eData[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
|
||||||
|
|
||||||
func(rData, aData, bData);
|
func(rData, aData, bData);
|
||||||
@@ -2823,7 +2822,7 @@ public:
|
|||||||
int16_t c[8] = { 1, 3, 9, 7, 5, 4, 2, 1 };
|
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 d[8] = { 2, 0,-6,-4,-2,-1, 1, 2 };
|
||||||
|
|
||||||
int16_t o[8];
|
int16_t o[8] {};
|
||||||
int oExp = 7 * 3;
|
int oExp = 7 * 3;
|
||||||
|
|
||||||
func(a, b, c, d, o);
|
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 aData[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||||
static const uint32_t bData[8] = { 6, 3, 5, 9, 1, 8, 7, 2 };
|
static const uint32_t bData[8] = { 6, 3, 5, 9, 1, 8, 7, 2 };
|
||||||
|
|
||||||
uint32_t resultData[8];
|
uint32_t resultData[8] {};
|
||||||
uint32_t expectData[8];
|
uint32_t expectData[8] {};
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
expectData[i] = aData[i] * 8 + bData[i] + 1;
|
expectData[i] = aData[i] * 8 + bData[i] + 1;
|
||||||
|
|||||||
@@ -98,10 +98,6 @@ static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept {
|
|||||||
|
|
||||||
Error err = kErrorOk;
|
Error err = kErrorOk;
|
||||||
switch (emitterType) {
|
switch (emitterType) {
|
||||||
case EmitterType::kNone: {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case EmitterType::kAssembler: {
|
case EmitterType::kAssembler: {
|
||||||
printf("Using x86::Assembler:\n");
|
printf("Using x86::Assembler:\n");
|
||||||
x86::Assembler a(&code);
|
x86::Assembler a(&code);
|
||||||
@@ -138,6 +134,11 @@ static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
default: {
|
||||||
|
printf("** FAILURE: No emitter to use **\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the code generated to the runtime.
|
// Add the code generated to the runtime.
|
||||||
@@ -150,9 +151,9 @@ static uint32_t testFunc(JitRuntime& rt, EmitterType emitterType) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute the generated function.
|
// Execute the generated function.
|
||||||
int inA[4] = { 4, 3, 2, 1 };
|
static const int inA[4] = { 4, 3, 2, 1 };
|
||||||
int inB[4] = { 1, 5, 2, 8 };
|
static const int inB[4] = { 1, 5, 2, 8 };
|
||||||
int out[4];
|
int out[4] {};
|
||||||
fn(out, inA, inB);
|
fn(out, inA, inB);
|
||||||
|
|
||||||
// Should print {5 8 4 9}.
|
// Should print {5 8 4 9}.
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
using namespace asmjit;
|
using namespace asmjit;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
#if !defined(ASMJIT_NO_X86)
|
||||||
static char accessLetter(bool r, bool w) noexcept {
|
static char accessLetter(bool r, bool w) noexcept {
|
||||||
return r && w ? 'X' : r ? 'R' : w ? 'W' : '_';
|
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>(args)... };
|
Operand_ opArray[] = { std::forward<Args>(args)... };
|
||||||
printInfo(arch, inst, opArray, sizeof...(args));
|
printInfo(arch, inst, opArray, sizeof...(args));
|
||||||
}
|
}
|
||||||
|
#endif // !ASMJIT_NO_X86
|
||||||
|
|
||||||
static void testX86Arch() {
|
static void testX86Arch() {
|
||||||
#if !defined(ASMJIT_NO_X86)
|
#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::kNone, k1, zmm0, zmm1, zmm2);
|
||||||
printInfoExtra(arch, Inst::kIdVaddpd, InstOptions::kX86_ZMask, k1, zmm0, zmm1, zmm2);
|
printInfoExtra(arch, Inst::kIdVaddpd, InstOptions::kX86_ZMask, k1, zmm0, zmm1, zmm2);
|
||||||
#endif
|
#endif // !ASMJIT_NO_X86
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // {anonymous}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
printf("AsmJit Instruction Info Test-Suite v%u.%u.%u\n",
|
printf("AsmJit Instruction Info Test-Suite v%u.%u.%u\n",
|
||||||
unsigned((ASMJIT_LIBRARY_VERSION >> 16) ),
|
unsigned((ASMJIT_LIBRARY_VERSION >> 16) ),
|
||||||
|
|||||||
@@ -109,7 +109,8 @@ static void dumpSizeOf(void) noexcept {
|
|||||||
DUMP_TYPE(BaseBuilder);
|
DUMP_TYPE(BaseBuilder);
|
||||||
DUMP_TYPE(BaseNode);
|
DUMP_TYPE(BaseNode);
|
||||||
DUMP_TYPE(InstNode);
|
DUMP_TYPE(InstNode);
|
||||||
DUMP_TYPE(InstExNode);
|
DUMP_TYPE(InstNodeWithOperands<InstNode::kBaseOpCapacity>);
|
||||||
|
DUMP_TYPE(InstNodeWithOperands<InstNode::kFullOpCapacity>);
|
||||||
DUMP_TYPE(AlignNode);
|
DUMP_TYPE(AlignNode);
|
||||||
DUMP_TYPE(LabelNode);
|
DUMP_TYPE(LabelNode);
|
||||||
DUMP_TYPE(EmbedDataNode);
|
DUMP_TYPE(EmbedDataNode);
|
||||||
|
|||||||
@@ -8,8 +8,10 @@
|
|||||||
|
|
||||||
#include <asmjit/core.h>
|
#include <asmjit/core.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
ASMJIT_MAYBE_UNUSED
|
ASMJIT_MAYBE_UNUSED
|
||||||
static const char* asmjitArchAsString(asmjit::Arch arch) noexcept {
|
const char* asmjitArchAsString(asmjit::Arch arch) noexcept {
|
||||||
switch (arch) {
|
switch (arch) {
|
||||||
case asmjit::Arch::kX86 : return "X86";
|
case asmjit::Arch::kX86 : return "X86";
|
||||||
case asmjit::Arch::kX64 : return "X64";
|
case asmjit::Arch::kX64 : return "X64";
|
||||||
@@ -37,7 +39,7 @@ static const char* asmjitArchAsString(asmjit::Arch arch) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ASMJIT_MAYBE_UNUSED
|
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;
|
const char* start = str;
|
||||||
while (*str) {
|
while (*str) {
|
||||||
if (*str == '\n') {
|
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);
|
printf("%*s%.*s\n", int(indent), "", int(size), start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // {anonymous}
|
||||||
|
|
||||||
#endif // ASMJITUTILS_H_INCLUDED
|
#endif // ASMJITUTILS_H_INCLUDED
|
||||||
|
|||||||
@@ -11,3 +11,7 @@ echo ""
|
|||||||
echo "== [Configuring Build - Release_UBSAN] =="
|
echo "== [Configuring Build - Release_UBSAN] =="
|
||||||
eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Release_UBSAN" ${BUILD_OPTIONS} -DCMAKE_BUILD_TYPE=Release -DASMJIT_SANITIZE=undefined
|
eval cmake "${CURRENT_DIR}/.." -B "${BUILD_DIR}/Release_UBSAN" ${BUILD_OPTIONS} -DCMAKE_BUILD_TYPE=Release -DASMJIT_SANITIZE=undefined
|
||||||
echo ""
|
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 ""
|
||||||
|
|||||||
Reference in New Issue
Block a user