diff --git a/.temp b/.temp new file mode 100644 index 00000000..d01d39bc --- /dev/null +++ b/.temp @@ -0,0 +1,6 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ +!_TAG_PROGRAM_NAME Exuberant Ctags // +!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ +!_TAG_PROGRAM_VERSION 5.8 // diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a6fb626..9ab8703f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,8 +44,11 @@ if (MSVC) -Wno-signed-enum-bitfield -Wno-nonportable-system-include-path -Wno-newline-eof + -Wno-unknown-pragmas + -Wno-deprecated-declarations -Wno-documentation-unknown-command -Wno-c99-designator + -Wno-missing-braces ) add_compile_options( "$<$:${CXX_FLAGS}>" @@ -61,9 +64,25 @@ if (MSVC) "$<$:${CXX_DEFINES}>" ) else () - set(CXX_FLAGS -Wall -Wno-string-plus-int -Wno-signed-enum-bitfield -Wno-cast-qual -Wno-auto-var-id -Wno-unused-private-field -Wno-unknown-pragmas -Wno-inconsistent-missing-override -Wno-c99-designator) + set( + CXX_FLAGS + -Wall + -Wno-string-plus-int + -Wno-signed-enum-bitfield + -Wno-cast-qual + -Wno-auto-var-id + -Wno-unused-private-field + -Wno-unknown-pragmas + -Wno-inconsistent-missing-override + -Wno-c99-designator + -Wno-deprecated-declarations + -Wno-missing-braces + ) + set(CLANG_CXX_FLAGS -fcolor-diagnostics) + set(GCC_CXX_FLAGS -fdiagnostics-color=always -Wno-parentheses -Wno-sequence-point) + add_compile_options( "$<$:${CXX_FLAGS}>" "$<$:${GCC_CXX_FLAGS}>" @@ -80,7 +99,7 @@ endif() # zlib add_subdirectory(ext/zlib-1.2.11 EXCLUDE_FROM_ALL) set(ZLIB_FOUND ON) -set(ZLIB_ROOT "${CMAKE_SOURCE_DIR}/ext/zlib-1.2.11") +set(ZLIB_ROOT "${PROJECT_SOURCE_DIR}/ext/zlib-1.2.11") if (MSVC) if (CMAKE_BUILD_TYPE MATCHES Debug) set(ZLIB_LIBRARY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/zlibstaticd.lib") @@ -88,10 +107,7 @@ if (MSVC) set(ZLIB_LIBRARY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/zlibstatic.lib") endif () include_directories("${CMAKE_BINARY_DIR}/ext/zlib-1.2.11") -else () - set(ZLIB_LIBRARY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libz.a") endif() -#set(ZLIB_LIBRARIES "${ZLIB_LIBRARY}") # bzip2 set( @@ -107,8 +123,8 @@ set( add_library(bz2 STATIC ${BZIP2_SOURCES}) target_compile_definitions(bz2 PRIVATE -D_FILE_OFFSET_BITS=64) set_target_properties(bz2 PROPERTIES LIBRARY_OUTPUT_NAME bz2) -target_include_directories(bz2 INTERFACE "${CMAKE_SOURCE_DIR}/ext/bzip2-1.0.8") -set(BZIP2_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/ext/bzip2-1.0.8") +target_include_directories(bz2 INTERFACE "${PROJECT_SOURCE_DIR}/ext/bzip2-1.0.8") +set(BZIP2_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/ext/bzip2-1.0.8") set(BZIP2_INCLUDE_DIRS "${BZIP2_INCLUDE_DIR}") if (MSVC) set(BZIP2_LIBRARIES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/bz2.lib") @@ -116,32 +132,6 @@ else () set(BZIP2_LIBRARIES "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libbz2.a") endif () - -# asmjit -set(ASMJIT_STATIC 1) -add_subdirectory(ext/asmjit-master EXCLUDE_FROM_ALL) - -# libpng -option(PNG_STATIC "" ON) -option(PNG_SHARED "" OFF) -option(PNG_TESTS "" OFF) -add_subdirectory(ext/libpng-1.6.37 EXCLUDE_FROM_ALL) -set(PNG_PNG_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/ext/libpng-1.6.37") -set(PNG_PNG_INCLUDE_DIRS "${PNG_PNG_INCLUDE_DIR}") -if (MSVC) - if (CMAKE_BUILD_TYPE MATCHES Debug) - set(PNG_LIBRARY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libpng16_staticd.lib") - else () - set(PNG_LIBRARY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libpng16_static.lib") - endif () -else () - if (CMAKE_BUILD_TYPE MATCHES Debug) - set(PNG_LIBRARY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libpng16d.a") - else () - set(PNG_LIBRARY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libpng16.a") - endif () -endif () - # libfmt add_subdirectory(ext/fmt-7.0.3 EXCLUDE_FROM_ALL) @@ -150,40 +140,41 @@ option(SPDLOG_FMT_EXTERNAL "" ON) option(SPDLOG_INSTALL "" OFF) option(SPDLOG_BUILD_TESTS "" OFF) option(SPDLOG_BUILD_EXAMPLE "" OFF) -add_subdirectory(ext/spdlog-1.8.1 EXCLUDE_FROM_ALL) +add_subdirectory(ext/spdlog-1.9.0 EXCLUDE_FROM_ALL) # utf8proc add_subdirectory(ext/utf8proc-2.5.0 EXCLUDE_FROM_ALL) +target_include_directories(utf8proc PUBLIC ext/utf8proc-2.5.0) # blake3 set( BLAKE3_SOURCES - ext/blake3-0.3.1/blake3.c - ext/blake3-0.3.1/blake3_dispatch.c - ext/blake3-0.3.1/blake3_portable.c + ext/blake3-0.3.7/blake3.c + ext/blake3-0.3.7/blake3_dispatch.c + ext/blake3-0.3.7/blake3_portable.c ) if (WIN32) set( BLAKE3_SOURCES ${BLAKE3_SOURCES} - ext/blake3-0.3.1/blake3_sse41_x86-64_windows_gnu.S - ext/blake3-0.3.1/blake3_avx2_x86-64_windows_gnu.S - ext/blake3-0.3.1/blake3_avx512_x86-64_windows_gnu.S + ext/blake3-0.3.7/blake3_sse41_x86-64_windows_gnu.S + ext/blake3-0.3.7/blake3_avx2_x86-64_windows_gnu.S + ext/blake3-0.3.7/blake3_avx512_x86-64_windows_gnu.S ) else () set( BLAKE3_SOURCES ${BLAKE3_SOURCES} - ext/blake3-0.3.1/blake3_sse41_x86-64_unix.S - ext/blake3-0.3.1/blake3_avx2_x86-64_unix.S - ext/blake3-0.3.1/blake3_avx512_x86-64_unix.S + ext/blake3-0.3.7/blake3_sse41_x86-64_unix.S + ext/blake3-0.3.7/blake3_avx2_x86-64_unix.S + ext/blake3-0.3.7/blake3_avx512_x86-64_unix.S ) endif () add_library(blake3 ${BLAKE3_SOURCES}) if (NOT WIN32) target_compile_options(blake3 PUBLIC -march=native) endif() -target_include_directories(blake3 INTERFACE ext/blake3-0.3.1) +target_include_directories(blake3 INTERFACE ext/blake3-0.3.7) # dyncall add_subdirectory(ext/dyncall-1.1.0 EXCLUDE_FROM_ALL) @@ -191,18 +182,26 @@ target_include_directories(dyncall_s INTERFACE ext/dyncall-1.1.0) target_include_directories(dynload_s INTERFACE ext/dyncall-1.1.0) set (DYN_ALLOC_HEADER "${PROJECT_SOURCE_DIR}/include/basecode/core/memory/dyn_alloc.h") if (MSVC) - target_compile_options(dyncall_s PRIVATE "/FI${DYN_ALLOC_HEADER}") - target_compile_options(dynload_s PRIVATE "/FI${DYN_ALLOC_HEADER}") + target_compile_options( + dyncall_s PRIVATE + + "$<$:/FI${DYN_ALLOC_HEADER}>" + ) + target_compile_options( + dynload_s PRIVATE + + "$<$:/FI${DYN_ALLOC_HEADER}>" + ) else () target_compile_options( dyncall_s PRIVATE - "$<$:--include=${DYN_ALLOC_HEADER}>" - "$<$:--include=${DYN_ALLOC_HEADER}>" + + "$<$:--include=${DYN_ALLOC_HEADER}>" ) target_compile_options( dynload_s PRIVATE - "$<$:--include=${DYN_ALLOC_HEADER}>" - "$<$:--include=${DYN_ALLOC_HEADER}>" + + "$<$:--include=${DYN_ALLOC_HEADER}>" ) endif () @@ -212,12 +211,9 @@ set( ext/sqlite-3.33.0/sqlite3.c ) add_library(sqlite3 ${SQLITE3_SOURCES}) +target_compile_options(sqlite3 PRIVATE -Wno-unused-variable) target_include_directories(sqlite3 INTERFACE ext/sqlite-3.33.0) -if (WIN32) - include_directories(include/platform/win32) -endif() - # ----------------------------------------------------------------------------- # # Project @@ -230,3 +226,8 @@ set(PROJECT_DIR_BASE ${PROJECT_SOURCE_DIR}) add_subdirectory(src/libcore) add_subdirectory(src/libcore-test) add_subdirectory(src/libgfx) +add_subdirectory(src/libgfx-test) +add_subdirectory(src/libbinfmt) +add_subdirectory(src/libbinfmt-test) +add_subdirectory(src/scm) +add_subdirectory(src/objdump) diff --git a/src/libcore/fe/LICENSE b/CREDITS.md similarity index 89% rename from src/libcore/fe/LICENSE rename to CREDITS.md index 39ddd05c..293d9fb4 100644 --- a/src/libcore/fe/LICENSE +++ b/CREDITS.md @@ -1,3 +1,6 @@ +The scheme interpreter is based on the *fe* project found here: https://github.com/rxi/fe +The MIT license follows: + Copyright (c) 2020 rxi Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -17,3 +20,5 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- diff --git a/ext/spdlog-1.8.1/include/spdlog/fmt/bundled/LICENSE.rst b/LICENSE.md similarity index 72% rename from ext/spdlog-1.8.1/include/spdlog/fmt/bundled/LICENSE.rst rename to LICENSE.md index f0ec3db4..c586b018 100644 --- a/ext/spdlog-1.8.1/include/spdlog/fmt/bundled/LICENSE.rst +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2012 - present, Victor Zverovich +Copyright (c) 2018-2020 Jeff Panici. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -18,10 +18,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ---- Optional exception to the license --- - -As an exception, if, as a result of your compiling your source code, portions -of this Software are embedded into a machine-executable object form of such -source code, you may redistribute such embedded portions in such object form -without including the above copyright and permission notices. diff --git a/build.sh b/build.sh new file mode 100644 index 00000000..ba3a9749 --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +"C:/Program Files/JetBrains/CLion 2020.2.3/bin/cmake/win/bin/cmake.exe" --build C:/src/basecode-lang/foundation/build/msvc/debug --target $1 diff --git a/etc/basic.scm b/etc/basic.scm new file mode 100644 index 00000000..f22b87c9 --- /dev/null +++ b/etc/basic.scm @@ -0,0 +1,122 @@ +;; ---------------------------------------------------------------------------- +;; ____ _ +;; | _\ | | +;; | |_)| __ _ ___ ___ ___ ___ __| | ___ TM +;; | _< / _` / __|/ _ \/ __/ _ \ / _` |/ _ \ +;; | |_)| (_| \__ \ __/ (_| (_) | (_| | __/ +;; |____/\__,_|___/\___|\___\___/ \__,_|\___| +;; +;; F O U N D A T I O N P R O J E C T +;; +;; Copyright (C) 2017-2021 Jeff Panici +;; All rights reserved. +;; +;; This software source file is licensed under the terms of MIT license. +;; For details, please read the LICENSE file. +;; +;; ---------------------------------------------------------------------------- + +;; ---------------------------------------------------------------------------- +;; +;; basic procedures & macros +;; +;; ---------------------------------------------------------------------------- + +(define-macro add1 (lambda (e) + `(+ ,e 1))) + +(define-macro sub1 (lambda (e) + `(- ,e 1))) + +(define-macro ok? (lambda (s) + `(is ,s 0))) + +(define-macro let (lambda (args . body) + `(begin + (define proc (lambda ,(map (lambda (p) (car p)) args) + ,@body)) + (proc ,@(map (lambda (p) (car (cdr p))) args))))) + +(define-macro cond (lambda args + (if (not args) + ''() + (begin + (define next (car args)) + (define rest (cdr args)) + (define test (if (is (car next) 'else) + #t + (car next))) + (define expr (car (cdr next))) + `(if ,test ,expr (cond ,@rest)))))) + +(define-macro for (lambda (item lst . body) + `(begin + (define for-iter ,lst) + (while for-iter + (define ,item (car for-iter)) + (set! for-iter (cdr for-iter)) + (begin ,@body))))) + +(define-macro test-suite (lambda (title . body) + `(begin + (define pass-count 0) + (define fail-count 0) + (define sys-print print) + (define print (lambda (args) + (sys-print " " + (car args) + (car (cdr args))))) + (sys-print "TEST SUITE:" ,title) + (sys-print "----------------------------------------------------") + (sys-print " PASS | FAIL | Assert Expression ") + (sys-print "----------------------------------------------------") + + (define results (list ,@body)) + (for expr results + (define pass? (cdr (car expr))) + (define test (car (cdr expr))) + (if (is pass? 1) + (begin + (sys-print " P " test) + (set! pass-count (add1 pass-count)))) + (if (is pass? 2) + (begin + (sys-print " F " test) + (set! fail-count (add1 fail-count))))) + + (sys-print "====================================================") + (sys-print "PASS:" pass-count " FAIL:" fail-count) + (sys-print "")))) + +(define-macro assert (lambda (expr) + `(begin + (define result (eval ,expr)) + (if result + (list (cons 'assert 1) ,expr) + (list (cons 'assert 2) ,expr))))) + +(define map (lambda (proc lst) + (define res nil) + (while lst + (set! res (cons (proc (car lst)) res)) + (set! lst (cdr lst))) + (reverse res))) + +(define range (lambda (a b step) + (define lst '()) + (if (not step) + (set! step 1)) + (while (<= a b) + (set! lst (cons a lst)) + (set! a (+ a step))) + (reverse lst))) + +(define list-tail (lambda (ls k) + (while (> k 0) + (set! ls (cdr ls)) + (set! k (sub1 k))) + ls)) + +(define list-ref (lambda (ls k) + (car (list-tail ls k)))) + diff --git a/etc/binfmt-localization.scm b/etc/binfmt-localization.scm new file mode 100644 index 00000000..a6a728ab --- /dev/null +++ b/etc/binfmt-localization.scm @@ -0,0 +1,72 @@ +;; ---------------------------------------------------------------------------- +;; ____ _ +;; | _\ | | +;; | |_)| __ _ ___ ___ ___ ___ __| | ___ TM +;; | _< / _` / __|/ _ \/ __/ _ \ / _` |/ _ \ +;; | |_)| (_| \__ \ __/ (_| (_) | (_| | __/ +;; |____/\__,_|___/\___|\___\___/ \__,_|\___| +;; +;; F O U N D A T I O N P R O J E C T +;; +;; Copyright (C) 2017-2021 Jeff Panici +;; All rights reserved. +;; +;; This software source file is licensed under the terms of MIT license. +;; For details, please read the LICENSE file. +;; +;; ---------------------------------------------------------------------------- + +;; strings +(define read-error (localized-string 20000 'en_US "container read error")) +(define write-error (localized-string 20001 'en_US "container write error")) +(define import-failure (localized-string 20002 'en_US "section import failure")) +(define duplicate-import (localized-string 20003 'en_US "imported duplicate symbol")) +(define duplicate-symbol (localized-string 20004 'en_US "duplicate symbol")) +(define symbol-not-found (localized-string 20005 'en_US "symbol not found")) +(define config-eval-error (localized-string 20006 'en_US "unable to read/eval config")) +(define invalid-section-type (localized-string 20007 'en_US "invalid section type")) +(define container-init-error (localized-string 20008 'en_US "container init error")) +(define invalid-container-type (localized-string 20009 'en_US "invalid container type")) +(define spec-section-custom-name (localized-string 20010 'en_US "specification section cannot use custom name")) +(define not-implemented (localized-string 20011 'en_US "not implemented")) +(define invalid-machine (localized-string 20012 'en_US "invalid machine type")) +(define invalid-output-type (localized-string 20013 'en_US "invalid output type")) +(define cannot-map-section-name (localized-string 20014 'en_US "cannot map section name")) +(define section-not-found (localized-string 20015 'en_US "section not found")) +(define invalid-input-type (localized-string 20016 'en_US "invalid input type")) +(define not-ar-long-name (localized-string 20017 'en_US "not ar long name")) +(define sect-entry-out-of-bounds (localized-string 20018 'en_US "section entry out-of-bounds")) +(define bad-cv-signature (localized-string 20019 'en_US "bad CV signature")) +(define missing-linked-section (localized-string 20020 'en_US "missing linked section")) +(define custom-sect-missing-sym (localized-string 20021 'en_US "custom section missing symbol")) +(define invalid-file-type (localized-string 20022 'en_US "invalid file type")) +(define elf-unsupported-section (localized-string 20023 'en_US "elf unsupported section")) +(define invalid-reloc-type (localized-string 20024 'en_US "invalid relocation type")) + +;; errors +(localized-error read-error 'en_US 'BF001 read-error) +(localized-error write-error 'en_US 'BF002 write-error) +(localized-error import-failure 'en_US 'BF003 import-failure) +(localized-error duplicate-import 'en_US 'BF004 duplicate-import) +(localized-error duplicate-symbol 'en_US 'BF005 duplicate-symbol) +(localized-error symbol-not-found 'en_US 'BF006 symbol-not-found) +(localized-error config-eval-error 'en_US 'BF007 config-eval-error) +(localized-error invalid-section-type 'en_US 'BF008 invalid-section-type) +(localized-error container-init-error 'en_US 'BF009 container-init-error) +(localized-error invalid-container-type 'en_US 'BF010 invalid-container-type) +(localized-error spec-section-custom-name 'en_US 'BF011 spec-section-custom-name) +(localized-error not-implemented 'en_US 'BF012 not-implemented) +(localized-error invalid-machine 'en_US 'BF013 invalid-machine) +(localized-error invalid-output-type 'en_US 'BF014 invalid-output-type) +(localized-error cannot-map-section-name 'en_US 'BF015 cannot-map-section-name) +(localized-error section-not-found 'en_US 'BF016 section-not-found) +(localized-error invalid-input-type 'en_US 'BF017 invalid-input-type) +(localized-error not-ar-long-name 'en_US 'BF018 not-ar-long-name) +(localized-error sect-entry-out-of-bounds 'en_US 'BF019 sect-entry-out-of-bounds) +(localized-error bad-cv-signature 'en_US 'BF020 bad-cv-signature) +(localized-error missing-linked-section 'en_US 'BF021 missing-linked-section) +(localized-error custom-sect-missing-sym 'en_US 'BF022 custom-sect-missing-sym) +(localized-error invalid-file-type 'en_US 'BF023 invalid-file-type) +(localized-error elf-unsupported-section 'en_US 'BF024 elf-unsupported-section) +(localized-error invalid-reloc-type 'en_US 'BF025 invalid-reloc-type) + diff --git a/etc/binfmt-tests.scm b/etc/binfmt-tests.scm new file mode 100644 index 00000000..976724b5 --- /dev/null +++ b/etc/binfmt-tests.scm @@ -0,0 +1,22 @@ +;; ---------------------------------------------------------------------------- +;; ____ _ +;; | _\ | | +;; | |_)| __ _ ___ ___ ___ ___ __| | ___ TM +;; | _< / _` / __|/ _ \/ __/ _ \ / _` |/ _ \ +;; | |_)| (_| \__ \ __/ (_| (_) | (_| | __/ +;; |____/\__,_|___/\___|\___\___/ \__,_|\___| +;; +;; F O U N D A T I O N P R O J E C T +;; +;; Copyright (C) 2017-2021 Jeff Panici +;; All rights reserved. +;; +;; This software source file is licensed under the terms of MIT license. +;; For details, please read the LICENSE file. +;; +;; ---------------------------------------------------------------------------- + +(define binfmt-tests (lambda () + nil)) + +(binfmt-tests) diff --git a/etc/binfmt.scm b/etc/binfmt.scm new file mode 100644 index 00000000..30a0bff9 --- /dev/null +++ b/etc/binfmt.scm @@ -0,0 +1,19 @@ +;; ---------------------------------------------------------------------------- +;; ____ _ +;; | _\ | | +;; | |_)| __ _ ___ ___ ___ ___ __| | ___ TM +;; | _< / _` / __|/ _ \/ __/ _ \ / _` |/ _ \ +;; | |_)| (_| \__ \ __/ (_| (_) | (_| | __/ +;; |____/\__,_|___/\___|\___\___/ \__,_|\___| +;; +;; F O U N D A T I O N P R O J E C T +;; +;; Copyright (C) 2017-2021 Jeff Panici +;; All rights reserved. +;; +;; This software source file is licensed under the terms of MIT license. +;; For details, please read the LICENSE file. +;; +;; ---------------------------------------------------------------------------- + +(load "binfmt-localization.scm") diff --git a/etc/core-localization.scm b/etc/core-localization.scm new file mode 100644 index 00000000..6c21e159 --- /dev/null +++ b/etc/core-localization.scm @@ -0,0 +1,153 @@ +;; ---------------------------------------------------------------------------- +;; ____ _ +;; | _\ | | +;; | |_)| __ _ ___ ___ ___ ___ __| | ___ TM +;; | _< / _` / __|/ _ \/ __/ _ \ / _` |/ _ \ +;; | |_)| (_| \__ \ __/ (_| (_) | (_| | __/ +;; |____/\__,_|___/\___|\___\___/ \__,_|\___| +;; +;; F O U N D A T I O N P R O J E C T +;; +;; Copyright (C) 2017-2021 Jeff Panici +;; All rights reserved. +;; +;; This software source file is licensed under the terms of MIT license. +;; For details, please read the LICENSE file. +;; +;; ---------------------------------------------------------------------------- + +;; strings +(define str:ok (localized-string 0 'en_US "ok")) + +(define str:buf-unable_to_open_file (localized-string 100 'en_US "buf: unable to open file")) + +(define str:eav-error (localized-string 101 'en_US "eav: error")) +(define str:eav-not-found (localized-string 102 'en_US "eav: not found")) +(define str:eav-sql-error (localized-string 103 'en_US "eav: sql error")) +(define str:eav-invalid-rowid (localized-string 104 'en_US "eav: invalid rowid")) +(define str:eav-invalid-entity (localized-string 105 'en_US "eav: invalid entity")) + +(define str:event-error (localized-string 106 'en_US "event: error")) +(define str:event-timeout (localized-string 107 'en_US "event: timeout")) + +(define str:ffi-addr-null (localized-string 108 'en_US "ffi: address null")) +(define str:ffi-proto-null (localized-string 109 'en_US "ffi: prototype null")) +(define str:ffi-lib-not-loaded (localized-string 110 'en_US "ffi: lib not loaded")) +(define str:ffi-symbol-not-found (localized-string 111 'en_US "ffi: symbol not found")) +(define str:ffi-invalid-int-sz (localized-string 112 'en_US "ffi: invalid int size")) +(define str:ffi-invalid-float-sz (localized-string 113 'en_US "ffi: invalid float size")) +(define str:ffi-load-failure (localized-string 114 'en_US "ffi: load library failure")) +(define str:ffi-sbv-not-impl (localized-string 115 'en_US "ffi: struct by value not implemented")) + +(define str:fs-not-dir (localized-string 116 'en_US "filesys: not dir")) +(define str:fs-not-file (localized-string 117 'en_US "filesys: not file")) +(define str:fs-not-exists (localized-string 118 'en_US "filesys: not exists")) +(define str:fs-invalid-dir (localized-string 119 'en_US "filesys: invalid dir")) +(define str:fs-chdir-failure (localized-string 120 'en_US "filesys: chdir failure")) +(define str:fs-file-writable (localized-string 121 'en_US "filesys: file writable")) +(define str:fs-mkdir-failure (localized-string 122 'en_US "filesys: mkdir failure")) +(define str:fs-getcwd-failure (localized-string 123 'en_US "filesys: getcwd failure")) +(define str:fs-rename-failure (localized-string 124 'en_US "filesys: rename failure")) +(define str:fs-remove-failure (localized-string 125 'en_US "filesys: remove failure")) +(define str:fs-not-equivalent (localized-string 126 'en_US "filesys: not equivalent")) +(define str:fs-mkdtemp-failure (localized-string 127 'en_US "filesys: mkdtemp failure")) +(define str:fs-not-implemented (localized-string 128 'en_US "filesys: not implemented")) +(define str:fs-unexpected-path (localized-string 129 'en_US "filesys: unexpected path")) +(define str:fs-realpath-failure (localized-string 130 'en_US "filesys: realpath failure")) +(define str:fs-cannot-modify-root (localized-string 131 'en_US "filesys: cannot modify root")) +(define str:fs-empty-path (localized-string 132 'en_US "filesys: unexpected empty path")) +(define str:fs-rename-to-existing (localized-string 133 'en_US "filesys: cannot rename to existing file")) + +(define str:forth-error (localized-string 134 'en_US "forth: error")) + +(define str:intern-no-bucket (localized-string 135 'en_US "intern: no bucket")) +(define str:intern-not-found (localized-string 136 'en_US "intern: not found")) + +(define str:ipc-error (localized-string 137 'en_US "ipc: error")) + +(define str:job-busy (localized-string 138 'en_US "job: busy")) +(define str:job-error (localized-string 139 'en_US "job: error")) +(define str:job-invalid-job-id (localized-string 140 'en_US "job: invalid job id")) +(define str:job-invalid-job-state (localized-string 141 'en_US "job: invalid job state")) +(define str:job-label-intern-failure (localized-string 142 'en_US "job: label intern failure")) + +(define str:mutex-busy (localized-string 143 'en_US "mutex: busy")) +(define str:mutex-error (localized-string 144 'en_US "mutex: error")) +(define str:mutex-invalid-mutex (localized-string 145 'en_US "mutex: invalid mutex")) +(define str:mutex-out-of-memory (localized-string 146 'en_US "mutex: out of memory")) +(define str:mutex-create-failure (localized-string 147 'en_US "mutex: create mutex failure")) +(define str:mutex-insufficient-priv (localized-string 148 'en_US "mutex: insufficient privilege")) +(define str:mutex-thread-owns-lock (localized-string 149 'en_US "mutex: thread already owns lock")) + +(define str:net-bind-failure (localized-string 150 'en_US "net: bind failure")) +(define str:net-listen-failure (localized-string 151 'en_US "net: listen failure")) +(define str:net-connect-failure (localized-string 152 'en_US "net: connect failure")) +(define str:net-dgram-error (localized-string 153 'en_US "net: socket dgram error")) +(define str:net-already-open (localized-string 154 'en_US "net: socket already open")) +(define str:net-winsock-init-failure (localized-string 155 'en_US "net: winsock init failure")) +(define str:net-socket-closed (localized-string 156 'en_US "net: socket already closed")) +(define str:net-invalid-bind (localized-string 157 'en_US "net: invalid address and port")) +(define str:net-opt-broadcast-err (localized-string 158 'en_US "net: socket option broadcast error")) + +(define str:path-too-long (localized-string 159 'en_US "path: too long")) +(define str:path-no-parent (localized-string 160 'en_US "path: no parent path")) +(define str:path-empty (localized-string 161 'en_US "path: unexpected empty path")) +(define str:path-expected-relative (localized-string 162 'en_US "path: expected relative path")) +(define str:path-empty-ext (localized-string 163 'en_US "path: unexpected empty extension")) + +(define str:prof-no_cpu_rtdscp (localized-string 164 'en_US "profiler: no cpu rtdscp support")) +(define str:prof-no_cpu_invariant (localized-string 165 'en_US "profiler: no cpu invariant tsc support")) + +(define str:thread-error (localized-string 167 'en_US "thread: error")) +(define str:thread-deadlock (localized-string 168 'en_US "thread: deadlock")) +(define str:thread-not-joinable (localized-string 169 'en_US "thread: not joinable")) +(define str:thread-invalid-state (localized-string 170 'en_US "thread: invalid state")) +(define str:thread-name-too-long (localized-string 171 'en_US "thread: name too long")) +(define str:thread-invalid-thread (localized-string 172 'en_US "thread: invalid thread")) +(define str:thread-already-joined (localized-string 173 'en_US "thread: already joined")) +(define str:thread-not-cancelable (localized-string 174 'en_US "thread: not cancelable")) +(define str:thread-already-canceled (localized-string 175 'en_US "thread: already canceled")) +(define str:thread-already-detached (localized-string 176 'en_US "thread: already detached")) +(define str:thread-create-thread (localized-string 177 'en_US "thread: create thread failure")) +(define str:thread-insuff-privilege (localized-string 178 'en_US "thread: insufficient privilege")) + +(define str:timer-error (localized-string 179 'en_US "timer: error")) + +(define str:cxx-error (localized-string 180 'en-US "cxx: error")) +(define str:cxx-lhs-not-found (localized-string 181 'en-US "cxx: lhs not found")) +(define str:cxx-rhs-not-found (localized-string 182 'en-US "cxx: rhs not found")) +(define str:cxx-pgm-not-found (localized-string 183 'en-US "cxx: pgm not found")) +(define str:cxx-list-not-found (localized-string 184 'en-US "cxx: list not found")) +(define str:cxx-scope-not-found (localized-string 185 'en-US "cxx: scope not found")) +(define str:cxx-label-not-found (localized-string 186 'en-US "cxx: label not found")) +(define str:cxx-child-not-found (localized-string 187 'en-US "cxx: child not found")) +(define str:cxx-invalid-pp-type (localized-string 188 'en-US "cxx: invalid pp type")) +(define str:cxx-intern-not-found (localized-string 189 'en-US "cxx: intern not found")) +(define str:cxx-invalid-revision (localized-string 190 'en-US "cxx: invalid revision")) +(define str:cxx-invalid-pos-type (localized-string 191 'en-US "cxx: invalid pos type")) +(define str:cxx-element-not-found (localized-string 192 'en-US "cxx: element not found")) +(define str:cxx-invalid-meta-type (localized-string 193 'en-US "cxx: invalid meta type")) +(define str:cxx-invalid-list-entry (localized-string 194 'en-US "cxx: invalid list entry")) +(define str:cxx-invalid-def-element (localized-string 195 'en-US "cxx: invalid def element")) +(define str:cxx-invalid-decl-element (localized-string 196 'en-US "cxx: invalid decl element")) +(define str:cxx-invalid-expr-element (localized-string 197 'en-US "cxx: invalid expr element")) +(define str:cxx-unsupported-revision (localized-string 198 'en-US "cxx: unsupported revision")) +(define str:cxx-not-implemented (localized-string 199 'en-US "cxx: not implemented")) + +(define str:rpn-error (localized-string 200 'en_US "rpn: error")) +(define str:rpn-invalid-array (localized-string 201 'en_US "rpn: invalid operator precedence array")) + +;; job states +(define str:job-state-queued (localized-string 250 'en_US "queued")) +(define str:job-state-created (localized-string 251 'en_US "created")) +(define str:job-state-running (localized-string 252 'en_US "running")) +(define str:job-state-finished (localized-string 253 'en_US "finished")) + +;; log types +(define str:log-type-default (localized-string 240 'en_US "default")) +(define str:log-type-spdlog (localized-string 241 'en_US "spdlog")) +(define str:log-type-syslog (localized-string 242 'en_US "syslog")) + +;; errors + + diff --git a/etc/core-tests.scm b/etc/core-tests.scm new file mode 100644 index 00000000..13a018eb --- /dev/null +++ b/etc/core-tests.scm @@ -0,0 +1,128 @@ +;; ---------------------------------------------------------------------------- +;; ____ _ +;; | _\ | | +;; | |_)| __ _ ___ ___ ___ ___ __| | ___ TM +;; | _< / _` / __|/ _ \/ __/ _ \ / _` |/ _ \ +;; | |_)| (_| \__ \ __/ (_| (_) | (_| | __/ +;; |____/\__,_|___/\___|\___\___/ \__,_|\___| +;; +;; F O U N D A T I O N P R O J E C T +;; +;; Copyright (C) 2017-2021 Jeff Panici +;; All rights reserved. +;; +;; This software source file is licensed under the terms of MIT license. +;; For details, please read the LICENSE file. +;; +;; ---------------------------------------------------------------------------- + +(define fizz-buzz-test (lambda () + (define fizz-buzz 0) + (define fizz 0) + (define buzz 0) + (define numbers 0) + (for n (range 1 50 1) + (cond + [(is (mod n 15) 0) (set! fizz-buzz (add1 fizz-buzz))] + [(is (mod n 3) 0) (set! fizz (add1 fizz))] + [(is (mod n 5) 0) (set! buzz (add1 buzz))] + [else (set! numbers (add1 numbers))])) + `((fizz-buzz . ,fizz-buzz) (fizz . ,fizz) (buzz . ,buzz) (numbers . ,numbers)))) + +(define core-tests (lambda () + ; basic assertions around scheme terp + (test-suite "scheme terp basic assertions" + (assert '(is '((fizz-buzz . 3) (fizz . 13) (buzz . 7) (numbers . 27)) (fizz-buzz-test))) + (assert '(< "a" "b")) + (assert '(> "j" "i")) + (assert '(is 15 (and 3 5 15))) + (assert '(is 2 (or nil 2 nil 4 nil 6))) + (assert '(is 5 (length '(1 2 3 4 5)))) + (assert '(is 2 2)) + (assert '(not (> 2 9))) + (assert '(>= 2 2)) + (assert '(is (mod 10 2) 0)) + (assert '(is '(10 20) + (begin + (define a 10) + (define b 20) + `(,a ,b)))) + (assert '(is '(10 20 30) + (begin + (define a 10) + (define b 20) + `(,a ,b ,(+ a b))))) + (assert '(is '(0 1 2 3 4 5) + `(0 1 ,@(list 2 3 4) 5))) + (assert '(is 300 (eval '(+ 100 200)))) + (assert '(is 42 (begin (define a 42) (eval 'a)))) + (assert '(is 15 (begin + (define sum 0) + (define expr '(for x (list 1 2 3 4 5) + (set! sum (+ sum x)))) + (eval expr) + sum))) + (assert '(> (begin + (define count 0) + (for arg (current-command-line) + (set! count (add1 count))) + count) + 0))) + + (test-suite "scheme + config module integration" + (assert '(is "Basecode Foundation Core Library" *product-name*)) + (assert '(is 0 *version-major*)) + (assert '(is 1 *version-minor*)) + (assert '(is 0 *version-revision*)) + (assert '(begin + (or (is "Debug" *build-type*) + (is "RelWithDebInfo" *build-type*) + (is "Release" *build-type*)))) + (assert '(begin + (or (is "Windows" *platform*) + (is "Linux" *platform*)))) + (assert '(is #t *test-runner*)) + + ; N.B. these initial values come from libcore-test's main.cpp + ; when it sets up the test runner. + (assert '(is #t *enable-console-color*)) + (assert '(is "/var/log" *log-path*)) + (assert '(is 47.314 *magick-weight*)) + + (set! *enable-console-color* #f) + (set! *log-path* "/var/log/basecode") + (set! *magick-weight* 12.6566) + + (assert '(is #f *enable-console-color*)) + (assert '(is "/var/log/basecode" *log-path*)) + (assert '(is 12.6566 *magick-weight*)) + (assert '(is #t (begin + (localized-string 5000 'en_US "US: test localized string: 0={} 1={} 2={}") + (localized-string 5001 'en_US "duplicate cvar") + (localized-string 5002 'en_US "cvar not found") + (localized-string 5003 'en_US "invalid modification of constant: {}") + (localized-string 5004 'en_GB "GB: test localized string: 0={} 1={} 2={}") + + (define str:undecl-msg (localized-string 5005 'en_US "undeclared identifier: {}")) + (localized-error 5000 'en_US 'BC001 str:undecl-msg) + #t))) + ))) + +(core-tests) +(begin + (define color-logger (log-create-color 'out)) + (define syslog-logger (syslog-create "bc-libcore-tests" + (list 'opt-pid 'opt-ndelay 'opt-cons 'opt-perror) + 'local0)) + (define basic-file-logger (log-create-basic-file "test.log")) + (define daily-file-logger (log-create-daily-file "daily.log" 23 0)) + (define rotating-file-logger (log-create-rotating-file "rotating.log" + (* 256 1024) + 256)) + + (logger-append-child (current-logger) color-logger) + (logger-append-child (current-logger) basic-file-logger) + (logger-append-child (current-logger) daily-file-logger) + (logger-append-child (current-logger) rotating-file-logger) + (logger-append-child (current-logger) syslog-logger)) + diff --git a/etc/core.fe b/etc/core.fe deleted file mode 100644 index 0977da47..00000000 --- a/etc/core.fe +++ /dev/null @@ -1,221 +0,0 @@ -;; ------------------------------------------------------------- -;; -;; support macros / functions -;; -;; ------------------------------------------------------------- -(= for (mac (item lst . body) - (list 'do - (list 'let 'for-iter lst) - (list 'while 'for-iter - (list 'let item '(car for-iter)) - '(= for-iter (cdr for-iter)) - (cons 'do body) - ) - ) -)) - -;; ------------------------------------------------------------- -;; -;; localization -;; -;; ------------------------------------------------------------- - -;; strings -(= str:ok (localized-string 0 'en_US "ok")) - -(= str:buf-unable_to_open_file (localized-string 100 'en_US "buf: unable to open file")) - -(= str:eav-error (localized-string 101 'en_US "eav: error")) -(= str:eav-not-found (localized-string 102 'en_US "eav: not found")) -(= str:eav-sql-error (localized-string 103 'en_US "eav: sql error")) -(= str:eav-invalid-rowid (localized-string 104 'en_US "eav: invalid rowid")) -(= str:eav-invalid-entity (localized-string 105 'en_US "eav: invalid entity")) - -(= str:event-error (localized-string 106 'en_US "event: error")) -(= str:event-timeout (localized-string 107 'en_US "event: timeout")) - -(= str:ffi-addr-null (localized-string 108 'en_US "ffi: address null")) -(= str:ffi-proto-null (localized-string 109 'en_US "ffi: prototype null")) -(= str:ffi-lib-not-loaded (localized-string 110 'en_US "ffi: lib not loaded")) -(= str:ffi-symbol-not-found (localized-string 111 'en_US "ffi: symbol not found")) -(= str:ffi-invalid-int-sz (localized-string 112 'en_US "ffi: invalid int size")) -(= str:ffi-invalid-float-sz (localized-string 113 'en_US "ffi: invalid float size")) -(= str:ffi-load-failure (localized-string 114 'en_US "ffi: load library failure")) -(= str:ffi-sbv-not-impl (localized-string 115 'en_US "ffi: struct by value not implemented")) - -(= str:fs-not-dir (localized-string 116 'en_US "filesys: not dir")) -(= str:fs-not-file (localized-string 117 'en_US "filesys: not file")) -(= str:fs-not-exists (localized-string 118 'en_US "filesys: not exists")) -(= str:fs-invalid-dir (localized-string 119 'en_US "filesys: invalid dir")) -(= str:fs-chdir-failure (localized-string 120 'en_US "filesys: chdir failure")) -(= str:fs-file-writable (localized-string 121 'en_US "filesys: file writable")) -(= str:fs-mkdir-failure (localized-string 122 'en_US "filesys: mkdir failure")) -(= str:fs-getcwd-failure (localized-string 123 'en_US "filesys: getcwd failure")) -(= str:fs-rename-failure (localized-string 124 'en_US "filesys: rename failure")) -(= str:fs-remove-failure (localized-string 125 'en_US "filesys: remove failure")) -(= str:fs-not-equivalent (localized-string 126 'en_US "filesys: not equivalent")) -(= str:fs-mkdtemp-failure (localized-string 127 'en_US "filesys: mkdtemp failure")) -(= str:fs-not-implemented (localized-string 128 'en_US "filesys: not implemented")) -(= str:fs-unexpected-path (localized-string 129 'en_US "filesys: unexpected path")) -(= str:fs-realpath-failure (localized-string 130 'en_US "filesys: realpath failure")) -(= str:fs-cannot-modify-root (localized-string 131 'en_US "filesys: cannot modify root")) -(= str:fs-empty-path (localized-string 132 'en_US "filesys: unexpected empty path")) -(= str:fs-rename-to-existing (localized-string 133 'en_US "filesys: cannot rename to existing file")) - -(= str:forth-error (localized-string 134 'en_US "forth: error")) - -(= str:intern-no-bucket (localized-string 135 'en_US "intern: no bucket")) -(= str:intern-not-found (localized-string 136 'en_US "intern: not found")) - -(= str:ipc-error (localized-string 137 'en_US "ipc: error")) - -(= str:job-busy (localized-string 138 'en_US "job: busy")) -(= str:job-error (localized-string 139 'en_US "job: error")) -(= str:job-invalid-job-id (localized-string 140 'en_US "job: invalid job id")) -(= str:job-invalid-job-state (localized-string 141 'en_US "job: invalid job state")) -(= str:job-label-intern-failure (localized-string 142 'en_US "job: label intern failure")) - -(= str:mutex-busy (localized-string 143 'en_US "mutex: busy")) -(= str:mutex-error (localized-string 144 'en_US "mutex: error")) -(= str:mutex-invalid-mutex (localized-string 145 'en_US "mutex: invalid mutex")) -(= str:mutex-out-of-memory (localized-string 146 'en_US "mutex: out of memory")) -(= str:mutex-create-failure (localized-string 147 'en_US "mutex: create mutex failure")) -(= str:mutex-insufficient-priv (localized-string 148 'en_US "mutex: insufficient privilege")) -(= str:mutex-thread-owns-lock (localized-string 149 'en_US "mutex: thread already owns lock")) - -(= str:net-bind-failure (localized-string 150 'en_US "net: bind failure")) -(= str:net-listen-failure (localized-string 151 'en_US "net: listen failure")) -(= str:net-connect-failure (localized-string 152 'en_US "net: connect failure")) -(= str:net-dgram-error (localized-string 153 'en_US "net: socket dgram error")) -(= str:net-already-open (localized-string 154 'en_US "net: socket already open")) -(= str:net-winsock-init-failure (localized-string 155 'en_US "net: winsock init failure")) -(= str:net-socket-closed (localized-string 156 'en_US "net: socket already closed")) -(= str:net-invalid-bind (localized-string 157 'en_US "net: invalid address and port")) -(= str:net-opt-broadcast-err (localized-string 158 'en_US "net: socket option broadcast error")) - -(= str:path-too-long (localized-string 159 'en_US "path: too long")) -(= str:path-no-parent (localized-string 160 'en_US "path: no parent path")) -(= str:path-empty (localized-string 161 'en_US "path: unexpected empty path")) -(= str:path-expected-relative (localized-string 162 'en_US "path: expected relative path")) -(= str:path-empty-ext (localized-string 163 'en_US "path: unexpected empty extension")) - -(= str:prof-no_cpu_rtdscp (localized-string 164 'en_US "profiler: no cpu rtdscp support")) -(= str:prof-no_cpu_invariant (localized-string 165 'en_US "profiler: no cpu invariant tsc support")) - -(= str:thread-error (localized-string 167 'en_US "thread: error")) -(= str:thread-deadlock (localized-string 168 'en_US "thread: deadlock")) -(= str:thread-not-joinable (localized-string 169 'en_US "thread: not joinable")) -(= str:thread-invalid-state (localized-string 170 'en_US "thread: invalid state")) -(= str:thread-name-too-long (localized-string 171 'en_US "thread: name too long")) -(= str:thread-invalid-thread (localized-string 172 'en_US "thread: invalid thread")) -(= str:thread-already-joined (localized-string 173 'en_US "thread: already joined")) -(= str:thread-not-cancelable (localized-string 174 'en_US "thread: not cancelable")) -(= str:thread-already-canceled (localized-string 175 'en_US "thread: already canceled")) -(= str:thread-already-detached (localized-string 176 'en_US "thread: already detached")) -(= str:thread-create-thread (localized-string 177 'en_US "thread: create thread failure")) -(= str:thread-insuff-privilege (localized-string 178 'en_US "thread: insufficient privilege")) - -(= str:timer-error (localized-string 179 'en_US "timer: error")) - -(= str:cxx-error (localized-string 180 'en-US "cxx: error")) -(= str:cxx-lhs-not-found (localized-string 181 'en-US "cxx: lhs not found")) -(= str:cxx-rhs-not-found (localized-string 182 'en-US "cxx: rhs not found")) -(= str:cxx-pgm-not-found (localized-string 183 'en-US "cxx: pgm not found")) -(= str:cxx-list-not-found (localized-string 184 'en-US "cxx: list not found")) -(= str:cxx-scope-not-found (localized-string 185 'en-US "cxx: scope not found")) -(= str:cxx-label-not-found (localized-string 186 'en-US "cxx: label not found")) -(= str:cxx-child-not-found (localized-string 187 'en-US "cxx: child not found")) -(= str:cxx-invalid-pp-type (localized-string 188 'en-US "cxx: invalid pp type")) -(= str:cxx-intern-not-found (localized-string 189 'en-US "cxx: intern not found")) -(= str:cxx-invalid-revision (localized-string 190 'en-US "cxx: invalid revision")) -(= str:cxx-invalid-pos-type (localized-string 191 'en-US "cxx: invalid pos type")) -(= str:cxx-element-not-found (localized-string 192 'en-US "cxx: element not found")) -(= str:cxx-invalid-meta-type (localized-string 193 'en-US "cxx: invalid meta type")) -(= str:cxx-invalid-list-entry (localized-string 194 'en-US "cxx: invalid list entry")) -(= str:cxx-invalid-def-element (localized-string 195 'en-US "cxx: invalid def element")) -(= str:cxx-invalid-decl-element (localized-string 196 'en-US "cxx: invalid decl element")) -(= str:cxx-invalid-expr-element (localized-string 197 'en-US "cxx: invalid expr element")) -(= str:cxx-unsupported-revision (localized-string 198 'en-US "cxx: unsupported revision")) -(= str:cxx-not-implemented (localized-string 199 'en-US "cxx: not implemented")) - -(= str:rpn-error (localized-string 200 'en_US "rpn: error")) -(= str:rpn-invalid-array (localized-string 201 'en_US "rpn: invalid operator precedence array")) - -;; job states -(= str:job-state-queued (localized-string 250 'en_US "queued")) -(= str:job-state-created (localized-string 251 'en_US "created")) -(= str:job-state-running (localized-string 252 'en_US "running")) -(= str:job-state-finished (localized-string 253 'en_US "finished")) - -;; log types -(= str:log-type-default (localized-string 240 'en_US "default")) -(= str:log-type-spdlog (localized-string 241 'en_US "spdlog")) -(= str:log-type-syslog (localized-string 242 'en_US "syslog")) - -;; errors - - -;; ------------------------------------------------------------- -;; -;; test runner support -;; -;; ------------------------------------------------------------- -(if (cvar-ref cvar:test-runner) - (do - (localized-string 5000 'en_US "US: test localized string: 0={} 1={} 2={}") - (localized-string 5001 'en_US "duplicate cvar") - (localized-string 5002 'en_US "cvar not found") - (localized-string 5003 'en_US "invalid modification of constant: {}") - (localized-string 5004 'en_GB "GB: test localized string: 0={} 1={} 2={}") - - (let str:undecl-msg (localized-string 5005 'en_US "undeclared identifier: {}")) - (localized-error 5000 'en_US 'BC001 str:undecl-msg) - - (do - (log-info "product-name = {}" (cvar-ref cvar:product-name)) - (log-info "version-major = {}" (cvar-ref cvar:version-major)) - (log-info "version-minor = {}" (cvar-ref cvar:version-minor)) - (log-info "version-revision = {}" (cvar-ref cvar:version-revision)) - (log-info "build-type = {}" (cvar-ref cvar:build-type)) - (log-info "platform = {}" (cvar-ref cvar:platform)) - (log-info "test-runner = {}" (cvar-ref cvar:test-runner)) - - (let print-cvars (fn () - (print "enable-console-color =" (cvar-ref cvar:enable-console-color)) - (print "log-path =" (cvar-ref cvar:log-path)) - (print "magick-weight =" (cvar-ref cvar:magick-weight)))) - - (do - (let i 0) - (for arg (current-command-line) - (print i "=" arg) - (= i (+ i 1)))) - - (print-cvars) - - (cvar-set! cvar:enable-console-color nil) - (cvar-set! cvar:log-path "/var/log/basecode") - (cvar-set! cvar:magick-weight 12.6566) - - (print-cvars)) - - (do - (let parent-logger (current-logger)) - (let color-logger (log-create-color 'out)) - (let syslog-logger (syslog-create "bc-libcore-tests" - (list 'opt-pid 'opt-ndelay 'opt-cons 'opt-perror) - 'local0)) - (let basic-file-logger (log-create-basic-file "test.log")) - (let daily-file-logger (log-create-daily-file "daily.log" 23 0)) - (let rotating-file-logger (log-create-rotating-file "rotating.log" (* 256 1024) 256)) - - (logger-append-child parent-logger color-logger) - (logger-append-child parent-logger basic-file-logger) - (logger-append-child parent-logger daily-file-logger) - (logger-append-child parent-logger rotating-file-logger) - (logger-append-child parent-logger syslog-logger) - - (log-info "example log message!") - (log-warn "oh, shit!") - (log-error "this should really stick out")))) - diff --git a/etc/core.scm b/etc/core.scm new file mode 100644 index 00000000..a138e2f8 --- /dev/null +++ b/etc/core.scm @@ -0,0 +1,19 @@ +;; ---------------------------------------------------------------------------- +;; ____ _ +;; | _\ | | +;; | |_)| __ _ ___ ___ ___ ___ __| | ___ TM +;; | _< / _` / __|/ _ \/ __/ _ \ / _` |/ _ \ +;; | |_)| (_| \__ \ __/ (_| (_) | (_| | __/ +;; |____/\__,_|___/\___|\___\___/ \__,_|\___| +;; +;; F O U N D A T I O N P R O J E C T +;; +;; Copyright (C) 2017-2021 Jeff Panici +;; All rights reserved. +;; +;; This software source file is licensed under the terms of MIT license. +;; For details, please read the LICENSE file. +;; +;; ---------------------------------------------------------------------------- + +(load "core-localization.scm") diff --git a/etc/first.scm b/etc/first.scm new file mode 100644 index 00000000..dc081e29 --- /dev/null +++ b/etc/first.scm @@ -0,0 +1,33 @@ +;; ---------------------------------------------------------------------------- +;; ____ _ +;; | _\ | | +;; | |_)| __ _ ___ ___ ___ ___ __| | ___ TM +;; | _< / _` / __|/ _ \/ __/ _ \ / _` |/ _ \ +;; | |_)| (_| \__ \ __/ (_| (_) | (_| | __/ +;; |____/\__,_|___/\___|\___\___/ \__,_|\___| +;; +;; F O U N D A T I O N P R O J E C T +;; +;; Copyright (C) 2017-2021 Jeff Panici +;; All rights reserved. +;; +;; This software source file is licensed under the terms of MIT license. +;; For details, please read the LICENSE file. +;; +;; ---------------------------------------------------------------------------- + +(load "basic.scm") + +(print (format "Product: {}" *product-name*)) +(print (format "Version: {}.{}" *version-major* *version-minor*)) +(print (format "Platform: {}" *platform*)) + +(load "core.scm" + "binfmt.scm") + +(cond + [(is *product-name* "Basecode Foundation Core Library") + (load "core-tests.scm")] + + [(is *product-name* "Basecode Foundation Binary Format Library") + (load "binfmt-tests.scm")]) diff --git a/etc/hello.wasm b/etc/hello.wasm new file mode 100644 index 00000000..f17becca Binary files /dev/null and b/etc/hello.wasm differ diff --git a/etc/instructions.ig b/etc/instructions.ig index 01a0a616..a4b8ba71 100644 --- a/etc/instructions.ig +++ b/etc/instructions.ig @@ -8,7 +8,7 @@ // // V I R T U A L M A C H I N E P R O J E C T // -// Copyright (C) 2020 Jeff Panici +// Copyright (C) 2017-2021 Jeff Panici // All rights reserved. // // This software source file is licensed under the terms of MIT license. diff --git a/etc/lldb/basecode.py b/etc/lldb/basecode.py index bbdadbd6..97855847 100644 --- a/etc/lldb/basecode.py +++ b/etc/lldb/basecode.py @@ -90,12 +90,19 @@ def get_child_at_index(self, index): def __lldb_init_module(debugger, dict): log("in __lldb_init_module") - debugger.HandleCommand("type synthetic add -x \"basecode::array_t<.+>\" --python-class basecode.Array_Provider") - debugger.HandleCommand("type synthetic add -x \"basecode::stack_t<.+>\" --python-class basecode.Stack_Provider") + debugger.HandleCommand("type synthetic add -x \"basecode::array_t<.+>\" " + "--python-class basecode.Array_Provider") + debugger.HandleCommand("type synthetic add -x \"basecode::stack_t<.+>\" " + "--python-class basecode.Stack_Provider") + debugger.HandleCommand("type synthetic add -x \"basecode::stable_array_t<.+>\" " + "--python-class basecode.Array_Provider") debugger.HandleCommand("type summary add -e -h --summary-string " "\"alloc=${var.alloc} capacity=${var.capacity} size=${svar%#}\" " " -w basecode -x \"basecode::stack_t<.+>\"") debugger.HandleCommand("type summary add -e -h --summary-string " "\"alloc=${var.alloc} capacity=${var.capacity} size=${svar%#}\" " " -w basecode -x \"basecode::array_t<.+>\"") + debugger.HandleCommand("type summary add -e -h --summary-string " + "\"alloc=${var.alloc} capacity=${var.capacity} size=${svar%#}\" " + " -w basecode -x \"basecode::stable_array_t<.+>\"") debugger.HandleCommand("type category enable basecode") diff --git a/ext/asmjit-master/.editorconfig b/ext/asmjit-master/.editorconfig deleted file mode 100644 index 5a3a48d3..00000000 --- a/ext/asmjit-master/.editorconfig +++ /dev/null @@ -1,10 +0,0 @@ -# Editor configuration, see https://editorconfig.org for more details. -root = true - -[*.{cpp,h,natvis}] -charset = utf-8 -end_of_line = lf -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true diff --git a/ext/asmjit-master/.gitignore b/ext/asmjit-master/.gitignore deleted file mode 100644 index 34bbad2b..00000000 --- a/ext/asmjit-master/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.vscode -.kdev4 -*.kdev4 -build -build_* -tools/asmdb diff --git a/ext/asmjit-master/.travis.yml b/ext/asmjit-master/.travis.yml deleted file mode 100644 index 0d541e6c..00000000 --- a/ext/asmjit-master/.travis.yml +++ /dev/null @@ -1,343 +0,0 @@ -language: cpp - -git: - depth: false - -env: - global: - - BUILD_TOOLCHAIN="Unix Makefiles" - - MAKEFLAGS="-j2" - -dist: bionic - -matrix: - include: - - name: "Source Code Check" - env: BUILD_MATRIX="SOURCE_CODE_CHECK=1" - os: linux - language: node_js - node_js: - - node - - - name: "Linux Clang Default [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=clang-9 && CXX=clang++-9" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [clang++-9] - - - name: "Linux Clang Default [64-bit] [REL]" - env: BUILD_MATRIX="BUILD_TYPE=Release && CC=clang-9 && CXX=clang++-9" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [clang++-9] - - - name: "Linux Clang Default [64-bit] [REL] [Valgrind]" - env: BUILD_MATRIX="BUILD_TYPE=Release && CC=clang-9 && CXX=clang++-9" USE_VALGRIND=1 - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [clang++-9, valgrind] - - - name: "Linux Clang Default [64-bit] [REL] [Sanitize=Address]" - env: BUILD_MATRIX="BUILD_TYPE=Release && CC=clang-9 && CXX=clang++-9" EXTRA_OPTIONS="-DASMJIT_SANITIZE=address" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [clang++-9] - - - name: "Linux Clang Default [64-bit] [REL] [Sanitize=Undefined]" - env: BUILD_MATRIX="BUILD_TYPE=Release && CC=clang-9 && CXX=clang++-9" EXTRA_OPTIONS="-DASMJIT_SANITIZE=undefined" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [clang++-9] - - - name: "Linux Clang Default [64-bit] [REL] [NoDeprecated]" - env: BUILD_MATRIX="BUILD_TYPE=Release && CC=clang-9 && CXX=clang++-9" EXTRA_OPTIONS="-DASMJIT_NO_DEPRECATED=1" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [clang++-9] - - - name: "Linux Clang Default [64-bit] [REL] [NoIntrinsics]" - env: BUILD_MATRIX="BUILD_TYPE=Release && CC=clang-9 && CXX=clang++-9" EXTRA_OPTIONS="-DASMJIT_NO_INTRINSICS=1" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [clang++-9] - - - name: "Linux Clang Default [64-bit] [REL] [NoLogging]" - env: BUILD_MATRIX="BUILD_TYPE=Release && CC=clang-9 && CXX=clang++-9" EXTRA_OPTIONS="-DASMJIT_NO_LOGGING=1" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [clang++-9] - - - name: "Linux Clang Default [64-bit] [REL] [NoBuilder]" - env: BUILD_MATRIX="BUILD_TYPE=Release && CC=clang-9 && CXX=clang++-9" EXTRA_OPTIONS="-DASMJIT_NO_BUILDER=1" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [clang++-9] - - - name: "Linux Clang Default [64-bit] [REL] [NoCompiler]" - env: BUILD_MATRIX="BUILD_TYPE=Release && CC=clang-9 && CXX=clang++-9" EXTRA_OPTIONS="-DASMJIT_NO_COMPILER=1" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [clang++-9] - - - name: "Linux GCC 4.8 [32-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-4.8 && CXX=g++-4.8" CXXFLAGS=-m32 LDFLAGS=-m32 - os: linux - addons: - apt: - packages: [g++-4.8, g++-4.8-multilib, "linux-libc-dev:i386"] - - - name: "Linux GCC 4.8 [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-4.8 && CXX=g++-4.8" - os: linux - addons: - apt: - packages: [g++-4.8] - - - name: "Linux GCC 5 [32-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-5 && CXX=g++-5" CXXFLAGS=-m32 LDFLAGS=-m32 - os: linux - addons: - apt: - packages: [g++-5, g++-5-multilib, "linux-libc-dev:i386"] - - - name: "Linux GCC 5 [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-5 && CXX=g++-5" - os: linux - addons: - apt: - packages: [g++-5] - - - name: "Linux GCC 6 [32-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-6 && CXX=g++-6" CXXFLAGS=-m32 LDFLAGS=-m32 - os: linux - addons: - apt: - packages: [g++-6, g++-6-multilib, "linux-libc-dev:i386"] - - - name: "Linux GCC 6 [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-6 && CXX=g++-6" - os: linux - addons: - apt: - packages: [g++-6] - - - name: "Linux GCC 7 [32-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-7 && CXX=g++-7" CXXFLAGS=-m32 LDFLAGS=-m32 - os: linux - addons: - apt: - packages: [g++-7, g++-7-multilib, "linux-libc-dev:i386"] - - - name: "Linux GCC 7 [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-7 && CXX=g++-7" - os: linux - addons: - apt: - packages: [g++-7] - - - name: "Linux GCC 8 [32-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-8 && CXX=g++-8" CXXFLAGS=-m32 LDFLAGS=-m32 - os: linux - addons: - apt: - packages: [g++-8, g++-8-multilib, "linux-libc-dev:i386"] - - - name: "Linux GCC 8 [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-8 && CXX=g++-8" - os: linux - addons: - apt: - packages: [g++-8] - - - name: "Linux GCC 9 [32-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-9 && CXX=g++-9" CXXFLAGS=-m32 LDFLAGS=-m32 - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [g++-9, g++-9-multilib, "linux-libc-dev:i386"] - - - name: "Linux GCC 9 [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-9 && CXX=g++-9" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [g++-9] - - - name: "Linux GCC 10 [32-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-10 && CXX=g++-10" CXXFLAGS=-m32 LDFLAGS=-m32 - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [g++-10, g++-10-multilib, "linux-libc-dev:i386"] - - - name: "Linux GCC 10 [32-bit] [REL]" - env: BUILD_MATRIX="BUILD_TYPE=Release && CC=gcc-10 && CXX=g++-10" CXXFLAGS=-m32 LDFLAGS=-m32 - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [g++-10, g++-10-multilib, "linux-libc-dev:i386"] - - - name: "Linux GCC 10 [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug && CC=gcc-10 && CXX=g++-10" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [g++-10] - - - name: "Linux GCC 10 [64-bit] [REL]" - env: BUILD_MATRIX="BUILD_TYPE=Release && CC=gcc-10 && CXX=g++-10" - os: linux - addons: - apt: - sources: - - sourceline: "ppa:ubuntu-toolchain-r/test" - packages: [g++-10] - - - name: "OSX Clang XCode 9.4 [32-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug" CXXFLAGS=-m32 LDFLAGS=-m32 - os: osx - osx_image: xcode9.4 - - - name: "OSX Clang XCode 9.4 [32-bit] [REL]" - env: BUILD_MATRIX="BUILD_TYPE=Release" CXXFLAGS=-m32 LDFLAGS=-m32 - os: osx - osx_image: xcode9.4 - - - name: "OSX Clang XCode 9.4 [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug" - os: osx - osx_image: xcode9.4 - - - name: "OSX Clang XCode 9.4 [64-bit] [REL]" - env: BUILD_MATRIX="BUILD_TYPE=Release" - os: osx - osx_image: xcode9.4 - - - name: "OSX Clang XCode 10.2 [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug" - os: osx - osx_image: xcode10.2 - - - name: "OSX Clang XCode 10.2 [64-bit] [REL]" - env: BUILD_MATRIX="BUILD_TYPE=Release" - os: osx - osx_image: xcode10.2 - - - name: "OSX Clang XCode 11 [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug" - os: osx - osx_image: xcode11 - - - name: "OSX Clang XCode 11 [64-bit] [REL]" - env: BUILD_MATRIX="BUILD_TYPE=Release" - os: osx - osx_image: xcode11 - - - name: "Windows VS2017 [32-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug" BUILD_TOOLCHAIN="Visual Studio 15 2017" - os: windows - - - name: "Windows VS2017 [32-bit] [REL]" - env: BUILD_MATRIX="BUILD_TYPE=Release" BUILD_TOOLCHAIN="Visual Studio 15 2017" - os: windows - - - name: "Windows VS2017 [64-bit] [DBG]" - env: BUILD_MATRIX="BUILD_TYPE=Debug" BUILD_TOOLCHAIN="Visual Studio 15 2017 Win64" - os: windows - - - name: "Windows VS2017 [64-bit] [REL]" - env: BUILD_MATRIX="BUILD_TYPE=Release" BUILD_TOOLCHAIN="Visual Studio 15 2017 Win64" - os: windows - -before_install: - - eval "$BUILD_MATRIX" - -before_script: - - | - if [ -z $SOURCE_CODE_CHECK ]; then - mkdir build - cd build - if [[ "$BUILD_TOOLCHAIN" =~ ^Visual\ Studio ]]; then - cmake .. -G"${BUILD_TOOLCHAIN}" -DASMJIT_TEST=1 ${EXTRA_OPTIONS} - else - cmake .. -G"${BUILD_TOOLCHAIN}" -DASMJIT_TEST=1 ${EXTRA_OPTIONS} -DCMAKE_PREFIX_PATH="${MINGW_PATH}" -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" - fi - cd .. - fi - -script: - - | - if [ -z $SOURCE_CODE_CHECK ]; then - cd build - if [[ "$BUILD_TOOLCHAIN" =~ ^Visual\ Studio ]]; then - cmake --build . --config ${BUILD_TYPE} -- -nologo -v:minimal || exit 1 - cd ${BUILD_TYPE} - else - cmake --build . || exit 1 - fi - echo "" - echo "=== Starting Tests ===" - echo "" - if [ "$USE_VALGRIND" = "1" ]; then - RUN_CMD="valgrind --leak-check=full --show-reachable=yes --track-origins=yes" - fi - eval "$RUN_CMD ./asmjit_test_unit --quick" || exit 1 - echo "" - eval "$RUN_CMD ./asmjit_test_opcode > /dev/null" || exit 1 - echo "" - eval "$RUN_CMD ./asmjit_test_x86_asm" || exit 1 - echo "" - eval "$RUN_CMD ./asmjit_test_x86_sections" || exit 1 - if [ -f ./asmjit_test_x86_instinfo ]; then - echo "" - eval "$RUN_CMD ./asmjit_test_x86_instinfo" || exit 1 - fi - if [ -f ./asmjit_test_x86_cc ]; then - echo "" - eval "$RUN_CMD ./asmjit_test_x86_cc" || exit 1 - fi - else - cd tools - ./enumgen.sh --verify || exit 1 - cd .. - fi diff --git a/ext/asmjit-master/CMakeLists.txt b/ext/asmjit-master/CMakeLists.txt deleted file mode 100644 index e033c3ff..00000000 --- a/ext/asmjit-master/CMakeLists.txt +++ /dev/null @@ -1,532 +0,0 @@ -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -cmake_policy(PUSH) - -if(POLICY CMP0063) - cmake_policy(SET CMP0063 NEW) # Honor visibility properties. -endif() - -if(POLICY CMP0092) - cmake_policy(SET CMP0092 NEW) # Don't add -W3 warning level by default. -endif() - -include(CheckCXXCompilerFlag) - -# Don't create a project if it was already created by another CMakeLists.txt. -# This allows one library to embed another library without making a collision. -if (NOT CMAKE_PROJECT_NAME OR "${CMAKE_PROJECT_NAME}" STREQUAL "asmjit") - project(asmjit CXX) -endif() - -# ============================================================================= -# [AsmJit - Deprecated] -# ============================================================================= - -if (DEFINED ASMJIT_BUILD_EMBED) - message(DEPRECATION "ASMJIT_BUILD_EMBED is deprecated, use ASMJIT_EMBED") - set(ASMJIT_EMBED "${ASMJIT_BUILD_EMBED}") -endif() - -if (DEFINED ASMJIT_BUILD_STATIC) - message(DEPRECATION "ASMJIT_BUILD_STATIC is deprecated, use ASMJIT_STATIC") - set(ASMJIT_STATIC "${ASMJIT_BUILD_STATIC}") -endif() - -# ============================================================================= -# [AsmJit - Configuration] -# ============================================================================= - -if (NOT DEFINED ASMJIT_EMBED) - set(ASMJIT_EMBED FALSE) -endif() - -if (NOT DEFINED ASMJIT_STATIC) - set(ASMJIT_STATIC ${ASMJIT_EMBED}) -endif() - -if (NOT DEFINED ASMJIT_BUILD_ARM) - set(ASMJIT_BUILD_ARM FALSE) -endif() - -if (NOT DEFINED ASMJIT_BUILD_X86) - set(ASMJIT_BUILD_X86 FALSE) -endif() - -if (NOT DEFINED ASMJIT_TEST) - set(ASMJIT_TEST FALSE) -endif() - -if (NOT DEFINED ASMJIT_NO_NATVIS) - set(ASMJIT_NO_NATVIS FALSE) -endif() - -# EMBED implies STATIC. -if (ASMJIT_EMBED AND NOT ASMJIT_STATIC) - set(ASMJIT_STATIC TRUE) -endif() - -set(ASMJIT_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE PATH "Location of 'asmjit'") -set(ASMJIT_TEST ${ASMJIT_TEST} CACHE BOOL "Build 'asmjit' test applications") -set(ASMJIT_EMBED ${ASMJIT_EMBED} CACHE BOOL "Embed 'asmjit' library (no targets)") -set(ASMJIT_STATIC ${ASMJIT_STATIC} CACHE BOOL "Build 'asmjit' library as static") -set(ASMJIT_SANITIZE ${ASMJIT_SANITIZE} CACHE STRING "Build with sanitizers: 'address', 'undefined', etc...") -set(ASMJIT_BUILD_X86 ${ASMJIT_BUILD_X86} CACHE BOOL "Build X86 backends (X86 and X86_64)") -set(ASMJIT_BUILD_ARM ${ASMJIT_BUILD_ARM} CACHE BOOL "Build ARM backends (ARM/Trumb and AArch64") - -# ============================================================================= -# [AsmJit - Project] -# ============================================================================= - -set(ASMJIT_INCLUDE_DIRS "${ASMJIT_DIR}/src") # Include directory is the same as source dir. -set(ASMJIT_DEPS "") # AsmJit dependencies (libraries) for the linker. -set(ASMJIT_LIBS "") # Dependencies of libs/apps that want to use AsmJit. -set(ASMJIT_CFLAGS "") # Public compiler flags. -set(ASMJIT_PRIVATE_CFLAGS "") # Private compiler flags independent of build type. -set(ASMJIT_PRIVATE_CFLAGS_DBG "") # Private compiler flags used by debug builds. -set(ASMJIT_PRIVATE_CFLAGS_REL "") # Private compiler flags used by release builds. -set(ASMJIT_SANITIZE_CFLAGS "") # Compiler flags required by currently enabled sanitizers. -set(ASMJIT_SANITIZE_LFLAGS "") # Linker flags required by currently enabled sanitizers. - -# ============================================================================= -# [AsmJit - Utilities] -# ============================================================================= - -function(asmjit_detect_cflags out) - set(out_array ${${out}}) - foreach(flag ${ARGN}) - string(REGEX REPLACE "[+]" "x" flag_signature "${flag}") - string(REGEX REPLACE "[-=:;/.\]" "_" flag_signature "${flag_signature}") - check_cxx_compiler_flag(${flag} "__CxxFlag_${flag_signature}") - if (${__CxxFlag_${flag_signature}}) - list(APPEND out_array "${flag}") - endif() - endforeach() - set(${out} "${out_array}" PARENT_SCOPE) -endfunction() - -# Support for various sanitizers provided by C/C++ compilers. -function(asmjit_detect_sanitizers out) - set(_out_array ${${out}}) - set(_flags "") - - foreach(_arg ${ARGN}) - string(REPLACE "," ";" _arg "${_arg}") - list(APPEND _flags ${_arg}) - endforeach() - - foreach(_flag ${_flags}) - if (NOT "${_flag}" MATCHES "^-fsanitize=") - SET(_flag "-fsanitize=${_flag}") - endif() - - # Sanitizers also require link flags, see CMAKE_REQUIRED_FLAGS. - set(CMAKE_REQUIRED_FLAGS "${_flag}") - asmjit_detect_cflags(_out_array ${_flag}) - unset(CMAKE_REQUIRED_FLAGS) - endforeach() - - set(${out} "${_out_array}" PARENT_SCOPE) -endfunction() - -function(asmjit_add_target target target_type) - set(single_val "") - set(multi_val SOURCES LIBRARIES CFLAGS CFLAGS_DBG CFLAGS_REL) - cmake_parse_arguments("X" "" "${single_val}" "${multi_val}" ${ARGN}) - - if ("${target_type}" MATCHES "^(EXECUTABLE|TEST)$") - add_executable(${target} ${X_SOURCES}) - else() - add_library(${target} ${target_type} ${X_SOURCES}) - endif() - - target_link_libraries(${target} PRIVATE ${X_LIBRARIES}) - - # target_link_options was added in cmake v3.13, don't use it for now... - foreach(link_flag ${ASMJIT_SANITIZE_LFLAGS}) - set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${link_flag}") - endforeach() - - if (${CMAKE_VERSION} VERSION_LESS "3.8.0") - set_property(TARGET ${target} PROPERTY CXX_STANDARD 11) - else() - target_compile_features(${target} PUBLIC cxx_std_11) - endif() - set_property(TARGET ${target} PROPERTY CXX_EXTENSIONS NO) - set_property(TARGET ${target} PROPERTY CXX_VISIBILITY_PRESET hidden) - target_compile_options(${target} PRIVATE ${X_CFLAGS} ${ASMJIT_SANITIZE_CFLAGS} $<$:${X_CFLAGS_DBG}> $<$>:${X_CFLAGS_REL}>) - - if ("${target_type}" STREQUAL "TEST") - add_test(NAME ${target} COMMAND ${target}) - endif() -endfunction() - -# ============================================================================= -# [AsmJit - Compiler Support] -# ============================================================================= - -set(ASMJIT_INCLUDE_DIRS "${ASMJIT_DIR}/src") # Include directory is the same as source dir. -set(ASMJIT_DEPS "") # AsmJit dependencies (libraries) for the linker. -set(ASMJIT_LIBS "") # Dependencies of libs/apps that want to use AsmJit. -set(ASMJIT_CFLAGS "") # Public compiler flags. -set(ASMJIT_PRIVATE_CFLAGS "") # Private compiler flags independent of build type. -set(ASMJIT_PRIVATE_CFLAGS_DBG "") # Private compiler flags used by debug builds. -set(ASMJIT_PRIVATE_CFLAGS_REL "") # Private compiler flags used by release builds. -set(ASMJIT_SANITIZE_CFLAGS "") # Compiler flags required by currently enabled sanitizers. -set(ASMJIT_SANITIZE_LFLAGS "") # Linker flags required by currently enabled sanitizers. - -# We will have to keep this most likely forever as some users may still be using it. -set(ASMJIT_INCLUDE_DIR "${ASMJIT_INCLUDE_DIRS}") - -if (NOT ASMJIT_NO_CUSTOM_FLAGS) - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") - list(APPEND ASMJIT_PRIVATE_CFLAGS - -MP # [+] Multi-Process Compilation. - -GF # [+] Eliminate duplicate strings. - -Zc:inline # [+] Remove unreferenced COMDAT. - -Zc:strictStrings # [+] Strict const qualification of string literals. - -Zc:threadSafeInit- # [-] Thread-safe statics. - -W4) # [+] Warning level 4. - - list(APPEND ASMJIT_PRIVATE_CFLAGS_DBG - -GS) # [+] Buffer security-check. - - list(APPEND ASMJIT_PRIVATE_CFLAGS_REL - -GS- # [-] Buffer security-check. - -O2 # [+] Favor speed over size. - -Oi) # [+] Generate intrinsic functions. - elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(GNU|Clang|AppleClang)$") - list(APPEND ASMJIT_PRIVATE_CFLAGS -Wall -Wextra -Wconversion) - list(APPEND ASMJIT_PRIVATE_CFLAGS -fno-math-errno) - list(APPEND ASMJIT_PRIVATE_CFLAGS_REL -O2) - - asmjit_detect_cflags(ASMJIT_PRIVATE_CFLAGS - -fno-threadsafe-statics - -fno-semantic-interposition) - - # The following flags can save few bytes in the resulting binary. - asmjit_detect_cflags(ASMJIT_PRIVATE_CFLAGS_REL - -fmerge-all-constants # Merge all constants even if it violates ISO C++. - -fno-enforce-eh-specs) # Don't enforce termination if noexcept function throws. - endif() -endif() - -# Support for sanitizers. -if (ASMJIT_SANITIZE) - ASMJIT_detect_sanitizers(ASMJIT_SANITIZE_CFLAGS ${ASMJIT_SANITIZE}) - if (ASMJIT_SANITIZE_CFLAGS) - message("-- Enabling sanitizers: '${ASMJIT_SANITIZE_CFLAGS}'") - - # Linker must receive the same flags as the compiler when it comes to sanitizers. - set(ASMJIT_SANITIZE_LFLAGS ${ASMJIT_SANITIZE_CFLAGS}) - - # Don't omit frame pointer if sanitizers are enabled. - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") - list(APPEND ASMJIT_SANITIZE_CFLAGS -Oy-) - else() - list(APPEND ASMJIT_SANITIZE_CFLAGS -fno-omit-frame-pointer -g) - endif() - - list(APPEND ASMJIT_PRIVATE_CFLAGS ${ASMJIT_SANITIZE_CFLAGS}) - list(APPEND ASMJIT_PRIVATE_LFLAGS ${ASMJIT_SANITIZE_LFLAGS}) - endif() -endif() - -if (NOT WIN32) - list(APPEND ASMJIT_DEPS pthread) -endif() - -if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") - list(APPEND ASMJIT_DEPS rt) -endif() - -set(ASMJIT_LIBS ${ASMJIT_DEPS}) -if (NOT ASMJIT_EMBED) - list(INSERT ASMJIT_LIBS 0 asmjit) -endif() - -if (ASMJIT_EMBED) - set(ASMJIT_TARGET_TYPE "EMBED") -elseif (ASMJIT_STATIC) - set(ASMJIT_TARGET_TYPE "STATIC") -else() - set(ASMJIT_TARGET_TYPE "SHARED") -endif() - -foreach(build_option ASMJIT_STATIC - ASMJIT_BUILD_X86 - #ASMJIT_BUILD_ARM - ASMJIT_BUILD_A64 - ASMJIT_NO_DEPRECATED - ASMJIT_NO_JIT - ASMJIT_NO_LOGGING - ASMJIT_NO_BUILDER - ASMJIT_NO_COMPILER - ASMJIT_NO_TEXT - ASMJIT_NO_VALIDATION - ASMJIT_NO_INTROSPECTION) - if (${build_option}) - List(APPEND ASMJIT_CFLAGS "-D${build_option}") - List(APPEND ASMJIT_PRIVATE_CFLAGS "-D${build_option}") - endif() -endforeach() - -# ============================================================================= -# [AsmJit - Linker Support] -# ============================================================================= - -if (WIN32) - if(CMAKE_LINKER MATCHES "link\\.exe" OR CMAKE_LINKER MATCHES "lld-link\\.exe") - set(ASMJIT_LINKER_SUPPORTS_NATVIS TRUE) - endif() -endif() - -# ============================================================================= -# [AsmJit - Source] -# ============================================================================= - -set(ASMJIT_SRC_LIST - asmjit/asmjit.h - - asmjit/core.h - asmjit/core/api-build_p.h - asmjit/core/api-config.h - asmjit/core/arch.cpp - asmjit/core/arch.h - asmjit/core/assembler.cpp - asmjit/core/assembler.h - asmjit/core/builder.cpp - asmjit/core/builder.h - asmjit/core/callconv.cpp - asmjit/core/callconv.h - asmjit/core/codebuffer.h - asmjit/core/codebufferwriter_p.h - asmjit/core/codeholder.cpp - asmjit/core/codeholder.h - asmjit/core/compiler.cpp - asmjit/core/compiler.h - asmjit/core/constpool.cpp - asmjit/core/constpool.h - asmjit/core/cpuinfo.cpp - asmjit/core/cpuinfo.h - asmjit/core/datatypes.h - asmjit/core/emitter.cpp - asmjit/core/emitter.h - asmjit/core/emitterutils.cpp - asmjit/core/emitterutils_p.h - asmjit/core/environment.cpp - asmjit/core/environment.h - asmjit/core/errorhandler.cpp - asmjit/core/errorhandler.h - asmjit/core/features.h - asmjit/core/formatter.cpp - asmjit/core/formatter.h - asmjit/core/func.cpp - asmjit/core/func.h - asmjit/core/globals.cpp - asmjit/core/globals.h - asmjit/core/inst.cpp - asmjit/core/inst.h - asmjit/core/jitallocator.cpp - asmjit/core/jitallocator.h - asmjit/core/jitruntime.cpp - asmjit/core/jitruntime.h - asmjit/core/logger.cpp - asmjit/core/logger.h - asmjit/core/misc_p.h - asmjit/core/operand.cpp - asmjit/core/operand.h - asmjit/core/osutils.cpp - asmjit/core/osutils.h - asmjit/core/raassignment_p.h - asmjit/core/rabuilders_p.h - asmjit/core/radefs_p.h - asmjit/core/ralocal.cpp - asmjit/core/ralocal_p.h - asmjit/core/rapass.cpp - asmjit/core/rapass_p.h - asmjit/core/rastack.cpp - asmjit/core/rastack_p.h - asmjit/core/string.cpp - asmjit/core/string.h - asmjit/core/support.cpp - asmjit/core/support.h - asmjit/core/target.cpp - asmjit/core/target.h - asmjit/core/type.cpp - asmjit/core/type.h - asmjit/core/virtmem.cpp - asmjit/core/virtmem.h - asmjit/core/zone.cpp - asmjit/core/zone.h - asmjit/core/zonehash.cpp - asmjit/core/zonehash.h - asmjit/core/zonelist.cpp - asmjit/core/zonelist.h - asmjit/core/zonestack.cpp - asmjit/core/zonestack.h - asmjit/core/zonestring.h - asmjit/core/zonetree.cpp - asmjit/core/zonetree.h - asmjit/core/zonevector.cpp - asmjit/core/zonevector.h - - asmjit/x86.h - asmjit/x86/x86archdata.cpp - asmjit/x86/x86archdata_p.h - asmjit/x86/x86assembler.cpp - asmjit/x86/x86assembler.h - asmjit/x86/x86builder.cpp - asmjit/x86/x86builder.h - asmjit/x86/x86callconv.cpp - asmjit/x86/x86callconv_p.h - asmjit/x86/x86compiler.cpp - asmjit/x86/x86compiler.h - asmjit/x86/x86emitter.h - asmjit/x86/x86features.cpp - asmjit/x86/x86features.h - asmjit/x86/x86formatter.cpp - asmjit/x86/x86formatter_p.h - asmjit/x86/x86globals.h - asmjit/x86/x86internal.cpp - asmjit/x86/x86internal_p.h - asmjit/x86/x86instdb.cpp - asmjit/x86/x86instdb.h - asmjit/x86/x86instdb_p.h - asmjit/x86/x86instapi.cpp - asmjit/x86/x86instapi_p.h - asmjit/x86/x86operand.cpp - asmjit/x86/x86operand.h - asmjit/x86/x86rapass.cpp - asmjit/x86/x86rapass_p.h -) - -if (MSVC AND NOT ASMJIT_NO_NATVIS) - list(APPEND ASMJIT_SRC_LIST asmjit.natvis) -endif() - -set(ASMJIT_SRC "") -foreach(src_file ${ASMJIT_SRC_LIST}) - set(src_file "${ASMJIT_DIR}/src/${src_file}") - list(APPEND ASMJIT_SRC ${src_file}) - - if ("${src_file}" MATCHES "\\.natvis") - if (ASMJIT_LINKER_SUPPORTS_NATVIS) - list(APPEND ASMJIT_PRIVATE_LFLAGS "-natvis:${src_file}") - endif() - endif() -endforeach() - -if (NOT ${CMAKE_VERSION} VERSION_LESS "3.8.0") - source_group(TREE "${ASMJIT_DIR}" FILES ${ASMJIT_SRC}) -endif() - -# ============================================================================= -# [AsmJit - Summary] -# ============================================================================= - -message("** AsmJit Summary **") -message(" ASMJIT_DIR=${ASMJIT_DIR}") -message(" ASMJIT_TEST=${ASMJIT_TEST}") -message(" ASMJIT_TARGET_TYPE=${ASMJIT_TARGET_TYPE}") -message(" ASMJIT_DEPS=${ASMJIT_DEPS}") -message(" ASMJIT_LIBS=${ASMJIT_LIBS}") -message(" ASMJIT_CFLAGS=${ASMJIT_CFLAGS}") -message(" ASMJIT_PRIVATE_CFLAGS=${ASMJIT_PRIVATE_CFLAGS}") -message(" ASMJIT_PRIVATE_CFLAGS_DBG=${ASMJIT_PRIVATE_CFLAGS_DBG}") -message(" ASMJIT_PRIVATE_CFLAGS_REL=${ASMJIT_PRIVATE_CFLAGS_REL}") - -# ============================================================================= -# [AsmJit - Targets] -# ============================================================================= - -if (NOT ASMJIT_EMBED) - # Add AsmJit target. - asmjit_add_target(asmjit "${ASMJIT_TARGET_TYPE}" - SOURCES ${ASMJIT_SRC} - LIBRARIES ${ASMJIT_DEPS} - CFLAGS ${ASMJIT_PRIVATE_CFLAGS} - CFLAGS_DBG ${ASMJIT_PRIVATE_CFLAGS_DBG} - CFLAGS_REL ${ASMJIT_PRIVATE_CFLAGS_REL}) - target_include_directories(asmjit BEFORE INTERFACE ${ASMJIT_INCLUDE_DIRS}) - target_compile_options(asmjit INTERFACE ${ASMJIT_CFLAGS}) - add_library(AsmJit::AsmJit ALIAS asmjit) - - # Add AsmJit install instructions (library and public headers). - if (NOT ASMJIT_NO_INSTALL) - install(TARGETS asmjit RUNTIME DESTINATION "bin" - LIBRARY DESTINATION "lib${LIB_SUFFIX}" - ARCHIVE DESTINATION "lib${LIB_SUFFIX}") - foreach(_src_file ${ASMJIT_SRC_LIST}) - if ("${_src_file}" MATCHES "\\.h$" AND NOT "${_src_file}" MATCHES "_p\\.h$") - get_filename_component(_src_dir ${_src_file} PATH) - install(FILES "${ASMJIT_DIR}/src/${_src_file}" DESTINATION "include/${_src_dir}") - endif() - endforeach() - endif() - - # Add AsmJit tests. - if (ASMJIT_TEST) - enable_testing() - - # Special target that always uses embedded AsmJit. - asmjit_add_target(asmjit_test_unit TEST - SOURCES ${ASMJIT_SRC} - test/asmjit_test_unit.cpp - test/broken.cpp - test/broken.h - LIBRARIES ${ASMJIT_DEPS} - CFLAGS ${ASMJIT_PRIVATE_CFLAGS} - -DASMJIT_TEST - -DASMJIT_STATIC - CFLAGS_DBG ${ASMJIT_PRIVATE_CFLAGS_DBG} - CFLAGS_REL ${ASMJIT_PRIVATE_CFLAGS_REL}) - target_include_directories(asmjit_test_unit BEFORE PRIVATE ${ASMJIT_INCLUDE_DIRS}) - - foreach(_target asmjit_test_opcode - asmjit_test_x86_asm - asmjit_test_x86_sections) - asmjit_add_target(${_target} TEST - SOURCES test/${_target}.cpp - LIBRARIES AsmJit::AsmJit - CFLAGS ${ASMJIT_PRIVATE_CFLAGS} - CFLAGS_DBG ${ASMJIT_PRIVATE_CFLAGS_DBG} - CFLAGS_REL ${ASMJIT_PRIVATE_CFLAGS_REL}) - endforeach() - - if (NOT ASMJIT_NO_INTROSPECTION) - asmjit_add_target(asmjit_test_x86_instinfo TEST - SOURCES test/asmjit_test_x86_instinfo.cpp - LIBRARIES AsmJit::AsmJit - CFLAGS ${ASMJIT_PRIVATE_CFLAGS} - CFLAGS_DBG ${ASMJIT_PRIVATE_CFLAGS_DBG} - CFLAGS_REL ${ASMJIT_PRIVATE_CFLAGS_REL}) - endif() - - if (NOT (ASMJIT_NO_BUILDER OR ASMJIT_NO_COMPILER)) - # Vectorcall tests and XMM tests require at least SSE2 (required in 32-bit mode). - set(sse2_flags "") - if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC" OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") - asmjit_detect_cflags(sse2_flags "-arch:SSE2") - else() - asmjit_detect_cflags(sse2_flags "-msse2") - endif() - asmjit_add_target(asmjit_test_x86_cc TEST - SOURCES test/asmjit_test_x86_cc.cpp - LIBRARIES AsmJit::AsmJit - CFLAGS ${ASMJIT_PRIVATE_CFLAGS} ${sse2_flags} - CFLAGS_DBG ${ASMJIT_PRIVATE_CFLAGS_DBG} - CFLAGS_REL ${ASMJIT_PRIVATE_CFLAGS_REL}) - endif() - - foreach(_target asmjit_bench_x86) - asmjit_add_target(${_target} EXECUTABLE - SOURCES test/${_target}.cpp - LIBRARIES AsmJit::AsmJit - CFLAGS ${ASMJIT_PRIVATE_CFLAGS} - CFLAGS_DBG ${ASMJIT_PRIVATE_CFLAGS_DBG} - CFLAGS_REL ${ASMJIT_PRIVATE_CFLAGS_REL}) - endforeach() - endif() -endif() - -cmake_policy(POP) diff --git a/ext/asmjit-master/LICENSE.md b/ext/asmjit-master/LICENSE.md deleted file mode 100644 index 020a569d..00000000 --- a/ext/asmjit-master/LICENSE.md +++ /dev/null @@ -1,17 +0,0 @@ -Copyright (c) 2008-2020 The AsmJit Authors - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. diff --git a/ext/asmjit-master/README.md b/ext/asmjit-master/README.md deleted file mode 100644 index abe51bb2..00000000 --- a/ext/asmjit-master/README.md +++ /dev/null @@ -1,60 +0,0 @@ -AsmJit ------- - -AsmJit is a lightweight library for machine code generation written in C++ language. - - * [Official Home Page (asmjit.com)](https://asmjit.com) - * [Official Repository (asmjit/asmjit)](https://github.com/asmjit/asmjit) - * [Public Chat Channel](https://gitter.im/asmjit/asmjit) - * [Zlib License](./LICENSE.md) - -See [asmjit.com](https://asmjit.com) page for more details, examples, and documentation. - -Documentation -------------- - - * [Documentation Index](https://asmjit.com/doc/index.html) - * [Build Instructions](https://asmjit.com/doc/group__asmjit__build.html) - -Breaking Changes ----------------- - -Breaking the API is sometimes inevitable, what to do? - - * See [Breaking Changes Guide](https://asmjit.com/doc/group__asmjit__breaking__changes.html), which is now part of AsmJit documentation. - * See asmjit tests, they always compile and provide implementation of many use-cases: - * [asmjit_test_x86_asm.cpp](./test/asmjit_test_x86_asm.cpp) - Tests that demonstrate the purpose of emitters. - * [asmjit_test_x86_cc.cpp](./test/asmjit_test_x86_cc.cpp) - A lot of tests targeting Compiler infrastructure. - * [asmjit_test_x86_sections.cpp](./test/asmjit_test_x86_sections.cpp) - Multiple sections test. - * Visit our [Official Chat](https://gitter.im/asmjit/asmjit) if you need a quick help. - -Project Organization --------------------- - - * **`/`** - Project root. - * **src** - Source code. - * **asmjit** - Source code and headers (always point include path in here). - * **core** - Core API, backend independent except relocations. - * **arm** - ARM specific API, used only by ARM and AArch64 backends. - * **x86** - X86 specific API, used only by X86 and X64 backends. - * **test** - Unit and integration tests (don't embed in your project). - * **tools** - Tools used for configuring, documenting, and generating files. - -TODO ----- - - * [ ] Core: - * [ ] Add support for user external buffers in CodeHolder. - * [ ] Ports: - * [ ] ARM/Thumb/AArch64 support. - -Donors ------- - - * [ZehMatt](https://github.com/ZehMatt) - - -Authors & Maintainers ---------------------- - - * Petr Kobalicek diff --git a/ext/asmjit-master/src/asmjit.natvis b/ext/asmjit-master/src/asmjit.natvis deleted file mode 100644 index b73d8487..00000000 --- a/ext/asmjit-master/src/asmjit.natvis +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - {_small.data, s8} - {_large.data, s8} - - - Small - Large - External - - (int)_small.type, d - _large.size, d - asmjit::String::kSSOCapacity, d - _large.capacity, d - _small.data, s8 - _large.data, s8 - - - - - {{ [size={_size, d} capacity={_capacity, d}] }} - - _size, d - _capacity, d - - _size - (($T1*)_data) - - - - - - - - - - - - - - - - - - - - - - - - - - [None] - [Reg] {{ id={_baseId, d} group={regGroup(), d} type={regType(), d} size={opSize(), d} }} - [Mem] {{ baseId={memBaseId(), d} indexId={memIndexId(), d} offset={(__int64)memOffset(), d} }} - [Imm] {{ val={immValue(), d} hex={immValue(), X} }} - [Label] {{ id={_baseId} }} - [Unknown] - - _signature, X - (asmjit::Operand_::OpType)opType() - opSize(), d - (asmjit::BaseReg::RegType)regType() - (asmjit::BaseReg::RegGroup)regGroup() - (asmjit::BaseReg::RegType)memBaseType() - (asmjit::BaseReg::RegType)memIndexType() - (asmjit::BaseMem::AddrType)memAddrType() - (bool)memRegHome() - _baseId - _data[0] - _data[1] - _data[0] - _data[1] - _data[0] - _data[1] - - - - - - - - - - - - - - - [RegValue {{ regType={regType()} indirect={isIndirect()} done={isDone()} }}] - [StackValue {{ indirect={isIndirect()} done={isDone()} }}] - [Unknown] - - - _data - (asmjit::Type::Id)(typeId()) - (asmjit::BaseReg::RegType)regType() - regId() - stackOffset() - - - - - - - - - - - - - - - - - - - - - - - - - [InstNode] - [SectionNode] - [LabelNode] - [AlignNode] - [EmbedDataNode] - [EmbedLabelNode] - [EmbedLabelDeltaNode] - [ConstPoolNode] - [CommentNode] - [SentinelNode] - [JumpNode] - [FuncNode] - [FuncRetNode] - [InvokeNode] - [UnknownNode {nodeType(), d}] - - - _prev - _next - - (asmjit::BaseNode::NodeType)_any._nodeType - (asmjit::BaseNode::Flags)_any._nodeFlags - - _position - _userDataU64 - _userDataPtr - _passData - _inlineComment, s8 - - ((asmjit::InstNode*)this)->_baseInst - _inst._opCount - _inst._opCapacity - ((asmjit::InstNode*)this)->_opArray, [_inst._opCount] - - ((asmjit::SectionNode*)this)->_id - ((asmjit::SectionNode*)this)->_nextSection - - ((asmjit::LabelNode*)this)->_id - - ((asmjit::AlignNode*)this)->_alignMode - ((asmjit::AlignNode*)this)->_alignment - - _embed._typeId, d - _embed._typeSize, d - ((asmjit::EmbedDataNode*)this)->_itemCount - ((asmjit::EmbedDataNode*)this)->_repeatCount - ((asmjit::EmbedDataNode*)this)->_inlineData - ((asmjit::EmbedDataNode*)this)->_externalData - - ((asmjit::EmbedLabelNode*)this)->_id - - ((asmjit::EmbedLabelDeltaNode*)this)->_id - ((asmjit::EmbedLabelDeltaNode*)this)->_baseId - ((asmjit::EmbedLabelDeltaNode*)this)->_dataSize - - ((asmjit::ConstPoolNode*)this)->_constPool - - (asmjit::SentinelNode::SentinelType)_sentinel._sentinelType - - ((asmjit::JumpNode*)this)->_annotation - - ((asmjit::FuncNode*)this)->_funcDetail - ((asmjit::FuncNode*)this)->_frame - ((asmjit::FuncNode*)this)->_exitNode - ((asmjit::FuncNode*)this)->_end - ((asmjit::FuncNode*)this)->_args, [((asmjit::FuncNode*)this)->_funcDetail._argCount] - - ((asmjit::InvokeNode*)this)->_funcDetail - ((asmjit::InvokeNode*)this)->_rets, [((asmjit::InvokeNode*)this)->_funcDetail._retCount] - ((asmjit::InvokeNode*)this)->_args, [((asmjit::InvokeNode*)this)->_funcDetail._argCount] - - - diff --git a/ext/asmjit-master/src/asmjit/asmjit.h b/ext/asmjit-master/src/asmjit/asmjit.h deleted file mode 100644 index 400426c4..00000000 --- a/ext/asmjit-master/src/asmjit/asmjit.h +++ /dev/null @@ -1,37 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_ASMJIT_H_INCLUDED -#define ASMJIT_ASMJIT_H_INCLUDED - -#include "./core.h" - -#ifdef ASMJIT_BUILD_X86 - #include "./x86.h" -#endif - -#ifdef ASMJIT_BUILD_ARM - #include "./arm.h" -#endif - -#endif // ASMJIT_ASMJIT_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core.h b/ext/asmjit-master/src/asmjit/core.h deleted file mode 100644 index d0fb214d..00000000 --- a/ext/asmjit-master/src/asmjit/core.h +++ /dev/null @@ -1,2059 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_H_INCLUDED -#define ASMJIT_CORE_H_INCLUDED - -//! Root namespace used by AsmJit. -namespace asmjit { - -// ============================================================================ -// [Documentation - mainpage] -// ============================================================================ - -//! \mainpage API Reference -//! -//! AsmJit C++ API reference documentation generated by Doxygen. -//! -//! AsmJit library uses one global namespace called \ref asmjit, which provides -//! the whole functionality. Core functionality is within \ref asmjit namespace -//! and architecture specific functionality is always in its own namespace. For -//! example \ref asmjit::x86 provides both 32-bit and 64-bit X86 code generation. -//! -//! \section main_groups Documentation Groups -//! -//! AsmJit documentation is structured into groups. Groups can be followed in -//! order to learn AsmJit, but knowledge from multiple groups is required to -//! use AsmJit properly: -//! -//! $$DOCS_GROUP_OVERVIEW$$ -//! -//! \note It's important to understand that in order to learn AsmJit all groups -//! are important. Some groups can be omitted if a particular tool is out of -//! interest - for example \ref asmjit_assembler users don't need to know about -//! \ref asmjit_builder, but it's not the opposite. \ref asmjit_builder users -//! must know about \ref asmjit_assembler as it also uses operands, labels, and -//! other concepts. Similarly \ref asmjit_compiler users must know how both \ref -//! asmjit_assembler and \ref asmjit_builder tools work. -//! -//! \section where_to_start Where To Start -//! -//! AsmJit \ref asmjit_core provides the following two classes that are essential -//! from the code generation perspective: -//! -//! - \ref CodeHolder provides functionality -//! to temporarily hold the generated code. It stores all the necessary -//! information about the code - code buffers, sections, labels, symbols, -//! and information about relocations. -//! -//! - \ref BaseEmitter provides interface used -//! by emitter implementations. The interface provides basic building blocks -//! that are then implemented by \ref BaseAssembler, \ref BaseBuilder, and -//! \ref BaseCompiler. -//! -//! Code emitters: -//! -//! - \ref asmjit_assembler - provides direct machine code generation. -//! -//! - \ref asmjit_builder - provides intermediate code generation that can -//! be processed before it's serialized to \ref BaseAssembler. -//! -//! - \ref asmjit_compiler - provides high-level code generation with built-in -//! register allocation. -//! -//! - \ref FuncNode - provides insight into how function looks from the Compiler -//! perspective and how it's stored in a node-list. -//! -//! \section main_recommendations Recommendations -//! -//! The following steps are recommended for all AsmJit users: -//! -//! - Make sure that you use \ref Logger, see \ref asmjit_logging. -//! -//! - Make sure that you use \ref ErrorHandler, see \ref asmjit_error_handling. -//! -//! - Instruction validation in your debug builds can reveal problems too. -//! AsmJit provides validation at instruction level, that can be enabled -//! by \ref BaseEmitter::addValidationOptions(). -//! -//! See \ref BaseEmitter::ValidationOptions for more details. -//! -//! - Make sure you put a breakpoint into \ref DebugUtils::errored() function -//! if you have a problem with AsmJit returning errors during instruction -//! encoding or register allocation. Having an active breakpoint there can -//! help to reveal the origin of the error, to inspect variables and other -//! conditions that caused to it. -//! -//! The reason for using \ref Logger and \ref ErrorHandler is that they provide -//! a very useful information about what's happening inside emitters. In many -//! cases the information provided by these two is crucial to quickly fix issues -//! that happen during development (for example wrong instruction, address, or -//! register used). In addition, output from \ref Logger is always necessary -//! when filling bug reports. In other words, using logging and proper error -//! handling can save a lot of time during the development. -//! -//! \section main_other Other Pages -//! -//! - Class List - List of classes sorted alphabetically -//! - AsmJit Namespace - List of symbols provided by `asmjit` namespace - -// ============================================================================ -// [Documentation - asmjit_build] -// ============================================================================ - -//! \defgroup asmjit_build Build Instructions -//! \brief Build instructions, supported environments, and feature selection. -//! -//! ### Overview -//! -//! AsmJit is designed to be easy embeddable in any project. However, it depends -//! on some compile-time definitions that can be used to enable or disable -//! features to decrease the resulting binary size. A typical way of building -//! AsmJit is to use [cmake](https://www.cmake.org), but it's also possible to -//! just include AsmJit source code in your project and to just build it. The -//! easiest way to include AsmJit in your project is to just include **src** -//! directory in your project and to define \ref ASMJIT_STATIC. AsmJit can be -//! just updated from time to time without any changes to this integration -//! process. Do not embed AsmJit's `test` files in such case as these are used -//! exclusively for testing. -//! -//! ### Supported C++ Compilers -//! -//! - Requirements: -//! -//! - AsmJit won't build without C++11 enabled. If you use older GCC or Clang -//! you would have to enable at least C++11 standard through compiler flags. -//! -//! - Tested: -//! -//! - **Clang** - Tested by Travis-CI - Clang 3.9+ (with C++11 enabled) is -//! officially supported (older Clang versions having C++11 support are -//! probably fine, but are not regularly tested). -//! -//! - **GNU** - Tested by Travis-CI - GCC 4.8+ (with C++11 enabled) is -//! officially supported. -//! -//! - **MINGW** - Tested by Travis-CI - Use the latest version, if possible. -//! -//! - **MSVC** - Tested by Travis-CI - VS2017+ is officially supported, VS2015 -//! is reported to work. -//! -//! - Untested: -//! -//! - **Intel** - No maintainers and no CI environment to regularly test -//! this compiler. -//! -//! - **Other** C++ compilers would require basic support in -//! [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h). -//! -//! ### Supported Operating Systems and Platforms -//! -//! - Tested: -//! -//! - **Linux** - Tested by Travis-CI (any distribution is generally supported). -//! -//! - **OSX** - Tested by Travis-CI (any version is supported). -//! -//! - **Windows** - Tested by Travis-CI - (Windows 7+ is officially supported). -//! -//! - **Emscripten** - Works if compiled with \ref ASMJIT_NO_JIT. AsmJit -//! cannot generate WASM code, but can be used to generate X86/X64 code -//! within a browser, for example. -//! -//! - Untested: -//! -//! - **BSDs** - No maintainers, no CI environment to regularly test BSDs, -//! but they should work out of box. -//! -//! - **Haiku** - Not regularly tested, but reported to work. -//! -//! - **Other** operating systems would require some testing and support in -//! the following files: -//! - [core/api-config.h](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/api-config.h) -//! - [core/osutils.cpp](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/osutils.cpp) -//! - [core/virtmem.cpp](https://github.com/asmjit/asmjit/tree/master/src/asmjit/core/virtmem.cpp) -//! -//! ### Supported Backends / Architectures -//! -//! - **X86** - Both 32-bit and 64-bit backends tested by Travis-CI. -//! - **ARM** - Work-in-progress (not public at the moment). -//! -//! ### Static Builds and Embedding -//! -//! These definitions can be used to enable static library build. Embed is used -//! when AsmJit's source code is embedded directly in another project, implies -//! static build as well. -//! -//! - \ref ASMJIT_EMBED - Asmjit is embedded, implies \ref ASMJIT_STATIC. -//! - \ref ASMJIT_STATIC - Enable static-library build. -//! -//! \note Projects that use AsmJit statically must define \ref ASMJIT_STATIC in -//! all compilation units that use AsmJit, otherwise AsmJit would use dynamic -//! library imports in \ref ASMJIT_API decorator. The recommendation is to -//! define this macro across the whole project that uses AsmJit this way. -//! -//! ### Build Configuration -//! -//! These definitions control whether asserts are active or not. By default -//! AsmJit would autodetect build configuration from existing pre-processor -//! definitions, but this behavior can be overridden, for example to enable -//! debug asserts in release configuration. -//! -//! - \ref ASMJIT_BUILD_DEBUG - Overrides build configuration to debug, -//! asserts will be enabled in this case. -//! - \ref ASMJIT_BUILD_RELEASE - Overrides build configuration to release, -//! asserts will be disabled in this case. -//! -//! \note There is usually no need to override the build configuration. AsmJit -//! detects the build configuration by checking whether `NDEBUG` is defined and -//! automatically defines \ref ASMJIT_BUILD_RELEASE if configuration overrides -//! were not used. We only recommend using build configuration overrides in -//! special situations, like using AsmJit in release configuration with asserts -//! enabled for whatever reason. -//! -//! ### AsmJit Backends -//! -//! AsmJit currently supports only X86/X64 backend, but the plan is to add more -//! backends in the future. By default AsmJit builds only the host backend, which -//! is autodetected at compile-time, but this can be overridden. -//! -//! - \ref ASMJIT_BUILD_X86 - Always build X86 backend (X86 and X86_64). -//! - \ref ASMJIT_BUILD_ARM - Always build ARM backend (ARM and AArch64). -//! - \ref ASMJIT_BUILD_HOST - Always build the host backend, implied by default. -//! -//! ### Features Selection -//! -//! AsmJit builds by defaults all supported features, which includes all emitters, -//! logging, instruction validation and introspection, and JIT memory allocation. -//! Features can be disabled at compile time by using `ASMJIT_NO_...` definitions. -//! -//! - \ref ASMJIT_NO_DEPRECATED - Disables deprecated API at compile time -//! so it won't be available and the compilation will fail if there is -//! attempt to use such API. This includes deprecated classes, namespaces, -//! enumerations, and functions. -//! -//! - \ref ASMJIT_NO_BUILDER - Disables \ref asmjit_builder functionality -//! completely. This implies \ref ASMJIT_NO_COMPILER as \ref asmjit_compiler -//! cannot be used without \ref asmjit_builder. -//! -//! - \ref ASMJIT_NO_COMPILER - Disables \ref asmjit_compiler functionality -//! completely. -//! -//! - \ref ASMJIT_NO_JIT - Disables JIT memory management and \ref JitRuntime. -//! -//! - \ref ASMJIT_NO_LOGGING - Disables \ref Logger and \ref Formatter. -//! -//! - \ref ASMJIT_NO_TEXT - Disables everything that contains string -//! representation of AsmJit constants, should be used together with -//! \ref ASMJIT_NO_LOGGING as logging doesn't make sense without the -//! ability to quiry instruction names, register names, etc... -//! -//! - \ref ASMJIT_NO_VALIDATION - Disables validation API. -//! -//! - \ref ASMJIT_NO_INTROSPECTION - Disables instruction introspection API, -//! must be used together with \ref ASMJIT_NO_COMPILER as \ref asmjit_compiler -//! requires introspection for its liveness analysis and register allocation. -//! -//! \note It's not recommended to disable features if you plan to build AsmJit -//! as a shared library that will be used by multiple projects that you don't -//! control how AsmJit was built (for example AsmJit in a Linux distribution). -//! The possibility to disable certain features exists mainly for customized -//! AsmJit builds. - -// ============================================================================ -// [Documentation - asmjit_breaking_changes] -// ============================================================================ - -//! \defgroup asmjit_breaking_changes Breaking Changes -//! \brief Documentation of breaking changes -//! -//! ### Overview -//! -//! AsmJit is a live project that is being actively developed. Deprecating the -//! existing API in favor of a new one is preferred, but it's not always -//! possible if the changes are significant. AsmJit authors prefer to do -//! accumulated breaking changes at once instead of breaking the API often. -//! This page documents deprecated and removed APIs and should serve as a how-to -//! guide for people that want to port existing code to work with the newest AsmJit. -//! -//! ### Tips -//! -//! Useful tips before you start: -//! -//! - Visit our [Public Gitter Channel](https://gitter.im/asmjit/asmjit) if -//! you need a quick help. -//! -//! - Build AsmJit with `ASMJIT_NO_DEPRECATED` macro defined to make sure that -//! you are not using deprecated functionality at all. Deprecated functions -//! are decorated with `ASMJIT_DEPRECATED()` macro, but sometimes it's not -//! possible to decorate everything like classes, which are used by deprecated -//! functions as well, because some compilers would warn about that. If your -//! project compiles fine with `ASMJIT_NO_DEPRECATED` it's not using anything, -//! which was deprecated. -//! -//! ### Changes committed at 2020-05-30 -//! -//! AsmJit has been cleaned up significantly, many todo items have been fixed -//! and many functions and classes have been redesigned, some in an incompatible -//! way. -//! -//! Core changes: -//! -//! - \ref Imm operand has now only \ref Imm::value() and \ref Imm::valueAs() -//! functions that return its value content, and \ref Imm::setValue() function -//! that sets the content. Functions like `setI8()`, `setU8()` were deprecated. -//! -//! Old functions were deprecated, but code using them should still compile. -//! -//! - `ArchInfo` has been replaced with \ref Environment. Environment provides -//! more details about the architecture, but drops some properties that -//! were used by arch info - `gpSize(`) and `gpCount()`. `gpSize()` can -//! be replaced with `registerSize()` getter, which returns a native register -//! size of the architecture the environment uses. However, `gpCount()` was -//! removed - at the moment \ref ArchRegs can be used to access such properties. -//! -//! Some other functions were renamed, like `ArchInfo::isX86Family()` is -//! now \ref Environment::isFamilyX86(), etc. The reason for changing the -//! order was support for more propertries and all the accessors now -//! start with the type of the property, like \ref Environment::isPlatformWindows(). -//! -//! This function causes many other classes to provide `environment()` getter -//! instead of `archInfo()` getter. In addition, AsmJit now uses `arch()` to -//! get an architecture instead of `archId()`. `ArchInfo::kIdXXX` was renamed -//! to `Environment::kArchXXX`. -//! -//! Some functions were deprecated, some removed... -//! -//! - `CodeInfo` has been removed in favor of \ref Environment. If you used -//! `CodeInfo` to set architecture and base address, this is now possible -//! with \ref Environment and setting base address explicitly by \ref -//! CodeHolder::init() - the first argument is \ref Environment, and the -//! second argument is base address, which defaults to \ref -//! Globals::kNoBaseAddress. -//! -//! CodeInfo class was deprecated, but the code using it should still -//! compile with warnings. -//! -//! - \ref CallConv has been updated to offer a more unified way of representing -//! calling conventions - many calling conventions were abstracted to follow -//! standard naming like \ref CallConv::kIdCDecl or \ref CallConv::kIdStdCall. -//! -//! This change means that other APIs like \ref FuncDetail::init() now -//! require both, calling convention and target \ref Environment. -//! -//! - `Logging` namespace has been renamed to \ref Formatter, which now -//! provides general functionality for formatting in AsmJit. -//! -//! Logging namespace should still work, but its use is deprecated. -//! Unfortunately this will be without deprecation warnings, so please -//! make sure you don't use it. -//! -//! - `Data64`, `Data128`, and `Data256` structs were deprecated and should -//! no longer be used. There is no replacement, AsmJit users should simply -//! create their own structures if they need them or use the new repeated -//! embed API in emitters, see \ref BaseEmitter::embedDataArray(). -//! -//! Emitter changes: -//! -//! - \ref BaseEmitter::emit() function signature has been changed to accept -//! 3 operands by reference and the rest 3 operands as a continuous array. -//! This change is purely cosmetic and shouldn't affect users as emit() -//! has many overloads that dispatch to the right function. -//! -//! - \ref x86::Emitter (Assembler, Builder, Compiler) deprecates embed -//! utilities like `dint8()`, `duint8()`, `duint16()`, `dxmm()`, etc... -//! in favor of a new and more powerful \ref BaseEmitter::embedDataArray(). -//! This function also allows emitting repeated values and/or patterns, -//! which is used by helpers \ref BaseEmitter::embedUInt8(), and others... -//! -//! - Validation is now available through \ref BaseEmitter::ValidationOptions, -//! which can be enabled/disabled through \ref BaseEmitter::addValidationOptions() -//! and \ref BaseEmitter::clearValidationOptions(), respectively. Validation -//! options now separate between encoding and Builder/Compiler so it's possible -//! to choose the granularity required. -//! -//! Builder changes: -//! -//! - Internal functions for creating nodes were redesigned. They now accept -//! a pointer to the node created as a first parameter. These changes should -//! not affect AsmJit users as these functions were used internally. -//! -//! Compiler changes: -//! -//! - `FuncCallNode` has been renamed to \ref InvokeNode. Additionally, function -//! calls should now use \ref x86::Compiler::invoke() instead of `call()`. -//! The reason behind this is to remove the confusion between a `call` -//! instruction and AsmJit's `call()` intrinsic, which is now `invoke()`. -//! -//! - Creating new nodes also changed. Now the preferred way of invoking a -//! function is to call \ref x86::Compiler::invoke() where the first -//! argument is `InvokeNode**`. The function now returns an error and would -//! call \ref ErrorHandler in case of a failure. Error handling was -//! unspecified in the past - the function was marked noexcept, but called -//! error handler, which could throw. -//! -//! The reason behind this change is to make the API consistent with other -//! changes and to also make it possible to inspect the possible error. In -//! the previous API it returned a new node or `nullptr` in case of error, -//! which the user couldn't inspect unless there was an attached \ref -//! ErrorHandler. -//! -//! Samples: -//! -//! ``` -//! #include -//! using namespace asmjit; -//! -//! // The basic setup of JitRuntime and CodeHolder changed, use environment() -//! // instead of codeInfo(). -//! void basicSetup() { -//! JitRuntime rt; -//! CodeHolder code(rt.environment()); -//! } -//! -//! // Calling a function (Compiler) changed - use invoke() instead of call(). -//! void functionInvocation(x86::Compiler& cc) { -//! InvokeNode* invokeNode; -//! cc.invoke(&invokeNode, targetOperand, FuncSignatureT<...>(...)); -//! } -//! ``` - -// ============================================================================ -// [Documentation - asmjit_core] -// ============================================================================ - -//! \defgroup asmjit_core Core -//! \brief Globals, code storage, and emitter interface. -//! -//! ### Overview -//! -//! AsmJit library uses \ref CodeHolder to hold code during code generation and -//! emitters inheriting from \ref BaseEmitter to emit code. CodeHolder uses -//! containers to manage its data: -//! -//! - \ref Section - stores information about a code or data section. -//! - \ref CodeBuffer - stores actual code or data, part of \ref Section. -//! - \ref LabelEntry - stores information about a label - its name, offset, -//! section where it belongs to, and other bits. -//! - \ref LabelLink - stores information about yet unbound label, which was -//! already used by the assembler. -//! - \ref RelocEntry - stores information about a relocation. -//! - \ref AddressTableEntry - stores information about an address, which was -//! used in a jump or call. Such address may need relocation. -//! -//! To generate code you would need to instantiate at least the following classes: -//! -//! - \ref CodeHolder - to hold code during code generation. -//! - \ref BaseEmitter - to emit code into \ref CodeHolder. -//! - \ref Target (optional) - most likely \ref JitRuntime to keep the generated -//! code in executable memory. \ref Target can be customized by inheriting from -//! it. -//! -//! There are also other core classes that are important: -//! -//! - \ref Environment - describes where the code will run. Environment brings -//! the concept of target triples or tuples into AsmJit, which means that users -//! can specify target architecture, platform, and ABI. -//! - \ref Type - encapsulates lightweight type functionality that can be used -//! to describe primitive and vector types. Types are used by higher level -//! utilities, for example by \ref asmjit_function and \ref asmjit_compiler. -//! - \ref CpuInfo - encapsulates CPU information - stores both CPU information -//! and features described by \ref BaseFeatures. -//! -//! AsmJit also provides global constants: -//! -//! - \ref Globals - namespace that provides global constants. -//! - \ref ByteOrder - byte-order constants and functionality. -//! -//! \note CodeHolder examples use \ref x86::Assembler as abstract interfaces cannot -//! be used to generate code. -//! -//! ### CodeHolder & Emitters -//! -//! The example below shows how the mentioned classes interact to generate X86 code: -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! // Signature of the generated function. -//! typedef int (*Func)(void); -//! -//! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! -//! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize code to match the JIT environment. -//! -//! x86::Assembler a(&code); // Create and attach x86::Assembler to code. -//! a.mov(x86::eax, 1); // Move one to eax register. -//! a.ret(); // Return from function. -//! // ===== x86::Assembler is no longer needed from here and can be destroyed ===== -//! -//! Func fn; // Holds address to the generated function. -//! Error err = rt.add(&fn, &code); // Add the generated code to the runtime. -//! if (err) return 1; // Handle a possible error returned by AsmJit. -//! // ===== CodeHolder is no longer needed from here and can be destroyed ===== -//! -//! int result = fn(); // Execute the generated code. -//! printf("%d\n", result); // Print the resulting "1". -//! -//! // All classes use RAII, all resources will be released before `main()` returns, -//! // the generated function can be, however, released explicitly if you intend to -//! // reuse or keep the runtime alive, which you should in a production-ready code. -//! rt.release(fn); -//! -//! return 0; -//! } -//! ``` -//! -//! The example above used \ref x86::Assembler as an emitter. AsmJit provides the -//! following emitters that offer various levels of abstraction: -//! -//! - \ref asmjit_assembler - Low-level emitter that emits directly to \ref CodeBuffer. -//! - \ref asmjit_builder - Low-level emitter that emits to a \ref BaseNode list. -//! - \ref asmjit_compiler - High-level emitter that provides register allocation. -//! -//! ### Targets and JitRuntime -//! -//! AsmJit's \ref Target is an interface that provides basic target abstraction. -//! At the moment AsmJit provides only one implementation called \ref JitRuntime, -//! which as the name suggests provides JIT code target and execution runtime. -//! \ref JitRuntime provides all the necessary stuff to implement a simple JIT -//! compiler with basic memory management. It only provides \ref JitRuntime::add() -//! and \ref JitRuntime::release() functions that are used to either add code -//! to the runtime or release it. \ref JitRuntime doesn't do any decisions on -//! when the code should be released, the decision is up to the developer. -//! -//! See more at \ref asmjit_virtual_memory group. -//! -//! ### More About Environment -//! -//! In the previous example the \ref Environment is retrieved from \ref JitRuntime. -//! It's logical as \ref JitRuntime always returns an \ref Environment that is -//! compatible with the host. For example if your application runs in 64-bit mode -//! the \ref Environment returned will use \ref Environment::kArchX64 architecture -//! in contrast to \ref Environment::kArchX86, which will be used in 32-bit mode on -//! any X86 platform. -//! -//! AsmJit allows to setup the \ref Environment manually and to select a different -//! architecture and ABI when necessary. So let's do something else this time, let's -//! always generate a 32-bit code and print its binary representation. To do that, we -//! can create our own \ref Environment and initialize it to \ref Environment::kArchX86. -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! int main(int argc, char* argv[]) { -//! using namespace asmjit::x86; -//! -//! // Create a custom environment initialized to 32-bit X86 architecture. -//! Environment env; -//! env.setArch(Environment::kArchX86); -//! -//! CodeHolder code; // Create a CodeHolder. -//! code.init(env); // Initialize CodeHolder with custom environment. -//! -//! // Generate a 32-bit function that sums 4 floats and looks like: -//! // void func(float* dst, const float* a, const float* b) -//! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`. -//! -//! a.mov(eax, dword_ptr(esp, 4)); // Load the destination pointer. -//! a.mov(ecx, dword_ptr(esp, 8)); // Load the first source pointer. -//! a.mov(edx, dword_ptr(esp, 12)); // Load the second source pointer. -//! -//! a.movups(xmm0, ptr(ecx)); // Load 4 floats from [ecx] to XMM0. -//! a.movups(xmm1, ptr(edx)); // Load 4 floats from [edx] to XMM1. -//! a.addps(xmm0, xmm1); // Add 4 floats in XMM1 to XMM0. -//! a.movups(ptr(eax), xmm0); // Store the result to [eax]. -//! a.ret(); // Return from function. -//! -//! // We have no Runtime this time, it's on us what we do with the code. -//! // CodeHolder stores code in Section, which provides some basic properties -//! // and CodeBuffer structure. We are interested in section's CodeBuffer. -//! // -//! // NOTE: The first section is always '.text', it can be retrieved by -//! // code.sectionById(0) or simply by code.textSection(). -//! CodeBuffer& buffer = code.textSection()->buffer(); -//! -//! // Print the machine-code generated or do something else with it... -//! // 8B4424048B4C24048B5424040F28010F58010F2900C3 -//! for (size_t i = 0; i < buffer.length; i++) -//! printf("%02X", buffer.data[i]); -//! -//! return 0; -//! } -//! ``` -//! -//! ### Explicit Code Relocation -//! -//! In addition to \ref Environment, \ref CodeHolder can be configured to -//! specify a base-address (or a virtual base-address in a linker terminology), -//! which could be static (useful when you know the location where the target's -//! machine code will be) or dynamic. AsmJit assumes dynamic base-address by -//! default and relocates the code held by \ref CodeHolder to a user provided -//! address on-demand. To be able to relocate to a user provided address it needs -//! to store some information about relocations, which is represented by \ref -//! RelocEntry. Relocation entries are only required if you call external functions -//! from the generated code that cannot be encoded by using a 32-bit displacement -//! (64-bit displacements are not provided by aby supported architecture). -//! -//! There is also a concept called \ref LabelLink - label link is a lightweight -//! data structure that doesn't have any identifier and is stored in \ref LabelEntry -//! as a single-linked list. Label link represents either unbound yet used label -//! and cross-sections links (only relevant to code that uses multiple sections). -//! Since crossing sections is something that cannot be resolved immediately these -//! links persist until offsets of these sections are assigned and until -//! \ref CodeHolder::resolveUnresolvedLinks() is called. It's an error if you end -//! up with code that has unresolved label links after flattening. You can verify -//! it by calling \ref CodeHolder::hasUnresolvedLinks(), which inspects the value -//! returned by \ref CodeHolder::unresolvedLinkCount(). -//! -//! AsmJit can flatten code that uses multiple sections by assigning each section -//! an incrementing offset that respects its alignment. Use \ref CodeHolder::flatten() -//! to do that. After the sections are flattened their offsets and virtual-sizes -//! are adjusted to respect each section's buffer size and alignment. The \ref -//! CodeHolder::resolveUnresolvedLinks() function must be called before relocating -//! the code held by \ref CodeHolder. You can also flatten your code manually by -//! iterating over all sections and calculating their offsets (relative to base) -//! by your own algorithm. In that case \ref CodeHolder::flatten() should not be -//! called, however, \ref CodeHolder::resolveUnresolvedLinks() should be. -//! -//! The example below shows how to use a built-in virtual memory allocator -//! \ref JitAllocator instead of using \ref JitRuntime (just in case you want -//! to use your own memory management) and how to relocate the generated code -//! into your own memory block - you can use your own virtual memory allocator -//! if you prefer that, but that's OS specific and not covered by the documentation. -//! -//! The following code is similar to the previous one, but implements a function -//! working in both 32-bit and 64-bit environments: -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! typedef void (*SumIntsFunc)(int* dst, const int* a, const int* b); -//! -//! int main() { -//! // Create a custom environment that matches the current host environment. -//! Environment env = hostEnvironment(); -//! -//! CodeHolder code; // Create a CodeHolder. -//! code.init(env); // Initialize CodeHolder with environment. -//! -//! x86::Assembler a(&code); // Create and attach x86::Assembler to `code`. -//! -//! // Signature: 'void func(int* dst, const int* a, const int* b)'. -//! x86::Gp dst; -//! x86::Gp src_a; -//! x86::Gp src_b; -//! -//! // Handle the difference between 32-bit and 64-bit calling conventions -//! // (arguments passed through stack vs. arguments passed by registers). -//! if (env.is32Bit()) { -//! dst = x86::eax; -//! src_a = x86::ecx; -//! src_b = x86::edx; -//! a.mov(dst , x86::dword_ptr(x86::esp, 4)); -//! a.mov(src_a, x86::dword_ptr(x86::esp, 8)); -//! a.mov(src_b, x86::dword_ptr(x86::esp, 12)); -//! } -//! else { -//! if (env.isPlatformWindows()) { -//! dst = x86::rcx; // First argument (destination pointer). -//! src_a = x86::rdx; // Second argument (source 'a' pointer). -//! src_b = x86::r8; // Third argument (source 'b' pointer). -//! } -//! else { -//! dst = x86::rdi; // First argument (destination pointer). -//! src_a = x86::rsi; // Second argument (source 'a' pointer). -//! src_b = x86::rdx; // Third argument (source 'b' pointer). -//! } -//! } -//! -//! a.movdqu(x86::xmm0, x86::ptr(src_a)); // Load 4 ints from [src_a] to XMM0. -//! a.movdqu(x86::xmm1, x86::ptr(src_b)); // Load 4 ints from [src_b] to XMM1. -//! a.paddd(x86::xmm0, x86::xmm1); // Add 4 ints in XMM1 to XMM0. -//! a.movdqu(x86::ptr(dst), x86::xmm0); // Store the result to [dst]. -//! a.ret(); // Return from function. -//! -//! // Even when we didn't use multiple sections AsmJit could insert one section -//! // called '.addrtab' (address table section), which would be filled by data -//! // required by relocations (absolute jumps and calls). You can omit this code -//! // if you are 100% sure your code doesn't contain multiple sections and -//! // such relocations. You can use `CodeHolder::hasAddressTable()` to verify -//! // whether the address table section does exist. -//! code.flatten(); -//! code.resolveUnresolvedLinks(); -//! -//! // After the code was generated it can be relocated manually to any memory -//! // location, however, we need to know it's size before we perform memory -//! // allocation. `CodeHolder::codeSize()` returns the worst estimated code -//! // size in case that relocations are not possible without trampolines (in -//! // that case some extra code at the end of the current code buffer is -//! // generated during relocation). -//! size_t estimatedSize = code.codeSize(); -//! -//! // Instead of rolling up our own memory allocator we can use the one AsmJit -//! // provides. It's decoupled so you don't need to use `JitRuntime` for that. -//! JitAllocator allocator; -//! -//! // Allocate an executable virtual memory and handle a possible failure. -//! void* p = allocator.alloc(estimatedSize); -//! if (!p) -//! return 0; -//! -//! // Now relocate the code to the address provided by the memory allocator. -//! // Please note that this DOESN'T COPY anything to `p`. This function will -//! // store the address in CodeHolder and use relocation entries to patch the -//! // existing code in all sections to respect the base address provided. -//! code.relocateToBase((uint64_t)p); -//! -//! // This is purely optional. There are cases in which the relocation can omit -//! // unneeded data, which would shrink the size of address table. If that -//! // happened the codeSize returned after relocateToBase() would be smaller -//! // than the originally `estimatedSize`. -//! size_t codeSize = code.codeSize(); -//! -//! // This will copy code from all sections to `p`. Iterating over all sections -//! // and calling `memcpy()` would work as well, however, this function supports -//! // additional options that can be used to also zero pad sections' virtual -//! // size, etc. -//! // -//! // With some additional features, copyFlattenData() does roughly this: -//! // for (Section* section : code.sections()) -//! // memcpy((uint8_t*)p + section->offset(), -//! // section->data(), -//! // section->bufferSize()); -//! code.copyFlattenedData(p, codeSize, CodeHolder::kCopyPadSectionBuffer); -//! -//! // Execute the generated function. -//! int inA[4] = { 4, 3, 2, 1 }; -//! int inB[4] = { 1, 5, 2, 8 }; -//! int out[4]; -//! -//! // This code uses AsmJit's ptr_as_func<> to cast between void* and SumIntsFunc. -//! ptr_as_func(p)(out, inA, inB); -//! -//! // Prints {5 8 4 9} -//! printf("{%d %d %d %d}\n", out[0], out[1], out[2], out[3]); -//! -//! // Release 'p' is it's no longer needed. It will be destroyed with 'vm' -//! // instance anyway, but it's a good practice to release it explicitly -//! // when you know that the function will not be needed anymore. -//! allocator.release(p); -//! -//! return 0; -//! } -//! ``` -//! -//! If you know the base-address in advance (before the code generation) it can -//! be passed as a second argument to \ref CodeHolder::init(). In that case the -//! Assembler will know the absolute position of each instruction and would be -//! able to use it during instruction encoding to prevent relocations where -//! possible. The following example shows how to configure the base address: -//! -//! ``` -//! #include -//! #include -//! -//! void initializeCodeHolder(CodeHolder& code) { -//! Environment env = hostEnvironment(); -//! uint64_t baseAddress = uint64_t(0x1234); -//! -//! // initialize CodeHolder with environment and custom base address. -//! code.init(env, baseAddress); -//! } -//! ``` -//! -//! ### Label Offsets and Links -//! -//! When a label that is not yet bound is used by the Assembler, it creates a -//! \ref LabelLink, which is then added to a \ref LabelEntry. These links are -//! also created if a label is used in a different section than in which it -//! was bound. Let's examine some functions that can be used to check whether -//! there are any unresolved links. -//! -//! ``` -//! #include -//! #include -//! -//! void labelLinksExample(CodeHolder& code, const Label& label) { -//! // Tests whether the `label` is bound. -//! bool isBound = code.isLabelBound(label); -//! printf("Label %u is %s\n", label.id(), isBound ? "bound" : "not bound"); -//! -//! // Returns true if the code contains either referenced, but unbound -//! // labels, or cross-section label links that are not resolved yet. -//! bool hasUnresolved = code.hasUnresolvedLinks(); // Boolean answer. -//! size_t nUnresolved = code.unresolvedLinkCount(); // Count of unresolved links. -//! -//! printf("Number of unresolved links: %zu\n", nUnresolved); -//! } -//! ``` -//! -//! There is no function that would return the number of unbound labels as this -//! is completely unimportant from CodeHolder's perspective. If a label is not -//! used then it doesn't matter whether it's bound or not, only actually used -//! labels matter. After a Label is bound it's possible to query its offset -//! offset relative to the start of the section where it was bound: -//! -//! ``` -//! #include -//! #include -//! -//! void labelOffsetExample(CodeHolder& code, const Label& label) { -//! // Label offset is known after it's bound. The offset provided is relative -//! // to the start of the section, see below for alternative. If the given -//! // label is not bound the offset returned will be zero. It's recommended -//! // to always check whether the label is bound before using its offset. -//! uint64_t sectionOffset = code.labelOffset(label); -//! printf("Label offset relative to section: %llu\n", (unsigned long long)sectionOffset); -//! -//! // If you use multiple sections and want the offset relative to the base. -//! // NOTE: This function expects that the section has already an offset and -//! // the label-link was resolved (if this is not true you will still get an -//! // offset relative to the start of the section). -//! uint64_t baseOffset = code.labelOffsetFromBase(label); -//! printf("Label offset relative to base: %llu\n", (unsigned long long)baseOffset); -//! } -//! ``` -//! -//! ### Sections -//! -//! AsmJit allows to create multiple sections within the same \ref CodeHolder. -//! A test-case [asmjit_test_x86_sections.cpp](https://github.com/asmjit/asmjit/blob/master/test/asmjit_test_x86_sections.cpp) -//! can be used as a reference point although the following example should -//! also provide a useful insight: -//! -//! ``` -//! #include -//! #include -//! -//! void sectionsExample(CodeHolder& code) { -//! // Text section is always provided as the first section. -//! Section* text = code.textSection(); // or code.sectionById(0); -//! -//! // To create another section use CodeHolder::newSection(). -//! Section* data; -//! Error err = code.newSection(&data, -//! ".data", // Section name -//! SIZE_MAX, // Name length if the name is not null terminated (or SIZE_MAX). -//! 0, // Section flags, see Section::Flags. -//! 8); // Section alignment, must be power of 2. -//! -//! // When you switch sections in Assembler, Builder, or Compiler the cursor -//! // will always move to the end of that section. When you create an Assembler -//! // the cursor would be placed at the end of the first (.text) section, which -//! // is initially empty. -//! x86::Assembler a(&code); -//! Label L_Data = a.newLabel(); -//! -//! a.mov(x86::eax, x86::ebx); // Emits in .text section. -//! -//! a.section(data); // Switches to the end of .data section. -//! a.bind(L_Data); // Binds label in this .data section -//! a.db(0x01); // Emits byte in .data section. -//! -//! a.section(text); // Switches to the end of .text section. -//! a.add(x86::ebx, x86::eax); // Emits in .text section. -//! -//! // References a label in .text section, which was bound in .data section. -//! // This would create a LabelLink even when the L_Data is already bound, -//! // because the reference crosses sections. See below... -//! a.lea(x86::rsi, x86::ptr(L_Data)); -//! } -//! ``` -//! -//! The last line in the example above shows that a LabelLink would be created -//! even for bound labels that cross sections. In this case a referenced label -//! was bound in another section, which means that the link couldn't be resolved -//! at that moment. If your code uses sections, but you wish AsmJit to flatten -//! these sections (you don't plan to flatten them manually) then there is an -//! API for that. -//! -//! ``` -//! #include -//! #include -//! -//! // ... (continuing the previous example) ... -//! void sectionsExampleContinued(CodeHolder& code) { -//! // Suppose we have some code that contains multiple sections and -//! // we would like to flatten it by using AsmJit's built-in API: -//! Error err = code.flatten(); -//! if (err) { -//! // There are many reasons it can fail, so always handle a possible error. -//! printf("Failed to flatten the code: %s\n", DebugUtils::errorAsString(err)); -//! exit(1); -//! } -//! -//! // After flattening all sections would contain assigned offsets -//! // relative to base. Offsets are 64-bit unsigned integers so we -//! // cast them to `size_t` for simplicity. On 32-bit targets it's -//! // guaranteed that the offset cannot be greater than `2^32 - 1`. -//! printf("Data section offset %zu", size_t(data->offset())); -//! -//! // The flattening doesn't resolve unresolved label links, this -//! // has to be done manually as flattening can be done separately. -//! err = code.resolveUnresolvedLinks(); -//! if (err) { -//! // This is the kind of error that should always be handled... -//! printf("Failed to resolve label links: %s\n", DebugUtils::errorAsString(err)); -//! exit(1); -//! } -//! -//! if (code.hasUnresolvedLinks()) { -//! // This would mean either unbound label or some other issue. -//! printf("The code has %zu unbound labels\n", code.unresovedLinkCount()); -//! exit(1); -//! } -//! } -//! ``` - -// ============================================================================ -// [Documentation - asmjit_assembler] -// ============================================================================ - -//! \defgroup asmjit_assembler Assembler -//! \brief Assembler interface and operands. -//! -//! ### Overview -//! -//! AsmJit's Assembler is used to emit machine code directly into a \ref -//! CodeBuffer. In general, code generation with assembler requires the knowledge -//! of the following: -//! -//! - \ref BaseAssembler and architecture-specific assemblers: -//! - \ref x86::Assembler - Assembler specific to X86 architecture -//! - \ref Operand and its variations: -//! - \ref BaseReg - Base class for a register operand, inherited by: -//! - \ref x86::Reg - Register operand specific to X86 architecture. -//! - \ref BaseMem - Base class for a memory operand, inherited by: -//! - \ref x86::Mem - Memory operand specific to X86 architecture. -//! - \ref Imm - Immediate (value) operand. -//! - \ref Label - Label operand. -//! -//! \note Assembler examples use \ref x86::Assembler as abstract interfaces cannot -//! be used to generate code. -//! -//! ### Operand Basics -//! -//! Let's start with operands. \ref Operand is a data structure that defines a -//! data layout of any operand. It can be inherited, but any class inheriting -//! it cannot add any members to it, only the existing layout can be reused. -//! AsmJit allows to construct operands dynamically, to store them, and to query -//! a complete information about them at run-time. Operands are small (always 16 -//! bytes per \ref Operand) and can be copied and passed by value. Please never -//! allocate individual operands dynamically by using a `new` keyword - it would -//! work, but then you would have to be responsible for deleting such operands. -//! In AsmJit operands are always part of some other data structures like \ref -//! InstNode, which is part of \ref asmjit_builder tool. -//! -//! Operands contain only identifiers, but not pointers to any code-generation data. -//! For example \ref Label operand only provides label identifier, but not a pointer -//! to \ref LabelEntry structure. In AsmJit such IDs are used to link stuff together -//! without having to deal with pointers. -//! -//! AsmJit's operands all inherit from a base class called \ref Operand. Operands -//! have the following properties that are commonly accessible by getters and setters: -//! -//! - \ref Operand - Base operand, which only provides accessors that are common -//! to all operand types. -//! - \ref BaseReg - Describes either physical or virtual register. Physical -//! registers have id that matches the target's machine id directly whereas -//! virtual registers must be allocated into physical registers by a register -//! allocator pass. Register operand provides: -//! - Register Type - Unique id that describes each possible register provided -//! by the target architecture - for example X86 backend provides \ref -//! x86::Reg::RegType, which defines all variations of general purpose registers -//! (GPB-LO, GPB-HI, GPW, GPD, and GPQ) and all types of other registers like K, -//! MM, BND, XMM, YMM, and ZMM. -//! - Register Group - Groups multiple register types under a single group - for -//! example all general-purpose registers (of all sizes) on X86 are part of -//! \ref x86::Reg::kGroupGp and all SIMD registers (XMM, YMM, ZMM) are part -//! of \ref x86::Reg::kGroupVec. -//! - Register Size - Contains the size of the register in bytes. If the size -//! depends on the mode (32-bit vs 64-bit) then generally the higher size is -//! used (for example RIP register has size 8 by default). -//! - Register Id - Contains physical or virtual id of the register. -//! - \ref BaseMem - Used to reference a memory location. Memory operand provides: -//! - Base Register - A base register type and id (physical or virtual). -//! - Index Register - An index register type and id (physical or virtual). -//! - Offset - Displacement or absolute address to be referenced (32-bit if base -//! register is used and 64-bit if base register is not used). -//! - Flags that can describe various architecture dependent information (like -//! scale and segment-override on X86). -//! - \ref Imm - Immediate values are usually part of instructions (encoded within -//! the instruction itself) or data. -//! - \ref Label - used to reference a location in code or data. Labels must be -//! created by the \ref BaseEmitter or by \ref CodeHolder. Each label has its -//! unique id per \ref CodeHolder instance. -//! -//! ### Operand Manipulation -//! -//! AsmJit allows to construct operands dynamically, to store them, and to query -//! a complete information about them at run-time. Operands are small (always 16 -//! bytes per `Operand`) and should be always copied (by value) if you intend to -//! store them (don't create operands by using `new` keyword, it's not recommended). -//! Operands are safe to be passed to `memcpy()` and `memset()`, which becomes -//! handy when working with arrays of operands. If you set all members of an \ref -//! Operand to zero the operand would become NONE operand, which is the same as a -//! default constructed Operand. -//! -//! The example below illustrates how operands can be used and modified even -//! without using any other code generation classes. The example uses X86 -//! architecture-specific operands. -//! -//! ``` -//! #include -//! -//! using namespace asmjit; -//! -//! // Registers can be copied, it's a common practice. -//! x86::Gp dstRegByValue() { return x86::ecx; } -//! -//! void usingOperandsExample(x86::Assembler& a) { -//! // Gets `ecx` register returned by a function. -//! x86::Gp dst = dstRegByValue(); -//! // Gets `rax` register directly from the provided `x86` namespace. -//! x86::Gp src = x86::rax; -//! // Constructs `r10` dynamically. -//! x86::Gp idx = x86::gpq(10); -//! // Constructs [src + idx] memory address - referencing [rax + r10]. -//! x86::Mem m = x86::ptr(src, idx); -//! -//! // Examine `m`: Returns `x86::Reg::kTypeGpq`. -//! m.indexType(); -//! // Examine `m`: Returns 10 (`r10`). -//! m.indexId(); -//! -//! // Reconstruct `idx` stored in mem: -//! x86::Gp idx_2 = x86::Gp::fromTypeAndId(m.indexType(), m.indexId()); -//! -//! // True, `idx` and idx_2` are identical. -//! idx == idx_2; -//! -//! // Possible - op will still be the same as `m`. -//! Operand op = m; -//! // True (can be casted to BaseMem or architecture-specific Mem). -//! op.isMem(); -//! -//! // True, `op` is just a copy of `m`. -//! m == op; -//! -//! // Static cast is fine and valid here. -//! static_cast(op).addOffset(1); -//! // However, using `as()` to cast to a derived type is preferred. -//! op.as().addOffset(1); -//! // False, `op` now points to [rax + r10 + 2], which is not [rax + r10]. -//! m == op; -//! -//! // Emitting 'mov' - type safe way. -//! a.mov(dst, m); -//! // Not possible, `mov` doesn't provide mov(x86::Gp, Operand) overload. -//! a.mov(dst, op); -//! -//! // Type-unsafe, but possible. -//! a.emit(x86::Inst::kIdMov, dst, m); -//! // Also possible, `emit()` is typeless and can be used with raw Operand. -//! a.emit(x86::Inst::kIdMov, dst, op); -//! } -//! ``` -//! -//! Some operands have to be created explicitly by emitters. For example labels -//! must be created by \ref BaseEmitter::newLabel(), which creates a label entry -//! and returns a \ref Label operand with the id that refers to it. Such label -//! then can be used by emitters. -//! -//! ### Memory Operands -//! -//! Some architectures like X86 provide a complex memory addressing model that -//! allows to encode addresses having a BASE register, INDEX register with a -//! possible scale (left shift), and displacement (called offset in AsmJit). -//! Memory address on X86 can also specify memory segment (segment-override in -//! X86 terminology) and some instructions (gather / scatter) require INDEX to -//! be a \ref x86::Vec register instead of a general-purpose register. -//! -//! AsmJit allows to encode and work with all forms of addresses mentioned and -//! implemented by X86. In addition, it also allows to construct absolute 64-bit -//! memory address operands, which is only allowed in one form of 'mov' instruction. -//! -//! ``` -//! #include -//! -//! using namespace asmjit; -//! -//! void testX86Mem() { -//! // Makes it easier to access x86 stuff... -//! using namespace asmjit::x86; -//! -//! // BASE + OFFSET. -//! Mem a = ptr(rax); // a = [rax] -//! Mem b = ptr(rax, 15); // b = [rax + 15] -//! -//! // BASE + INDEX << SHIFT - Shift is in BITS as used by X86! -//! Mem c = ptr(rax, rbx); // c = [rax + rbx] -//! Mem d = ptr(rax, rbx, 2); // d = [rax + rbx << 2] -//! Mem e = ptr(rax, rbx, 2, 15); // e = [rax + rbx << 2 + 15] -//! -//! // BASE + VM (Vector Index) (encoded as MOD+VSIB). -//! Mem f = ptr(rax, xmm1); // f = [rax + xmm1] -//! Mem g = ptr(rax, xmm1, 2); // g = [rax + xmm1 << 2] -//! Mem h = ptr(rax, xmm1, 2, 15); // h = [rax + xmm1 << 2 + 15] -//! -//! // Absolute adddress: -//! uint64_t addr = (uint64_t)0x1234; -//! Mem i = ptr(addr); // i = [0x1234] -//! Mem j = ptr(addr, rbx); // j = [0x1234 + rbx] -//! Mem k = ptr(addr, rbx, 2); // k = [0x1234 + rbx << 2] -//! -//! // LABEL - Will be encoded as RIP (64-bit) or absolute address (32-bit). -//! Label L = ...; -//! Mem m = ptr(L); // m = [L] -//! Mem n = ptr(L, rbx); // n = [L + rbx] -//! Mem o = ptr(L, rbx, 2); // o = [L + rbx << 2] -//! Mem p = ptr(L, rbx, 2, 15); // p = [L + rbx << 2 + 15] -//! -//! // RIP - 64-bit only (RIP can't use INDEX). -//! Mem q = ptr(rip, 24); // q = [rip + 24] -//! } -//! ``` -//! -//! Memory operands can optionally contain memory size. This is required by -//! instructions where the memory size cannot be deduced from other operands, -//! like `inc` and `dec` on X86: -//! -//! ``` -//! #include -//! -//! using namespace asmjit; -//! -//! void testX86Mem() { -//! // The same as: dword ptr [rax + rbx]. -//! x86::Mem a = x86::dword_ptr(rax, rbx); -//! -//! // The same as: qword ptr [rdx + rsi << 0 + 1]. -//! x86::Mem b = x86::qword_ptr(rdx, rsi, 0, 1); -//! } -//! ``` -//! -//! Memory operands provide API that can be used to access its properties: -//! -//! ``` -//! #include -//! -//! using namespace asmjit; -//! -//! void testX86Mem() { -//! // The same as: dword ptr [rax + 12]. -//! x86::Mem mem = x86::dword_ptr(rax, 12); -//! -//! mem.hasBase(); // true. -//! mem.hasIndex(); // false. -//! mem.size(); // 4. -//! mem.offset(); // 12. -//! -//! mem.setSize(0); // Sets the size to 0 (makes it sizeless). -//! mem.addOffset(-1); // Adds -1 to the offset and makes it 11. -//! mem.setOffset(0); // Sets the offset to 0. -//! mem.setBase(rcx); // Changes BASE to RCX. -//! mem.setIndex(rax); // Changes INDEX to RAX. -//! mem.hasIndex(); // true. -//! } -//! // ... -//! ``` -//! -//! Making changes to memory operand is very comfortable when emitting loads -//! and stores: -//! -//! ``` -//! #include -//! -//! using namespace asmjit; -//! -//! void testX86Mem(CodeHolder& code) { -//! x86::Assembler a(code); // Your initialized x86::Assembler. -//! x86::Mem mSrc = x86::ptr(eax); // Construct [eax] memory operand. -//! -//! // One way of emitting bunch of loads is to use `mem.adjusted()`, which -//! // returns a new memory operand and keeps the source operand unchanged. -//! a.movaps(x86::xmm0, mSrc); // No adjustment needed to load [eax]. -//! a.movaps(x86::xmm1, mSrc.adjusted(16)); // Loads from [eax + 16]. -//! a.movaps(x86::xmm2, mSrc.adjusted(32)); // Loads from [eax + 32]. -//! a.movaps(x86::xmm3, mSrc.adjusted(48)); // Loads from [eax + 48]. -//! -//! // ... do something with xmm0-3 ... -//! -//! // Another way of adjusting memory is to change the operand in-place. -//! // If you want to keep the original operand you can simply clone it. -//! x86::Mem mDst = mSrc.clone(); // Clone mSrc. -//! -//! a.movaps(mDst, x86::xmm0); // Stores xmm0 to [eax]. -//! mDst.addOffset(16); // Adds 16 to `mDst`. -//! -//! a.movaps(mDst, x86::xmm1); // Stores to [eax + 16] . -//! mDst.addOffset(16); // Adds 16 to `mDst`. -//! -//! a.movaps(mDst, x86::xmm2); // Stores to [eax + 32]. -//! mDst.addOffset(16); // Adds 16 to `mDst`. -//! -//! a.movaps(mDst, x86::xmm3); // Stores to [eax + 48]. -//! } -//! ``` -//! -//! ### Assembler Examples -//! -//! - \ref x86::Assembler provides many X86/X64 examples. - -// ============================================================================ -// [Documentation - asmjit_builder] -// ============================================================================ - -//! \defgroup asmjit_builder Builder -//! \brief Builder interface, nodes, and passes. -//! -//! ### Overview -//! -//! Both \ref BaseBuilder and \ref BaseCompiler interfaces describe emitters -//! that emit into a representation that allows further processing. The code -//! stored in such representation is completely safe to be patched, simplified, -//! reordered, obfuscated, removed, injected, analyzed, or processed some other -//! way. Each instruction, label, directive, or other building block is stored -//! as \ref BaseNode (or derived class like \ref InstNode or \ref LabelNode) -//! and contains all the information necessary to pass that node later to the -//! assembler. -//! -//! \ref BaseBuilder is an emitter that inherits from \ref BaseEmitter interface. -//! It was designed to provide a maximum compatibility with the existing \ref -//! BaseAssembler emitter so users can move from assembler to builder when needed, -//! for example to implement post-processing, which is not possible with Assembler. -//! -//! ### Builder Nodes -//! -//! \ref BaseBuilder doesn't generate machine code directly, it uses an intermediate -//! representation based on nodes, however, it allows to serialize to \ref BaseAssembler -//! when the code is ready to be encoded. -//! -//! There are multiple node types used by both \ref BaseBuilder and \ref BaseCompiler : -//! -//! - Basic nodes: -//! - \ref BaseNode - Base class for all nodes. -//! - \ref InstNode - Represents an instruction node. -//! - \ref AlignNode - Represents an alignment directive (.align). -//! - \ref LabelNode - Represents a location where to bound a \ref Label. -//! -//! - Data nodes: -//! - \ref EmbedDataNode - Represents data. -//! - \ref EmbedLabelNode - Represents \ref Label address embedded as data. -//! - \ref EmbedLabelDeltaNode - Represents a difference of two labels -//! embedded in data. -//! - \ref ConstPoolNode - Represents a constant pool data embedded as data. -//! -//! - Informative nodes: -//! - \ref CommentNode - Represents a comment string, doesn't affect code -//! generation. -//! - \ref SentinelNode - A marker that can be used to remember certain -//! position in code or data, doesn't affect code generation. Used by -//! \ref FuncNode to mark the end of a function. -//! -//! - Other nodes are provided by \ref asmjit_compiler infrastructure. -//! -//! ### Builder Examples -//! -//! - \ref x86::Builder provides many X86/X64 examples. - -// ============================================================================ -// [Documentation - asmjit_compiler] -// ============================================================================ - -//! \defgroup asmjit_compiler Compiler -//! \brief Compiler interface. -//! -//! ### Overview -//! -//! \ref BaseCompiler is a high-level interface built on top of \ref BaseBuilder -//! interface, which provides register allocation and support for defining and -//! invoking functions. At the moment it's the easiest way of generating code -//! in AsmJit as most architecture and OS specifics is properly abstracted and -//! handled by AsmJit automatically. However, abstractions also mean restrictions, -//! which means that \ref BaseCompiler has more limitations that \ref BaseAssembler -//! or \ref BaseBuilder. -//! -//! Since \ref BaseCompiler provides register allocation it also establishes the -//! concept of functions - a function in Compiler sense is a unit in which virtual -//! registers are allocated into physical registers by the register allocator. -//! In addition, it enables to use such virtual registers in function invocations. -//! -//! \ref BaseCompiler automatically handles function calling conventions. It's -//! still architecture dependent, but makes the code generation much easies. -//! Functions are essential; the first-step to generate some code is to define a -//! signature of the function to be generated (before generating the function body -//! itself). Function arguments and return value(s) are handled by assigning -//! virtual registers to them. Similarly, function calls are handled the same way. -//! -//! ### Compiler Nodes -//! -//! \ref BaseCompiler adds some nodes that are required for function generation -//! and invocation: -//! -//! - \ref FuncNode - Represents a function definition. -//! - \ref FuncRetNode - Represents a function return. -//! - \ref InvokeNode - Represents a function invocation. -//! -//! \ref BaseCompiler also makes the use of passes (\ref Pass) and automatically -//! adds an architecture-dependent register allocator pass to the list of passes -//! when attached to \ref CodeHolder. -//! -//! ### Compiler Examples -//! -//! - \ref x86::Compiler provides many X86/X64 examples. -//! -//! ### Compiler Tips -//! -//! Users of AsmJit have done mistakes in the past, this section should provide -//! some useful tips for beginners: -//! -//! - Virtual registers in compiler are bound to a single function. At the -//! moment the implementation doesn't care whether a single virtual register -//! is used in multiple functions, but it sees it as two independent virtual -//! registers in that case. This means that virtual registers cannot be used -//! to implement global variables. Global variables are basically memory -//! addresses which functions can read from and write to, and they have to -//! be implemented in the same way. -//! -//! - Compiler provides a useful debugging functionality, which can be turned -//! on through \ref FormatOptions::Flags. Use \ref Logger::addFlags() to -//! turn on additional logging features when using Compiler. - -// ============================================================================ -// [Documentation - asmjit_function] -// ============================================================================ - -//! \defgroup asmjit_function Function -//! \brief Function definitions. -//! -//! ### Overview -//! -//! AsmJit provides functionality that can be used to define function signatures -//! and to calculate automatically optimal function frame that can be used directly -//! by a prolog and epilog insertion. This feature was exclusive to AsmJit's Compiler -//! for a very long time, but was abstracted out and is now available for all users -//! regardless of the emitter they use. The following use cases are possible: -//! -//! - Calculate function frame before the function is generated - this is the -//! only way available to \ref BaseAssembler users and it will be described -//! in this section. -//! -//! - Calculate function frame after the function is generated - this way is -//! generally used by \ref BaseBuilder and \ref BaseCompiler emitters and -//! this way is generally described in \ref asmjit_compiler section. -//! -//! The following concepts are used to describe and create functions in AsmJit: -//! -//! - \ref Type::Id - Type-id is an 8-bit value that describes a platform -//! independent type as we know from C/C++. It provides abstractions for -//! most common types like `int8_t`, `uint32_t`, `uintptr_t`, `float`, -//! `double`, and all possible vector types to match ISAs up to AVX512. -//! \ref Type::Id was introduced originally for \ref asmjit_compiler, but -//! it's now used by \ref FuncSignature as well. -//! -//! - \ref CallConv - Describes a calling convention - this class contains -//! instructions to assign registers and stack addresses to function -//! arguments and return value(s), but doesn't specify any function -//! signature itself. Calling conventions are architecture and OS dependent. -//! -//! - \ref FuncSignature - Describes a function signature, for example -//! `int func(int, int)`. FuncSignature contains a function calling convention -//! id, return value type, and function arguments. The signature itself is -//! platform independent and uses \ref Type::Id to describe types of function -//! arguments and function return value(s). -//! -//! - \ref FuncDetail - Architecture and ABI dependent information that describes -//! \ref CallConv and expanded \ref FuncSignature. Each function argument and -//! return value is represented as \ref FuncValue that contains the original -//! \ref Type::Id enriched with additional information that specifies whether -//! the value is passed or returned by register (and which register) or by -//! stack. Each value also contains some other metadata that provide additional -//! information required to handle it properly (for example whether a vector is -//! passed indirectly by a pointer as required by WIN64 calling convention). -//! -//! - \ref FuncFrame - Contains information about the function frame that can -//! be used by prolog/epilog inserter (PEI). Holds call stack size size and -//! alignment, local stack size and alignment, and various attributes that -//! describe how prolog and epilog should be constructed. `FuncFrame` doesn't -//! know anything about function's arguments or return values, it hold only -//! information necessary to create a valid and ABI conforming function prologs -//! and epilogs. -//! -//! - \ref FuncArgsAssignment - A helper class that can be used to reassign -//! function arguments into user specified registers. It's architecture and -//! ABI dependent mapping from function arguments described by \ref CallConv -//! and \ref FuncDetail into registers specified by the user. -//! -//! It's a lot of concepts where each represents one step in a function frame -//! calculation. It can be used to create function prologs, epilogs, and also -//! to calculate information necessary to perform function calls. - -// ============================================================================ -// [Documentation - asmjit_logging] -// ============================================================================ - -//! \defgroup asmjit_logging Logging -//! \brief Logging and formatting. -//! -//! ### Overview -//! -//! The initial phase of a project that generates machine code is not always smooth. -//! Failure cases are common not just at the beginning phase, but also during the -//! development or refactoring. AsmJit provides logging functionality to address -//! this issue. AsmJit does already a good job with function overloading to prevent -//! from emitting unencodable instructions, but it can't prevent from emitting machine -//! code that is correct at instruction level, but doesn't work when it's executed as -//! a whole. Logging has always been an important part of AsmJit's infrastructure and -//! looking at logs can sometimes reveal code generation issues quickly. -//! -//! AsmJit provides API for logging and formatting: -//! - \ref Logger - A logger that you can pass to \ref CodeHolder and all emitters -//! that inherit from \ref BaseEmitter. -//! - \ref FormatOptions - Formatting options that can change how instructions and -//! operands are formatted. -//! - \ref Formatter - A namespace that provides functions that can format input -//! data like \ref Operand, \ref BaseReg, \ref Label, and \ref BaseNode into -//! \ref String. -//! -//! AsmJit's \ref Logger serves the following purposes: -//! - Provides a basic foundation for logging. -//! - Abstract class leaving the implementation on users. The following built-in -//! inplementations are provided for simplicty: -//! - \ref FileLogger implements logging into a standard `FILE` stream. -//! - \ref StringLogger serializes all logs into a \ref String instance. -//! -//! AsmJit's \ref FormatOptions provides the following to customize the formatting of -//! instructions and operands through: -//! - \ref FormatOptions::Flags -//! - \ref FormatOptions::IndentationType -//! -//! ### Logging -//! -//! A \ref Logger is typically attached to a \ref CodeHolder, which propagates it -//! to all attached emitters automatically. The example below illustrates how to -//! use \ref FileLogger that outputs to standard output: -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! FileLogger logger(stdout); // Logger should always survive CodeHolder. -//! -//! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime. -//! code.setLogger(&logger); // Attach the `logger` to `code` holder. -//! -//! // ... code as usual, everything emitted will be logged to `stdout` ... -//! return 0; -//! } -//! ``` -//! -//! If output to FILE stream is not desired it's possible to use \ref StringLogger, -//! which concatenates everything into a multi-line string: -//! -//! ``` -//! #include -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! int main() { -//! JitRuntime rt; // Runtime specialized for JIT code execution. -//! StringLogger logger; // Logger should always survive CodeHolder. -//! -//! CodeHolder code; // Holds code and relocation information. -//! code.init(rt.environment()); // Initialize to the same arch as JIT runtime. -//! code.setLogger(&logger); // Attach the `logger` to `code` holder. -//! -//! // ... code as usual, logging will be concatenated to logger string ... -//! -//! // You can either use the string from StringLogger directly or you can -//! // move it. Logger::data() returns its content as null terminated char[]. -//! printf("Logger content: %s\n", logger.data()); -//! -//! // It can be moved into your own string like this: -//! String content = std::move(logger.content()); -//! printf("The same content: %s\n", content.data()); -//! -//! return 0; -//! } -//! ``` -//! -//! ### Formatting -//! -//! AsmJit uses \ref Formatter to format inputs that are then passed to \ref -//! Logger. Formatting is public and can be used by AsmJit users as well. The -//! most important thing to know regarding formatting is that \ref Formatter -//! always appends to the output string, so it can be used to build complex -//! strings without having to concatenate intermediate strings. -//! -//! The first example illustrates how to format operands: -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! void logOperand(uint32_t arch, const Operand_& op) { -//! // The emitter is optional (named labels and virtual registers need it). -//! BaseEmitter* emitter = nullptr; -//! -//! // No flags by default. -//! uint32_t formatFlags = FormatOptions::kNoFlags; -//! -//! StringTmp<128> sb; -//! Formatter::formatOperand(sb, formatFlags, emitter, arch, op); -//! printf("%s\n", sb.data()); -//! } -//! -//! void formattingExample() { -//! using namespace x86; -//! -//! // Architecture is not part of operand, it must be passed explicitly. -//! // Format flags. We pass it explicitly also to 'logOperand' to make -//! // compatible with what AsmJit normally does. -//! uint32_t arch = Environment::kArchX64; -//! -//! log(arch, rax); // Prints 'rax'. -//! log(arch, ptr(rax, rbx, 2)); // Prints '[rax + rbx * 4]`. -//! log(arch, dword_ptr(rax, rbx, 2)); // Prints 'dword [rax + rbx * 4]`. -//! log(arch, imm(42)); // Prints '42'. -//! } -//! ``` -//! -//! Next example illustrates how to format whole instructions: -//! -//! ``` -//! #include -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! template -//! void logInstruction(uint32_t arch, const BaseInst& inst, Args&&... args) { -//! // The emitter is optional (named labels and virtual registers need it). -//! BaseEmitter* emitter = nullptr; -//! -//! // No flags by default. -//! uint32_t formatFlags = FormatOptions::kNoFlags; -//! -//! // The formatter expects operands in an array. -//! Operand_ operands { std::forward(args)... }; -//! -//! StringTmp<128> sb; -//! Formatter::formatInstruction( -//! sb, formatFlags, emitter, arch, inst, operands, sizeof...(args)); -//! printf("%s\n", sb.data()); -//! } -//! -//! void formattingExample() { -//! using namespace x86; -//! -//! // Architecture is not part of operand, it must be passed explicitly. -//! // Format flags. We pass it explicitly also to 'logOperand' to make -//! // compatible with what AsmJit normally does. -//! uint32_t arch = Environment::kArchX64; -//! -//! // Prints 'mov rax, rcx'. -//! logInstruction(arch, BaseInst(Inst::kIdMov), rax, rcx); -//! -//! // Prints 'vaddpd zmm0, zmm1, [rax] {1to8}'. -//! logInstruction(arch, -//! BaseInst(Inst::kIdVaddpd), -//! zmm0, zmm1, ptr(rax)._1toN()); -//! -//! // BaseInst abstracts instruction id, instruction options, and extraReg. -//! // Prints 'lock add [rax], rcx'. -//! logInstruction(arch, -//! BaseInst(Inst::kIdAdd, Inst::kOptionLock), -//! x86::ptr(rax), rcx); -//! -//! // Similarly an extra register (like AVX-512 selector) can be used. -//! // Prints 'vaddpd zmm0 {k2} {z}, zmm1, [rax]'. -//! logInstruction(arch, -//! BaseInst(Inst::kIdAdd, Inst::kOptionZMask, k2), -//! zmm0, zmm1, ptr(rax)); -//! } -//! ``` -//! -//! And finally, the example below illustrates how to use a built-in function -//! to format the content of \ref BaseBuilder, which consists of nodes: -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! void formattingExample(BaseBuilder* builder) { -//! uint32_t formatFlags = FormatOptions::kNoFlags; -//! -//! // This also shows how temporary strings can be used. -//! StringTmp<512> sb; -//! -//! // FormatNodeList requires the String for output, formatting flags, which -//! // were zero (no extra flags), and the builder instance, which we have -//! // provided. An overloaded version also exists, which accepts begin and -//! // and end nodes, which can be used to only format a range of nodes. -//! Formatter::formatNodeList(sb, formatFlags, builder); -//! -//! // You can do whatever else with the string, it's always null terminated, -//! // so it can be passed to C functions like printf(). -//! printf("%s\n", sb.data()); -//! } -//! ``` - -// ============================================================================ -// [Documentation - asmjit_error_handling] -// ============================================================================ - -//! \defgroup asmjit_error_handling Error Handling -//! \brief Error handling. -//! -//! ### Overview -//! -//! AsmJit uses error codes to represent and return errors. Every function that -//! can fail returns an \ref Error code. Exceptions are never thrown by AsmJit -//! itself even in extreme conditions like out-of-memory, but it's possible to -//! override \ref ErrorHandler::handleError() to throw, in that case no error -//! will be returned and exception will be thrown instead. All functions where -//! this can happen are not marked `noexcept`. -//! -//! Errors should never be ignored, however, checking errors after each AsmJit -//! API call would simply overcomplicate the whole code generation experience. -//! \ref ErrorHandler exists to make the use of AsmJit API simpler as it allows -//! to customize how errors can be handled: -//! -//! - Record the error and continue (the way how the error is user-implemented). -//! - Throw an exception. AsmJit doesn't use exceptions and is completely -//! exception-safe, but it's perfectly legal to throw an exception from -//! the error handler. -//! - Use plain old C's `setjmp()` and `longjmp()`. Asmjit always puts Assembler, -//! Builder and Compiler to a consistent state before calling \ref -//! ErrorHandler::handleError(), so `longjmp()` can be used without issues to -//! cancel the code-generation if an error occurred. This method can be used if -//! exception handling in your project is turned off and you still want some -//! comfort. In most cases it should be safe as AsmJit uses \ref Zone memory -//! and the ownership of memory it allocates always ends with the instance that -//! allocated it. If using this approach please never jump outside the life-time -//! of \ref CodeHolder and \ref BaseEmitter. -//! -//! ### Using ErrorHandler -//! -//! An example of attaching \ref ErrorHandler to \ref CodeHolder. -//! -//! ``` -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! // A simple error handler implementation, extend according to your needs. -//! class MyErrorHandler : public ErrorHandler { -//! public: -//! void handleError(Error err, const char* message, BaseEmitter* origin) override { -//! printf("AsmJit error: %s\n", message); -//! } -//! }; -//! -//! int main() { -//! JitRuntime rt; -//! -//! MyErrorHandler myErrorHandler; -//! CodeHolder code; -//! -//! code.init(rt.environment()); -//! code.setErrorHandler(&myErrorHandler); -//! -//! x86::Assembler a(&code); -//! // ... code generation ... -//! -//! return 0; -//! } -//! ``` -//! -//! Useful classes in error handling group: -//! -//! - See \ref DebugUtils that provides utilities useful for debugging. -//! - See \ref Error that lists error codes that AsmJit uses. -//! - See \ref ErrorHandler for more details about error handling. - -// ============================================================================ -// [Documentation - asmjit_instruction_db] -// ============================================================================ - -//! \defgroup asmjit_instruction_db Instruction DB -//! \brief Instruction database (introspection, read/write, validation, ...). -//! -//! ### Overview -//! -//! AsmJit provides a public instruction database that can be used to query -//! information about a complete instruction. The instruction database requires -//! the knowledge of the following: -//! -//! - \ref BaseInst - Base instruction that contains instruction id, options, -//! and a possible extra-register that represents either REP prefix counter -//! or AVX-512 selector (mask). -//! - \ref Operand - Represents operands of an instruction. -//! -//! Each instruction can be then queried for the following information: -//! -//! - \ref InstRWInfo - Read/write information of instruction and its oprands. -//! - \ref OpRWInfo - Read/write information of a single operand, part of -//! \ref InstRWInfo data structure. -//! - \ref BaseFeatures - CPU features required to execute the instruction. -//! -//! In addition to query functionality AsmJit is also able to validate whether -//! an instruction and its operands are valid. This is useful for making sure -//! that what user tries to emit is correct and it can be also used by other -//! projects that parse user input, like AsmTK project. -//! -//! ### Query API -//! -//! The instruction query API is provided by \ref InstAPI namespace. The -//! following queries are possible: -//! -//! - \ref InstAPI::queryRWInfo() - queries read/write information of the -//! given instruction and its operands. Includes also CPU flags read/written. -//! -//! - \ref InstAPI::queryFeatures() - queries CPU features that are required -//! to execute the given instruction. A full instruction with operands must -//! be given as some architectures like X86 may require different features -//! for the same instruction based on its operands. -//! -//! - asmjit_test_x86_instinfo.cpp -//! can be also used as a reference about accessing instruction information. -//! -//! ### Validation API -//! -//! The instruction validation API is provided by \ref InstAPI namespace in the -//! similar fashion like the Query API, however, validation can also be turned -//! on at \ref BaseEmitter level. The following is possible: -//! -//! - \ref InstAPI::validate() - low-level instruction validation function -//! that is used internally by emitters if strict validation is enabled. -//! -//! - \ref BaseEmitter::addValidationOptions() - can be used to enable -//! validation at emitter level, see \ref BaseEmitter::ValidationOptions. - - -// ============================================================================ -// [Documentation - asmjit_virtual_memory] -// ============================================================================ - -//! \defgroup asmjit_virtual_memory Virtual Memory -//! \brief Virtual memory management. -//! -//! ### Overview -//! -//! AsmJit's virtual memory management is divided into two main categories: -//! -//! - Low level API that provides cross-platform abstractions for virtual -//! memory allocation. Implemented in \ref VirtMem namespace. -//! - High level API that makes it very easy to store generated code for -//! execution. See \ref JitRuntime, which is used by many examples for its -//! simplicity and easy integration with \ref CodeHolder. There is also -//! \ref JitAllocator, which lays somewhere between RAW memory allocation -//! and \ref JitRuntime. - -// ============================================================================ -// [Documentation - asmjit_zone_memory] -// ============================================================================ - -//! \defgroup asmjit_zone Zone Memory -//! \brief Zone memory allocator and containers. -//! -//! ### Overview -//! -//! AsmJit uses zone memory allocation (also known as Arena allocation) to allocate -//! most of the data it uses. It's a fast allocator that allows AsmJit to allocate -//! a lot of small data structures fast and without `malloc()` overhead. Since -//! code generators and all related classes are usually short-lived this approach -//! decreases memory usage and fragmentation as arena-based allocators always -//! allocate larger blocks of memory, which are then split into smaller chunks. -//! -//! Another advantage of zone memory allocation is that since the whole library -//! uses this strategy it's very easy to deallocate everything that a particular -//! instance is holding by simply releasing the memory the allocator holds. This -//! improves destruction time of such objects as there is no destruction at all. -//! Long-lived objects just reset its data in destructor or in their reset() -//! member function for a future reuse. For this purpose all containers in AsmJit -//! are also zone allocated. -//! -//! ### Zone Allocation -//! -//! - \ref Zone - Incremental zone memory allocator with minimum features. It -//! can only allocate memory without the possibility to return it back to -//! the allocator. -//! -//! - \ref ZoneTmp - A temporary \ref Zone with some initial static storage. -//! If the allocation requests fit the static storage allocated then there -//! will be no dynamic memory allocation during the lifetime of \ref ZoneTmp, -//! otherwise it would act as \ref Zone with one preallocated block on the -//! stack. -//! -//! - \ref ZoneAllocator - A wrapper of \ref Zone that provides the capability -//! of returning memory to the allocator. Such memory is stored in a pool for -//! later reuse. -//! -//! ### Zone Allocated Containers -//! -//! - \ref ZoneString - Zone allocated string. -//! - \ref ZoneHash - Zone allocated hash table. -//! - \ref ZoneTree - Zone allocated red-black tree. -//! - \ref ZoneList - Zone allocated double-linked list. -//! - \ref ZoneStack - Zone allocated stack. -//! - \ref ZoneVector - Zone allocated vector. -//! - \ref ZoneBitVector - Zone allocated vector of bits. -//! -//! ### Using Zone Allocated Containers -//! -//! The most common data structure exposed by AsmJit is \ref ZoneVector. It's very -//! similar to `std::vector`, but the implementation doesn't use exceptions and -//! uses the mentioned \ref ZoneAllocator for performance reasons. You don't have -//! to worry about allocations as you should not need to add items to AsmJit's -//! data structures directly as there should be API for all required operations. -//! -//! The following APIs in \ref CodeHolder returns \ref ZoneVector reference: -//! -//! ``` -//! using namespace asmjit; -//! -//! void example(CodeHolder& code) { -//! // Contains all emitters attached to CodeHolder. -//! const ZoneVector& emitters = code.emitters(); -//! -//! // Contains all section entries managed by CodeHolder. -//! const ZoneVector& sections = code.sections(); -//! -//! // Contains all label entries managed by CodeHolder. -//! const ZoneVector& labelEntries = code.labelEntries(); -//! -//! // Contains all relocation entries managed by CodeHolder. -//! const ZoneVector& relocEntries = code.relocEntries(); -//! } -//! ``` -//! -//! \ref ZoneVector has overloaded array access operator to make it possible -//! to access its elements through operator[]. Some standard functions like -//! \ref ZoneVector::empty(), \ref ZoneVector::size(), and \ref ZoneVector::data() -//! are provided as well. Vectors are also iterable through a range-based for loop: -//! -//! ``` -//! using namespace asmjit; -//! -//! void example(CodeHolder& code) { -//! for (LabelEntry* le : code.labelEntries()) { -//! printf("Label #%u {Bound=%s Offset=%llu}", -//! le->id(), -//! le->isBound() ? "true" : "false", -//! (unsigned long long)le->offset()); -//! } -//! } -//! ``` -//! -//! ### Design Considerations -//! -//! Zone-allocated containers do not store the allocator within the container. -//! This decision was made to reduce the footprint of such containers as AsmJit -//! tooling, especially Compiler's register allocation, may use many instances -//! of such containers to perform code analysis and register allocation. -//! -//! For example to append an item into a \ref ZoneVector it's required to pass -//! the allocator as the first argument, so it can be used in case that the -//! vector needs a reallocation. Such function also returns an error, which -//! must be propagated to the caller. -//! -//! ``` -//! using namespace asmjit -//! -//! Error example(ZoneAllocator* allocator) { -//! ZoneVector vector; -//! -//! // Unfortunately, allocator must be provided to all functions that mutate -//! // the vector. However, AsmJit users should never need to do this as all -//! // manipulation should be done through public API, which takes care of -//! // that. -//! for (int i = 0; i < 100; i++) { -//! ASMJIT_PROPAGATE(vector.append(allocator, i)); -//! } -//! -//! // By default vector's destructor doesn't release anything as it knows -//! // that its content is zone allocated. However, \ref ZoneVector::release -//! // can be used to explicitly release the vector data to the allocator if -//! // necessary -//! vector.release(allocator); -//! } -//! ``` -//! -//! Containers like \ref ZoneVector also provide a functionality to reserve a -//! certain number of items before any items are added to it. This approach is -//! used internally in most places as it allows to prepare space for data that -//! will be added to some container before the data itself was created. -//! -//! ``` -//! using namespace asmjit -//! -//! Error example(ZoneAllocator* allocator) { -//! ZoneVector vector; -//! -//! ASMJIT_PROPAGATE(vector.willGrow(100)); -//! for (int i = 0; i < 100; i++) { -//! // Cannot fail. -//! vector.appendUnsafe(allocator, i); -//! } -//! -//! vector.release(allocator); -//! } -//! ``` - -// ============================================================================ -// [Documentation - asmjit_utilities] -// ============================================================================ - -//! \defgroup asmjit_utilities Utilities -//! \brief Utility classes and functions. -//! -//! ### Overview -//! -//! AsmJit uses and provides utility classes and functions, that can be used -//! with AsmJit. The functionality can be divided into the following topics: -//! -//! ### String Functionality -//! -//! - \ref String - AsmJit's string container, which is used internally -//! and which doesn't use exceptions and has a stable layout, which is -//! not dependent on C++ standard library. -//! - \ref StringTmp - String that can have base storage allocated on -//! stack. The amount of storage on stack can be specified as a template -//! parameter. -//! - \ref FixedString - Fixed string container limited up to N characters. -//! -//! ### Code Generation Utilities -//! -//! - \ref ConstPool - Constant pool used by \ref BaseCompiler, but also -//! available to users that may find use of it. -//! -//! ### Support Functionality Used by AsmJit -//! -//! - \ref Support namespace provides many other utility functions and -//! classes that are used by AsmJit, and made public. - -// ============================================================================ -// [Documentation - asmjit_ backends] -// ============================================================================ - -//! \defgroup asmjit_x86 X86 Backend -//! \brief X86/X64 backend. - -// ============================================================================ -// [Documentation - asmjit_ra] -// ============================================================================ - -//! \cond INTERNAL -//! \defgroup asmjit_ra RA -//! \brief Register allocator internals. -//! \endcond - -} // {asmjit} - -// ============================================================================ -// [Core Headers] -// ============================================================================ - -#include "./core/globals.h" - -#include "./core/arch.h" -#include "./core/assembler.h" -#include "./core/builder.h" -#include "./core/callconv.h" -#include "./core/codeholder.h" -#include "./core/compiler.h" -#include "./core/constpool.h" -#include "./core/cpuinfo.h" -#include "./core/datatypes.h" -#include "./core/emitter.h" -#include "./core/environment.h" -#include "./core/errorhandler.h" -#include "./core/features.h" -#include "./core/formatter.h" -#include "./core/func.h" -#include "./core/inst.h" -#include "./core/jitallocator.h" -#include "./core/jitruntime.h" -#include "./core/logger.h" -#include "./core/operand.h" -#include "./core/osutils.h" -#include "./core/string.h" -#include "./core/support.h" -#include "./core/target.h" -#include "./core/type.h" -#include "./core/virtmem.h" -#include "./core/zone.h" -#include "./core/zonehash.h" -#include "./core/zonelist.h" -#include "./core/zonetree.h" -#include "./core/zonestack.h" -#include "./core/zonestring.h" -#include "./core/zonevector.h" - -// ============================================================================ -// [Deprecated] -// ============================================================================ - -#ifndef ASMJIT_NO_DEPRECATED -namespace asmjit { - -#ifndef ASMJIT_NO_COMPILER -ASMJIT_DEPRECATED("Use InvokeNode instead of FuncCallNode") -typedef InvokeNode FuncCallNode; -#endif // !ASMJIT_NO_COMPILER - -#ifndef ASMJIT_NO_LOGGING -namespace Logging { using namespace Formatter; } -#endif //! ASMJIT_NO_LOGGING - -} // {asmjit} -#endif // !ASMJIT_NO_DEPRECATED - -#endif // ASMJIT_CORE_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/api-build_p.h b/ext/asmjit-master/src/asmjit/core/api-build_p.h deleted file mode 100644 index db37ca77..00000000 --- a/ext/asmjit-master/src/asmjit/core/api-build_p.h +++ /dev/null @@ -1,77 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_API_BUILD_P_H_INCLUDED -#define ASMJIT_CORE_API_BUILD_P_H_INCLUDED - -#define ASMJIT_EXPORTS - -// Only turn-off these warnings when building asmjit itself. -#ifdef _MSC_VER - #ifndef _CRT_SECURE_NO_DEPRECATE - #define _CRT_SECURE_NO_DEPRECATE - #endif - #ifndef _CRT_SECURE_NO_WARNINGS - #define _CRT_SECURE_NO_WARNINGS - #endif -#endif - -// Dependencies only required for asmjit build, but never exposed through public headers. -#ifdef _WIN32 - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #ifndef NOMINMAX - #define NOMINMAX - #endif - #include -#endif - -// ============================================================================ -// [asmjit::Build - Globals - Build-Only] -// ============================================================================ - -#include "./api-config.h" - -#if !defined(ASMJIT_BUILD_DEBUG) && defined(__GNUC__) && !defined(__clang__) - #define ASMJIT_FAVOR_SIZE __attribute__((__optimize__("Os"))) - #define ASMJIT_FAVOR_SPEED __attribute__((__optimize__("O3"))) -#elif ASMJIT_CXX_HAS_ATTRIBUTE(__minsize__, 0) - #define ASMJIT_FAVOR_SIZE __attribute__((__minsize__)) - #define ASMJIT_FAVOR_SPEED -#else - #define ASMJIT_FAVOR_SIZE - #define ASMJIT_FAVOR_SPEED -#endif - -// Make sure '#ifdef'ed unit tests are properly highlighted in IDE. -#if !defined(ASMJIT_TEST) && defined(__INTELLISENSE__) - #define ASMJIT_TEST -#endif - -// Include a unit testing package if this is a `asmjit_test_unit` build. -#if defined(ASMJIT_TEST) - #include "../../../test/broken.h" -#endif - -#endif // ASMJIT_CORE_API_BUILD_P_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/api-config.h b/ext/asmjit-master/src/asmjit/core/api-config.h deleted file mode 100644 index 1388da49..00000000 --- a/ext/asmjit-master/src/asmjit/core/api-config.h +++ /dev/null @@ -1,540 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_API_CONFIG_H_INCLUDED -#define ASMJIT_CORE_API_CONFIG_H_INCLUDED - -// ============================================================================ -// [asmjit::Version] -// ============================================================================ - -//! \addtogroup asmjit_core -//! \{ - -//! AsmJit library version in `(Major << 16) | (Minor << 8) | (Patch)` format. -#define ASMJIT_LIBRARY_VERSION 0x010400 /* 1.4.0 */ - -//! \} - -// ============================================================================ -// [asmjit::Build - Documentation] -// ============================================================================ - -// NOTE: Doxygen cannot document macros that are not defined, that's why we have -// to define them and then undefine them, so it won't use the macros with its -// own preprocessor. -#ifdef _DOXYGEN -namespace asmjit { - -//! \addtogroup asmjit_build -//! \{ - -//! Asmjit is embedded, implies \ref ASMJIT_STATIC. -#define ASMJIT_EMBED - -//! Enables static-library build. -#define ASMJIT_STATIC - -//! Defined when AsmJit's build configuration is 'Debug'. -//! -//! \note Can be defined explicitly to bypass autodetection. -#define ASMJIT_BUILD_DEBUG - -//! Defined when AsmJit's build configuration is 'Release'. -//! -//! \note Can be defined explicitly to bypass autodetection. -#define ASMJIT_BUILD_RELEASE - -//! Defined to build X86/X64 backend. -#define ASMJIT_BUILD_X86 - -//! Defined to build ARM/AArch64 backend. -#define ASMJIT_BUILD_ARM - -//! Defined to build host backend autodetected at compile-time. -#define ASMJIT_BUILD_HOST - -//! Disables deprecated API at compile time. -#define ASMJIT_NO_DEPRECATED - -//! Disables \ref asmjit_builder functionality completely. -#define ASMJIT_NO_BUILDER - -//! Disables \ref asmjit_compiler functionality completely. -#define ASMJIT_NO_COMPILER - -//! Disables JIT memory management and \ref JitRuntime. -#define ASMJIT_NO_JIT - -//! Disables \ref Logger and \ref Formatter. -#define ASMJIT_NO_LOGGING - -//! Disables everything that contains text. -#define ASMJIT_NO_TEXT - -//! Disables instruction validation API. -#define ASMJIT_NO_VALIDATION - -//! Disables instruction introspection API. -#define ASMJIT_NO_INTROSPECTION - -// Avoid doxygen preprocessor using feature-selection definitions. -#undef ASMJIT_NO_DEPRECATED -#undef ASMJIT_NO_BUILDER -#undef ASMJIT_NO_COMPILER -#undef ASMJIT_NO_JIT -#undef ASMJIT_NO_LOGGING -#undef ASMJIT_NO_TEXT -#undef ASMJIT_NO_VALIDATION -#undef ASMJIT_NO_INTROSPECTION - -//! \} - -} // {asmjit} -#endif // _DOXYGEN - -// ============================================================================ -// [asmjit::Dependencies] -// ============================================================================ - -// We really want std-types as globals. -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#if !defined(_WIN32) && !defined(__EMSCRIPTEN__) - #include -#endif - - -// ============================================================================ -// [asmjit::Options] -// ============================================================================ - -// ASMJIT_NO_BUILDER implies ASMJIT_NO_COMPILER. -#if defined(ASMJIT_NO_BUILDER) && !defined(ASMJIT_NO_COMPILER) - #define ASMJIT_NO_COMPILER -#endif - -// Prevent compile-time errors caused by misconfiguration. -#if defined(ASMJIT_NO_TEXT) && !defined(ASMJIT_NO_LOGGING) - #pragma "ASMJIT_NO_TEXT can only be defined when ASMJIT_NO_LOGGING is defined." - #undef ASMJIT_NO_TEXT -#endif - -#if defined(ASMJIT_NO_INTROSPECTION) && !defined(ASMJIT_NO_COMPILER) - #pragma message("ASMJIT_NO_INTROSPECTION can only be defined when ASMJIT_NO_COMPILER is defined") - #undef ASMJIT_NO_INTROSPECTION -#endif - -// ============================================================================ -// [asmjit::Build - Globals - Deprecated] -// ============================================================================ - -#ifndef ASMJIT_NO_DEPRECATED - #if defined(ASMJIT_BUILD_EMBED) || defined(ASMJIT_BUILD_STATIC) - #if defined(ASMJIT_BUILD_EMBED) - #pragma message("'ASMJIT_BUILD_EMBED' is deprecated, use 'ASMJIT_STATIC'") - #endif - #if defined(ASMJIT_BUILD_STATIC) - #pragma message("'ASMJIT_BUILD_STATIC' is deprecated, use 'ASMJIT_STATIC'") - #endif - - #if !defined(ASMJIT_STATIC) - #define ASMJIT_STATIC - #endif - #endif -#endif // !ASMJIT_NO_DEPRECATED - -// ============================================================================ -// [asmjit::Build - Globals - Build Mode] -// ============================================================================ - -// Detect ASMJIT_BUILD_DEBUG and ASMJIT_BUILD_RELEASE if not defined. -#if !defined(ASMJIT_BUILD_DEBUG) && !defined(ASMJIT_BUILD_RELEASE) - #if !defined(NDEBUG) - #define ASMJIT_BUILD_DEBUG - #else - #define ASMJIT_BUILD_RELEASE - #endif -#endif - -// ============================================================================ -// [asmjit::Build - Globals - Target Architecture] -// ============================================================================ - -#if defined(_M_X64) || defined(__x86_64__) - #define ASMJIT_ARCH_X86 64 -#elif defined(_M_IX86) || defined(__X86__) || defined(__i386__) - #define ASMJIT_ARCH_X86 32 -#else - #define ASMJIT_ARCH_X86 0 -#endif - -#if defined(__arm64__) || defined(__aarch64__) -# define ASMJIT_ARCH_ARM 64 -#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__) || defined(__thumb2__) - #define ASMJIT_ARCH_ARM 32 -#else - #define ASMJIT_ARCH_ARM 0 -#endif - -#if defined(_MIPS_ARCH_MIPS64) || defined(__mips64) - #define ASMJIT_ARCH_MIPS 64 -#elif defined(_MIPS_ARCH_MIPS32) || defined(_M_MRX000) || defined(__mips__) - #define ASMJIT_ARCH_MIPS 32 -#else - #define ASMJIT_ARCH_MIPS 0 -#endif - -#define ASMJIT_ARCH_BITS (ASMJIT_ARCH_X86 | ASMJIT_ARCH_ARM | ASMJIT_ARCH_MIPS) -#if ASMJIT_ARCH_BITS == 0 - #undef ASMJIT_ARCH_BITS - #if defined (__LP64__) || defined(_LP64) - #define ASMJIT_ARCH_BITS 64 - #else - #define ASMJIT_ARCH_BITS 32 - #endif -#endif - -#if (defined(__ARMEB__)) || \ - (defined(__MIPSEB__)) || \ - (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) - #define ASMJIT_ARCH_LE 0 - #define ASMJIT_ARCH_BE 1 -#else - #define ASMJIT_ARCH_LE 1 - #define ASMJIT_ARCH_BE 0 -#endif - -// Build host architecture if no architecture is selected. -#if !defined(ASMJIT_BUILD_HOST) && \ - !defined(ASMJIT_BUILD_X86) && \ - !defined(ASMJIT_BUILD_ARM) - #define ASMJIT_BUILD_HOST -#endif - -// Detect host architecture if building only for host. -#if ASMJIT_ARCH_X86 && defined(ASMJIT_BUILD_HOST) && !defined(ASMJIT_BUILD_X86) - #define ASMJIT_BUILD_X86 -#endif - -#if ASMJIT_ARCH_ARM && defined(ASMJIT_BUILD_HOST) && !defined(ASMJIT_BUILD_ARM) - #define ASMJIT_BUILD_ARM -#endif - -// ============================================================================ -// [asmjit::Build - Globals - C++ Compiler and Features Detection] -// ============================================================================ - -#define ASMJIT_CXX_GNU 0 -#define ASMJIT_CXX_MAKE_VER(MAJOR, MINOR) ((MAJOR) * 1000 + (MINOR)) - -// Intel Compiler [pretends to be GNU or MSC, so it must be checked first]: -// - https://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler -// - https://software.intel.com/en-us/articles/c14-features-supported-by-intel-c-compiler -// - https://software.intel.com/en-us/articles/c17-features-supported-by-intel-c-compiler -#if defined(__INTEL_COMPILER) - -// MSC Compiler: -// - https://msdn.microsoft.com/en-us/library/hh567368.aspx -// -// Version List: -// - 16.00.0 == VS2010 -// - 17.00.0 == VS2012 -// - 18.00.0 == VS2013 -// - 19.00.0 == VS2015 -// - 19.10.0 == VS2017 -#elif defined(_MSC_VER) && defined(_MSC_FULL_VER) - -// Clang Compiler [Pretends to be GNU, so it must be checked before]: -// - https://clang.llvm.org/cxx_status.html -#elif defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) - -// GNU Compiler: -// - https://gcc.gnu.org/projects/cxx-status.html -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) - - #undef ASMJIT_CXX_GNU - #define ASMJIT_CXX_GNU ASMJIT_CXX_MAKE_VER(__GNUC__, __GNUC_MINOR__) - -#endif - -// Compiler features detection macros. -#if defined(__clang__) && defined(__has_attribute) - #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (__has_attribute(NAME)) -#else - #define ASMJIT_CXX_HAS_ATTRIBUTE(NAME, CHECK) (!(!(CHECK))) -#endif - -// ============================================================================ -// [asmjit::Build - Globals - API Decorators & Language Extensions] -// ============================================================================ - -// API (Export / Import). -#if !defined(ASMJIT_STATIC) - #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) - #ifdef ASMJIT_EXPORTS - #define ASMJIT_API __declspec(dllexport) - #else - #define ASMJIT_API __declspec(dllimport) - #endif - #elif defined(_WIN32) && defined(__GNUC__) - #ifdef ASMJIT_EXPORTS - #define ASMJIT_API __attribute__((__dllexport__)) - #else - #define ASMJIT_API __attribute__((__dllimport__)) - #endif - #elif defined(__GNUC__) - #define ASMJIT_API __attribute__((__visibility__("default"))) - #endif -#endif - -#if !defined(ASMJIT_API) - #define ASMJIT_API -#endif - -#if !defined(ASMJIT_VARAPI) - #define ASMJIT_VARAPI extern ASMJIT_API -#endif - -// This is basically a workaround. When using MSVC and marking class as DLL -// export everything gets exported, which is unwanted in most projects. MSVC -// automatically exports typeinfo and vtable if at least one symbol of the -// class is exported. However, GCC has some strange behavior that even if -// one or more symbol is exported it doesn't export typeinfo unless the -// class itself is decorated with "visibility(default)" (i.e. ASMJIT_API). -#if !defined(_WIN32) && defined(__GNUC__) - #define ASMJIT_VIRTAPI ASMJIT_API -#else - #define ASMJIT_VIRTAPI -#endif - -// Function attributes. -#if !defined(ASMJIT_BUILD_DEBUG) && defined(__GNUC__) - #define ASMJIT_INLINE inline __attribute__((__always_inline__)) -#elif !defined(ASMJIT_BUILD_DEBUG) && defined(_MSC_VER) - #define ASMJIT_INLINE __forceinline -#else - #define ASMJIT_INLINE inline -#endif - -#if defined(__GNUC__) - #define ASMJIT_NOINLINE __attribute__((__noinline__)) - #define ASMJIT_NORETURN __attribute__((__noreturn__)) -#elif defined(_MSC_VER) - #define ASMJIT_NOINLINE __declspec(noinline) - #define ASMJIT_NORETURN __declspec(noreturn) -#else - #define ASMJIT_NOINLINE - #define ASMJIT_NORETURN -#endif - -// Calling conventions. -#if ASMJIT_ARCH_X86 == 32 && defined(__GNUC__) - #define ASMJIT_CDECL __attribute__((__cdecl__)) - #define ASMJIT_STDCALL __attribute__((__stdcall__)) - #define ASMJIT_FASTCALL __attribute__((__fastcall__)) - #define ASMJIT_REGPARM(N) __attribute__((__regparm__(N))) -#elif ASMJIT_ARCH_X86 == 32 && defined(_MSC_VER) - #define ASMJIT_CDECL __cdecl - #define ASMJIT_STDCALL __stdcall - #define ASMJIT_FASTCALL __fastcall - #define ASMJIT_REGPARM(N) -#else - #define ASMJIT_CDECL - #define ASMJIT_STDCALL - #define ASMJIT_FASTCALL - #define ASMJIT_REGPARM(N) -#endif - -#if ASMJIT_ARCH_X86 && defined(_WIN32) && defined(_MSC_VER) - #define ASMJIT_VECTORCALL __vectorcall -#elif ASMJIT_ARCH_X86 && defined(_WIN32) - #define ASMJIT_VECTORCALL __attribute__((__vectorcall__)) -#else - #define ASMJIT_VECTORCALL -#endif - - -// Type alignment (not allowed by C++11 'alignas' keyword). -#if defined(__GNUC__) - #define ASMJIT_ALIGN_TYPE(TYPE, N) __attribute__((__aligned__(N))) TYPE -#elif defined(_MSC_VER) - #define ASMJIT_ALIGN_TYPE(TYPE, N) __declspec(align(N)) TYPE -#else - #define ASMJIT_ALIGN_TYPE(TYPE, N) TYPE -#endif - -//! \def ASMJIT_MAY_ALIAS -//! -//! Expands to `__attribute__((__may_alias__))` if supported. -#if defined(__GNUC__) - #define ASMJIT_MAY_ALIAS __attribute__((__may_alias__)) -#else - #define ASMJIT_MAY_ALIAS -#endif - -//! \def ASMJIT_LIKELY(...) -//! -//! Condition is likely to be taken (mostly error handling and edge cases). - -//! \def ASMJIT_UNLIKELY(...) -//! -//! Condition is unlikely to be taken (mostly error handling and edge cases). -#if defined(__GNUC__) - #define ASMJIT_LIKELY(...) __builtin_expect(!!(__VA_ARGS__), 1) - #define ASMJIT_UNLIKELY(...) __builtin_expect(!!(__VA_ARGS__), 0) -#else - #define ASMJIT_LIKELY(...) (__VA_ARGS__) - #define ASMJIT_UNLIKELY(...) (__VA_ARGS__) -#endif - -//! \def ASMJIT_FALLTHROUGH -//! -//! Portable [[fallthrough]] attribute. -#if defined(__clang__) && __cplusplus >= 201103L - #define ASMJIT_FALLTHROUGH [[clang::fallthrough]] -#elif defined(__GNUC__) && __GNUC__ >= 7 - #define ASMJIT_FALLTHROUGH __attribute__((__fallthrough__)) -#else - #define ASMJIT_FALLTHROUGH ((void)0) /* fallthrough */ -#endif - -//! \def ASMJIT_DEPRECATED -//! -//! Marks function, class, struct, enum, or anything else as deprecated. -#if defined(__GNUC__) - #define ASMJIT_DEPRECATED(MESSAGE) __attribute__((__deprecated__(MESSAGE))) - #if defined(__clang__) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) __attribute__((__deprecated__(MESSAGE))) - #else - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */ - #endif -#elif defined(_MSC_VER) - #define ASMJIT_DEPRECATED(MESSAGE) __declspec(deprecated(MESSAGE)) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) /* not usable if a deprecated function uses it */ -#else - #define ASMJIT_DEPRECATED(MESSAGE) - #define ASMJIT_DEPRECATED_STRUCT(MESSAGE) -#endif - -// Utilities. -#define ASMJIT_OFFSET_OF(STRUCT, MEMBER) ((int)(intptr_t)((const char*)&((const STRUCT*)0x100)->MEMBER) - 0x100) -#define ASMJIT_ARRAY_SIZE(X) uint32_t(sizeof(X) / sizeof(X[0])) - -#if ASMJIT_CXX_HAS_ATTRIBUTE(no_sanitize, 0) - #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize__("undefined"))) -#elif ASMJIT_CXX_GNU >= ASMJIT_CXX_MAKE_VER(4, 9) - #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF __attribute__((__no_sanitize_undefined__)) -#else - #define ASMJIT_ATTRIBUTE_NO_SANITIZE_UNDEF -#endif - -// ============================================================================ -// [asmjit::Build - Globals - Begin-Namespace / End-Namespace] -// ============================================================================ - -#if defined(__clang__) - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { \ - _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 { \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") - #define ASMJIT_END_NAMESPACE \ - _Pragma("GCC diagnostic pop") \ - } -#elif defined(__GNUC__) && __GNUC__ >= 8 - #define ASMJIT_BEGIN_NAMESPACE \ - namespace asmjit { \ - _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 { \ - __pragma(warning(push)) \ - __pragma(warning(disable: 4127)) /* conditional expression is const */ \ - __pragma(warning(disable: 4201)) /* nameless struct/union */ - #define ASMJIT_END_NAMESPACE \ - __pragma(warning(pop)) \ - } -#endif - -#if !defined(ASMJIT_BEGIN_NAMESPACE) && !defined(ASMJIT_END_NAMESPACE) - #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { - #define ASMJIT_END_NAMESPACE } -#endif - -#define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) \ - ASMJIT_BEGIN_NAMESPACE \ - namespace NAMESPACE { - -#define ASMJIT_END_SUB_NAMESPACE \ - } \ - ASMJIT_END_NAMESPACE - -// ============================================================================ -// [asmjit::Build - Globals - Utilities] -// ============================================================================ - -#define ASMJIT_NONCOPYABLE(...) \ - private: \ - __VA_ARGS__(const __VA_ARGS__& other) = delete; \ - __VA_ARGS__& operator=(const __VA_ARGS__& other) = delete; \ - public: - -#define ASMJIT_NONCONSTRUCTIBLE(...) \ - private: \ - __VA_ARGS__() = delete; \ - __VA_ARGS__(const __VA_ARGS__& other) = delete; \ - __VA_ARGS__& operator=(const __VA_ARGS__& other) = delete; \ - public: - -// ============================================================================ -// [asmjit::Build - Globals - Cleanup] -// ============================================================================ - -// Cleanup definitions that are only used within this header file. -#undef ASMJIT_CXX_GNU -#undef ASMJIT_CXX_MAKE_VER - -#endif // ASMJIT_CORE_API_CONFIG_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/arch.cpp b/ext/asmjit-master/src/asmjit/core/arch.cpp deleted file mode 100644 index 7200897b..00000000 --- a/ext/asmjit-master/src/asmjit/core/arch.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/arch.h" - -#ifdef ASMJIT_BUILD_X86 - #include "../x86/x86archdata_p.h" -#endif - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/armarchdata_p.h" -#endif - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::ArchUtils] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error ArchUtils::typeIdToRegInfo(uint32_t arch, uint32_t typeId, uint32_t* typeIdOut, RegInfo* regInfoOut) noexcept { - // Zero the output in case the input is invalid. - *typeIdOut = 0; - regInfoOut->reset(); - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::ArchInternal::typeIdToRegInfo(arch, typeId, typeIdOut, regInfoOut); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::ArchInternal::typeIdToRegInfo(arch, typeId, typeIdOut, regInfoOut); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/arch.h b/ext/asmjit-master/src/asmjit/core/arch.h deleted file mode 100644 index 4991a333..00000000 --- a/ext/asmjit-master/src/asmjit/core/arch.h +++ /dev/null @@ -1,64 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_ARCH_H_INCLUDED -#define ASMJIT_CORE_ARCH_H_INCLUDED - -#include "../core/environment.h" -#include "../core/operand.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::ArchRegs] -// ============================================================================ - -//! Information about registers of a CPU architecture. -struct ArchRegs { - //! Register information and signatures indexed by `BaseReg::RegType`. - RegInfo regInfo[BaseReg::kTypeMax + 1]; - //! Count (maximum) of registers per `BaseReg::RegType`. - uint8_t regCount[BaseReg::kTypeMax + 1]; - //! Converts RegType to TypeId, see `Type::Id`. - uint8_t regTypeToTypeId[BaseReg::kTypeMax + 1]; -}; - -// ============================================================================ -// [asmjit::ArchUtils] -// ============================================================================ - -//! Architecture utilities. -namespace ArchUtils { - -ASMJIT_API Error typeIdToRegInfo(uint32_t arch, uint32_t typeId, uint32_t* typeIdOut, RegInfo* regInfo) noexcept; - -} // {ArchUtils} - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_ARCH_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/assembler.cpp b/ext/asmjit-master/src/asmjit/core/assembler.cpp deleted file mode 100644 index 08ca9735..00000000 --- a/ext/asmjit-master/src/asmjit/core/assembler.cpp +++ /dev/null @@ -1,403 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/assembler.h" -#include "../core/codebufferwriter_p.h" -#include "../core/constpool.h" -#include "../core/emitterutils_p.h" -#include "../core/formatter.h" -#include "../core/logger.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::BaseAssembler - Construction / Destruction] -// ============================================================================ - -BaseAssembler::BaseAssembler() noexcept - : BaseEmitter(kTypeAssembler), - _section(nullptr), - _bufferData(nullptr), - _bufferEnd(nullptr), - _bufferPtr(nullptr) {} -BaseAssembler::~BaseAssembler() noexcept {} - -// ============================================================================ -// [asmjit::BaseAssembler - Buffer Management] -// ============================================================================ - -Error BaseAssembler::setOffset(size_t offset) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - size_t size = Support::max(_section->bufferSize(), this->offset()); - if (ASMJIT_UNLIKELY(offset > size)) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - _bufferPtr = _bufferData + offset; - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseAssembler - Section Management] -// ============================================================================ - -static void BaseAssembler_initSection(BaseAssembler* self, Section* section) noexcept { - uint8_t* p = section->_buffer._data; - - self->_section = section; - self->_bufferData = p; - self->_bufferPtr = p + section->_buffer._size; - self->_bufferEnd = p + section->_buffer._capacity; -} - -Error BaseAssembler::section(Section* section) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - if (!_code->isSectionValid(section->id()) || _code->_sections[section->id()] != section) - return reportError(DebugUtils::errored(kErrorInvalidSection)); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) - _logger->logf(".section %s {#%u}\n", section->name(), section->id()); -#endif - - BaseAssembler_initSection(this, section); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseAssembler - Label Management] -// ============================================================================ - -Label BaseAssembler::newLabel() { - uint32_t labelId = Globals::kInvalidId; - if (ASMJIT_LIKELY(_code)) { - LabelEntry* le; - Error err = _code->newLabelEntry(&le); - if (ASMJIT_UNLIKELY(err)) - reportError(err); - else - labelId = le->id(); - } - return Label(labelId); -} - -Label BaseAssembler::newNamedLabel(const char* name, size_t nameSize, uint32_t type, uint32_t parentId) { - uint32_t labelId = Globals::kInvalidId; - if (ASMJIT_LIKELY(_code)) { - LabelEntry* le; - Error err = _code->newNamedLabelEntry(&le, name, nameSize, type, parentId); - if (ASMJIT_UNLIKELY(err)) - reportError(err); - else - labelId = le->id(); - } - return Label(labelId); -} - -Error BaseAssembler::bind(const Label& label) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - Error err = _code->bindLabel(label, _section->id(), offset()); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) - EmitterUtils::logLabelBound(this, label); -#endif - - resetInlineComment(); - if (err) - return reportError(err); - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseAssembler - Embed] -// ============================================================================ - -#ifndef ASMJIT_NO_LOGGING -struct DataSizeByPower { - char str[4]; -}; - -static const DataSizeByPower dataSizeByPowerTable[] = { - { "db" }, - { "dw" }, - { "dd" }, - { "dq" } -}; -#endif - -Error BaseAssembler::embed(const void* data, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - if (dataSize == 0) - return kErrorOk; - - CodeBufferWriter writer(this); - ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize)); - - writer.emitData(data, dataSize); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) - _logger->logBinary(data, dataSize); -#endif - - writer.done(this); - return kErrorOk; -} - -Error BaseAssembler::embedDataArray(uint32_t typeId, const void* data, size_t itemCcount, size_t repeatCount) { - uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize()); - uint32_t finalTypeId = Type::deabstract(typeId, deabstractDelta); - - if (ASMJIT_UNLIKELY(!Type::isValid(finalTypeId))) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - if (itemCcount == 0 || repeatCount == 0) - return kErrorOk; - - uint32_t typeSize = Type::sizeOf(finalTypeId); - Support::FastUInt8 of = 0; - - size_t dataSize = Support::mulOverflow(itemCcount, size_t(typeSize), &of); - size_t totalSize = Support::mulOverflow(dataSize, repeatCount, &of); - - if (ASMJIT_UNLIKELY(of)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - CodeBufferWriter writer(this); - ASMJIT_PROPAGATE(writer.ensureSpace(this, totalSize)); - -#ifndef ASMJIT_NO_LOGGING - const uint8_t* start = writer.cursor(); -#endif - - for (size_t i = 0; i < repeatCount; i++) { - writer.emitData(data, dataSize); - } - -#ifndef ASMJIT_NO_LOGGING - if (_logger) - _logger->logBinary(start, totalSize); -#endif - - writer.done(this); - return kErrorOk; -} - -Error BaseAssembler::embedConstPool(const Label& label, const ConstPool& pool) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - if (ASMJIT_UNLIKELY(!isLabelValid(label))) - return reportError(DebugUtils::errored(kErrorInvalidLabel)); - - ASMJIT_PROPAGATE(align(kAlignData, uint32_t(pool.alignment()))); - ASMJIT_PROPAGATE(bind(label)); - - size_t size = pool.size(); - CodeBufferWriter writer(this); - ASMJIT_PROPAGATE(writer.ensureSpace(this, size)); - - pool.fill(writer.cursor()); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) - _logger->logBinary(writer.cursor(), size); -#endif - - writer.advance(size); - writer.done(this); - - return kErrorOk; -} - -Error BaseAssembler::embedLabel(const Label& label, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - ASMJIT_ASSERT(_code != nullptr); - RelocEntry* re; - LabelEntry* le = _code->labelEntry(label); - - if (ASMJIT_UNLIKELY(!le)) - return reportError(DebugUtils::errored(kErrorInvalidLabel)); - - if (dataSize == 0) - dataSize = registerSize(); - - if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8)) - return reportError(DebugUtils::errored(kErrorInvalidOperandSize)); - - CodeBufferWriter writer(this); - ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize)); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) { - StringTmp<256> sb; - sb.appendFormat("%s ", dataSizeByPowerTable[Support::ctz(dataSize)].str); - Formatter::formatLabel(sb, 0, this, label.id()); - sb.append('\n'); - _logger->log(sb); - } -#endif - - Error err = _code->newRelocEntry(&re, RelocEntry::kTypeRelToAbs, uint32_t(dataSize)); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - re->_sourceSectionId = _section->id(); - re->_sourceOffset = offset(); - - if (le->isBound()) { - re->_targetSectionId = le->section()->id(); - re->_payload = le->offset(); - } - else { - LabelLink* link = _code->newLabelLink(le, _section->id(), offset(), 0); - if (ASMJIT_UNLIKELY(!link)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - link->relocId = re->id(); - } - - // Emit dummy DWORD/QWORD depending on the data size. - writer.emitZeros(dataSize); - writer.done(this); - - return kErrorOk; -} - -Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - - LabelEntry* labelEntry = _code->labelEntry(label); - LabelEntry* baseEntry = _code->labelEntry(base); - - if (ASMJIT_UNLIKELY(!labelEntry || !baseEntry)) - return reportError(DebugUtils::errored(kErrorInvalidLabel)); - - if (dataSize == 0) - dataSize = registerSize(); - - if (ASMJIT_UNLIKELY(!Support::isPowerOf2(dataSize) || dataSize > 8)) - return reportError(DebugUtils::errored(kErrorInvalidOperandSize)); - - CodeBufferWriter writer(this); - ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize)); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) { - StringTmp<256> sb; - sb.appendFormat(".%s (", dataSizeByPowerTable[Support::ctz(dataSize)].str); - Formatter::formatLabel(sb, 0, this, label.id()); - sb.append(" - "); - Formatter::formatLabel(sb, 0, this, base.id()); - sb.append(")\n"); - _logger->log(sb); - } -#endif - - // If both labels are bound within the same section it means the delta can be calculated now. - if (labelEntry->isBound() && baseEntry->isBound() && labelEntry->section() == baseEntry->section()) { - uint64_t delta = labelEntry->offset() - baseEntry->offset(); - writer.emitValueLE(delta, dataSize); - } - else { - RelocEntry* re; - Error err = _code->newRelocEntry(&re, RelocEntry::kTypeExpression, uint32_t(dataSize)); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - Expression* exp = _code->_zone.newT(); - if (ASMJIT_UNLIKELY(!exp)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - exp->reset(); - exp->opType = Expression::kOpSub; - exp->setValueAsLabel(0, labelEntry); - exp->setValueAsLabel(1, baseEntry); - - re->_sourceSectionId = _section->id(); - re->_sourceOffset = offset(); - re->_payload = (uint64_t)(uintptr_t)exp; - - writer.emitZeros(dataSize); - } - - writer.done(this); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseAssembler - Comment] -// ============================================================================ - -Error BaseAssembler::comment(const char* data, size_t size) { - if (ASMJIT_UNLIKELY(!_code)) - return reportError(DebugUtils::errored(kErrorNotInitialized)); - -#ifndef ASMJIT_NO_LOGGING - if (_logger) { - _logger->log(data, size); - _logger->log("\n", 1); - return kErrorOk; - } -#else - DebugUtils::unused(data, size); -#endif - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseAssembler - Events] -// ============================================================================ - -Error BaseAssembler::onAttach(CodeHolder* code) noexcept { - ASMJIT_PROPAGATE(Base::onAttach(code)); - - // Attach to the end of the .text section. - BaseAssembler_initSection(this, code->_sections[0]); - - return kErrorOk; -} - -Error BaseAssembler::onDetach(CodeHolder* code) noexcept { - _section = nullptr; - _bufferData = nullptr; - _bufferEnd = nullptr; - _bufferPtr = nullptr; - return Base::onDetach(code); -} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/assembler.h b/ext/asmjit-master/src/asmjit/core/assembler.h deleted file mode 100644 index fb842074..00000000 --- a/ext/asmjit-master/src/asmjit/core/assembler.h +++ /dev/null @@ -1,152 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_ASSEMBLER_H_INCLUDED -#define ASMJIT_CORE_ASSEMBLER_H_INCLUDED - -#include "../core/codeholder.h" -#include "../core/datatypes.h" -#include "../core/emitter.h" -#include "../core/operand.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_assembler -//! \{ - -// ============================================================================ -// [asmjit::BaseAssembler] -// ============================================================================ - -//! Base assembler. -//! -//! This is a base class that provides interface used by architecture specific -//! assembler implementations. Assembler doesn't hold any data, instead it's -//! attached to \ref CodeHolder, which provides all the data that Assembler -//! needs and which can be altered by it. -//! -//! Check out architecture specific assemblers for more details and examples: -//! -//! - \ref x86::Assembler - X86/X64 assembler implementation. -class ASMJIT_VIRTAPI BaseAssembler : public BaseEmitter { -public: - ASMJIT_NONCOPYABLE(BaseAssembler) - typedef BaseEmitter Base; - - //! Current section where the assembling happens. - Section* _section; - //! Start of the CodeBuffer of the current section. - uint8_t* _bufferData; - //! End (first invalid byte) of the current section. - uint8_t* _bufferEnd; - //! Pointer in the CodeBuffer of the current section. - uint8_t* _bufferPtr; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `BaseAssembler` instance. - ASMJIT_API BaseAssembler() noexcept; - //! Destroys the `BaseAssembler` instance. - ASMJIT_API virtual ~BaseAssembler() noexcept; - - //! \} - - //! \name Code-Buffer Management - //! \{ - - //! Returns the capacity of the current CodeBuffer. - inline size_t bufferCapacity() const noexcept { return (size_t)(_bufferEnd - _bufferData); } - //! Returns the number of remaining bytes in the current CodeBuffer. - inline size_t remainingSpace() const noexcept { return (size_t)(_bufferEnd - _bufferPtr); } - - //! Returns the current position in the CodeBuffer. - inline size_t offset() const noexcept { return (size_t)(_bufferPtr - _bufferData); } - - //! Sets the current position in the CodeBuffer to `offset`. - //! - //! \note The `offset` cannot be greater than buffer size even if it's - //! within the buffer's capacity. - ASMJIT_API Error setOffset(size_t offset); - - //! Returns the start of the CodeBuffer in the current section. - inline uint8_t* bufferData() const noexcept { return _bufferData; } - //! Returns the end (first invalid byte) in the current section. - inline uint8_t* bufferEnd() const noexcept { return _bufferEnd; } - //! Returns the current pointer in the CodeBuffer in the current section. - inline uint8_t* bufferPtr() const noexcept { return _bufferPtr; } - - //! \} - - //! \name Section Management - //! \{ - - //! Returns the current section. - inline Section* currentSection() const noexcept { return _section; } - - ASMJIT_API Error section(Section* section) override; - - //! \} - - //! \name Label Management - //! \{ - - ASMJIT_API Label newLabel() override; - ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, uint32_t type = Label::kTypeGlobal, uint32_t parentId = Globals::kInvalidId) override; - ASMJIT_API Error bind(const Label& label) override; - - //! \} - - //! \name Embed - //! \{ - - ASMJIT_API Error embed(const void* data, size_t dataSize) override; - ASMJIT_API Error embedDataArray(uint32_t typeId, const void* data, size_t itemCcount, size_t repeatCount = 1) override; - ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override; - - ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override; - ASMJIT_API Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) override; - - //! \} - - //! \name Comment - //! \{ - - ASMJIT_API Error comment(const char* data, size_t size = SIZE_MAX) override; - - //! \} - - //! \name Events - //! \{ - - ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; - ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_ASSEMBLER_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/builder.cpp b/ext/asmjit-master/src/asmjit/core/builder.cpp deleted file mode 100644 index 8455dc8e..00000000 --- a/ext/asmjit-master/src/asmjit/core/builder.cpp +++ /dev/null @@ -1,927 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_BUILDER - -#include "../core/builder.h" -#include "../core/emitterutils_p.h" -#include "../core/errorhandler.h" -#include "../core/formatter.h" -#include "../core/logger.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::PostponedErrorHandler (Internal)] -// ============================================================================ - -//! Postponed error handler that never throws. Used as a temporal error handler -//! to run passes. If error occurs, the caller is notified and will call the -//! real error handler, that can throw. -class PostponedErrorHandler : public ErrorHandler { -public: - void handleError(Error err, const char* message, BaseEmitter* origin) override { - DebugUtils::unused(err, origin); - _message.assign(message); - } - - StringTmp<128> _message; -}; - -// ============================================================================ -// [asmjit::BaseBuilder - Utilities] -// ============================================================================ - -static void BaseBuilder_deletePasses(BaseBuilder* self) noexcept { - for (Pass* pass : self->_passes) - pass->~Pass(); - self->_passes.reset(); -} - -// ============================================================================ -// [asmjit::BaseBuilder - Construction / Destruction] -// ============================================================================ - -BaseBuilder::BaseBuilder() noexcept - : BaseEmitter(kTypeBuilder), - _codeZone(32768 - Zone::kBlockOverhead), - _dataZone(16384 - Zone::kBlockOverhead), - _passZone(65536 - Zone::kBlockOverhead), - _allocator(&_codeZone), - _passes(), - _labelNodes(), - _cursor(nullptr), - _firstNode(nullptr), - _lastNode(nullptr), - _nodeFlags(0) {} - -BaseBuilder::~BaseBuilder() noexcept { - BaseBuilder_deletePasses(this); -} - -// ============================================================================ -// [asmjit::BaseBuilder - Node Management] -// ============================================================================ - -Error BaseBuilder::_newInstNode(InstNode** out, uint32_t instId, uint32_t instOptions, uint32_t opCount) { - uint32_t opCapacity = InstNode::capacityOfOpCount(opCount); - ASMJIT_ASSERT(opCapacity >= InstNode::kBaseOpCapacity); - - InstNode* node = _allocator.allocT(InstNode::nodeSizeOfOpCapacity(opCapacity)); - if (ASMJIT_UNLIKELY(!node)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - *out = new(node) InstNode(this, instId, instOptions, opCount, opCapacity); - return kErrorOk; -} - - -Error BaseBuilder::_newLabelNode(LabelNode** out) { - *out = nullptr; - - ASMJIT_PROPAGATE(_newNodeT(out)); - return registerLabelNode(*out); -} - -Error BaseBuilder::_newAlignNode(AlignNode** out, uint32_t alignMode, uint32_t alignment) { - *out = nullptr; - return _newNodeT(out, alignMode, alignment); -} - -Error BaseBuilder::_newEmbedDataNode(EmbedDataNode** out, uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount) { - *out = nullptr; - - uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize()); - uint32_t finalTypeId = Type::deabstract(typeId, deabstractDelta); - - if (ASMJIT_UNLIKELY(!Type::isValid(finalTypeId))) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - uint32_t typeSize = Type::sizeOf(finalTypeId); - Support::FastUInt8 of = 0; - - size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of); - if (ASMJIT_UNLIKELY(of)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - EmbedDataNode* node; - ASMJIT_PROPAGATE(_newNodeT(&node)); - - node->_embed._typeId = uint8_t(typeId); - node->_embed._typeSize = uint8_t(typeSize); - node->_itemCount = itemCount; - node->_repeatCount = repeatCount; - - uint8_t* dstData = node->_inlineData; - if (dataSize > EmbedDataNode::kInlineBufferSize) { - dstData = static_cast(_dataZone.alloc(dataSize, 8)); - if (ASMJIT_UNLIKELY(!dstData)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - node->_externalData = dstData; - } - - if (data) - memcpy(dstData, data, dataSize); - - *out = node; - return kErrorOk; -} - -Error BaseBuilder::_newConstPoolNode(ConstPoolNode** out) { - *out = nullptr; - - ASMJIT_PROPAGATE(_newNodeT(out)); - return registerLabelNode(*out); -} - -Error BaseBuilder::_newCommentNode(CommentNode** out, const char* data, size_t size) { - *out = nullptr; - - if (data) { - if (size == SIZE_MAX) - size = strlen(data); - - if (size > 0) { - data = static_cast(_dataZone.dup(data, size, true)); - if (ASMJIT_UNLIKELY(!data)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - } - } - - return _newNodeT(out, data); -} - -BaseNode* BaseBuilder::addNode(BaseNode* node) noexcept { - ASMJIT_ASSERT(node); - ASMJIT_ASSERT(!node->_prev); - ASMJIT_ASSERT(!node->_next); - ASMJIT_ASSERT(!node->isActive()); - - if (!_cursor) { - if (!_firstNode) { - _firstNode = node; - _lastNode = node; - } - else { - node->_next = _firstNode; - _firstNode->_prev = node; - _firstNode = node; - } - } - else { - BaseNode* prev = _cursor; - BaseNode* next = _cursor->next(); - - node->_prev = prev; - node->_next = next; - - prev->_next = node; - if (next) - next->_prev = node; - else - _lastNode = node; - } - - node->addFlags(BaseNode::kFlagIsActive); - if (node->isSection()) - _dirtySectionLinks = true; - - _cursor = node; - return node; -} - -BaseNode* BaseBuilder::addAfter(BaseNode* node, BaseNode* ref) noexcept { - ASMJIT_ASSERT(node); - ASMJIT_ASSERT(ref); - - ASMJIT_ASSERT(!node->_prev); - ASMJIT_ASSERT(!node->_next); - - BaseNode* prev = ref; - BaseNode* next = ref->next(); - - node->_prev = prev; - node->_next = next; - - node->addFlags(BaseNode::kFlagIsActive); - if (node->isSection()) - _dirtySectionLinks = true; - - prev->_next = node; - if (next) - next->_prev = node; - else - _lastNode = node; - - return node; -} - -BaseNode* BaseBuilder::addBefore(BaseNode* node, BaseNode* ref) noexcept { - ASMJIT_ASSERT(node != nullptr); - ASMJIT_ASSERT(!node->_prev); - ASMJIT_ASSERT(!node->_next); - ASMJIT_ASSERT(!node->isActive()); - ASMJIT_ASSERT(ref != nullptr); - ASMJIT_ASSERT(ref->isActive()); - - BaseNode* prev = ref->prev(); - BaseNode* next = ref; - - node->_prev = prev; - node->_next = next; - - node->addFlags(BaseNode::kFlagIsActive); - if (node->isSection()) - _dirtySectionLinks = true; - - next->_prev = node; - if (prev) - prev->_next = node; - else - _firstNode = node; - - return node; -} - -BaseNode* BaseBuilder::removeNode(BaseNode* node) noexcept { - if (!node->isActive()) - return node; - - BaseNode* prev = node->prev(); - BaseNode* next = node->next(); - - if (_firstNode == node) - _firstNode = next; - else - prev->_next = next; - - if (_lastNode == node) - _lastNode = prev; - else - next->_prev = prev; - - node->_prev = nullptr; - node->_next = nullptr; - node->clearFlags(BaseNode::kFlagIsActive); - if (node->isSection()) - _dirtySectionLinks = true; - - if (_cursor == node) - _cursor = prev; - - return node; -} - -void BaseBuilder::removeNodes(BaseNode* first, BaseNode* last) noexcept { - if (first == last) { - removeNode(first); - return; - } - - if (!first->isActive()) - return; - - BaseNode* prev = first->prev(); - BaseNode* next = last->next(); - - if (_firstNode == first) - _firstNode = next; - else - prev->_next = next; - - if (_lastNode == last) - _lastNode = prev; - else - next->_prev = prev; - - BaseNode* node = first; - uint32_t didRemoveSection = false; - - for (;;) { - next = node->next(); - ASMJIT_ASSERT(next != nullptr); - - node->_prev = nullptr; - node->_next = nullptr; - node->clearFlags(BaseNode::kFlagIsActive); - didRemoveSection |= uint32_t(node->isSection()); - - if (_cursor == node) - _cursor = prev; - - if (node == last) - break; - node = next; - } - - if (didRemoveSection) - _dirtySectionLinks = true; -} - -BaseNode* BaseBuilder::setCursor(BaseNode* node) noexcept { - BaseNode* old = _cursor; - _cursor = node; - return old; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Section] -// ============================================================================ - -Error BaseBuilder::sectionNodeOf(SectionNode** out, uint32_t sectionId) { - *out = nullptr; - - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (ASMJIT_UNLIKELY(!_code->isSectionValid(sectionId))) - return reportError(DebugUtils::errored(kErrorInvalidSection)); - - if (sectionId >= _sectionNodes.size()) { - Error err = _sectionNodes.reserve(&_allocator, sectionId + 1); - if (ASMJIT_UNLIKELY(err != kErrorOk)) - return reportError(err); - } - - SectionNode* node = nullptr; - if (sectionId < _sectionNodes.size()) - node = _sectionNodes[sectionId]; - - if (!node) { - ASMJIT_PROPAGATE(_newNodeT(&node, sectionId)); - - // We have already reserved enough space, this cannot fail now. - if (sectionId >= _sectionNodes.size()) - _sectionNodes.resize(&_allocator, sectionId + 1); - - _sectionNodes[sectionId] = node; - } - - *out = node; - return kErrorOk; -} - -Error BaseBuilder::section(Section* section) { - SectionNode* node; - ASMJIT_PROPAGATE(sectionNodeOf(&node, section->id())); - - if (!node->isActive()) { - // Insert the section at the end if it was not part of the code. - addAfter(node, lastNode()); - _cursor = node; - } - else { - // This is a bit tricky. We cache section links to make sure that - // switching sections doesn't involve traversal in linked-list unless - // the position of the section has changed. - if (hasDirtySectionLinks()) - updateSectionLinks(); - - if (node->_nextSection) - _cursor = node->_nextSection->_prev; - else - _cursor = _lastNode; - } - - return kErrorOk; -} - -void BaseBuilder::updateSectionLinks() noexcept { - if (!_dirtySectionLinks) - return; - - BaseNode* node_ = _firstNode; - SectionNode* currentSection = nullptr; - - while (node_) { - if (node_->isSection()) { - if (currentSection) - currentSection->_nextSection = node_->as(); - currentSection = node_->as(); - } - node_ = node_->next(); - } - - if (currentSection) - currentSection->_nextSection = nullptr; - - _dirtySectionLinks = false; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Labels] -// ============================================================================ - -Error BaseBuilder::labelNodeOf(LabelNode** out, uint32_t labelId) { - *out = nullptr; - - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - uint32_t index = labelId; - if (ASMJIT_UNLIKELY(index >= _code->labelCount())) - return DebugUtils::errored(kErrorInvalidLabel); - - if (index >= _labelNodes.size()) - ASMJIT_PROPAGATE(_labelNodes.resize(&_allocator, index + 1)); - - LabelNode* node = _labelNodes[index]; - if (!node) { - ASMJIT_PROPAGATE(_newNodeT(&node, labelId)); - _labelNodes[index] = node; - } - - *out = node; - return kErrorOk; -} - -Error BaseBuilder::registerLabelNode(LabelNode* node) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - LabelEntry* le; - ASMJIT_PROPAGATE(_code->newLabelEntry(&le)); - uint32_t labelId = le->id(); - - // We just added one label so it must be true. - ASMJIT_ASSERT(_labelNodes.size() < labelId + 1); - ASMJIT_PROPAGATE(_labelNodes.resize(&_allocator, labelId + 1)); - - _labelNodes[labelId] = node; - node->_labelId = labelId; - - return kErrorOk; -} - -static Error BaseBuilder_newLabelInternal(BaseBuilder* self, uint32_t labelId) { - ASMJIT_ASSERT(self->_labelNodes.size() < labelId + 1); - - uint32_t growBy = labelId - self->_labelNodes.size(); - Error err = self->_labelNodes.willGrow(&self->_allocator, growBy); - - if (ASMJIT_UNLIKELY(err)) - return self->reportError(err); - - LabelNode* node; - ASMJIT_PROPAGATE(self->_newNodeT(&node, labelId)); - - self->_labelNodes.resize(&self->_allocator, labelId + 1); - self->_labelNodes[labelId] = node; - node->_labelId = labelId; - return kErrorOk; -} - -Label BaseBuilder::newLabel() { - uint32_t labelId = Globals::kInvalidId; - LabelEntry* le; - - if (_code && - _code->newLabelEntry(&le) == kErrorOk && - BaseBuilder_newLabelInternal(this, le->id()) == kErrorOk) { - labelId = le->id(); - } - - return Label(labelId); -} - -Label BaseBuilder::newNamedLabel(const char* name, size_t nameSize, uint32_t type, uint32_t parentId) { - uint32_t labelId = Globals::kInvalidId; - LabelEntry* le; - - if (_code && - _code->newNamedLabelEntry(&le, name, nameSize, type, parentId) == kErrorOk && - BaseBuilder_newLabelInternal(this, le->id()) == kErrorOk) { - labelId = le->id(); - } - - return Label(labelId); -} - -Error BaseBuilder::bind(const Label& label) { - LabelNode* node; - ASMJIT_PROPAGATE(labelNodeOf(&node, label)); - - addNode(node); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Passes] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Pass* BaseBuilder::passByName(const char* name) const noexcept { - for (Pass* pass : _passes) - if (strcmp(pass->name(), name) == 0) - return pass; - return nullptr; -} - -ASMJIT_FAVOR_SIZE Error BaseBuilder::addPass(Pass* pass) noexcept { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (ASMJIT_UNLIKELY(pass == nullptr)) { - // Since this is directly called by `addPassT()` we treat `null` argument - // as out-of-memory condition. Otherwise it would be API misuse. - return DebugUtils::errored(kErrorOutOfMemory); - } - else if (ASMJIT_UNLIKELY(pass->_cb)) { - // Kinda weird, but okay... - if (pass->_cb == this) - return kErrorOk; - return DebugUtils::errored(kErrorInvalidState); - } - - ASMJIT_PROPAGATE(_passes.append(&_allocator, pass)); - pass->_cb = this; - return kErrorOk; -} - -ASMJIT_FAVOR_SIZE Error BaseBuilder::deletePass(Pass* pass) noexcept { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (ASMJIT_UNLIKELY(pass == nullptr)) - return DebugUtils::errored(kErrorInvalidArgument); - - if (pass->_cb != nullptr) { - if (pass->_cb != this) - return DebugUtils::errored(kErrorInvalidState); - - uint32_t index = _passes.indexOf(pass); - ASMJIT_ASSERT(index != Globals::kNotFound); - - pass->_cb = nullptr; - _passes.removeAt(index); - } - - pass->~Pass(); - return kErrorOk; -} - -Error BaseBuilder::runPasses() { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (_passes.empty()) - return kErrorOk; - - ErrorHandler* prev = errorHandler(); - PostponedErrorHandler postponed; - - Error err = kErrorOk; - setErrorHandler(&postponed); - - for (Pass* pass : _passes) { - _passZone.reset(); - err = pass->run(&_passZone, _logger); - if (err) - break; - } - _passZone.reset(); - setErrorHandler(prev); - - if (ASMJIT_UNLIKELY(err)) - return reportError(err, !postponed._message.empty() ? postponed._message.data() : nullptr); - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Emit] -// ============================================================================ - -Error BaseBuilder::_emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { - uint32_t opCount = EmitterUtils::opCountFromEmitArgs(o0, o1, o2, opExt); - uint32_t options = instOptions() | forcedInstOptions(); - - if (options & BaseInst::kOptionReserved) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - -#ifndef ASMJIT_NO_VALIDATION - // Strict validation. - if (hasValidationOption(kValidationOptionIntermediate)) { - Operand_ opArray[Globals::kMaxOpCount]; - EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - - Error err = InstAPI::validate(arch(), BaseInst(instId, options, _extraReg), opArray, opCount); - if (ASMJIT_UNLIKELY(err)) { - resetInstOptions(); - resetExtraReg(); - resetInlineComment(); - return reportError(err); - } - } -#endif - - // Clear options that should never be part of `InstNode`. - options &= ~BaseInst::kOptionReserved; - } - - uint32_t opCapacity = InstNode::capacityOfOpCount(opCount); - ASMJIT_ASSERT(opCapacity >= InstNode::kBaseOpCapacity); - - InstNode* node = _allocator.allocT(InstNode::nodeSizeOfOpCapacity(opCapacity)); - const char* comment = inlineComment(); - - resetInstOptions(); - resetInlineComment(); - - if (ASMJIT_UNLIKELY(!node)) { - resetExtraReg(); - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - } - - node = new(node) InstNode(this, instId, options, opCount, opCapacity); - node->setExtraReg(extraReg()); - node->setOp(0, o0); - node->setOp(1, o1); - node->setOp(2, o2); - for (uint32_t i = 3; i < opCount; i++) - node->setOp(i, opExt[i - 3]); - node->resetOpRange(opCount, opCapacity); - - if (comment) - node->setInlineComment(static_cast(_dataZone.dup(comment, strlen(comment), true))); - - addNode(node); - resetExtraReg(); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Align] -// ============================================================================ - -Error BaseBuilder::align(uint32_t alignMode, uint32_t alignment) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - AlignNode* node; - ASMJIT_PROPAGATE(_newAlignNode(&node, alignMode, alignment)); - - addNode(node); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Embed] -// ============================================================================ - -Error BaseBuilder::embed(const void* data, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - EmbedDataNode* node; - ASMJIT_PROPAGATE(_newEmbedDataNode(&node, Type::kIdU8, data, dataSize)); - - addNode(node); - return kErrorOk; -} - -Error BaseBuilder::embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t itemRepeat) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - EmbedDataNode* node; - ASMJIT_PROPAGATE(_newEmbedDataNode(&node, typeId, data, itemCount, itemRepeat)); - - addNode(node); - return kErrorOk; -} - -Error BaseBuilder::embedConstPool(const Label& label, const ConstPool& pool) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (!isLabelValid(label)) - return reportError(DebugUtils::errored(kErrorInvalidLabel)); - - ASMJIT_PROPAGATE(align(kAlignData, uint32_t(pool.alignment()))); - ASMJIT_PROPAGATE(bind(label)); - - EmbedDataNode* node; - ASMJIT_PROPAGATE(_newEmbedDataNode(&node, Type::kIdU8, nullptr, pool.size())); - - pool.fill(node->data()); - addNode(node); - return kErrorOk; -} - -// EmbedLabel / EmbedLabelDelta -// ---------------------------- -// -// If dataSize is zero it means that the size is the same as target register -// width, however, if it's provided we really want to validate whether it's -// within the possible range. - -static inline bool BaseBuilder_checkDataSize(size_t dataSize) noexcept { - return !dataSize || (Support::isPowerOf2(dataSize) && dataSize <= 8); -} - -Error BaseBuilder::embedLabel(const Label& label, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (!BaseBuilder_checkDataSize(dataSize)) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - EmbedLabelNode* node; - ASMJIT_PROPAGATE(_newNodeT(&node, label.id(), uint32_t(dataSize))); - - addNode(node); - return kErrorOk; -} - -Error BaseBuilder::embedLabelDelta(const Label& label, const Label& base, size_t dataSize) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - if (!BaseBuilder_checkDataSize(dataSize)) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - EmbedLabelDeltaNode* node; - ASMJIT_PROPAGATE(_newNodeT(&node, label.id(), base.id(), uint32_t(dataSize))); - - addNode(node); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Comment] -// ============================================================================ - -Error BaseBuilder::comment(const char* data, size_t size) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - - CommentNode* node; - ASMJIT_PROPAGATE(_newCommentNode(&node, data, size)); - - addNode(node); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Serialize] -// ============================================================================ - -Error BaseBuilder::serialize(BaseEmitter* dst) { - Error err = kErrorOk; - BaseNode* node_ = _firstNode; - - Operand_ opArray[Globals::kMaxOpCount]; - - do { - dst->setInlineComment(node_->inlineComment()); - - if (node_->isInst()) { - InstNode* node = node_->as(); - - // NOTE: Inlined to remove one additional call per instruction. - dst->setInstOptions(node->instOptions()); - dst->setExtraReg(node->extraReg()); - - const Operand_* op = node->operands(); - const Operand_* opExt = EmitterUtils::noExt; - - uint32_t opCount = node->opCount(); - if (opCount > 3) { - uint32_t i = 4; - opArray[3] = op[3]; - - while (i < opCount) { - opArray[i].copyFrom(op[i]); - i++; - } - while (i < Globals::kMaxOpCount) { - opArray[i].reset(); - i++; - } - opExt = opArray + 3; - } - - err = dst->_emit(node->id(), op[0], op[1], op[2], opExt); - } - else if (node_->isLabel()) { - if (node_->isConstPool()) { - ConstPoolNode* node = node_->as(); - err = dst->embedConstPool(node->label(), node->constPool()); - } - else { - LabelNode* node = node_->as(); - err = dst->bind(node->label()); - } - } - else if (node_->isAlign()) { - AlignNode* node = node_->as(); - err = dst->align(node->alignMode(), node->alignment()); - } - else if (node_->isEmbedData()) { - EmbedDataNode* node = node_->as(); - err = dst->embedDataArray(node->typeId(), node->data(), node->itemCount(), node->repeatCount()); - } - else if (node_->isEmbedLabel()) { - EmbedLabelNode* node = node_->as(); - err = dst->embedLabel(node->label(), node->dataSize()); - } - else if (node_->isEmbedLabelDelta()) { - EmbedLabelDeltaNode* node = node_->as(); - err = dst->embedLabelDelta(node->label(), node->baseLabel(), node->dataSize()); - } - else if (node_->isSection()) { - SectionNode* node = node_->as(); - err = dst->section(_code->sectionById(node->id())); - } - else if (node_->isComment()) { - CommentNode* node = node_->as(); - err = dst->comment(node->inlineComment()); - } - - if (err) break; - node_ = node_->next(); - } while (node_); - - return err; -} - -// ============================================================================ -// [asmjit::BaseBuilder - Events] -// ============================================================================ - -Error BaseBuilder::onAttach(CodeHolder* code) noexcept { - ASMJIT_PROPAGATE(Base::onAttach(code)); - - SectionNode* initialSection; - Error err = sectionNodeOf(&initialSection, 0); - - if (!err) - err = _passes.willGrow(&_allocator, 8); - - if (ASMJIT_UNLIKELY(err)) { - onDetach(code); - return err; - } - - _cursor = initialSection; - _firstNode = initialSection; - _lastNode = initialSection; - initialSection->setFlags(BaseNode::kFlagIsActive); - - return kErrorOk; -} - -Error BaseBuilder::onDetach(CodeHolder* code) noexcept { - BaseBuilder_deletePasses(this); - _sectionNodes.reset(); - _labelNodes.reset(); - - _allocator.reset(&_codeZone); - _codeZone.reset(); - _dataZone.reset(); - _passZone.reset(); - - _nodeFlags = 0; - - _cursor = nullptr; - _firstNode = nullptr; - _lastNode = nullptr; - - return Base::onDetach(code); -} - -// ============================================================================ -// [asmjit::Pass - Construction / Destruction] -// ============================================================================ - -Pass::Pass(const char* name) noexcept - : _cb(nullptr), - _name(name) {} -Pass::~Pass() noexcept {} - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_BUILDER diff --git a/ext/asmjit-master/src/asmjit/core/builder.h b/ext/asmjit-master/src/asmjit/core/builder.h deleted file mode 100644 index ee3c78b5..00000000 --- a/ext/asmjit-master/src/asmjit/core/builder.h +++ /dev/null @@ -1,1430 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_BUILDER_H_INCLUDED -#define ASMJIT_CORE_BUILDER_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_BUILDER - -#include "../core/assembler.h" -#include "../core/codeholder.h" -#include "../core/constpool.h" -#include "../core/formatter.h" -#include "../core/inst.h" -#include "../core/operand.h" -#include "../core/string.h" -#include "../core/support.h" -#include "../core/type.h" -#include "../core/zone.h" -#include "../core/zonevector.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_builder -//! \{ - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class BaseBuilder; -class Pass; - -class BaseNode; -class InstNode; -class SectionNode; -class LabelNode; -class AlignNode; -class EmbedDataNode; -class EmbedLabelNode; -class ConstPoolNode; -class CommentNode; -class SentinelNode; -class LabelDeltaNode; - -// Only used by Compiler infrastructure. -class JumpAnnotation; - -// ============================================================================ -// [asmjit::BaseBuilder] -// ============================================================================ - -//! Builder interface. -//! -//! `BaseBuilder` interface was designed to be used as a \ref BaseAssembler -//! replacement in case pre-processing or post-processing of the generated code -//! is required. The code can be modified during or after code generation. Pre -//! or post processing can be done manually or through a \ref Pass object. \ref -//! BaseBuilder stores the emitted code as a double-linked list of nodes, which -//! allows O(1) insertion and removal during processing. -//! -//! Check out architecture specific builders for more details and examples: -//! -//! - \ref x86::Builder - X86/X64 builder implementation. -class ASMJIT_VIRTAPI BaseBuilder : public BaseEmitter { -public: - ASMJIT_NONCOPYABLE(BaseBuilder) - typedef BaseEmitter Base; - - //! Base zone used to allocate nodes and passes. - Zone _codeZone; - //! Data zone used to allocate data and names. - Zone _dataZone; - //! Pass zone, passed to `Pass::run()`. - Zone _passZone; - //! Allocator that uses `_codeZone`. - ZoneAllocator _allocator; - - //! Array of `Pass` objects. - ZoneVector _passes; - //! Maps section indexes to `LabelNode` nodes. - ZoneVector _sectionNodes; - //! Maps label indexes to `LabelNode` nodes. - ZoneVector _labelNodes; - - //! Current node (cursor). - BaseNode* _cursor; - //! First node of the current section. - BaseNode* _firstNode; - //! Last node of the current section. - BaseNode* _lastNode; - - //! Flags assigned to each new node. - uint32_t _nodeFlags; - //! The sections links are dirty (used internally). - bool _dirtySectionLinks; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `BaseBuilder` instance. - ASMJIT_API BaseBuilder() noexcept; - //! Destroys the `BaseBuilder` instance. - ASMJIT_API virtual ~BaseBuilder() noexcept; - - //! \} - - //! \name Node Management - //! \{ - - //! Returns the first node. - inline BaseNode* firstNode() const noexcept { return _firstNode; } - //! Returns the last node. - inline BaseNode* lastNode() const noexcept { return _lastNode; } - - //! Allocates and instantiates a new node of type `T` and returns its instance. - //! If the allocation fails `nullptr` is returned. - //! - //! The template argument `T` must be a type that is extends \ref BaseNode. - //! - //! \remarks The pointer returned (if non-null) is owned by the Builder or - //! Compiler. When the Builder/Compiler is destroyed it destroys all nodes - //! it created so no manual memory management is required. - template - inline Error _newNodeT(T** out, Args&&... args) { - *out = _allocator.newT(this, std::forward(args)...); - if (ASMJIT_UNLIKELY(!*out)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - return kErrorOk; - } - - //! Creates a new \ref InstNode. - ASMJIT_API Error _newInstNode(InstNode** out, uint32_t instId, uint32_t instOptions, uint32_t opCount); - //! Creates a new \ref LabelNode. - ASMJIT_API Error _newLabelNode(LabelNode** out); - //! Creates a new \ref AlignNode. - ASMJIT_API Error _newAlignNode(AlignNode** out, uint32_t alignMode, uint32_t alignment); - //! Creates a new \ref EmbedDataNode. - ASMJIT_API Error _newEmbedDataNode(EmbedDataNode** out, uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1); - //! Creates a new \ref ConstPoolNode. - ASMJIT_API Error _newConstPoolNode(ConstPoolNode** out); - //! Creates a new \ref CommentNode. - ASMJIT_API Error _newCommentNode(CommentNode** out, const char* data, size_t size); - - //! Adds `node` after the current and sets the current node to the given `node`. - ASMJIT_API BaseNode* addNode(BaseNode* node) noexcept; - //! Inserts the given `node` after `ref`. - ASMJIT_API BaseNode* addAfter(BaseNode* node, BaseNode* ref) noexcept; - //! Inserts the given `node` before `ref`. - ASMJIT_API BaseNode* addBefore(BaseNode* node, BaseNode* ref) noexcept; - //! Removes the given `node`. - ASMJIT_API BaseNode* removeNode(BaseNode* node) noexcept; - //! Removes multiple nodes. - ASMJIT_API void removeNodes(BaseNode* first, BaseNode* last) noexcept; - - //! Returns the cursor. - //! - //! When the Builder/Compiler is created it automatically creates a '.text' - //! \ref SectionNode, which will be the initial one. When instructions are - //! added they are always added after the cursor and the cursor is changed - //! to be that newly added node. Use `setCursor()` to change where new nodes - //! are inserted. - inline BaseNode* cursor() const noexcept { - return _cursor; - } - - //! Sets the current node to `node` and return the previous one. - ASMJIT_API BaseNode* setCursor(BaseNode* node) noexcept; - - //! Sets the current node without returning the previous node. - //! - //! Only use this function if you are concerned about performance and want - //! this inlined (for example if you set the cursor in a loop, etc...). - inline void _setCursor(BaseNode* node) noexcept { - _cursor = node; - } - - //! \} - - //! \name Section Management - //! \{ - - //! Returns a vector of SectionNode objects. - //! - //! \note If a section of some id is not associated with the Builder/Compiler - //! it would be null, so always check for nulls if you iterate over the vector. - inline const ZoneVector& sectionNodes() const noexcept { - return _sectionNodes; - } - - //! Tests whether the `SectionNode` of the given `sectionId` was registered. - inline bool hasRegisteredSectionNode(uint32_t sectionId) const noexcept { - return sectionId < _sectionNodes.size() && _sectionNodes[sectionId] != nullptr; - } - - //! Returns or creates a `SectionNode` that matches the given `sectionId`. - //! - //! \remarks This function will either get the existing `SectionNode` or create - //! it in case it wasn't created before. You can check whether a section has a - //! registered `SectionNode` by using `BaseBuilder::hasRegisteredSectionNode()`. - ASMJIT_API Error sectionNodeOf(SectionNode** out, uint32_t sectionId); - - ASMJIT_API Error section(Section* section) override; - - //! Returns whether the section links of active section nodes are dirty. You can - //! update these links by calling `updateSectionLinks()` in such case. - inline bool hasDirtySectionLinks() const noexcept { return _dirtySectionLinks; } - - //! Updates links of all active section nodes. - ASMJIT_API void updateSectionLinks() noexcept; - - //! \} - - //! \name Label Management - //! \{ - - //! Returns a vector of \ref LabelNode nodes. - //! - //! \note If a label of some id is not associated with the Builder/Compiler - //! it would be null, so always check for nulls if you iterate over the vector. - inline const ZoneVector& labelNodes() const noexcept { return _labelNodes; } - - //! Tests whether the `LabelNode` of the given `labelId` was registered. - inline bool hasRegisteredLabelNode(uint32_t labelId) const noexcept { - return labelId < _labelNodes.size() && _labelNodes[labelId] != nullptr; - } - - //! \overload - inline bool hasRegisteredLabelNode(const Label& label) const noexcept { - return hasRegisteredLabelNode(label.id()); - } - - //! Gets or creates a \ref LabelNode that matches the given `labelId`. - //! - //! \remarks This function will either get the existing `LabelNode` or create - //! it in case it wasn't created before. You can check whether a label has a - //! registered `LabelNode` by calling \ref BaseBuilder::hasRegisteredLabelNode(). - ASMJIT_API Error labelNodeOf(LabelNode** out, uint32_t labelId); - - //! \overload - inline Error labelNodeOf(LabelNode** out, const Label& label) { - return labelNodeOf(out, label.id()); - } - - //! Registers this \ref LabelNode (internal). - //! - //! This function is used internally to register a newly created `LabelNode` - //! with this instance of Builder/Compiler. Use \ref labelNodeOf() functions - //! to get back \ref LabelNode from a label or its identifier. - ASMJIT_API Error registerLabelNode(LabelNode* node); - - ASMJIT_API Label newLabel() override; - ASMJIT_API Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, uint32_t type = Label::kTypeGlobal, uint32_t parentId = Globals::kInvalidId) override; - ASMJIT_API Error bind(const Label& label) override; - - //! \} - - //! \name Passes - //! \{ - - //! Returns a vector of `Pass` instances that will be executed by `runPasses()`. - inline const ZoneVector& passes() const noexcept { return _passes; } - - //! Allocates and instantiates a new pass of type `T` and returns its instance. - //! If the allocation fails `nullptr` is returned. - //! - //! The template argument `T` must be a type that is extends \ref Pass. - //! - //! \remarks The pointer returned (if non-null) is owned by the Builder or - //! Compiler. When the Builder/Compiler is destroyed it destroys all passes - //! it created so no manual memory management is required. - template - inline T* newPassT() noexcept { return _codeZone.newT(); } - - //! \overload - template - inline T* newPassT(Args&&... args) noexcept { return _codeZone.newT(std::forward(args)...); } - - template - inline Error addPassT() { return addPass(newPassT()); } - - template - inline Error addPassT(Args&&... args) { return addPass(newPassT(std::forward(args)...)); } - - //! Returns `Pass` by name. - //! - //! If the pass having the given `name` doesn't exist `nullptr` is returned. - ASMJIT_API Pass* passByName(const char* name) const noexcept; - //! Adds `pass` to the list of passes. - ASMJIT_API Error addPass(Pass* pass) noexcept; - //! Removes `pass` from the list of passes and delete it. - ASMJIT_API Error deletePass(Pass* pass) noexcept; - - //! Runs all passes in order. - ASMJIT_API Error runPasses(); - - //! \} - - //! \name Emit - //! \{ - - ASMJIT_API Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) override; - - //! \} - - //! \name Align - //! \{ - - ASMJIT_API Error align(uint32_t alignMode, uint32_t alignment) override; - - //! \} - - //! \name Embed - //! \{ - - ASMJIT_API Error embed(const void* data, size_t dataSize) override; - ASMJIT_API Error embedDataArray(uint32_t typeId, const void* data, size_t count, size_t repeat = 1) override; - ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override; - - ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override; - ASMJIT_API Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) override; - - //! \} - - //! \name Comment - //! \{ - - ASMJIT_API Error comment(const char* data, size_t size = SIZE_MAX) override; - - //! \} - - //! \name Serialization - //! \{ - - //! Serializes everything the given emitter `dst`. - //! - //! Although not explicitly required the emitter will most probably be of - //! Assembler type. The reason is that there is no known use of serializing - //! nodes held by Builder/Compiler into another Builder-like emitter. - ASMJIT_API Error serialize(BaseEmitter* dst); - - //! \} - - //! \name Events - //! \{ - - ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; - ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED -#ifndef ASMJIT_NO_LOGGING - ASMJIT_DEPRECATED("Use Formatter::formatNodeList(sb, formatFlags, builder)") - inline Error dump(String& sb, uint32_t formatFlags = 0) const noexcept { - return Formatter::formatNodeList(sb, formatFlags, this); - } -#endif // !ASMJIT_NO_LOGGING -#endif // !ASMJIT_NO_DEPRECATED -}; - -// ============================================================================ -// [asmjit::BaseNode] -// ============================================================================ - -//! Base node. -//! -//! Every node represents a building-block used by \ref BaseBuilder. It can -//! be instruction, data, label, comment, directive, or any other high-level -//! representation that can be transformed to the building blocks mentioned. -//! Every class that inherits \ref BaseBuilder can define its own high-level -//! nodes that can be later lowered to basic nodes like instructions. -class BaseNode { -public: - ASMJIT_NONCOPYABLE(BaseNode) - - union { - struct { - //! Previous node. - BaseNode* _prev; - //! Next node. - BaseNode* _next; - }; - //! Links (an alternative view to previous and next nodes). - BaseNode* _links[2]; - }; - - //! Data shared between all types of nodes. - struct AnyData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; - //! Not used by BaseNode. - uint8_t _reserved0; - //! Not used by BaseNode. - uint8_t _reserved1; - }; - - //! Data used by \ref InstNode. - struct InstData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; - //! Instruction operands count (used). - uint8_t _opCount; - //! Instruction operands capacity (allocated). - uint8_t _opCapacity; - }; - - //! Data used by \ref EmbedDataNode. - struct EmbedData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; - //! Type id, see \ref Type::Id. - uint8_t _typeId; - //! Size of `_typeId`. - uint8_t _typeSize; - }; - - //! Data used by \ref SentinelNode. - struct SentinelData { - //! Node type, see \ref NodeType. - uint8_t _nodeType; - //! Node flags, see \ref Flags. - uint8_t _nodeFlags; - //! Sentinel type. - uint8_t _sentinelType; - //! Not used by BaseNode. - uint8_t _reserved1; - }; - - //! Data that can have different meaning dependning on \ref NodeType. - union { - //! Data useful by any node type. - AnyData _any; - //! Data specific to \ref InstNode. - InstData _inst; - //! Data specific to \ref EmbedDataNode. - EmbedData _embed; - //! Data specific to \ref SentinelNode. - SentinelData _sentinel; - }; - - //! Node position in code (should be unique). - uint32_t _position; - - //! Value reserved for AsmJit users never touched by AsmJit itself. - union { - //! User data as 64-bit integer. - uint64_t _userDataU64; - //! User data as pointer. - void* _userDataPtr; - }; - - //! Data used exclusively by the current `Pass`. - void* _passData; - - //! Inline comment/annotation or nullptr if not used. - const char* _inlineComment; - - //! Type of `BaseNode`. - enum NodeType : uint32_t { - //! Invalid node (internal, don't use). - kNodeNone = 0, - - // [BaseBuilder] - - //! Node is \ref InstNode or \ref InstExNode. - kNodeInst = 1, - //! Node is \ref SectionNode. - kNodeSection = 2, - //! Node is \ref LabelNode. - kNodeLabel = 3, - //! Node is \ref AlignNode. - kNodeAlign = 4, - //! Node is \ref EmbedDataNode. - kNodeEmbedData = 5, - //! Node is \ref EmbedLabelNode. - kNodeEmbedLabel = 6, - //! Node is \ref EmbedLabelDeltaNode. - kNodeEmbedLabelDelta = 7, - //! Node is \ref ConstPoolNode. - kNodeConstPool = 8, - //! Node is \ref CommentNode. - kNodeComment = 9, - //! Node is \ref SentinelNode. - kNodeSentinel = 10, - - // [BaseCompiler] - - //! Node is \ref JumpNode (acts as InstNode). - kNodeJump = 15, - //! Node is \ref FuncNode (acts as LabelNode). - kNodeFunc = 16, - //! Node is \ref FuncRetNode (acts as InstNode). - kNodeFuncRet = 17, - //! Node is \ref InvokeNode (acts as InstNode). - kNodeInvoke = 18, - - // [UserDefined] - - //! First id of a user-defined node. - kNodeUser = 32, - -#ifndef ASMJIT_NO_DEPRECATED - kNodeFuncCall = kNodeInvoke -#endif // !ASMJIT_NO_DEPRECATED - }; - - //! Node flags, specify what the node is and/or does. - enum Flags : uint32_t { - //! Node is code that can be executed (instruction, label, align, etc...). - kFlagIsCode = 0x01u, - //! Node is data that cannot be executed (data, const-pool, etc...). - kFlagIsData = 0x02u, - //! Node is informative, can be removed and ignored. - kFlagIsInformative = 0x04u, - //! Node can be safely removed if unreachable. - kFlagIsRemovable = 0x08u, - //! Node does nothing when executed (label, align, explicit nop). - kFlagHasNoEffect = 0x10u, - //! Node is an instruction or acts as it. - kFlagActsAsInst = 0x20u, - //! Node is a label or acts as it. - kFlagActsAsLabel = 0x40u, - //! Node is active (part of the code). - kFlagIsActive = 0x80u - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `BaseNode` - always use `BaseBuilder` to allocate nodes. - ASMJIT_INLINE BaseNode(BaseBuilder* cb, uint32_t type, uint32_t flags = 0) noexcept { - _prev = nullptr; - _next = nullptr; - _any._nodeType = uint8_t(type); - _any._nodeFlags = uint8_t(flags | cb->_nodeFlags); - _any._reserved0 = 0; - _any._reserved1 = 0; - _position = 0; - _userDataU64 = 0; - _passData = nullptr; - _inlineComment = nullptr; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Casts this node to `T*`. - template - inline T* as() noexcept { return static_cast(this); } - //! Casts this node to `const T*`. - template - inline const T* as() const noexcept { return static_cast(this); } - - //! Returns previous node or `nullptr` if this node is either first or not - //! part of Builder/Compiler node-list. - inline BaseNode* prev() const noexcept { return _prev; } - //! Returns next node or `nullptr` if this node is either last or not part - //! of Builder/Compiler node-list. - inline BaseNode* next() const noexcept { return _next; } - - //! Returns the type of the node, see `NodeType`. - inline uint32_t type() const noexcept { return _any._nodeType; } - - //! Sets the type of the node, see `NodeType` (internal). - //! - //! \remarks You should never set a type of a node to anything else than the - //! initial value. This function is only provided for users that use custom - //! nodes and need to change the type either during construction or later. - inline void setType(uint32_t type) noexcept { _any._nodeType = uint8_t(type); } - - //! Tests whether this node is either `InstNode` or extends it. - inline bool isInst() const noexcept { return hasFlag(kFlagActsAsInst); } - //! Tests whether this node is `SectionNode`. - inline bool isSection() const noexcept { return type() == kNodeSection; } - //! Tests whether this node is either `LabelNode` or extends it. - inline bool isLabel() const noexcept { return hasFlag(kFlagActsAsLabel); } - //! Tests whether this node is `AlignNode`. - inline bool isAlign() const noexcept { return type() == kNodeAlign; } - //! Tests whether this node is `EmbedDataNode`. - inline bool isEmbedData() const noexcept { return type() == kNodeEmbedData; } - //! Tests whether this node is `EmbedLabelNode`. - inline bool isEmbedLabel() const noexcept { return type() == kNodeEmbedLabel; } - //! Tests whether this node is `EmbedLabelDeltaNode`. - inline bool isEmbedLabelDelta() const noexcept { return type() == kNodeEmbedLabelDelta; } - //! Tests whether this node is `ConstPoolNode`. - inline bool isConstPool() const noexcept { return type() == kNodeConstPool; } - //! Tests whether this node is `CommentNode`. - inline bool isComment() const noexcept { return type() == kNodeComment; } - //! Tests whether this node is `SentinelNode`. - inline bool isSentinel() const noexcept { return type() == kNodeSentinel; } - - //! Tests whether this node is `FuncNode`. - inline bool isFunc() const noexcept { return type() == kNodeFunc; } - //! Tests whether this node is `FuncRetNode`. - inline bool isFuncRet() const noexcept { return type() == kNodeFuncRet; } - //! Tests whether this node is `InvokeNode`. - inline bool isInvoke() const noexcept { return type() == kNodeInvoke; } - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use isInvoke") - inline bool isFuncCall() const noexcept { return isInvoke(); } -#endif // !ASMJIT_NO_DEPRECATED - - //! Returns the node flags, see \ref Flags. - inline uint32_t flags() const noexcept { return _any._nodeFlags; } - //! Tests whether the node has the given `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (uint32_t(_any._nodeFlags) & flag) != 0; } - //! Replaces node flags with `flags`. - inline void setFlags(uint32_t flags) noexcept { _any._nodeFlags = uint8_t(flags); } - //! Adds the given `flags` to node flags. - inline void addFlags(uint32_t flags) noexcept { _any._nodeFlags = uint8_t(_any._nodeFlags | flags); } - //! Clears the given `flags` from node flags. - inline void clearFlags(uint32_t flags) noexcept { _any._nodeFlags = uint8_t(_any._nodeFlags & (flags ^ 0xFF)); } - - //! Tests whether the node is code that can be executed. - inline bool isCode() const noexcept { return hasFlag(kFlagIsCode); } - //! Tests whether the node is data that cannot be executed. - inline bool isData() const noexcept { return hasFlag(kFlagIsData); } - //! Tests whether the node is informative only (is never encoded like comment, etc...). - inline bool isInformative() const noexcept { return hasFlag(kFlagIsInformative); } - //! Tests whether the node is removable if it's in an unreachable code block. - inline bool isRemovable() const noexcept { return hasFlag(kFlagIsRemovable); } - //! Tests whether the node has no effect when executed (label, .align, nop, ...). - inline bool hasNoEffect() const noexcept { return hasFlag(kFlagHasNoEffect); } - //! Tests whether the node is part of the code. - inline bool isActive() const noexcept { return hasFlag(kFlagIsActive); } - - //! Tests whether the node has a position assigned. - //! - //! \remarks Returns `true` if node position is non-zero. - inline bool hasPosition() const noexcept { return _position != 0; } - //! Returns node position. - inline uint32_t position() const noexcept { return _position; } - //! Sets node position. - //! - //! Node position is a 32-bit unsigned integer that is used by Compiler to - //! track where the node is relatively to the start of the function. It doesn't - //! describe a byte position in a binary, instead it's just a pseudo position - //! used by liveness analysis and other tools around Compiler. - //! - //! If you don't use Compiler then you may use `position()` and `setPosition()` - //! freely for your own purposes if the 32-bit value limit is okay for you. - inline void setPosition(uint32_t position) noexcept { _position = position; } - - //! Returns user data casted to `T*`. - //! - //! User data is decicated to be used only by AsmJit users and not touched - //! by the library. The data has a pointer size so you can either store a - //! pointer or `intptr_t` value through `setUserDataAsIntPtr()`. - template - inline T* userDataAsPtr() const noexcept { return static_cast(_userDataPtr); } - //! Returns user data casted to `int64_t`. - inline int64_t userDataAsInt64() const noexcept { return int64_t(_userDataU64); } - //! Returns user data casted to `uint64_t`. - inline uint64_t userDataAsUInt64() const noexcept { return _userDataU64; } - - //! Sets user data to `data`. - template - inline void setUserDataAsPtr(T* data) noexcept { _userDataPtr = static_cast(data); } - //! Sets used data to the given 64-bit signed `value`. - inline void setUserDataAsInt64(int64_t value) noexcept { _userDataU64 = uint64_t(value); } - //! Sets used data to the given 64-bit unsigned `value`. - inline void setUserDataAsUInt64(uint64_t value) noexcept { _userDataU64 = value; } - - //! Resets user data to zero / nullptr. - inline void resetUserData() noexcept { _userDataU64 = 0; } - - //! Tests whether the node has an associated pass data. - inline bool hasPassData() const noexcept { return _passData != nullptr; } - //! Returns the node pass data - data used during processing & transformations. - template - inline T* passData() const noexcept { return (T*)_passData; } - //! Sets the node pass data to `data`. - template - inline void setPassData(T* data) noexcept { _passData = (void*)data; } - //! Resets the node pass data to nullptr. - inline void resetPassData() noexcept { _passData = nullptr; } - - //! Tests whether the node has an inline comment/annotation. - inline bool hasInlineComment() const noexcept { return _inlineComment != nullptr; } - //! Returns an inline comment/annotation string. - inline const char* inlineComment() const noexcept { return _inlineComment; } - //! Sets an inline comment/annotation string to `s`. - inline void setInlineComment(const char* s) noexcept { _inlineComment = s; } - //! Resets an inline comment/annotation string to nullptr. - inline void resetInlineComment() noexcept { _inlineComment = nullptr; } - - //! \} -}; - -// ============================================================================ -// [asmjit::InstNode] -// ============================================================================ - -//! Instruction node. -//! -//! Wraps an instruction with its options and operands. -class InstNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(InstNode) - - enum : uint32_t { - //! Count of embedded operands per `InstNode` that are always allocated as - //! a part of the instruction. Minimum embedded operands is 4, but in 32-bit - //! more pointers are smaller and we can embed 5. The rest (up to 6 operands) - //! is always stored in `InstExNode`. - kBaseOpCapacity = uint32_t((128 - sizeof(BaseNode) - sizeof(BaseInst)) / sizeof(Operand_)) - }; - - //! Base instruction data. - BaseInst _baseInst; - //! First 4 or 5 operands (indexed from 0). - Operand_ _opArray[kBaseOpCapacity]; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `InstNode` instance. - ASMJIT_INLINE InstNode(BaseBuilder* cb, uint32_t instId, uint32_t options, uint32_t opCount, uint32_t opCapacity = kBaseOpCapacity) noexcept - : BaseNode(cb, kNodeInst, kFlagIsCode | kFlagIsRemovable | kFlagActsAsInst), - _baseInst(instId, options) { - _inst._opCapacity = uint8_t(opCapacity); - _inst._opCount = uint8_t(opCount); - } - - //! \cond INTERNAL - //! Reset all built-in operands, including `extraReg`. - inline void _resetOps() noexcept { - _baseInst.resetExtraReg(); - resetOpRange(0, opCapacity()); - } - //! \endcond - - //! \} - - //! \name Accessors - //! \{ - - inline BaseInst& baseInst() noexcept { return _baseInst; } - inline const BaseInst& baseInst() const noexcept { return _baseInst; } - - //! Returns the instruction id, see `BaseInst::Id`. - inline uint32_t id() const noexcept { return _baseInst.id(); } - //! Sets the instruction id to `id`, see `BaseInst::Id`. - inline void setId(uint32_t id) noexcept { _baseInst.setId(id); } - - //! Returns instruction options. - inline uint32_t instOptions() const noexcept { return _baseInst.options(); } - //! Sets instruction options. - inline void setInstOptions(uint32_t options) noexcept { _baseInst.setOptions(options); } - //! Adds instruction options. - inline void addInstOptions(uint32_t options) noexcept { _baseInst.addOptions(options); } - //! Clears instruction options. - inline void clearInstOptions(uint32_t options) noexcept { _baseInst.clearOptions(options); } - - //! Tests whether the node has an extra register operand. - inline bool hasExtraReg() const noexcept { return _baseInst.hasExtraReg(); } - //! Returns extra register operand. - inline RegOnly& extraReg() noexcept { return _baseInst.extraReg(); } - //! \overload - inline const RegOnly& extraReg() const noexcept { return _baseInst.extraReg(); } - //! Sets extra register operand to `reg`. - inline void setExtraReg(const BaseReg& reg) noexcept { _baseInst.setExtraReg(reg); } - //! Sets extra register operand to `reg`. - inline void setExtraReg(const RegOnly& reg) noexcept { _baseInst.setExtraReg(reg); } - //! Resets extra register operand. - inline void resetExtraReg() noexcept { _baseInst.resetExtraReg(); } - - //! Returns operand count. - inline uint32_t opCount() const noexcept { return _inst._opCount; } - //! Returns operand capacity. - inline uint32_t opCapacity() const noexcept { return _inst._opCapacity; } - - //! Sets operand count. - inline void setOpCount(uint32_t opCount) noexcept { _inst._opCount = uint8_t(opCount); } - - //! Returns operands array. - inline Operand* operands() noexcept { return (Operand*)_opArray; } - //! Returns operands array (const). - inline const Operand* operands() const noexcept { return (const Operand*)_opArray; } - - //! Returns operand at the given `index`. - inline Operand& op(uint32_t index) noexcept { - ASMJIT_ASSERT(index < opCapacity()); - return _opArray[index].as(); - } - - //! Returns operand at the given `index` (const). - inline const Operand& op(uint32_t index) const noexcept { - ASMJIT_ASSERT(index < opCapacity()); - return _opArray[index].as(); - } - - //! Sets operand at the given `index` to `op`. - inline void setOp(uint32_t index, const Operand_& op) noexcept { - ASMJIT_ASSERT(index < opCapacity()); - _opArray[index].copyFrom(op); - } - - //! Resets operand at the given `index` to none. - inline void resetOp(uint32_t index) noexcept { - ASMJIT_ASSERT(index < opCapacity()); - _opArray[index].reset(); - } - - //! Resets operands at `[start, end)` range. - inline void resetOpRange(uint32_t start, uint32_t end) noexcept { - for (uint32_t i = start; i < end; i++) - _opArray[i].reset(); - } - - //! \} - - //! \name Utilities - //! \{ - - inline bool hasOpType(uint32_t opType) const noexcept { - for (uint32_t i = 0, count = opCount(); i < count; i++) - if (_opArray[i].opType() == opType) - return true; - return false; - } - - inline bool hasRegOp() const noexcept { return hasOpType(Operand::kOpReg); } - inline bool hasMemOp() const noexcept { return hasOpType(Operand::kOpMem); } - inline bool hasImmOp() const noexcept { return hasOpType(Operand::kOpImm); } - inline bool hasLabelOp() const noexcept { return hasOpType(Operand::kOpLabel); } - - inline uint32_t indexOfOpType(uint32_t opType) const noexcept { - uint32_t i = 0; - uint32_t count = opCount(); - - while (i < count) { - if (_opArray[i].opType() == opType) - break; - i++; - } - - return i; - } - - inline uint32_t indexOfMemOp() const noexcept { return indexOfOpType(Operand::kOpMem); } - inline uint32_t indexOfImmOp() const noexcept { return indexOfOpType(Operand::kOpImm); } - inline uint32_t indexOfLabelOp() const noexcept { return indexOfOpType(Operand::kOpLabel); } - - //! \} - - //! \name Rewriting - //! \{ - - //! \cond INTERNAL - inline uint32_t* _getRewriteArray() noexcept { return &_baseInst._extraReg._id; } - inline const uint32_t* _getRewriteArray() const noexcept { return &_baseInst._extraReg._id; } - - ASMJIT_INLINE uint32_t getRewriteIndex(const uint32_t* id) const noexcept { - const uint32_t* array = _getRewriteArray(); - ASMJIT_ASSERT(array <= id); - - size_t index = (size_t)(id - array); - ASMJIT_ASSERT(index < 32); - - return uint32_t(index); - } - - ASMJIT_INLINE void rewriteIdAtIndex(uint32_t index, uint32_t id) noexcept { - uint32_t* array = _getRewriteArray(); - array[index] = id; - } - //! \endcond - - //! \} - - //! \name Static Functions - //! \{ - - //! \cond INTERNAL - static inline uint32_t capacityOfOpCount(uint32_t opCount) noexcept { - return opCount <= kBaseOpCapacity ? kBaseOpCapacity : Globals::kMaxOpCount; - } - - static inline size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept { - size_t base = sizeof(InstNode) - kBaseOpCapacity * sizeof(Operand); - return base + opCapacity * sizeof(Operand); - } - //! \endcond - - //! \} -}; - -// ============================================================================ -// [asmjit::InstExNode] -// ============================================================================ - -//! Instruction node with maximum number of operands. -//! -//! This node is created automatically by Builder/Compiler in case that the -//! required number of operands exceeds the default capacity of `InstNode`. -class InstExNode : public InstNode { -public: - ASMJIT_NONCOPYABLE(InstExNode) - - //! Continued `_opArray[]` to hold up to `kMaxOpCount` operands. - Operand_ _opArrayEx[Globals::kMaxOpCount - kBaseOpCapacity]; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `InstExNode` instance. - inline InstExNode(BaseBuilder* cb, uint32_t instId, uint32_t options, uint32_t opCapacity = Globals::kMaxOpCount) noexcept - : InstNode(cb, instId, options, opCapacity) {} - - //! \} -}; - -// ============================================================================ -// [asmjit::SectionNode] -// ============================================================================ - -//! Section node. -class SectionNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(SectionNode) - - //! Section id. - uint32_t _id; - - //! Next section node that follows this section. - //! - //! This link is only valid when the section is active (is part of the code) - //! and when `Builder::hasDirtySectionLinks()` returns `false`. If you intend - //! to use this field you should always call `Builder::updateSectionLinks()` - //! before you do so. - SectionNode* _nextSection; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `SectionNode` instance. - inline SectionNode(BaseBuilder* cb, uint32_t id = 0) noexcept - : BaseNode(cb, kNodeSection, kFlagHasNoEffect), - _id(id), - _nextSection(nullptr) {} - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the section id. - inline uint32_t id() const noexcept { return _id; } - - //! \} -}; - -// ============================================================================ -// [asmjit::LabelNode] -// ============================================================================ - -//! Label node. -class LabelNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(LabelNode) - - //! Label identifier. - uint32_t _labelId; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `LabelNode` instance. - inline LabelNode(BaseBuilder* cb, uint32_t labelId = 0) noexcept - : BaseNode(cb, kNodeLabel, kFlagHasNoEffect | kFlagActsAsLabel), - _labelId(labelId) {} - - //! \} - - //! \name Accessors - //! \{ - - //! Returns \ref Label representation of the \ref LabelNode. - inline Label label() const noexcept { return Label(_labelId); } - //! Returns the id of the label. - inline uint32_t labelId() const noexcept { return _labelId; } - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use labelId() instead") - inline uint32_t id() const noexcept { return labelId(); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -// ============================================================================ -// [asmjit::AlignNode] -// ============================================================================ - -//! Align directive (BaseBuilder). -//! -//! Wraps `.align` directive. -class AlignNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(AlignNode) - - //! Align mode, see `AlignMode`. - uint32_t _alignMode; - //! Alignment (in bytes). - uint32_t _alignment; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `AlignNode` instance. - inline AlignNode(BaseBuilder* cb, uint32_t alignMode, uint32_t alignment) noexcept - : BaseNode(cb, kNodeAlign, kFlagIsCode | kFlagHasNoEffect), - _alignMode(alignMode), - _alignment(alignment) {} - - //! \} - - //! \name Accessors - //! \{ - - //! Returns align mode. - inline uint32_t alignMode() const noexcept { return _alignMode; } - //! Sets align mode to `alignMode`. - inline void setAlignMode(uint32_t alignMode) noexcept { _alignMode = alignMode; } - - //! Returns align offset in bytes. - inline uint32_t alignment() const noexcept { return _alignment; } - //! Sets align offset in bytes to `offset`. - inline void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; } - - //! \} -}; - -// ============================================================================ -// [asmjit::EmbedDataNode] -// ============================================================================ - -//! Embed data node. -//! -//! Wraps `.data` directive. The node contains data that will be placed at the -//! node's position in the assembler stream. The data is considered to be RAW; -//! no analysis nor byte-order conversion is performed on RAW data. -class EmbedDataNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(EmbedDataNode) - - enum : uint32_t { - kInlineBufferSize = 128 - (sizeof(BaseNode) + sizeof(size_t) * 2) - }; - - size_t _itemCount; - size_t _repeatCount; - - union { - uint8_t* _externalData; - uint8_t _inlineData[kInlineBufferSize]; - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `EmbedDataNode` instance. - inline EmbedDataNode(BaseBuilder* cb) noexcept - : BaseNode(cb, kNodeEmbedData, kFlagIsData), - _itemCount(0), - _repeatCount(0) { - _embed._typeId = uint8_t(Type::kIdU8), - _embed._typeSize = uint8_t(1); - memset(_inlineData, 0, kInlineBufferSize); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns \ref Type::Id of the data. - inline uint32_t typeId() const noexcept { return _embed._typeId; } - //! Returns the size of a single data element. - inline uint32_t typeSize() const noexcept { return _embed._typeSize; } - - //! Returns a pointer to the data casted to `uint8_t`. - inline uint8_t* data() const noexcept { - return dataSize() <= kInlineBufferSize ? const_cast(_inlineData) : _externalData; - } - - //! Returns a pointer to the data casted to `T`. - template - inline T* dataAs() const noexcept { return reinterpret_cast(data()); } - - //! Returns the number of (typed) items in the array. - inline size_t itemCount() const noexcept { return _itemCount; } - - //! Returns how many times the data is repeated (default 1). - //! - //! Repeated data is useful when defining constants for SIMD, for example. - inline size_t repeatCount() const noexcept { return _repeatCount; } - - //! Returns the size of the data, not considering the number of times it repeats. - //! - //! \note The returned value is the same as `typeSize() * itemCount()`. - inline size_t dataSize() const noexcept { return typeSize() * _itemCount; } - - //! \} -}; - -// ============================================================================ -// [asmjit::EmbedLabelNode] -// ============================================================================ - -//! Label data node. -class EmbedLabelNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(EmbedLabelNode) - - uint32_t _labelId; - uint32_t _dataSize; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `EmbedLabelNode` instance. - inline EmbedLabelNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t dataSize = 0) noexcept - : BaseNode(cb, kNodeEmbedLabel, kFlagIsData), - _labelId(labelId), - _dataSize(dataSize) {} - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the label to embed as \ref Label operand. - inline Label label() const noexcept { return Label(_labelId); } - //! Returns the id of the label. - inline uint32_t labelId() const noexcept { return _labelId; } - - //! Sets the label id from `label` operand. - inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); } - //! Sets the label id (use with caution, improper use can break a lot of things). - inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; } - - //! Returns the data size. - inline uint32_t dataSize() const noexcept { return _dataSize; } - //! Sets the data size. - inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; } - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use labelId() instead") - inline uint32_t id() const noexcept { return labelId(); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -// ============================================================================ -// [asmjit::EmbedLabelDeltaNode] -// ============================================================================ - -//! Label data node. -class EmbedLabelDeltaNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(EmbedLabelDeltaNode) - - uint32_t _labelId; - uint32_t _baseLabelId; - uint32_t _dataSize; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `EmbedLabelDeltaNode` instance. - inline EmbedLabelDeltaNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t baseLabelId = 0, uint32_t dataSize = 0) noexcept - : BaseNode(cb, kNodeEmbedLabelDelta, kFlagIsData), - _labelId(labelId), - _baseLabelId(baseLabelId), - _dataSize(dataSize) {} - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the label as `Label` operand. - inline Label label() const noexcept { return Label(_labelId); } - //! Returns the id of the label. - inline uint32_t labelId() const noexcept { return _labelId; } - - //! Sets the label id from `label` operand. - inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); } - //! Sets the label id. - inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; } - - //! Returns the base label as `Label` operand. - inline Label baseLabel() const noexcept { return Label(_baseLabelId); } - //! Returns the id of the base label. - inline uint32_t baseLabelId() const noexcept { return _baseLabelId; } - - //! Sets the base label id from `label` operand. - inline void setBaseLabel(const Label& baseLabel) noexcept { setBaseLabelId(baseLabel.id()); } - //! Sets the base label id. - inline void setBaseLabelId(uint32_t baseLabelId) noexcept { _baseLabelId = baseLabelId; } - - //! Returns the size of the embedded label address. - inline uint32_t dataSize() const noexcept { return _dataSize; } - //! Sets the size of the embedded label address. - inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; } - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use labelId() instead") - inline uint32_t id() const noexcept { return labelId(); } - - ASMJIT_DEPRECATED("Use setLabelId() instead") - inline void setId(uint32_t id) noexcept { setLabelId(id); } - - ASMJIT_DEPRECATED("Use baseLabelId() instead") - inline uint32_t baseId() const noexcept { return baseLabelId(); } - - ASMJIT_DEPRECATED("Use setBaseLabelId() instead") - inline void setBaseId(uint32_t id) noexcept { setBaseLabelId(id); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -// ============================================================================ -// [asmjit::ConstPoolNode] -// ============================================================================ - -//! A node that wraps `ConstPool`. -class ConstPoolNode : public LabelNode { -public: - ASMJIT_NONCOPYABLE(ConstPoolNode) - - ConstPool _constPool; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `ConstPoolNode` instance. - inline ConstPoolNode(BaseBuilder* cb, uint32_t id = 0) noexcept - : LabelNode(cb, id), - _constPool(&cb->_codeZone) { - - setType(kNodeConstPool); - addFlags(kFlagIsData); - clearFlags(kFlagIsCode | kFlagHasNoEffect); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether the constant-pool is empty. - inline bool empty() const noexcept { return _constPool.empty(); } - //! Returns the size of the constant-pool in bytes. - inline size_t size() const noexcept { return _constPool.size(); } - //! Returns minimum alignment. - inline size_t alignment() const noexcept { return _constPool.alignment(); } - - //! Returns the wrapped `ConstPool` instance. - inline ConstPool& constPool() noexcept { return _constPool; } - //! Returns the wrapped `ConstPool` instance (const). - inline const ConstPool& constPool() const noexcept { return _constPool; } - - //! \} - - //! \name Utilities - //! \{ - - //! See `ConstPool::add()`. - inline Error add(const void* data, size_t size, size_t& dstOffset) noexcept { - return _constPool.add(data, size, dstOffset); - } - - //! \} -}; - -// ============================================================================ -// [asmjit::CommentNode] -// ============================================================================ - -//! Comment node. -class CommentNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(CommentNode) - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `CommentNode` instance. - inline CommentNode(BaseBuilder* cb, const char* comment) noexcept - : BaseNode(cb, kNodeComment, kFlagIsInformative | kFlagHasNoEffect | kFlagIsRemovable) { - _inlineComment = comment; - } - - //! \} -}; - -// ============================================================================ -// [asmjit::SentinelNode] -// ============================================================================ - -//! Sentinel node. -//! -//! Sentinel is a marker that is completely ignored by the code builder. It's -//! used to remember a position in a code as it never gets removed by any pass. -class SentinelNode : public BaseNode { -public: - ASMJIT_NONCOPYABLE(SentinelNode) - - //! Type of the sentinel (purery informative purpose). - enum SentinelType : uint32_t { - //! Type of the sentinel is not known. - kSentinelUnknown = 0u, - //! This is a sentinel used at the end of \ref FuncNode. - kSentinelFuncEnd = 1u - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `SentinelNode` instance. - inline SentinelNode(BaseBuilder* cb, uint32_t sentinelType = kSentinelUnknown) noexcept - : BaseNode(cb, kNodeSentinel, kFlagIsInformative | kFlagHasNoEffect) { - - _sentinel._sentinelType = uint8_t(sentinelType); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the type of the sentinel. - inline uint32_t sentinelType() const noexcept { - return _sentinel._sentinelType; - } - - //! Sets the type of the sentinel. - inline void setSentinelType(uint32_t type) noexcept { - _sentinel._sentinelType = uint8_t(type); - } - - //! \} -}; - -// ============================================================================ -// [asmjit::Pass] -// ============================================================================ - -//! Pass can be used to implement code transformations, analysis, and lowering. -class ASMJIT_VIRTAPI Pass { -public: - ASMJIT_BASE_CLASS(Pass) - ASMJIT_NONCOPYABLE(Pass) - - //! BaseBuilder this pass is assigned to. - BaseBuilder* _cb; - //! Name of the pass. - const char* _name; - - //! \name Construction & Destruction - //! \{ - - ASMJIT_API Pass(const char* name) noexcept; - ASMJIT_API virtual ~Pass() noexcept; - - //! \} - - //! \name Accessors - //! \{ - - //! Returns \ref BaseBuilder associated with the pass. - inline const BaseBuilder* cb() const noexcept { return _cb; } - //! Returns the name of the pass. - inline const char* name() const noexcept { return _name; } - - //! \} - - //! \name Pass Interface - //! \{ - - //! Processes the code stored in Builder or Compiler. - //! - //! This is the only function that is called by the `BaseBuilder` to process - //! the code. It passes `zone`, which will be reset after the `run()` finishes. - virtual Error run(Zone* zone, Logger* logger) = 0; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_BUILDER -#endif // ASMJIT_CORE_BUILDER_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/callconv.cpp b/ext/asmjit-master/src/asmjit/core/callconv.cpp deleted file mode 100644 index 722dbcdb..00000000 --- a/ext/asmjit-master/src/asmjit/core/callconv.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/arch.h" -#include "../core/func.h" -#include "../core/type.h" - -#ifdef ASMJIT_BUILD_X86 - #include "../x86/x86callconv_p.h" -#endif - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/armcallconv_p.h" -#endif - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::CallConv - Init / Reset] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error CallConv::init(uint32_t ccId, const Environment& environment) noexcept { - reset(); - -#ifdef ASMJIT_BUILD_X86 - if (environment.isFamilyX86()) - return x86::CallConvInternal::init(*this, ccId, environment); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment.isFamilyARM()) - return arm::CallConvInternal::init(*this, ccIdv, environment); -#endif - - return DebugUtils::errored(kErrorInvalidArgument); -} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/callconv.h b/ext/asmjit-master/src/asmjit/core/callconv.h deleted file mode 100644 index 6e75540c..00000000 --- a/ext/asmjit-master/src/asmjit/core/callconv.h +++ /dev/null @@ -1,374 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_CALLCONV_H_INCLUDED -#define ASMJIT_CORE_CALLCONV_H_INCLUDED - -#include "../core/arch.h" -#include "../core/operand.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_function -//! \{ - -// ============================================================================ -// [asmjit::CallConv] -// ============================================================================ - -//! Function calling convention. -//! -//! Function calling convention is a scheme that defines how function parameters -//! are passed and how function returns its result. AsmJit defines a variety of -//! architecture and OS specific calling conventions and also provides a compile -//! time detection to make the code-generation easier. -struct CallConv { - //! Calling convention id, see `Id`. - uint8_t _id; - //! Architecture identifier, see \ref Environment::Arch. - uint8_t _arch; - //! Register assignment strategy. - uint8_t _strategy; - //! Flags. - uint8_t _flags; - - //! Red zone size (AMD64 == 128 bytes). - uint8_t _redZoneSize; - //! Spill zone size (WIN64 == 32 bytes). - uint8_t _spillZoneSize; - //! Natural stack alignment as defined by OS/ABI. - uint8_t _naturalStackAlignment; - uint8_t _reserved[1]; - - //! Mask of all passed registers, per group. - uint32_t _passedRegs[BaseReg::kGroupVirt]; - //! Mask of all preserved registers, per group. - uint32_t _preservedRegs[BaseReg::kGroupVirt]; - - //! Internal limits of AsmJit's CallConv. - enum Limits : uint32_t { - kMaxRegArgsPerGroup = 16 - }; - - //! Passed registers' order. - union RegOrder { - //! Passed registers, ordered. - uint8_t id[kMaxRegArgsPerGroup]; - uint32_t packed[(kMaxRegArgsPerGroup + 3) / 4]; - }; - - //! Passed registers' order, per register group. - RegOrder _passedOrder[BaseReg::kGroupVirt]; - - //! Calling convention id. - //! - //! Calling conventions can be divided into the following groups: - //! - //! - Universal - calling conventions are applicable to any target. They - //! will be converted to a target dependent calling convention at runtime - //! by \ref init(). The purpose of these conventions is to make using - //! functions less target dependent and closer to how they are declared - //! in C and C++. - //! - //! - Target specific - calling conventions that are used by a particular - //! architecture and ABI. For example Windows 64-bit calling convention - //! and AMD64 SystemV calling convention. - enum Id : uint32_t { - //! None or invalid (can't be used). - kIdNone = 0, - - // ------------------------------------------------------------------------ - // [Universal Calling Conventions] - // ------------------------------------------------------------------------ - - //! Standard function call or explicit `__cdecl` where it can be specified. - //! - //! This is a universal convention, which is used to initialize specific - //! calling connventions based on architecture, platform, and its ABI. - kIdCDecl = 1, - - //! `__stdcall` on targets that support this calling convention. - //! - //! \note This calling convention is only supported on 32-bit X86. If used - //! on environment that doesn't support this calling convention \ref kIdCDecl - //! will be used instead. - kIdStdCall = 2, - - //! `__fastcall` on targets that support this calling convention. - //! - //! \note This calling convention is only supported on 32-bit X86. If used - //! on environment that doesn't support this calling convention \ref kIdCDecl - //! will be used instead. - kIdFastCall = 3, - - //! `__vectorcall` on targets that support this calling convention. - //! - //! \note This calling convention is only supported on 32-bit and 64-bit - //! X86 architecture on Windows platform. If used on environment that doesn't - //! support this calling convention \ref kIdCDecl will be used instead. - kIdVectorCall = 4, - - //! `__thiscall` on targets that support this calling convention. - //! - //! \note This calling convention is only supported on 32-bit X86 Windows - //! platform. If used on environment that doesn't support this calling - //! convention \ref kIdCDecl will be used instead. - kIdThisCall = 5, - - //! `__attribute__((regparm(1)))` convention (GCC and Clang). - kIdRegParm1 = 6, - //! `__attribute__((regparm(2)))` convention (GCC and Clang). - kIdRegParm2 = 7, - //! `__attribute__((regparm(3)))` convention (GCC and Clang). - kIdRegParm3 = 8, - - //! Soft-float calling convention (ARM). - //! - //! Floating point arguments are passed via general purpose registers. - kIdSoftFloat = 9, - - //! Hard-float calling convention (ARM). - //! - //! Floating point arguments are passed via SIMD registers. - kIdHardFloat = 10, - - //! AsmJit specific calling convention designed for calling functions - //! inside a multimedia code that don't use many registers internally, - //! but are long enough to be called and not inlined. These functions are - //! usually used to calculate trigonometric functions, logarithms, etc... - kIdLightCall2 = 16, - kIdLightCall3 = 17, - kIdLightCall4 = 18, - - // ------------------------------------------------------------------------ - // [ABI-Specific Calling Conventions] - // ------------------------------------------------------------------------ - - kIdX64SystemV = 32, - kIdX64Windows = 33, - - // ------------------------------------------------------------------------ - // [Host] - // ------------------------------------------------------------------------ - - kIdHost = -#if ASMJIT_ARCH_ARM == 32 && defined(__SOFTFP__) - kIdSoftFloat -#elif ASMJIT_ARCH_ARM == 32 && !defined(__SOFTFP__) - kIdHardFloat -#else - kIdCDecl -#endif - -#ifndef ASMJIT_NO_DEPRECATE - , kIdHostCDecl = kIdCDecl - , kIdHostStdCall = kIdStdCall - , kIdHostFastCall = kIdFastCall - , kIdHostLightCall2 = kIdLightCall2 - , kIdHostLightCall3 = kIdLightCall3 - , kIdHostLightCall4 = kIdLightCall4 -#endif // !ASMJIT_NO_DEPRECATE - }; - - //! Strategy used to assign registers to function arguments. - //! - //! This is AsmJit specific. It basically describes how AsmJit should convert - //! the function arguments defined by `FuncSignature` into register IDs and - //! stack offsets. The default strategy `kStrategyDefault` assigns registers - //! and then stack whereas `kStrategyWin64` strategy does register shadowing - //! as defined by WIN64 calling convention - it applies to 64-bit calling - //! conventions only. - enum Strategy : uint32_t { - //! Default register assignment strategy. - kStrategyDefault = 0, - //! Windows 64-bit ABI register assignment strategy. - kStrategyX64Windows = 1, - //! Windows 64-bit __vectorcall register assignment strategy. - kStrategyX64VectorCall = 2, - - //! Number of assignment strategies. - kStrategyCount = 3 - }; - - //! Calling convention flags. - enum Flags : uint32_t { - //! Callee is responsible for cleaning up the stack. - kFlagCalleePopsStack = 0x01u, - //! Pass vector arguments indirectly (as a pointer). - kFlagIndirectVecArgs = 0x02u, - //! Pass F32 and F64 arguments by VEC128 register. - kFlagPassFloatsByVec = 0x04u, - //! Pass MMX and vector arguments by stack if the function has variable arguments. - kFlagPassVecByStackIfVA = 0x08u, - //! MMX registers are passed and returned via GP registers. - kFlagPassMmxByGp = 0x10u, - //! MMX registers are passed and returned via XMM registers. - kFlagPassMmxByXmm = 0x20u, - //! Calling convention can be used with variable arguments. - kFlagVarArgCompatible = 0x80u - }; - - //! \name Construction & Destruction - //! \{ - - //! Initializes this calling convention to the given `ccId` based on the - //! `environment`. - //! - //! See \ref Id and \ref Environment for more details. - ASMJIT_API Error init(uint32_t ccId, const Environment& environment) noexcept; - - //! Resets this CallConv struct into a defined state. - //! - //! It's recommended to reset the \ref CallConv struct in case you would - //! like create a custom calling convention as it prevents from using an - //! uninitialized data (CallConv doesn't have a constructor that would - //! initialize it, it's just a struct). - inline void reset() noexcept { - memset(this, 0, sizeof(*this)); - memset(_passedOrder, 0xFF, sizeof(_passedOrder)); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the calling convention id, see `Id`. - inline uint32_t id() const noexcept { return _id; } - //! Sets the calling convention id, see `Id`. - inline void setId(uint32_t id) noexcept { _id = uint8_t(id); } - - //! Returns the calling function architecture id. - inline uint32_t arch() const noexcept { return _arch; } - //! Sets the calling function architecture id. - inline void setArch(uint32_t arch) noexcept { _arch = uint8_t(arch); } - - //! Returns the strategy used to assign registers to arguments, see `Strategy`. - inline uint32_t strategy() const noexcept { return _strategy; } - //! Sets the strategy used to assign registers to arguments, see `Strategy`. - inline void setStrategy(uint32_t strategy) noexcept { _strategy = uint8_t(strategy); } - - //! Tests whether the calling convention has the given `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (uint32_t(_flags) & flag) != 0; } - //! Returns the calling convention flags, see `Flags`. - inline uint32_t flags() const noexcept { return _flags; } - //! Adds the calling convention flags, see `Flags`. - inline void setFlags(uint32_t flag) noexcept { _flags = uint8_t(flag); }; - //! Adds the calling convention flags, see `Flags`. - inline void addFlags(uint32_t flags) noexcept { _flags = uint8_t(_flags | flags); }; - - //! Tests whether this calling convention specifies 'RedZone'. - inline bool hasRedZone() const noexcept { return _redZoneSize != 0; } - //! Tests whether this calling convention specifies 'SpillZone'. - inline bool hasSpillZone() const noexcept { return _spillZoneSize != 0; } - - //! Returns size of 'RedZone'. - inline uint32_t redZoneSize() const noexcept { return _redZoneSize; } - //! Returns size of 'SpillZone'. - inline uint32_t spillZoneSize() const noexcept { return _spillZoneSize; } - - //! Sets size of 'RedZone'. - inline void setRedZoneSize(uint32_t size) noexcept { _redZoneSize = uint8_t(size); } - //! Sets size of 'SpillZone'. - inline void setSpillZoneSize(uint32_t size) noexcept { _spillZoneSize = uint8_t(size); } - - //! Returns a natural stack alignment. - inline uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; } - //! Sets a natural stack alignment. - //! - //! This function can be used to override the default stack alignment in case - //! that you know that it's alignment is different. For example it allows to - //! implement custom calling conventions that guarantee higher stack alignment. - inline void setNaturalStackAlignment(uint32_t value) noexcept { _naturalStackAlignment = uint8_t(value); } - - //! Returns the order of passed registers of the given `group`, see \ref BaseReg::RegGroup. - inline const uint8_t* passedOrder(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _passedOrder[group].id; - } - - //! Returns the mask of passed registers of the given `group`, see \ref BaseReg::RegGroup. - inline uint32_t passedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _passedRegs[group]; - } - - inline void _setPassedPacked(uint32_t group, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - - _passedOrder[group].packed[0] = p0; - _passedOrder[group].packed[1] = p1; - _passedOrder[group].packed[2] = p2; - _passedOrder[group].packed[3] = p3; - } - - //! Resets the order and mask of passed registers. - inline void setPassedToNone(uint32_t group) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - - _setPassedPacked(group, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu); - _passedRegs[group] = 0u; - } - - //! Sets the order and mask of passed registers. - inline void setPassedOrder(uint32_t group, uint32_t a0, uint32_t a1 = 0xFF, uint32_t a2 = 0xFF, uint32_t a3 = 0xFF, uint32_t a4 = 0xFF, uint32_t a5 = 0xFF, uint32_t a6 = 0xFF, uint32_t a7 = 0xFF) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - - // NOTE: This should always be called with all arguments known at compile time, - // so even if it looks scary it should be translated into few instructions. - _setPassedPacked(group, Support::bytepack32_4x8(a0, a1, a2, a3), - Support::bytepack32_4x8(a4, a5, a6, a7), - 0xFFFFFFFFu, - 0xFFFFFFFFu); - - _passedRegs[group] = (a0 != 0xFF ? 1u << a0 : 0u) | - (a1 != 0xFF ? 1u << a1 : 0u) | - (a2 != 0xFF ? 1u << a2 : 0u) | - (a3 != 0xFF ? 1u << a3 : 0u) | - (a4 != 0xFF ? 1u << a4 : 0u) | - (a5 != 0xFF ? 1u << a5 : 0u) | - (a6 != 0xFF ? 1u << a6 : 0u) | - (a7 != 0xFF ? 1u << a7 : 0u) ; - } - - //! Returns preserved register mask of the given `group`, see \ref BaseReg::RegGroup. - inline uint32_t preservedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _preservedRegs[group]; - } - - //! Sets preserved register mask of the given `group`, see \ref BaseReg::RegGroup. - inline void setPreservedRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - _preservedRegs[group] = regs; - } - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_CALLCONV_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/codebuffer.h b/ext/asmjit-master/src/asmjit/core/codebuffer.h deleted file mode 100644 index 76c86b1f..00000000 --- a/ext/asmjit-master/src/asmjit/core/codebuffer.h +++ /dev/null @@ -1,126 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_CODEBUFFER_H_INCLUDED -#define ASMJIT_CORE_CODEBUFFER_H_INCLUDED - -#include "../core/globals.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::CodeBuffer] -// ============================================================================ - -//! Code or data buffer. -struct CodeBuffer { - //! The content of the buffer (data). - uint8_t* _data; - //! Number of bytes of `data` used. - size_t _size; - //! Buffer capacity (in bytes). - size_t _capacity; - //! Buffer flags. - uint32_t _flags; - - //! Code buffer flags. - enum Flags : uint32_t { - //! Buffer is external (not allocated by asmjit). - kFlagIsExternal = 0x00000001u, - //! Buffer is fixed (cannot be reallocated). - kFlagIsFixed = 0x00000002u - }; - - //! \name Overloaded Operators - //! \{ - - //! Returns a referebce to the byte at the given `index`. - inline uint8_t& operator[](size_t index) noexcept { - ASMJIT_ASSERT(index < _size); - return _data[index]; - } - //! \overload - inline const uint8_t& operator[](size_t index) const noexcept { - ASMJIT_ASSERT(index < _size); - return _data[index]; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns code buffer flags, see \ref Flags. - inline uint32_t flags() const noexcept { return _flags; } - //! Tests whether the code buffer has the given `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } - - //! Tests whether this code buffer has a fixed size. - //! - //! Fixed size means that the code buffer is fixed and cannot grow. - inline bool isFixed() const noexcept { return hasFlag(kFlagIsFixed); } - - //! Tests whether the data in this code buffer is external. - //! - //! External data can only be provided by users, it's never used by AsmJit. - inline bool isExternal() const noexcept { return hasFlag(kFlagIsExternal); } - - //! Tests whether the data in this code buffer is allocated (non-null). - inline bool isAllocated() const noexcept { return _data != nullptr; } - - //! Tests whether the code buffer is empty. - inline bool empty() const noexcept { return !_size; } - - //! Returns the size of the data. - inline size_t size() const noexcept { return _size; } - //! Returns the capacity of the data. - inline size_t capacity() const noexcept { return _capacity; } - - //! Returns the pointer to the data the buffer references. - inline uint8_t* data() noexcept { return _data; } - //! \overload - inline const uint8_t* data() const noexcept { return _data; } - - //! \} - - //! \name Iterators - //! \{ - - inline uint8_t* begin() noexcept { return _data; } - inline const uint8_t* begin() const noexcept { return _data; } - - inline uint8_t* end() noexcept { return _data + _size; } - inline const uint8_t* end() const noexcept { return _data + _size; } - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_CODEBUFFER_H_INCLUDED - diff --git a/ext/asmjit-master/src/asmjit/core/codebufferwriter_p.h b/ext/asmjit-master/src/asmjit/core/codebufferwriter_p.h deleted file mode 100644 index 75ee0474..00000000 --- a/ext/asmjit-master/src/asmjit/core/codebufferwriter_p.h +++ /dev/null @@ -1,189 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_CODEBUFFERWRITER_P_H_INCLUDED -#define ASMJIT_CORE_CODEBUFFERWRITER_P_H_INCLUDED - -#include "../core/assembler.h" -#include "../core/codebuffer.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_assembler -//! \{ - -// ============================================================================ -// [asmjit::CodeBufferWriter] -// ============================================================================ - -//! Helper that is used to write into a `CodeBuffer` held by `BaseAssembler`. -class CodeBufferWriter { -public: - uint8_t* _cursor; - - ASMJIT_INLINE explicit CodeBufferWriter(BaseAssembler* a) noexcept - : _cursor(a->_bufferPtr) {} - - ASMJIT_INLINE Error ensureSpace(BaseAssembler* a, size_t n) noexcept { - size_t remainingSpace = (size_t)(a->_bufferEnd - _cursor); - if (ASMJIT_UNLIKELY(remainingSpace < n)) { - CodeBuffer& buffer = a->_section->_buffer; - Error err = a->_code->growBuffer(&buffer, n); - if (ASMJIT_UNLIKELY(err)) - return a->reportError(err); - _cursor = a->_bufferPtr; - } - return kErrorOk; - } - - ASMJIT_INLINE uint8_t* cursor() const noexcept { return _cursor; } - ASMJIT_INLINE void setCursor(uint8_t* cursor) noexcept { _cursor = cursor; } - ASMJIT_INLINE void advance(size_t n) noexcept { _cursor += n; } - - ASMJIT_INLINE size_t offsetFrom(uint8_t* from) const noexcept { - ASMJIT_ASSERT(_cursor >= from); - return (size_t)(_cursor - from); - } - - template - ASMJIT_INLINE void emit8(T val) noexcept { - typedef typename std::make_unsigned::type U; - _cursor[0] = uint8_t(U(val) & U(0xFF)); - _cursor++; - } - - template - ASMJIT_INLINE void emit8If(T val, Y cond) noexcept { - typedef typename std::make_unsigned::type U; - ASMJIT_ASSERT(size_t(cond) <= 1u); - - _cursor[0] = uint8_t(U(val) & U(0xFF)); - _cursor += size_t(cond); - } - - template - ASMJIT_INLINE void emit16uLE(T val) noexcept { - typedef typename std::make_unsigned::type U; - Support::writeU16uLE(_cursor, uint32_t(U(val) & 0xFFFFu)); - _cursor += 2; - } - - template - ASMJIT_INLINE void emit16uBE(T val) noexcept { - typedef typename std::make_unsigned::type U; - Support::writeU16uBE(_cursor, uint32_t(U(val) & 0xFFFFu)); - _cursor += 2; - } - - template - ASMJIT_INLINE void emit32uLE(T val) noexcept { - typedef typename std::make_unsigned::type U; - Support::writeU32uLE(_cursor, uint32_t(U(val) & 0xFFFFFFFFu)); - _cursor += 4; - } - - template - ASMJIT_INLINE void emit32uBE(T val) noexcept { - typedef typename std::make_unsigned::type U; - Support::writeU32uBE(_cursor, uint32_t(U(val) & 0xFFFFFFFFu)); - _cursor += 4; - } - - ASMJIT_INLINE void emitData(const void* data, size_t size) noexcept { - ASMJIT_ASSERT(size != 0); - memcpy(_cursor, data, size); - _cursor += size; - } - - template - ASMJIT_INLINE void emitValueLE(const T& value, size_t size) noexcept { - typedef typename std::make_unsigned::type U; - ASMJIT_ASSERT(size <= sizeof(T)); - - U v = U(value); - for (uint32_t i = 0; i < size; i++) { - _cursor[i] = uint8_t(v & 0xFFu); - v >>= 8; - } - _cursor += size; - } - - template - ASMJIT_INLINE void emitValueBE(const T& value, size_t size) noexcept { - typedef typename std::make_unsigned::type U; - ASMJIT_ASSERT(size <= sizeof(T)); - - U v = U(value); - for (uint32_t i = 0; i < size; i++) { - _cursor[i] = uint8_t(v >> (sizeof(T) - 8)); - v <<= 8; - } - _cursor += size; - } - - ASMJIT_INLINE void emitZeros(size_t size) noexcept { - ASMJIT_ASSERT(size != 0); - memset(_cursor, 0, size); - _cursor += size; - } - - ASMJIT_INLINE void remove8(uint8_t* where) noexcept { - ASMJIT_ASSERT(where < _cursor); - - uint8_t* p = where; - while (++p != _cursor) - p[-1] = p[0]; - _cursor--; - } - - template - ASMJIT_INLINE void insert8(uint8_t* where, T val) noexcept { - uint8_t* p = _cursor; - - while (p != where) { - p[0] = p[-1]; - p--; - } - - *p = uint8_t(val & 0xFF); - _cursor++; - } - - ASMJIT_INLINE void done(BaseAssembler* a) noexcept { - CodeBuffer& buffer = a->_section->_buffer; - size_t newSize = (size_t)(_cursor - a->_bufferData); - ASMJIT_ASSERT(newSize <= buffer.capacity()); - - a->_bufferPtr = _cursor; - buffer._size = Support::max(buffer._size, newSize); - } -}; - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_CODEBUFFERWRITER_P_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/codeholder.cpp b/ext/asmjit-master/src/asmjit/core/codeholder.cpp deleted file mode 100644 index 8711e382..00000000 --- a/ext/asmjit-master/src/asmjit/core/codeholder.cpp +++ /dev/null @@ -1,1108 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/assembler.h" -#include "../core/logger.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [Globals] -// ============================================================================ - -static const char CodeHolder_addrTabName[] = ".addrtab"; - -//! Encode MOD byte. -static inline uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) noexcept { - return (m << 6) | (o << 3) | rm; -} - -// ============================================================================ -// [asmjit::LabelLinkIterator] -// ============================================================================ - -class LabelLinkIterator { -public: - ASMJIT_INLINE LabelLinkIterator(LabelEntry* le) noexcept { reset(le); } - - ASMJIT_INLINE explicit operator bool() const noexcept { return isValid(); } - ASMJIT_INLINE bool isValid() const noexcept { return _link != nullptr; } - - ASMJIT_INLINE LabelLink* link() const noexcept { return _link; } - ASMJIT_INLINE LabelLink* operator->() const noexcept { return _link; } - - ASMJIT_INLINE void reset(LabelEntry* le) noexcept { - _pPrev = &le->_links; - _link = *_pPrev; - } - - ASMJIT_INLINE void next() noexcept { - _pPrev = &_link->next; - _link = *_pPrev; - } - - ASMJIT_INLINE void resolveAndNext(CodeHolder* code) noexcept { - LabelLink* linkToDelete = _link; - - _link = _link->next; - *_pPrev = _link; - - code->_unresolvedLinkCount--; - code->_allocator.release(linkToDelete, sizeof(LabelLink)); - } - - LabelLink** _pPrev; - LabelLink* _link; -}; - -// ============================================================================ -// [asmjit::CodeHolder - Utilities] -// ============================================================================ - -static void CodeHolder_resetInternal(CodeHolder* self, uint32_t resetPolicy) noexcept { - uint32_t i; - const ZoneVector& emitters = self->emitters(); - - i = emitters.size(); - while (i) - self->detach(emitters[--i]); - - // Reset everything into its construction state. - self->_environment.reset(); - self->_baseAddress = Globals::kNoBaseAddress; - self->_logger = nullptr; - self->_errorHandler = nullptr; - - // Reset all sections. - uint32_t numSections = self->_sections.size(); - for (i = 0; i < numSections; i++) { - Section* section = self->_sections[i]; - if (section->_buffer.data() && !section->_buffer.isExternal()) - ::free(section->_buffer._data); - section->_buffer._data = nullptr; - section->_buffer._capacity = 0; - } - - // Reset zone allocator and all containers using it. - ZoneAllocator* allocator = self->allocator(); - - self->_emitters.reset(); - self->_namedLabels.reset(); - self->_relocations.reset(); - self->_labelEntries.reset(); - self->_sections.reset(); - - self->_unresolvedLinkCount = 0; - self->_addressTableSection = nullptr; - self->_addressTableEntries.reset(); - - allocator->reset(&self->_zone); - self->_zone.reset(resetPolicy); -} - -static void CodeHolder_onSettingsUpdated(CodeHolder* self) noexcept { - // Notify all attached emitters about a settings update. - for (BaseEmitter* emitter : self->emitters()) { - emitter->onSettingsUpdated(); - } -} - -// ============================================================================ -// [asmjit::CodeHolder - Construction / Destruction] -// ============================================================================ - -CodeHolder::CodeHolder() noexcept - : _environment(), - _baseAddress(Globals::kNoBaseAddress), - _logger(nullptr), - _errorHandler(nullptr), - _zone(16384 - Zone::kBlockOverhead), - _allocator(&_zone), - _unresolvedLinkCount(0), - _addressTableSection(nullptr) {} - -CodeHolder::~CodeHolder() noexcept { - CodeHolder_resetInternal(this, Globals::kResetHard); -} - -// ============================================================================ -// [asmjit::CodeHolder - Init / Reset] -// ============================================================================ - -inline void CodeHolder_setSectionDefaultName( - Section* section, - char c0 = 0, char c1 = 0, char c2 = 0, char c3 = 0, - char c4 = 0, char c5 = 0, char c6 = 0, char c7 = 0) noexcept { - - section->_name.u32[0] = Support::bytepack32_4x8(uint8_t(c0), uint8_t(c1), uint8_t(c2), uint8_t(c3)); - section->_name.u32[1] = Support::bytepack32_4x8(uint8_t(c4), uint8_t(c5), uint8_t(c6), uint8_t(c7)); -} - -Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noexcept { - // Cannot reinitialize if it's locked or there is one or more emitter attached. - if (isInitialized()) - return DebugUtils::errored(kErrorAlreadyInitialized); - - // If we are just initializing there should be no emitters attached. - ASMJIT_ASSERT(_emitters.empty()); - - // Create a default section and insert it to the `_sections` array. - Error err = _sections.willGrow(&_allocator); - if (err == kErrorOk) { - Section* section = _allocator.allocZeroedT
(); - if (ASMJIT_LIKELY(section)) { - section->_flags = Section::kFlagExec | Section::kFlagConst; - CodeHolder_setSectionDefaultName(section, '.', 't', 'e', 'x', 't'); - _sections.appendUnsafe(section); - } - else { - err = DebugUtils::errored(kErrorOutOfMemory); - } - } - - if (ASMJIT_UNLIKELY(err)) { - _zone.reset(); - return err; - } - else { - _environment = environment; - _baseAddress = baseAddress; - return kErrorOk; - } -} - -void CodeHolder::reset(uint32_t resetPolicy) noexcept { - CodeHolder_resetInternal(this, resetPolicy); -} - -// ============================================================================ -// [asmjit::CodeHolder - Attach / Detach] -// ============================================================================ - -Error CodeHolder::attach(BaseEmitter* emitter) noexcept { - // Catch a possible misuse of the API. - if (ASMJIT_UNLIKELY(!emitter)) - return DebugUtils::errored(kErrorInvalidArgument); - - // Invalid emitter, this should not be possible. - uint32_t type = emitter->emitterType(); - if (ASMJIT_UNLIKELY(type == BaseEmitter::kTypeNone || type >= BaseEmitter::kTypeCount)) - return DebugUtils::errored(kErrorInvalidState); - - // This is suspicious, but don't fail if `emitter` is already attached - // to this code holder. This is not error, but it's not recommended. - if (emitter->_code != nullptr) { - if (emitter->_code == this) - return kErrorOk; - return DebugUtils::errored(kErrorInvalidState); - } - - // Reserve the space now as we cannot fail after `onAttach()` succeeded. - ASMJIT_PROPAGATE(_emitters.willGrow(&_allocator, 1)); - ASMJIT_PROPAGATE(emitter->onAttach(this)); - - // Connect CodeHolder <-> BaseEmitter. - ASMJIT_ASSERT(emitter->_code == this); - _emitters.appendUnsafe(emitter); - - return kErrorOk; -} - -Error CodeHolder::detach(BaseEmitter* emitter) noexcept { - if (ASMJIT_UNLIKELY(!emitter)) - return DebugUtils::errored(kErrorInvalidArgument); - - if (ASMJIT_UNLIKELY(emitter->_code != this)) - return DebugUtils::errored(kErrorInvalidState); - - // NOTE: We always detach if we were asked to, if error happens during - // `emitter->onDetach()` we just propagate it, but the BaseEmitter will - // be detached. - Error err = kErrorOk; - if (!emitter->isDestroyed()) - err = emitter->onDetach(this); - - // Disconnect CodeHolder <-> BaseEmitter. - uint32_t index = _emitters.indexOf(emitter); - ASMJIT_ASSERT(index != Globals::kNotFound); - - _emitters.removeAt(index); - emitter->_code = nullptr; - - return err; -} - -// ============================================================================ -// [asmjit::CodeHolder - Logging] -// ============================================================================ - -void CodeHolder::setLogger(Logger* logger) noexcept { -#ifndef ASMJIT_NO_LOGGING - _logger = logger; - CodeHolder_onSettingsUpdated(this); -#else - DebugUtils::unused(logger); -#endif -} - -// ============================================================================ -// [asmjit::CodeHolder - Error Handling] -// ============================================================================ - -void CodeHolder::setErrorHandler(ErrorHandler* errorHandler) noexcept { - _errorHandler = errorHandler; - CodeHolder_onSettingsUpdated(this); -} - -// ============================================================================ -// [asmjit::CodeHolder - Code Buffer] -// ============================================================================ - -static Error CodeHolder_reserveInternal(CodeHolder* self, CodeBuffer* cb, size_t n) noexcept { - uint8_t* oldData = cb->_data; - uint8_t* newData; - - if (oldData && !cb->isExternal()) - newData = static_cast(::realloc(oldData, n)); - else - newData = static_cast(::malloc(n)); - - if (ASMJIT_UNLIKELY(!newData)) - return DebugUtils::errored(kErrorOutOfMemory); - - cb->_data = newData; - cb->_capacity = n; - - // Update pointers used by assemblers, if attached. - for (BaseEmitter* emitter : self->emitters()) { - if (emitter->isAssembler()) { - BaseAssembler* a = static_cast(emitter); - if (&a->_section->_buffer == cb) { - size_t offset = a->offset(); - - a->_bufferData = newData; - a->_bufferEnd = newData + n; - a->_bufferPtr = newData + offset; - } - } - } - - return kErrorOk; -} - -Error CodeHolder::growBuffer(CodeBuffer* cb, size_t n) noexcept { - // The size of the section must be valid. - size_t size = cb->size(); - if (ASMJIT_UNLIKELY(n > std::numeric_limits::max() - size)) - return DebugUtils::errored(kErrorOutOfMemory); - - // We can now check if growing the buffer is really necessary. It's unlikely - // that this function is called while there is still room for `n` bytes. - size_t capacity = cb->capacity(); - size_t required = cb->size() + n; - if (ASMJIT_UNLIKELY(required <= capacity)) - return kErrorOk; - - if (cb->isFixed()) - return DebugUtils::errored(kErrorTooLarge); - - size_t kInitialCapacity = 8096; - if (capacity < kInitialCapacity) - capacity = kInitialCapacity; - else - capacity += Globals::kAllocOverhead; - - do { - size_t old = capacity; - if (capacity < Globals::kGrowThreshold) - capacity *= 2; - else - capacity += Globals::kGrowThreshold; - - // Overflow. - if (ASMJIT_UNLIKELY(old > capacity)) - return DebugUtils::errored(kErrorOutOfMemory); - } while (capacity - Globals::kAllocOverhead < required); - - return CodeHolder_reserveInternal(this, cb, capacity - Globals::kAllocOverhead); -} - -Error CodeHolder::reserveBuffer(CodeBuffer* cb, size_t n) noexcept { - size_t capacity = cb->capacity(); - if (n <= capacity) return kErrorOk; - - if (cb->isFixed()) - return DebugUtils::errored(kErrorTooLarge); - - return CodeHolder_reserveInternal(this, cb, n); -} - -// ============================================================================ -// [asmjit::CodeHolder - Sections] -// ============================================================================ - -Error CodeHolder::newSection(Section** sectionOut, const char* name, size_t nameSize, uint32_t flags, uint32_t alignment) noexcept { - *sectionOut = nullptr; - - if (nameSize == SIZE_MAX) - nameSize = strlen(name); - - if (alignment == 0) - alignment = 1; - - if (ASMJIT_UNLIKELY(!Support::isPowerOf2(alignment))) - return DebugUtils::errored(kErrorInvalidArgument); - - if (ASMJIT_UNLIKELY(nameSize > Globals::kMaxSectionNameSize)) - return DebugUtils::errored(kErrorInvalidSectionName); - - uint32_t sectionId = _sections.size(); - if (ASMJIT_UNLIKELY(sectionId == Globals::kInvalidId)) - return DebugUtils::errored(kErrorTooManySections); - - ASMJIT_PROPAGATE(_sections.willGrow(&_allocator)); - Section* section = _allocator.allocZeroedT
(); - - if (ASMJIT_UNLIKELY(!section)) - return DebugUtils::errored(kErrorOutOfMemory); - - section->_id = sectionId; - section->_flags = flags; - section->_alignment = alignment; - memcpy(section->_name.str, name, nameSize); - _sections.appendUnsafe(section); - - *sectionOut = section; - return kErrorOk; -} - -Section* CodeHolder::sectionByName(const char* name, size_t nameSize) const noexcept { - if (nameSize == SIZE_MAX) - nameSize = strlen(name); - - // This could be also put in a hash-table similarly like we do with labels, - // however it's questionable as the number of sections should be pretty low - // in general. Create an issue if this becomes a problem. - if (ASMJIT_UNLIKELY(nameSize <= Globals::kMaxSectionNameSize)) { - for (Section* section : _sections) - if (memcmp(section->_name.str, name, nameSize) == 0 && section->_name.str[nameSize] == '\0') - return section; - } - - return nullptr; -} - -Section* CodeHolder::ensureAddressTableSection() noexcept { - if (_addressTableSection) - return _addressTableSection; - - newSection(&_addressTableSection, CodeHolder_addrTabName, sizeof(CodeHolder_addrTabName) - 1, 0, _environment.registerSize()); - return _addressTableSection; -} - -Error CodeHolder::addAddressToAddressTable(uint64_t address) noexcept { - AddressTableEntry* entry = _addressTableEntries.get(address); - if (entry) - return kErrorOk; - - Section* section = ensureAddressTableSection(); - if (ASMJIT_UNLIKELY(!section)) - return DebugUtils::errored(kErrorOutOfMemory); - - entry = _zone.newT(address); - if (ASMJIT_UNLIKELY(!entry)) - return DebugUtils::errored(kErrorOutOfMemory); - - _addressTableEntries.insert(entry); - section->_virtualSize += _environment.registerSize(); - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::CodeHolder - Labels / Symbols] -// ============================================================================ - -//! Only used to lookup a label from `_namedLabels`. -class LabelByName { -public: - inline LabelByName(const char* key, size_t keySize, uint32_t hashCode, uint32_t parentId) noexcept - : _key(key), - _keySize(uint32_t(keySize)), - _hashCode(hashCode), - _parentId(parentId) {} - - inline uint32_t hashCode() const noexcept { return _hashCode; } - - inline bool matches(const LabelEntry* entry) const noexcept { - return entry->nameSize() == _keySize && - entry->parentId() == _parentId && - ::memcmp(entry->name(), _key, _keySize) == 0; - } - - const char* _key; - uint32_t _keySize; - uint32_t _hashCode; - uint32_t _parentId; -}; - -// Returns a hash of `name` and fixes `nameSize` if it's `SIZE_MAX`. -static uint32_t CodeHolder_hashNameAndGetSize(const char* name, size_t& nameSize) noexcept { - uint32_t hashCode = 0; - if (nameSize == SIZE_MAX) { - size_t i = 0; - for (;;) { - uint8_t c = uint8_t(name[i]); - if (!c) break; - hashCode = Support::hashRound(hashCode, c); - i++; - } - nameSize = i; - } - else { - for (size_t i = 0; i < nameSize; i++) { - uint8_t c = uint8_t(name[i]); - if (ASMJIT_UNLIKELY(!c)) return DebugUtils::errored(kErrorInvalidLabelName); - hashCode = Support::hashRound(hashCode, c); - } - } - return hashCode; -} - -static bool CodeHolder_writeDisplacement(void* dst, int64_t displacement, uint32_t displacementSize) { - if (displacementSize == 4 && Support::isInt32(displacement)) { - Support::writeI32uLE(dst, int32_t(displacement)); - return true; - } - else if (displacementSize == 1 && Support::isInt8(displacement)) { - Support::writeI8(dst, int8_t(displacement)); - return true; - } - - return false; -} - -LabelLink* CodeHolder::newLabelLink(LabelEntry* le, uint32_t sectionId, size_t offset, intptr_t rel) noexcept { - LabelLink* link = _allocator.allocT(); - if (ASMJIT_UNLIKELY(!link)) return nullptr; - - link->next = le->_links; - le->_links = link; - - link->sectionId = sectionId; - link->relocId = Globals::kInvalidId; - link->offset = offset; - link->rel = rel; - - _unresolvedLinkCount++; - return link; -} - -Error CodeHolder::newLabelEntry(LabelEntry** entryOut) noexcept { - *entryOut = nullptr; - - uint32_t labelId = _labelEntries.size(); - if (ASMJIT_UNLIKELY(labelId == Globals::kInvalidId)) - return DebugUtils::errored(kErrorTooManyLabels); - - ASMJIT_PROPAGATE(_labelEntries.willGrow(&_allocator)); - LabelEntry* le = _allocator.allocZeroedT(); - - if (ASMJIT_UNLIKELY(!le)) - return DebugUtils::errored(kErrorOutOfMemory); - - le->_setId(labelId); - le->_parentId = Globals::kInvalidId; - le->_offset = 0; - _labelEntries.appendUnsafe(le); - - *entryOut = le; - return kErrorOk; -} - -Error CodeHolder::newNamedLabelEntry(LabelEntry** entryOut, const char* name, size_t nameSize, uint32_t type, uint32_t parentId) noexcept { - *entryOut = nullptr; - uint32_t hashCode = CodeHolder_hashNameAndGetSize(name, nameSize); - - if (ASMJIT_UNLIKELY(nameSize == 0)) - return DebugUtils::errored(kErrorInvalidLabelName); - - if (ASMJIT_UNLIKELY(nameSize > Globals::kMaxLabelNameSize)) - return DebugUtils::errored(kErrorLabelNameTooLong); - - switch (type) { - case Label::kTypeLocal: - if (ASMJIT_UNLIKELY(parentId >= _labelEntries.size())) - return DebugUtils::errored(kErrorInvalidParentLabel); - - hashCode ^= parentId; - break; - - case Label::kTypeGlobal: - if (ASMJIT_UNLIKELY(parentId != Globals::kInvalidId)) - return DebugUtils::errored(kErrorNonLocalLabelCannotHaveParent); - - break; - - default: - return DebugUtils::errored(kErrorInvalidArgument); - } - - // Don't allow to insert duplicates. Local labels allow duplicates that have - // different id, this is already accomplished by having a different hashes - // between the same label names having different parent labels. - LabelEntry* le = _namedLabels.get(LabelByName(name, nameSize, hashCode, parentId)); - if (ASMJIT_UNLIKELY(le)) - return DebugUtils::errored(kErrorLabelAlreadyDefined); - - Error err = kErrorOk; - uint32_t labelId = _labelEntries.size(); - - if (ASMJIT_UNLIKELY(labelId == Globals::kInvalidId)) - return DebugUtils::errored(kErrorTooManyLabels); - - ASMJIT_PROPAGATE(_labelEntries.willGrow(&_allocator)); - le = _allocator.allocZeroedT(); - - if (ASMJIT_UNLIKELY(!le)) - return DebugUtils::errored(kErrorOutOfMemory); - - le->_hashCode = hashCode; - le->_setId(labelId); - le->_type = uint8_t(type); - le->_parentId = parentId; - le->_offset = 0; - ASMJIT_PROPAGATE(le->_name.setData(&_zone, name, nameSize)); - - _labelEntries.appendUnsafe(le); - _namedLabels.insert(allocator(), le); - - *entryOut = le; - return err; -} - -uint32_t CodeHolder::labelIdByName(const char* name, size_t nameSize, uint32_t parentId) noexcept { - uint32_t hashCode = CodeHolder_hashNameAndGetSize(name, nameSize); - if (ASMJIT_UNLIKELY(!nameSize)) - return 0; - - if (parentId != Globals::kInvalidId) - hashCode ^= parentId; - - LabelEntry* le = _namedLabels.get(LabelByName(name, nameSize, hashCode, parentId)); - return le ? le->id() : uint32_t(Globals::kInvalidId); -} - -ASMJIT_API Error CodeHolder::resolveUnresolvedLinks() noexcept { - if (!hasUnresolvedLinks()) - return kErrorOk; - - Error err = kErrorOk; - for (LabelEntry* le : labelEntries()) { - if (!le->isBound()) - continue; - - LabelLinkIterator link(le); - if (link) { - Support::FastUInt8 of = 0; - Section* toSection = le->section(); - uint64_t toOffset = Support::addOverflow(toSection->offset(), le->offset(), &of); - - do { - uint32_t linkSectionId = link->sectionId; - if (link->relocId == Globals::kInvalidId) { - Section* fromSection = sectionById(linkSectionId); - size_t linkOffset = link->offset; - - CodeBuffer& buf = _sections[linkSectionId]->buffer(); - ASMJIT_ASSERT(linkOffset < buf.size()); - - // Calculate the offset relative to the start of the virtual base. - uint64_t fromOffset = Support::addOverflow(fromSection->offset(), linkOffset, &of); - int64_t displacement = int64_t(toOffset - fromOffset + uint64_t(int64_t(link->rel))); - - if (!of) { - ASMJIT_ASSERT(size_t(linkOffset) < buf.size()); - - // Size of the value we are going to patch. Only BYTE/DWORD is allowed. - uint32_t displacementSize = buf._data[linkOffset]; - ASMJIT_ASSERT(buf.size() - size_t(linkOffset) >= displacementSize); - - // Overwrite a real displacement in the CodeBuffer. - if (CodeHolder_writeDisplacement(buf._data + linkOffset, displacement, displacementSize)) { - link.resolveAndNext(this); - continue; - } - } - - err = DebugUtils::errored(kErrorInvalidDisplacement); - // Falls through to `link.next()`. - } - - link.next(); - } while (link); - } - } - - return err; -} - -ASMJIT_API Error CodeHolder::bindLabel(const Label& label, uint32_t toSectionId, uint64_t toOffset) noexcept { - LabelEntry* le = labelEntry(label); - if (ASMJIT_UNLIKELY(!le)) - return DebugUtils::errored(kErrorInvalidLabel); - - if (ASMJIT_UNLIKELY(toSectionId > _sections.size())) - return DebugUtils::errored(kErrorInvalidSection); - - // Label can be bound only once. - if (ASMJIT_UNLIKELY(le->isBound())) - return DebugUtils::errored(kErrorLabelAlreadyBound); - - // Bind the label. - Section* section = _sections[toSectionId]; - le->_section = section; - le->_offset = toOffset; - - Error err = kErrorOk; - CodeBuffer& buf = section->buffer(); - - // Fix all links to this label we have collected so far if they are within - // the same section. We ignore any inter-section links as these have to be - // fixed later. - LabelLinkIterator link(le); - while (link) { - uint32_t linkSectionId = link->sectionId; - size_t linkOffset = link->offset; - - uint32_t relocId = link->relocId; - if (relocId != Globals::kInvalidId) { - // Adjust relocation data only. - RelocEntry* re = _relocations[relocId]; - re->_payload += toOffset; - re->_targetSectionId = toSectionId; - } - else { - if (linkSectionId != toSectionId) { - link.next(); - continue; - } - - ASMJIT_ASSERT(linkOffset < buf.size()); - int64_t displacement = int64_t(toOffset - uint64_t(linkOffset) + uint64_t(int64_t(link->rel))); - - // Size of the value we are going to patch. Only BYTE/DWORD is allowed. - uint32_t displacementSize = buf._data[linkOffset]; - ASMJIT_ASSERT(buf.size() - size_t(linkOffset) >= displacementSize); - - // Overwrite a real displacement in the CodeBuffer. - if (!CodeHolder_writeDisplacement(buf._data + linkOffset, displacement, displacementSize)) { - err = DebugUtils::errored(kErrorInvalidDisplacement); - link.next(); - continue; - } - } - - link.resolveAndNext(this); - } - - return err; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Relocations] -// ============================================================================ - -Error CodeHolder::newRelocEntry(RelocEntry** dst, uint32_t relocType, uint32_t valueSize) noexcept { - ASMJIT_PROPAGATE(_relocations.willGrow(&_allocator)); - - uint32_t relocId = _relocations.size(); - if (ASMJIT_UNLIKELY(relocId == Globals::kInvalidId)) - return DebugUtils::errored(kErrorTooManyRelocations); - - RelocEntry* re = _allocator.allocZeroedT(); - if (ASMJIT_UNLIKELY(!re)) - return DebugUtils::errored(kErrorOutOfMemory); - - re->_id = relocId; - re->_relocType = uint8_t(relocType); - re->_valueSize = uint8_t(valueSize); - re->_sourceSectionId = Globals::kInvalidId; - re->_targetSectionId = Globals::kInvalidId; - _relocations.appendUnsafe(re); - - *dst = re; - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Expression Evaluation] -// ============================================================================ - -static Error CodeHolder_evaluateExpression(CodeHolder* self, Expression* exp, uint64_t* out) noexcept { - uint64_t value[2]; - for (size_t i = 0; i < 2; i++) { - uint64_t v; - switch (exp->valueType[i]) { - case Expression::kValueNone: { - v = 0; - break; - } - - case Expression::kValueConstant: { - v = exp->value[i].constant; - break; - } - - case Expression::kValueLabel: { - LabelEntry* le = exp->value[i].label; - if (!le->isBound()) - return DebugUtils::errored(kErrorExpressionLabelNotBound); - v = le->section()->offset() + le->offset(); - break; - } - - case Expression::kValueExpression: { - Expression* nested = exp->value[i].expression; - ASMJIT_PROPAGATE(CodeHolder_evaluateExpression(self, nested, &v)); - break; - } - - default: - return DebugUtils::errored(kErrorInvalidState); - } - - value[i] = v; - } - - uint64_t result; - uint64_t& a = value[0]; - uint64_t& b = value[1]; - - switch (exp->opType) { - case Expression::kOpAdd: - result = a + b; - break; - - case Expression::kOpSub: - result = a - b; - break; - - case Expression::kOpMul: - result = a * b; - break; - - case Expression::kOpSll: - result = (b > 63) ? uint64_t(0) : uint64_t(a << b); - break; - - case Expression::kOpSrl: - result = (b > 63) ? uint64_t(0) : uint64_t(a >> b); - break; - - case Expression::kOpSra: - result = Support::sar(a, Support::min(b, 63)); - break; - - default: - return DebugUtils::errored(kErrorInvalidState); - } - - *out = result; - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Utilities] -// ============================================================================ - -Error CodeHolder::flatten() noexcept { - uint64_t offset = 0; - for (Section* section : _sections) { - uint64_t realSize = section->realSize(); - if (realSize) { - uint64_t alignedOffset = Support::alignUp(offset, section->alignment()); - if (ASMJIT_UNLIKELY(alignedOffset < offset)) - return DebugUtils::errored(kErrorTooLarge); - - Support::FastUInt8 of = 0; - offset = Support::addOverflow(alignedOffset, realSize, &of); - - if (ASMJIT_UNLIKELY(of)) - return DebugUtils::errored(kErrorTooLarge); - } - } - - // Now we know that we can assign offsets of all sections properly. - Section* prev = nullptr; - offset = 0; - for (Section* section : _sections) { - uint64_t realSize = section->realSize(); - if (realSize) - offset = Support::alignUp(offset, section->alignment()); - section->_offset = offset; - - // Make sure the previous section extends a bit to cover the alignment. - if (prev) - prev->_virtualSize = offset - prev->_offset; - - prev = section; - offset += realSize; - } - - return kErrorOk; -} - -size_t CodeHolder::codeSize() const noexcept { - Support::FastUInt8 of = 0; - uint64_t offset = 0; - - for (Section* section : _sections) { - uint64_t realSize = section->realSize(); - - if (realSize) { - uint64_t alignedOffset = Support::alignUp(offset, section->alignment()); - ASMJIT_ASSERT(alignedOffset >= offset); - offset = Support::addOverflow(alignedOffset, realSize, &of); - } - } - - if ((sizeof(uint64_t) > sizeof(size_t) && offset > SIZE_MAX) || of) - return SIZE_MAX; - - return size_t(offset); -} - -Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept { - // Base address must be provided. - if (ASMJIT_UNLIKELY(baseAddress == Globals::kNoBaseAddress)) - return DebugUtils::errored(kErrorInvalidArgument); - - _baseAddress = baseAddress; - uint32_t addressSize = _environment.registerSize(); - - Section* addressTableSection = _addressTableSection; - uint32_t addressTableEntryCount = 0; - uint8_t* addressTableEntryData = nullptr; - - if (addressTableSection) { - ASMJIT_PROPAGATE( - reserveBuffer(&addressTableSection->_buffer, size_t(addressTableSection->virtualSize()))); - addressTableEntryData = addressTableSection->_buffer.data(); - } - - // Relocate all recorded locations. - for (const RelocEntry* re : _relocations) { - // Possibly deleted or optimized-out entry. - if (re->relocType() == RelocEntry::kTypeNone) - continue; - - Section* sourceSection = sectionById(re->sourceSectionId()); - Section* targetSection = nullptr; - - if (re->targetSectionId() != Globals::kInvalidId) - targetSection = sectionById(re->targetSectionId()); - - uint64_t value = re->payload(); - uint64_t sectionOffset = sourceSection->offset(); - uint64_t sourceOffset = re->sourceOffset(); - - // Make sure that the `RelocEntry` doesn't go out of bounds. - size_t regionSize = re->leadingSize() + re->valueSize() + re->trailingSize(); - if (ASMJIT_UNLIKELY(re->sourceOffset() >= sourceSection->bufferSize() || - sourceSection->bufferSize() - size_t(re->sourceOffset()) < regionSize)) - return DebugUtils::errored(kErrorInvalidRelocEntry); - - uint8_t* buffer = sourceSection->data(); - size_t valueOffset = size_t(re->sourceOffset()) + re->leadingSize(); - - switch (re->relocType()) { - case RelocEntry::kTypeExpression: { - Expression* expression = (Expression*)(uintptr_t(value)); - ASMJIT_PROPAGATE(CodeHolder_evaluateExpression(this, expression, &value)); - break; - } - - case RelocEntry::kTypeAbsToAbs: { - break; - } - - case RelocEntry::kTypeRelToAbs: { - // Value is currently a relative offset from the start of its section. - // We have to convert it to an absolute offset (including base address). - if (ASMJIT_UNLIKELY(!targetSection)) - return DebugUtils::errored(kErrorInvalidRelocEntry); - - //value += baseAddress + sectionOffset + sourceOffset + regionSize; - value += baseAddress + targetSection->offset(); - break; - } - - case RelocEntry::kTypeAbsToRel: { - value -= baseAddress + sectionOffset + sourceOffset + regionSize; - if (addressSize > 4 && !Support::isInt32(int64_t(value))) - return DebugUtils::errored(kErrorRelocOffsetOutOfRange); - break; - } - - case RelocEntry::kTypeX64AddressEntry: { - if (re->valueSize() != 4 || re->leadingSize() < 2) - return DebugUtils::errored(kErrorInvalidRelocEntry); - - // First try whether a relative 32-bit displacement would work. - value -= baseAddress + sectionOffset + sourceOffset + regionSize; - if (!Support::isInt32(int64_t(value))) { - // Relative 32-bit displacement is not possible, use '.addrtab' section. - AddressTableEntry* atEntry = _addressTableEntries.get(re->payload()); - if (ASMJIT_UNLIKELY(!atEntry)) - return DebugUtils::errored(kErrorInvalidRelocEntry); - - // Cannot be null as we have just matched the `AddressTableEntry`. - ASMJIT_ASSERT(addressTableSection != nullptr); - - if (!atEntry->hasAssignedSlot()) - atEntry->_slot = addressTableEntryCount++; - - size_t atEntryIndex = size_t(atEntry->slot()) * addressSize; - uint64_t addrSrc = sectionOffset + sourceOffset + regionSize; - uint64_t addrDst = addressTableSection->offset() + uint64_t(atEntryIndex); - - value = addrDst - addrSrc; - if (!Support::isInt32(int64_t(value))) - return DebugUtils::errored(kErrorRelocOffsetOutOfRange); - - // Bytes that replace [REX, OPCODE] bytes. - uint32_t byte0 = 0xFF; - uint32_t byte1 = buffer[valueOffset - 1]; - - if (byte1 == 0xE8) { - // Patch CALL/MOD byte to FF /2 (-> 0x15). - byte1 = x86EncodeMod(0, 2, 5); - } - else if (byte1 == 0xE9) { - // Patch JMP/MOD byte to FF /4 (-> 0x25). - byte1 = x86EncodeMod(0, 4, 5); - } - else { - return DebugUtils::errored(kErrorInvalidRelocEntry); - } - - // Patch `jmp/call` instruction. - buffer[valueOffset - 2] = uint8_t(byte0); - buffer[valueOffset - 1] = uint8_t(byte1); - - Support::writeU64uLE(addressTableEntryData + atEntryIndex, re->payload()); - } - break; - } - - default: - return DebugUtils::errored(kErrorInvalidRelocEntry); - } - - switch (re->valueSize()) { - case 1: - Support::writeU8(buffer + valueOffset, uint32_t(value & 0xFFu)); - break; - - case 2: - Support::writeU16uLE(buffer + valueOffset, uint32_t(value & 0xFFFFu)); - break; - - case 4: - Support::writeU32uLE(buffer + valueOffset, uint32_t(value & 0xFFFFFFFFu)); - break; - - case 8: - Support::writeU64uLE(buffer + valueOffset, value); - break; - - default: - return DebugUtils::errored(kErrorInvalidRelocEntry); - } - } - - // Fixup the virtual size of the address table if it's the last section. - if (_sections.last() == addressTableSection) { - size_t addressTableSize = addressTableEntryCount * addressSize; - addressTableSection->_buffer._size = addressTableSize; - addressTableSection->_virtualSize = addressTableSize; - } - - return kErrorOk; -} - -Error CodeHolder::copySectionData(void* dst, size_t dstSize, uint32_t sectionId, uint32_t copyOptions) noexcept { - if (ASMJIT_UNLIKELY(!isSectionValid(sectionId))) - return DebugUtils::errored(kErrorInvalidSection); - - Section* section = sectionById(sectionId); - size_t bufferSize = section->bufferSize(); - - if (ASMJIT_UNLIKELY(dstSize < bufferSize)) - return DebugUtils::errored(kErrorInvalidArgument); - - memcpy(dst, section->data(), bufferSize); - - if (bufferSize < dstSize && (copyOptions & kCopyPadSectionBuffer)) { - size_t paddingSize = dstSize - bufferSize; - memset(static_cast(dst) + bufferSize, 0, paddingSize); - } - - return kErrorOk; -} - -Error CodeHolder::copyFlattenedData(void* dst, size_t dstSize, uint32_t copyOptions) noexcept { - size_t end = 0; - for (Section* section : _sections) { - if (section->offset() > dstSize) - return DebugUtils::errored(kErrorInvalidArgument); - - size_t bufferSize = section->bufferSize(); - size_t offset = size_t(section->offset()); - - if (ASMJIT_UNLIKELY(dstSize - offset < bufferSize)) - return DebugUtils::errored(kErrorInvalidArgument); - - uint8_t* dstTarget = static_cast(dst) + offset; - size_t paddingSize = 0; - memcpy(dstTarget, section->data(), bufferSize); - - if ((copyOptions & kCopyPadSectionBuffer) && bufferSize < section->virtualSize()) { - paddingSize = Support::min(dstSize - offset, size_t(section->virtualSize())) - bufferSize; - memset(dstTarget + bufferSize, 0, paddingSize); - } - - end = Support::max(end, offset + bufferSize + paddingSize); - } - - if (end < dstSize && (copyOptions & kCopyPadTargetBuffer)) { - memset(static_cast(dst) + end, 0, dstSize - end); - } - - return kErrorOk; -} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/codeholder.h b/ext/asmjit-master/src/asmjit/core/codeholder.h deleted file mode 100644 index 9b3466db..00000000 --- a/ext/asmjit-master/src/asmjit/core/codeholder.h +++ /dev/null @@ -1,929 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_CODEHOLDER_H_INCLUDED -#define ASMJIT_CORE_CODEHOLDER_H_INCLUDED - -#include "../core/arch.h" -#include "../core/codebuffer.h" -#include "../core/datatypes.h" -#include "../core/errorhandler.h" -#include "../core/operand.h" -#include "../core/string.h" -#include "../core/support.h" -#include "../core/target.h" -#include "../core/zone.h" -#include "../core/zonehash.h" -#include "../core/zonestring.h" -#include "../core/zonetree.h" -#include "../core/zonevector.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class BaseEmitter; -class CodeHolder; -class LabelEntry; -class Logger; - -// ============================================================================ -// [asmjit::AlignMode] -// ============================================================================ - -//! Align mode. -enum AlignMode : uint32_t { - //! Align executable code. - kAlignCode = 0, - //! Align non-executable code. - kAlignData = 1, - //! Align by a sequence of zeros. - kAlignZero = 2, - //! Count of alignment modes. - kAlignCount = 3 -}; - -// ============================================================================ -// [asmjit::Section] -// ============================================================================ - -//! Section entry. -class Section { -public: - //! Section id. - uint32_t _id; - //! Section flags. - uint32_t _flags; - //! Section alignment requirements (0 if no requirements). - uint32_t _alignment; - //! Reserved for future use (padding). - uint32_t _reserved; - //! Offset of this section from base-address. - uint64_t _offset; - //! Virtual size of the section (zero initialized sections). - uint64_t _virtualSize; - //! Section name (max 35 characters, PE allows max 8). - FixedString _name; - //! Code or data buffer. - CodeBuffer _buffer; - - //! Section flags. - enum Flags : uint32_t { - //! Executable (.text sections). - kFlagExec = 0x00000001u, - //! Read-only (.text and .data sections). - kFlagConst = 0x00000002u, - //! Zero initialized by the loader (BSS). - kFlagZero = 0x00000004u, - //! Info / comment flag. - kFlagInfo = 0x00000008u, - //! Section created implicitly and can be deleted by \ref Target. - kFlagImplicit = 0x80000000u - }; - - //! \name Accessors - //! \{ - - //! Returns the section id. - inline uint32_t id() const noexcept { return _id; } - //! Returns the section name, as a null terminated string. - inline const char* name() const noexcept { return _name.str; } - - //! Returns the section data. - inline uint8_t* data() noexcept { return _buffer.data(); } - //! \overload - inline const uint8_t* data() const noexcept { return _buffer.data(); } - - //! Returns the section flags, see \ref Flags. - inline uint32_t flags() const noexcept { return _flags; } - //! Tests whether the section has the given `flag`. - inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } - //! Adds `flags` to the section flags. - inline void addFlags(uint32_t flags) noexcept { _flags |= flags; } - //! Removes `flags` from the section flags. - inline void clearFlags(uint32_t flags) noexcept { _flags &= ~flags; } - - //! Returns the minimum section alignment - inline uint32_t alignment() const noexcept { return _alignment; } - //! Sets the minimum section alignment - inline void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; } - - //! Returns the section offset, relative to base. - inline uint64_t offset() const noexcept { return _offset; } - //! Set the section offset. - inline void setOffset(uint64_t offset) noexcept { _offset = offset; } - - //! Returns the virtual size of the section. - //! - //! Virtual size is initially zero and is never changed by AsmJit. It's normal - //! if virtual size is smaller than size returned by `bufferSize()` as the buffer - //! stores real data emitted by assemblers or appended by users. - //! - //! Use `realSize()` to get the real and final size of this section. - inline uint64_t virtualSize() const noexcept { return _virtualSize; } - //! Sets the virtual size of the section. - inline void setVirtualSize(uint64_t virtualSize) noexcept { _virtualSize = virtualSize; } - - //! Returns the buffer size of the section. - inline size_t bufferSize() const noexcept { return _buffer.size(); } - //! Returns the real size of the section calculated from virtual and buffer sizes. - inline uint64_t realSize() const noexcept { return Support::max(virtualSize(), bufferSize()); } - - //! Returns the `CodeBuffer` used by this section. - inline CodeBuffer& buffer() noexcept { return _buffer; } - //! Returns the `CodeBuffer` used by this section (const). - inline const CodeBuffer& buffer() const noexcept { return _buffer; } - - //! \} -}; - -// ============================================================================ -// [asmjit::LabelLink] -// ============================================================================ - -//! Data structure used to link either unbound labels or cross-section links. -struct LabelLink { - //! Next link (single-linked list). - LabelLink* next; - //! Section id where the label is bound. - uint32_t sectionId; - //! Relocation id or Globals::kInvalidId. - uint32_t relocId; - //! Label offset relative to the start of the section. - size_t offset; - //! Inlined rel8/rel32. - intptr_t rel; -}; - -// ============================================================================ -// [asmjit::Expression] -// ============================================================================ - -//! Expression node that can reference constants, labels, and another expressions. -struct Expression { - //! Operation type. - enum OpType : uint8_t { - //! Addition. - kOpAdd = 0, - //! Subtraction. - kOpSub = 1, - //! Multiplication - kOpMul = 2, - //! Logical left shift. - kOpSll = 3, - //! Logical right shift. - kOpSrl = 4, - //! Arithmetic right shift. - kOpSra = 5 - }; - - //! Type of \ref Value. - enum ValueType : uint8_t { - //! No value or invalid. - kValueNone = 0, - //! Value is 64-bit unsigned integer (constant). - kValueConstant = 1, - //! Value is \ref LabelEntry, which references a \ref Label. - kValueLabel = 2, - //! Value is \ref Expression - kValueExpression = 3 - }; - - //! Expression value. - union Value { - //! Constant. - uint64_t constant; - //! Pointer to another expression. - Expression* expression; - //! Poitner to \ref LabelEntry. - LabelEntry* label; - }; - - //! Operation type. - uint8_t opType; - //! Value types of \ref value. - uint8_t valueType[2]; - //! Reserved for future use, should be initialized to zero. - uint8_t reserved[5]; - //! Expression left and right values. - Value value[2]; - - //! Resets the whole expression. - //! - //! Changes both values to \ref kValueNone. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! Sets the value type at `index` to \ref kValueConstant and its content to `constant`. - inline void setValueAsConstant(size_t index, uint64_t constant) noexcept { - valueType[index] = kValueConstant; - value[index].constant = constant; - } - - //! Sets the value type at `index` to \ref kValueLabel and its content to `labelEntry`. - inline void setValueAsLabel(size_t index, LabelEntry* labelEntry) noexcept { - valueType[index] = kValueLabel; - value[index].label = labelEntry; - } - - //! Sets the value type at `index` to \ref kValueExpression and its content to `expression`. - inline void setValueAsExpression(size_t index, Expression* expression) noexcept { - valueType[index] = kValueLabel; - value[index].expression = expression; - } -}; - -// ============================================================================ -// [asmjit::LabelEntry] -// ============================================================================ - -//! Label entry. -//! -//! Contains the following properties: -//! * Label id - This is the only thing that is set to the `Label` operand. -//! * Label name - Optional, used mostly to create executables and libraries. -//! * Label type - Type of the label, default `Label::kTypeAnonymous`. -//! * Label parent id - Derived from many assemblers that allow to define a -//! local label that falls under a global label. This allows to define -//! many labels of the same name that have different parent (global) label. -//! * Offset - offset of the label bound by `Assembler`. -//! * Links - single-linked list that contains locations of code that has -//! to be patched when the label gets bound. Every use of unbound label -//! adds one link to `_links` list. -//! * HVal - Hash value of label's name and optionally parentId. -//! * HashNext - Hash-table implementation detail. -class LabelEntry : public ZoneHashNode { -public: - // Let's round the size of `LabelEntry` to 64 bytes (as `ZoneAllocator` has - // granularity of 32 bytes anyway). This gives `_name` the remaining space, - // which is should be 16 bytes on 64-bit and 28 bytes on 32-bit architectures. - static constexpr uint32_t kStaticNameSize = - 64 - (sizeof(ZoneHashNode) + 8 + sizeof(Section*) + sizeof(size_t) + sizeof(LabelLink*)); - - //! Label type, see `Label::LabelType`. - uint8_t _type; - //! Must be zero. - uint8_t _flags; - //! Reserved. - uint16_t _reserved16; - //! Label parent id or zero. - uint32_t _parentId; - //! Label offset relative to the start of the `_section`. - uint64_t _offset; - //! Section where the label was bound. - Section* _section; - //! Label links. - LabelLink* _links; - //! Label name. - ZoneString _name; - - //! \name Accessors - //! \{ - - // NOTE: Label id is stored in `_customData`, which is provided by ZoneHashNode - // to fill a padding that a C++ compiler targeting 64-bit CPU will add to align - // the structure to 64-bits. - - //! Returns label id. - inline uint32_t id() const noexcept { return _customData; } - //! Sets label id (internal, used only by `CodeHolder`). - inline void _setId(uint32_t id) noexcept { _customData = id; } - - //! Returns label type, see `Label::LabelType`. - inline uint32_t type() const noexcept { return _type; } - //! Returns label flags, returns 0 at the moment. - inline uint32_t flags() const noexcept { return _flags; } - - //! Tests whether the label has a parent label. - inline bool hasParent() const noexcept { return _parentId != Globals::kInvalidId; } - //! Returns label's parent id. - inline uint32_t parentId() const noexcept { return _parentId; } - - //! Returns the section where the label was bound. - //! - //! If the label was not yet bound the return value is `nullptr`. - inline Section* section() const noexcept { return _section; } - - //! Tests whether the label has name. - inline bool hasName() const noexcept { return !_name.empty(); } - - //! Returns the label's name. - //! - //! \note Local labels will return their local name without their parent - //! part, for example ".L1". - inline const char* name() const noexcept { return _name.data(); } - - //! Returns size of label's name. - //! - //! \note Label name is always null terminated, so you can use `strlen()` to - //! get it, however, it's also cached in `LabelEntry` itself, so if you want - //! to know the size the fastest way is to call `LabelEntry::nameSize()`. - inline uint32_t nameSize() const noexcept { return _name.size(); } - - //! Returns links associated with this label. - inline LabelLink* links() const noexcept { return _links; } - - //! Tests whether the label is bound. - inline bool isBound() const noexcept { return _section != nullptr; } - //! Tests whether the label is bound to a the given `sectionId`. - inline bool isBoundTo(Section* section) const noexcept { return _section == section; } - - //! Returns the label offset (only useful if the label is bound). - inline uint64_t offset() const noexcept { return _offset; } - - //! Returns the hash-value of label's name and its parent label (if any). - //! - //! Label hash is calculated as `HASH(Name) ^ ParentId`. The hash function - //! is implemented in `Support::hashString()` and `Support::hashRound()`. - inline uint32_t hashCode() const noexcept { return _hashCode; } - - //! \} -}; - -// ============================================================================ -// [asmjit::RelocEntry] -// ============================================================================ - -//! Relocation entry. -//! -//! We describe relocation data in the following way: -//! -//! ``` -//! +- Start of the buffer +- End of the data -//! | |*PATCHED*| | or instruction -//! |xxxxxxxxxxxxxxxxxxxxxx|LeadSize|ValueSize|TrailSize|xxxxxxxxxxxxxxxxxxxx-> -//! | -//! +- Source offset -//! ``` -struct RelocEntry { - //! Relocation id. - uint32_t _id; - //! Type of the relocation. - uint8_t _relocType; - //! Size of the relocation data/value (1, 2, 4 or 8 bytes). - uint8_t _valueSize; - //! Number of bytes after `_sourceOffset` to reach the value to be patched. - uint8_t _leadingSize; - //! Number of bytes after `_sourceOffset + _valueSize` to reach end of the - //! instruction. - uint8_t _trailingSize; - //! Source section id. - uint32_t _sourceSectionId; - //! Target section id. - uint32_t _targetSectionId; - //! Source offset (relative to start of the section). - uint64_t _sourceOffset; - //! Payload (target offset, target address, expression, etc). - uint64_t _payload; - - //! Relocation type. - enum RelocType : uint32_t { - //! None/deleted (no relocation). - kTypeNone = 0, - //! Expression evaluation, `_payload` is pointer to `Expression`. - kTypeExpression = 1, - //! Relocate absolute to absolute. - kTypeAbsToAbs = 2, - //! Relocate relative to absolute. - kTypeRelToAbs = 3, - //! Relocate absolute to relative. - kTypeAbsToRel = 4, - //! Relocate absolute to relative or use trampoline. - kTypeX64AddressEntry = 5 - }; - - //! \name Accessors - //! \{ - - inline uint32_t id() const noexcept { return _id; } - - inline uint32_t relocType() const noexcept { return _relocType; } - inline uint32_t valueSize() const noexcept { return _valueSize; } - - inline uint32_t leadingSize() const noexcept { return _leadingSize; } - inline uint32_t trailingSize() const noexcept { return _trailingSize; } - - inline uint32_t sourceSectionId() const noexcept { return _sourceSectionId; } - inline uint32_t targetSectionId() const noexcept { return _targetSectionId; } - - inline uint64_t sourceOffset() const noexcept { return _sourceOffset; } - inline uint64_t payload() const noexcept { return _payload; } - - Expression* payloadAsExpression() const noexcept { - return reinterpret_cast(uintptr_t(_payload)); - } - - //! \} -}; - -// ============================================================================ -// [asmjit::AddressTableEntry] -// ============================================================================ - -//! Entry in an address table. -class AddressTableEntry : public ZoneTreeNodeT { -public: - ASMJIT_NONCOPYABLE(AddressTableEntry) - - //! Address. - uint64_t _address; - //! Slot. - uint32_t _slot; - - //! \name Construction & Destruction - //! \{ - - inline explicit AddressTableEntry(uint64_t address) noexcept - : _address(address), - _slot(0xFFFFFFFFu) {} - - //! \} - - //! \name Accessors - //! \{ - - inline uint64_t address() const noexcept { return _address; } - inline uint32_t slot() const noexcept { return _slot; } - - inline bool hasAssignedSlot() const noexcept { return _slot != 0xFFFFFFFFu; } - - inline bool operator<(const AddressTableEntry& other) const noexcept { return _address < other._address; } - inline bool operator>(const AddressTableEntry& other) const noexcept { return _address > other._address; } - - inline bool operator<(uint64_t queryAddress) const noexcept { return _address < queryAddress; } - inline bool operator>(uint64_t queryAddress) const noexcept { return _address > queryAddress; } - - //! \} -}; - -// ============================================================================ -// [asmjit::CodeHolder] -// ============================================================================ - -//! Contains basic information about the target architecture and its options. -//! -//! In addition, it holds assembled code & data (including sections, labels, and -//! relocation information). `CodeHolder` can store both binary and intermediate -//! representation of assembly, which can be generated by \ref BaseAssembler, -//! \ref BaseBuilder, and \ref BaseCompiler -//! -//! \note `CodeHolder` has an ability to attach an \ref ErrorHandler, however, -//! the error handler is not triggered by `CodeHolder` itself, it's instead -//! propagated to all emitters that attach to it. -class CodeHolder { -public: - ASMJIT_NONCOPYABLE(CodeHolder) - - //! Environment information. - Environment _environment; - //! Base address or \ref Globals::kNoBaseAddress. - uint64_t _baseAddress; - - //! Attached `Logger`, used by all consumers. - Logger* _logger; - //! Attached `ErrorHandler`. - ErrorHandler* _errorHandler; - - //! Code zone (used to allocate core structures). - Zone _zone; - //! Zone allocator, used to manage internal containers. - ZoneAllocator _allocator; - - //! Attached emitters. - ZoneVector _emitters; - //! Section entries. - ZoneVector _sections; - //! Label entries. - ZoneVector _labelEntries; - //! Relocation entries. - ZoneVector _relocations; - //! Label name -> LabelEntry (only named labels). - ZoneHash _namedLabels; - - //! Count of label links, which are not resolved. - size_t _unresolvedLinkCount; - //! Pointer to an address table section (or null if this section doesn't exist). - Section* _addressTableSection; - //! Address table entries. - ZoneTree _addressTableEntries; - - //! Options that can be used with \ref copySectionData() and \ref copyFlattenedData(). - enum CopyOptions : uint32_t { - //! If virtual size of a section is greater than the size of its \ref CodeBuffer - //! then all bytes between the buffer size and virtual size will be zeroed. - //! If this option is not set then those bytes would be left as is, which - //! means that if the user didn't initialize them they would have a previous - //! content, which may be unwanted. - kCopyPadSectionBuffer = 0x00000001u, - -#ifndef ASMJIT_NO_DEPRECATED - kCopyWithPadding = kCopyPadSectionBuffer, -#endif // !ASMJIT_NO_DEPRECATED - - //! Zeroes the target buffer if the flattened data is less than the destination - //! size. This option works only with \ref copyFlattenedData() as it processes - //! multiple sections. It is ignored by \ref copySectionData(). - kCopyPadTargetBuffer = 0x00000002u - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates an uninitialized CodeHolder (you must init() it before it can be used). - ASMJIT_API CodeHolder() noexcept; - //! Destroys the CodeHolder. - ASMJIT_API ~CodeHolder() noexcept; - - //! Tests whether the `CodeHolder` has been initialized. - //! - //! Emitters can be only attached to initialized `CodeHolder` instances. - inline bool isInitialized() const noexcept { return _environment.isInitialized(); } - - //! Initializes CodeHolder to hold code described by code `info`. - ASMJIT_API Error init(const Environment& environment, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept; - //! Detaches all code-generators attached and resets the `CodeHolder`. - ASMJIT_API void reset(uint32_t resetPolicy = Globals::kResetSoft) noexcept; - - //! \} - - //! \name Attach & Detach - //! \{ - - //! Attaches an emitter to this `CodeHolder`. - ASMJIT_API Error attach(BaseEmitter* emitter) noexcept; - //! Detaches an emitter from this `CodeHolder`. - ASMJIT_API Error detach(BaseEmitter* emitter) noexcept; - - //! \} - - //! \name Allocators - //! \{ - - //! Returns the allocator that the `CodeHolder` uses. - //! - //! \note This should be only used for AsmJit's purposes. Code holder uses - //! arena allocator to allocate everything, so anything allocated through - //! this allocator will be invalidated by \ref CodeHolder::reset() or by - //! CodeHolder's destructor. - inline ZoneAllocator* allocator() const noexcept { return const_cast(&_allocator); } - - //! \} - - //! \name Code & Architecture - //! \{ - - //! Returns the target environment information, see \ref Environment. - inline const Environment& environment() const noexcept { return _environment; } - - //! Returns the target architecture. - inline uint32_t arch() const noexcept { return environment().arch(); } - //! Returns the target sub-architecture. - inline uint32_t subArch() const noexcept { return environment().subArch(); } - - //! Tests whether a static base-address is set. - inline bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; } - //! Returns a static base-address or \ref Globals::kNoBaseAddress, if not set. - inline uint64_t baseAddress() const noexcept { return _baseAddress; } - - //! \} - - //! \name Emitters - //! \{ - - //! Returns a vector of attached emitters. - inline const ZoneVector& emitters() const noexcept { return _emitters; } - - //! \} - - //! \name Logging - //! \{ - - //! Returns the attached logger, see \ref Logger. - inline Logger* logger() const noexcept { return _logger; } - //! Attaches a `logger` to CodeHolder and propagates it to all attached emitters. - ASMJIT_API void setLogger(Logger* logger) noexcept; - //! Resets the logger to none. - inline void resetLogger() noexcept { setLogger(nullptr); } - - //! \name Error Handling - //! \{ - - //! Tests whether the CodeHolder has an attached error handler, see \ref ErrorHandler. - inline bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; } - //! Returns the attached error handler. - inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; } - //! Attach an error handler to this `CodeHolder`. - ASMJIT_API void setErrorHandler(ErrorHandler* errorHandler) noexcept; - //! Resets the error handler to none. - inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); } - - //! \} - - //! \name Code Buffer - //! \{ - - //! Makes sure that at least `n` bytes can be added to CodeHolder's buffer `cb`. - //! - //! \note The buffer `cb` must be managed by `CodeHolder` - otherwise the - //! behavior of the function is undefined. - ASMJIT_API Error growBuffer(CodeBuffer* cb, size_t n) noexcept; - - //! Reserves the size of `cb` to at least `n` bytes. - //! - //! \note The buffer `cb` must be managed by `CodeHolder` - otherwise the - //! behavior of the function is undefined. - ASMJIT_API Error reserveBuffer(CodeBuffer* cb, size_t n) noexcept; - - //! \} - - //! \name Sections - //! \{ - - //! Returns an array of `Section*` records. - inline const ZoneVector& sections() const noexcept { return _sections; } - //! Returns the number of sections. - inline uint32_t sectionCount() const noexcept { return _sections.size(); } - - //! Tests whether the given `sectionId` is valid. - inline bool isSectionValid(uint32_t sectionId) const noexcept { return sectionId < _sections.size(); } - - //! Creates a new section and return its pointer in `sectionOut`. - //! - //! Returns `Error`, does not report a possible error to `ErrorHandler`. - ASMJIT_API Error newSection(Section** sectionOut, const char* name, size_t nameSize = SIZE_MAX, uint32_t flags = 0, uint32_t alignment = 1) noexcept; - - //! Returns a section entry of the given index. - inline Section* sectionById(uint32_t sectionId) const noexcept { return _sections[sectionId]; } - - //! Returns section-id that matches the given `name`. - //! - //! If there is no such section `Section::kInvalidId` is returned. - ASMJIT_API Section* sectionByName(const char* name, size_t nameSize = SIZE_MAX) const noexcept; - - //! Returns '.text' section (section that commonly represents code). - //! - //! \note Text section is always the first section in \ref CodeHolder::sections() array. - inline Section* textSection() const noexcept { return _sections[0]; } - - //! Tests whether '.addrtab' section exists. - inline bool hasAddressTable() const noexcept { return _addressTableSection != nullptr; } - - //! Returns '.addrtab' section. - //! - //! This section is used exclusively by AsmJit to store absolute 64-bit - //! addresses that cannot be encoded in instructions like 'jmp' or 'call'. - //! - //! \note This section is created on demand, the returned pointer can be null. - inline Section* addressTableSection() const noexcept { return _addressTableSection; } - - //! Ensures that '.addrtab' section exists (creates it if it doesn't) and - //! returns it. Can return `nullptr` on out of memory condition. - ASMJIT_API Section* ensureAddressTableSection() noexcept; - - //! Used to add an address to an address table. - //! - //! This implicitly calls `ensureAddressTableSection()` and then creates - //! `AddressTableEntry` that is inserted to `_addressTableEntries`. If the - //! address already exists this operation does nothing as the same addresses - //! use the same slot. - //! - //! This function should be considered internal as it's used by assemblers to - //! insert an absolute address into the address table. Inserting address into - //! address table without creating a particula relocation entry makes no sense. - ASMJIT_API Error addAddressToAddressTable(uint64_t address) noexcept; - - //! \} - - //! \name Labels & Symbols - //! \{ - - //! Returns array of `LabelEntry*` records. - inline const ZoneVector& labelEntries() const noexcept { return _labelEntries; } - - //! Returns number of labels created. - inline uint32_t labelCount() const noexcept { return _labelEntries.size(); } - - //! Tests whether the label having `id` is valid (i.e. created by `newLabelEntry()`). - inline bool isLabelValid(uint32_t labelId) const noexcept { - return labelId < _labelEntries.size(); - } - - //! Tests whether the `label` is valid (i.e. created by `newLabelEntry()`). - inline bool isLabelValid(const Label& label) const noexcept { - return label.id() < _labelEntries.size(); - } - - //! \overload - inline bool isLabelBound(uint32_t labelId) const noexcept { - return isLabelValid(labelId) && _labelEntries[labelId]->isBound(); - } - - //! Tests whether the `label` is already bound. - //! - //! Returns `false` if the `label` is not valid. - inline bool isLabelBound(const Label& label) const noexcept { - return isLabelBound(label.id()); - } - - //! Returns LabelEntry of the given label `id`. - inline LabelEntry* labelEntry(uint32_t labelId) const noexcept { - return isLabelValid(labelId) ? _labelEntries[labelId] : static_cast(nullptr); - } - - //! Returns LabelEntry of the given `label`. - inline LabelEntry* labelEntry(const Label& label) const noexcept { - return labelEntry(label.id()); - } - - //! Returns offset of a `Label` by its `labelId`. - //! - //! The offset returned is relative to the start of the section. Zero offset - //! is returned for unbound labels, which is their initial offset value. - inline uint64_t labelOffset(uint32_t labelId) const noexcept { - ASMJIT_ASSERT(isLabelValid(labelId)); - return _labelEntries[labelId]->offset(); - } - - //! \overload - inline uint64_t labelOffset(const Label& label) const noexcept { - return labelOffset(label.id()); - } - - //! Returns offset of a label by it's `labelId` relative to the base offset. - //! - //! \remarks The offset of the section where the label is bound must be valid - //! in order to use this function, otherwise the value returned will not be - //! reliable. - inline uint64_t labelOffsetFromBase(uint32_t labelId) const noexcept { - ASMJIT_ASSERT(isLabelValid(labelId)); - const LabelEntry* le = _labelEntries[labelId]; - return (le->isBound() ? le->section()->offset() : uint64_t(0)) + le->offset(); - } - - //! \overload - inline uint64_t labelOffsetFromBase(const Label& label) const noexcept { - return labelOffsetFromBase(label.id()); - } - - //! Creates a new anonymous label and return its id in `idOut`. - //! - //! Returns `Error`, does not report error to `ErrorHandler`. - ASMJIT_API Error newLabelEntry(LabelEntry** entryOut) noexcept; - - //! Creates a new named \ref LabelEntry of the given label `type`. - //! - //! \param entryOut Where to store the created \ref LabelEntry. - //! \param name The name of the label. - //! \param nameSize The length of `name` argument, or `SIZE_MAX` if `name` is - //! a null terminated string, which means that the `CodeHolder` will - //! use `strlen()` to determine the length. - //! \param type The type of the label to create, see \ref Label::LabelType. - //! \param parentId Parent id of a local label, otherwise it must be - //! \ref Globals::kInvalidId. - //! - //! \retval Always returns \ref Error, does not report a possible error to - //! the attached \ref ErrorHandler. - //! - //! AsmJit has a support for local labels (\ref Label::kTypeLocal) which - //! require a parent label id (parentId). The names of local labels can - //! conflict with names of other local labels that have a different parent. - ASMJIT_API Error newNamedLabelEntry(LabelEntry** entryOut, const char* name, size_t nameSize, uint32_t type, uint32_t parentId = Globals::kInvalidId) noexcept; - - //! Returns a label by name. - //! - //! If the named label doesn't a default constructed \ref Label is returned, - //! which has its id set to \ref Globals::kInvalidId. - inline Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept { - return Label(labelIdByName(name, nameSize, parentId)); - } - - //! Returns a label id by name. - //! - //! If the named label doesn't exist \ref Globals::kInvalidId is returned. - ASMJIT_API uint32_t labelIdByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept; - - //! Tests whether there are any unresolved label links. - inline bool hasUnresolvedLinks() const noexcept { return _unresolvedLinkCount != 0; } - //! Returns the number of label links, which are unresolved. - inline size_t unresolvedLinkCount() const noexcept { return _unresolvedLinkCount; } - - //! Creates a new label-link used to store information about yet unbound labels. - //! - //! Returns `null` if the allocation failed. - ASMJIT_API LabelLink* newLabelLink(LabelEntry* le, uint32_t sectionId, size_t offset, intptr_t rel) noexcept; - - //! Resolves cross-section links (`LabelLink`) associated with each label that - //! was used as a destination in code of a different section. It's only useful - //! to people that use multiple sections as it will do nothing if the code only - //! contains a single section in which cross-section links are not possible. - ASMJIT_API Error resolveUnresolvedLinks() noexcept; - - //! Binds a label to a given `sectionId` and `offset` (relative to start of the section). - //! - //! This function is generally used by `BaseAssembler::bind()` to do the heavy lifting. - ASMJIT_API Error bindLabel(const Label& label, uint32_t sectionId, uint64_t offset) noexcept; - - //! \} - - //! \name Relocations - //! \{ - - //! Tests whether the code contains relocation entries. - inline bool hasRelocEntries() const noexcept { return !_relocations.empty(); } - //! Returns array of `RelocEntry*` records. - inline const ZoneVector& relocEntries() const noexcept { return _relocations; } - - //! Returns a RelocEntry of the given `id`. - inline RelocEntry* relocEntry(uint32_t id) const noexcept { return _relocations[id]; } - - //! Creates a new relocation entry of type `relocType` and size `valueSize`. - //! - //! Additional fields can be set after the relocation entry was created. - ASMJIT_API Error newRelocEntry(RelocEntry** dst, uint32_t relocType, uint32_t valueSize) noexcept; - - //! \} - - //! \name Utilities - //! \{ - - //! Flattens all sections by recalculating their offsets, starting at 0. - //! - //! \note This should never be called more than once. - ASMJIT_API Error flatten() noexcept; - - //! Returns computed the size of code & data of all sections. - //! - //! \note All sections will be iterated over and the code size returned - //! would represent the minimum code size of all combined sections after - //! applying minimum alignment. Code size may decrease after calling - //! `flatten()` and `relocateToBase()`. - ASMJIT_API size_t codeSize() const noexcept; - - //! Relocates the code to the given `baseAddress`. - //! - //! \param baseAddress Absolute base address where the code will be relocated - //! to. Please note that nothing is copied to such base address, it's just an - //! absolute value used by the relocator to resolve all stored relocations. - //! - //! \note This should never be called more than once. - ASMJIT_API Error relocateToBase(uint64_t baseAddress) noexcept; - - //! Copies a single section into `dst`. - ASMJIT_API Error copySectionData(void* dst, size_t dstSize, uint32_t sectionId, uint32_t copyOptions = 0) noexcept; - - //! Copies all sections into `dst`. - //! - //! This should only be used if the data was flattened and there are no gaps - //! between the sections. The `dstSize` is always checked and the copy will - //! never write anything outside the provided buffer. - ASMJIT_API Error copyFlattenedData(void* dst, size_t dstSize, uint32_t copyOptions = 0) noexcept; - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use 'CodeHolder::init(const Environment& environment, uint64_t baseAddress)' instead") - inline Error init(const CodeInfo& codeInfo) noexcept { return init(codeInfo._environment, codeInfo._baseAddress); } - - ASMJIT_DEPRECATED("Use nevironment() instead") - inline CodeInfo codeInfo() const noexcept { return CodeInfo(_environment, _baseAddress); } - - ASMJIT_DEPRECATED("Use BaseEmitter::encodingOptions() - this function always returns zero") - inline uint32_t emitterOptions() const noexcept { return 0; } - - ASMJIT_DEPRECATED("Use BaseEmitter::addEncodingOptions() - this function does nothing") - inline void addEmitterOptions(uint32_t options) noexcept { DebugUtils::unused(options); } - - ASMJIT_DEPRECATED("Use BaseEmitter::clearEncodingOptions() - this function does nothing") - inline void clearEmitterOptions(uint32_t options) noexcept { DebugUtils::unused(options); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_CODEHOLDER_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/compiler.cpp b/ext/asmjit-master/src/asmjit/core/compiler.cpp deleted file mode 100644 index 6e48253b..00000000 --- a/ext/asmjit-master/src/asmjit/core/compiler.cpp +++ /dev/null @@ -1,645 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_COMPILER - -#include "../core/assembler.h" -#include "../core/compiler.h" -#include "../core/cpuinfo.h" -#include "../core/logger.h" -#include "../core/rapass_p.h" -#include "../core/rastack_p.h" -#include "../core/support.h" -#include "../core/type.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::GlobalConstPoolPass] -// ============================================================================ - -class GlobalConstPoolPass : public Pass { - typedef Pass Base; - ASMJIT_NONCOPYABLE(GlobalConstPoolPass) - - GlobalConstPoolPass() noexcept : Pass("GlobalConstPoolPass") {} - - Error run(Zone* zone, Logger* logger) override { - DebugUtils::unused(zone, logger); - - // Flush the global constant pool. - BaseCompiler* compiler = static_cast(_cb); - if (compiler->_globalConstPool) { - compiler->addAfter(compiler->_globalConstPool, compiler->lastNode()); - compiler->_globalConstPool = nullptr; - } - - return kErrorOk; - } -}; - -// ============================================================================ -// [asmjit::InvokeNode - Arg / Ret] -// ============================================================================ - -bool InvokeNode::_setArg(uint32_t i, const Operand_& op) noexcept { - if ((i & ~kFuncArgHi) >= _funcDetail.argCount()) - return false; - - _args[i] = op; - return true; -} - -bool InvokeNode::_setRet(uint32_t i, const Operand_& op) noexcept { - if (i >= 2) - return false; - - _rets[i] = op; - return true; -} - -// ============================================================================ -// [asmjit::BaseCompiler - Construction / Destruction] -// ============================================================================ - -BaseCompiler::BaseCompiler() noexcept - : BaseBuilder(), - _func(nullptr), - _vRegZone(4096 - Zone::kBlockOverhead), - _vRegArray(), - _localConstPool(nullptr), - _globalConstPool(nullptr) { - - _emitterType = uint8_t(kTypeCompiler); - _validationFlags = uint8_t(InstAPI::kValidationFlagVirtRegs); -} -BaseCompiler::~BaseCompiler() noexcept {} - -// ============================================================================ -// [asmjit::BaseCompiler - Function Management] -// ============================================================================ - -Error BaseCompiler::_newFuncNode(FuncNode** out, const FuncSignature& signature) { - *out = nullptr; - - // Create FuncNode together with all the required surrounding nodes. - FuncNode* funcNode; - ASMJIT_PROPAGATE(_newNodeT(&funcNode)); - ASMJIT_PROPAGATE(_newLabelNode(&funcNode->_exitNode)); - ASMJIT_PROPAGATE(_newNodeT(&funcNode->_end, SentinelNode::kSentinelFuncEnd)); - - // Initialize the function's detail info. - Error err = funcNode->detail().init(signature, environment()); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - // If the Target guarantees greater stack alignment than required by the - // calling convention then override it as we can prevent having to perform - // dynamic stack alignment - uint32_t environmentStackAlignment = _environment.stackAlignment(); - - if (funcNode->_funcDetail._callConv.naturalStackAlignment() < environmentStackAlignment) - funcNode->_funcDetail._callConv.setNaturalStackAlignment(environmentStackAlignment); - - // Initialize the function frame. - err = funcNode->_frame.init(funcNode->_funcDetail); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - // Allocate space for function arguments. - funcNode->_args = nullptr; - if (funcNode->argCount() != 0) { - funcNode->_args = _allocator.allocT(funcNode->argCount() * sizeof(VirtReg*)); - if (ASMJIT_UNLIKELY(!funcNode->_args)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - memset(funcNode->_args, 0, funcNode->argCount() * sizeof(VirtReg*)); - } - - ASMJIT_PROPAGATE(registerLabelNode(funcNode)); - - *out = funcNode; - return kErrorOk; -} - -Error BaseCompiler::_addFuncNode(FuncNode** out, const FuncSignature& signature) { - ASMJIT_PROPAGATE(_newFuncNode(out, signature)); - addFunc(*out); - return kErrorOk; -} - -Error BaseCompiler::_newRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) { - uint32_t opCount = !o1.isNone() ? 2u : !o0.isNone() ? 1u : 0u; - FuncRetNode* node; - - ASMJIT_PROPAGATE(_newNodeT(&node)); - node->setOpCount(opCount); - node->setOp(0, o0); - node->setOp(1, o1); - node->resetOpRange(2, node->opCapacity()); - - *out = node; - return kErrorOk; -} - -Error BaseCompiler::_addRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1) { - ASMJIT_PROPAGATE(_newRetNode(out, o0, o1)); - addNode(*out); - return kErrorOk; -} - -FuncNode* BaseCompiler::addFunc(FuncNode* func) { - ASMJIT_ASSERT(_func == nullptr); - _func = func; - - addNode(func); // Function node. - BaseNode* prev = cursor(); // {CURSOR}. - addNode(func->exitNode()); // Function exit label. - addNode(func->endNode()); // Function end sentinel. - - _setCursor(prev); - return func; -} - -Error BaseCompiler::endFunc() { - FuncNode* func = _func; - - if (ASMJIT_UNLIKELY(!func)) - return reportError(DebugUtils::errored(kErrorInvalidState)); - - // Add the local constant pool at the end of the function (if exists). - if (_localConstPool) { - setCursor(func->endNode()->prev()); - addNode(_localConstPool); - _localConstPool = nullptr; - } - - // Mark as finished. - _func = nullptr; - - SentinelNode* end = func->endNode(); - setCursor(end); - - return kErrorOk; -} - -Error BaseCompiler::setArg(uint32_t argIndex, const BaseReg& r) { - FuncNode* func = _func; - - if (ASMJIT_UNLIKELY(!func)) - return reportError(DebugUtils::errored(kErrorInvalidState)); - - if (ASMJIT_UNLIKELY(!isVirtRegValid(r))) - return reportError(DebugUtils::errored(kErrorInvalidVirtId)); - - VirtReg* vReg = virtRegByReg(r); - func->setArg(argIndex, vReg); - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseCompiler - Function Invocation] -// ============================================================================ - -Error BaseCompiler::_newInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature) { - InvokeNode* node; - ASMJIT_PROPAGATE(_newNodeT(&node, instId, 0u)); - - node->setOpCount(1); - node->setOp(0, o0); - node->resetOpRange(1, node->opCapacity()); - - Error err = node->detail().init(signature, environment()); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - // Skip the allocation if there are no arguments. - uint32_t argCount = signature.argCount(); - if (argCount) { - node->_args = static_cast(_allocator.alloc(argCount * sizeof(Operand))); - if (!node->_args) - reportError(DebugUtils::errored(kErrorOutOfMemory)); - memset(node->_args, 0, argCount * sizeof(Operand)); - } - - *out = node; - return kErrorOk; -} - -Error BaseCompiler::_addInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature) { - ASMJIT_PROPAGATE(_newInvokeNode(out, instId, o0, signature)); - addNode(*out); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseCompiler - Virtual Registers] -// ============================================================================ - -static void BaseCompiler_assignGenericName(BaseCompiler* self, VirtReg* vReg) { - uint32_t index = unsigned(Operand::virtIdToIndex(vReg->_id)); - - char buf[64]; - int size = snprintf(buf, ASMJIT_ARRAY_SIZE(buf), "%%%u", unsigned(index)); - - ASMJIT_ASSERT(size > 0 && size < int(ASMJIT_ARRAY_SIZE(buf))); - vReg->_name.setData(&self->_dataZone, buf, unsigned(size)); -} - -Error BaseCompiler::newVirtReg(VirtReg** out, uint32_t typeId, uint32_t signature, const char* name) { - *out = nullptr; - uint32_t index = _vRegArray.size(); - - if (ASMJIT_UNLIKELY(index >= uint32_t(Operand::kVirtIdCount))) - return reportError(DebugUtils::errored(kErrorTooManyVirtRegs)); - - if (ASMJIT_UNLIKELY(_vRegArray.willGrow(&_allocator) != kErrorOk)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - VirtReg* vReg = _vRegZone.allocZeroedT(); - if (ASMJIT_UNLIKELY(!vReg)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - uint32_t size = Type::sizeOf(typeId); - uint32_t alignment = Support::min(size, 64); - - vReg = new(vReg) VirtReg(Operand::indexToVirtId(index), signature, size, alignment, typeId); - -#ifndef ASMJIT_NO_LOGGING - if (name && name[0] != '\0') - vReg->_name.setData(&_dataZone, name, SIZE_MAX); - else - BaseCompiler_assignGenericName(this, vReg); -#else - DebugUtils::unused(name); -#endif - - _vRegArray.appendUnsafe(vReg); - *out = vReg; - - return kErrorOk; -} - -Error BaseCompiler::_newReg(BaseReg* out, uint32_t typeId, const char* name) { - out->reset(); - - RegInfo regInfo; - Error err = ArchUtils::typeIdToRegInfo(arch(), typeId, &typeId, ®Info); - - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - VirtReg* vReg; - ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regInfo.signature(), name)); - - out->_initReg(regInfo.signature(), vReg->id()); - return kErrorOk; -} - -Error BaseCompiler::_newRegFmt(BaseReg* out, uint32_t typeId, const char* fmt, ...) { - va_list ap; - StringTmp<256> sb; - - va_start(ap, fmt); - sb.appendVFormat(fmt, ap); - va_end(ap); - - return _newReg(out, typeId, sb.data()); -} - -Error BaseCompiler::_newReg(BaseReg* out, const BaseReg& ref, const char* name) { - out->reset(); - - RegInfo regInfo; - uint32_t typeId; - - if (isVirtRegValid(ref)) { - VirtReg* vRef = virtRegByReg(ref); - typeId = vRef->typeId(); - - // NOTE: It's possible to cast one register type to another if it's the - // same register group. However, VirtReg always contains the TypeId that - // was used to create the register. This means that in some cases we may - // end up having different size of `ref` and `vRef`. In such case we - // adjust the TypeId to match the `ref` register type instead of the - // original register type, which should be the expected behavior. - uint32_t typeSize = Type::sizeOf(typeId); - uint32_t refSize = ref.size(); - - if (typeSize != refSize) { - if (Type::isInt(typeId)) { - // GP register - change TypeId to match `ref`, but keep sign of `vRef`. - switch (refSize) { - case 1: typeId = Type::kIdI8 | (typeId & 1); break; - case 2: typeId = Type::kIdI16 | (typeId & 1); break; - case 4: typeId = Type::kIdI32 | (typeId & 1); break; - case 8: typeId = Type::kIdI64 | (typeId & 1); break; - default: typeId = Type::kIdVoid; break; - } - } - else if (Type::isMmx(typeId)) { - // MMX register - always use 64-bit. - typeId = Type::kIdMmx64; - } - else if (Type::isMask(typeId)) { - // Mask register - change TypeId to match `ref` size. - switch (refSize) { - case 1: typeId = Type::kIdMask8; break; - case 2: typeId = Type::kIdMask16; break; - case 4: typeId = Type::kIdMask32; break; - case 8: typeId = Type::kIdMask64; break; - default: typeId = Type::kIdVoid; break; - } - } - else { - // VEC register - change TypeId to match `ref` size, keep vector metadata. - uint32_t elementTypeId = Type::baseOf(typeId); - - switch (refSize) { - case 16: typeId = Type::_kIdVec128Start + (elementTypeId - Type::kIdI8); break; - case 32: typeId = Type::_kIdVec256Start + (elementTypeId - Type::kIdI8); break; - case 64: typeId = Type::_kIdVec512Start + (elementTypeId - Type::kIdI8); break; - default: typeId = Type::kIdVoid; break; - } - } - - if (typeId == Type::kIdVoid) - return reportError(DebugUtils::errored(kErrorInvalidState)); - } - } - else { - typeId = ref.type(); - } - - Error err = ArchUtils::typeIdToRegInfo(arch(), typeId, &typeId, ®Info); - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - VirtReg* vReg; - ASMJIT_PROPAGATE(newVirtReg(&vReg, typeId, regInfo.signature(), name)); - - out->_initReg(regInfo.signature(), vReg->id()); - return kErrorOk; -} - -Error BaseCompiler::_newRegFmt(BaseReg* out, const BaseReg& ref, const char* fmt, ...) { - va_list ap; - StringTmp<256> sb; - - va_start(ap, fmt); - sb.appendVFormat(fmt, ap); - va_end(ap); - - return _newReg(out, ref, sb.data()); -} - -Error BaseCompiler::_newStack(BaseMem* out, uint32_t size, uint32_t alignment, const char* name) { - out->reset(); - - if (size == 0) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - if (alignment == 0) - alignment = 1; - - if (!Support::isPowerOf2(alignment)) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - if (alignment > 64) - alignment = 64; - - VirtReg* vReg; - ASMJIT_PROPAGATE(newVirtReg(&vReg, 0, 0, name)); - - vReg->_virtSize = size; - vReg->_isStack = true; - vReg->_alignment = uint8_t(alignment); - - // Set the memory operand to GPD/GPQ and its id to VirtReg. - *out = BaseMem(BaseMem::Decomposed { _gpRegInfo.type(), vReg->id(), BaseReg::kTypeNone, 0, 0, 0, BaseMem::kSignatureMemRegHomeFlag }); - return kErrorOk; -} - -Error BaseCompiler::setStackSize(uint32_t virtId, uint32_t newSize, uint32_t newAlignment) { - if (!isVirtIdValid(virtId)) - return DebugUtils::errored(kErrorInvalidVirtId); - - if (newAlignment && !Support::isPowerOf2(newAlignment)) - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - if (newAlignment > 64) - newAlignment = 64; - - VirtReg* vReg = virtRegById(virtId); - if (newSize) - vReg->_virtSize = newSize; - - if (newAlignment) - vReg->_alignment = uint8_t(newAlignment); - - // This is required if the RAPass is already running. There is a chance that - // a stack-slot has been already allocated and in that case it has to be - // updated as well, otherwise we would allocate wrong amount of memory. - RAWorkReg* workReg = vReg->_workReg; - if (workReg && workReg->_stackSlot) { - workReg->_stackSlot->_size = vReg->_virtSize; - workReg->_stackSlot->_alignment = vReg->_alignment; - } - - return kErrorOk; -} - -Error BaseCompiler::_newConst(BaseMem* out, uint32_t scope, const void* data, size_t size) { - out->reset(); - ConstPoolNode** pPool; - - if (scope == ConstPool::kScopeLocal) - pPool = &_localConstPool; - else if (scope == ConstPool::kScopeGlobal) - pPool = &_globalConstPool; - else - return reportError(DebugUtils::errored(kErrorInvalidArgument)); - - if (!*pPool) - ASMJIT_PROPAGATE(_newConstPoolNode(pPool)); - - ConstPoolNode* pool = *pPool; - size_t off; - Error err = pool->add(data, size, off); - - if (ASMJIT_UNLIKELY(err)) - return reportError(err); - - *out = BaseMem(BaseMem::Decomposed { - Label::kLabelTag, // Base type. - pool->labelId(), // Base id. - 0, // Index type. - 0, // Index id. - int32_t(off), // Offset. - uint32_t(size), // Size. - 0 // Flags. - }); - - return kErrorOk; -} - -void BaseCompiler::rename(const BaseReg& reg, const char* fmt, ...) { - if (!reg.isVirtReg()) return; - - VirtReg* vReg = virtRegById(reg.id()); - if (!vReg) return; - - if (fmt && fmt[0] != '\0') { - char buf[128]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf), fmt, ap); - va_end(ap); - - vReg->_name.setData(&_dataZone, buf, SIZE_MAX); - } - else { - BaseCompiler_assignGenericName(this, vReg); - } -} - -// ============================================================================ -// [asmjit::BaseCompiler - Jump Annotations] -// ============================================================================ - -Error BaseCompiler::newJumpNode(JumpNode** out, uint32_t instId, uint32_t instOptions, const Operand_& o0, JumpAnnotation* annotation) { - JumpNode* node = _allocator.allocT(); - uint32_t opCount = 1; - - *out = node; - if (ASMJIT_UNLIKELY(!node)) - return reportError(DebugUtils::errored(kErrorOutOfMemory)); - - node = new(node) JumpNode(this, instId, instOptions, opCount, annotation); - node->setOp(0, o0); - node->resetOpRange(opCount, JumpNode::kBaseOpCapacity); - - return kErrorOk; -} - -Error BaseCompiler::emitAnnotatedJump(uint32_t instId, const Operand_& o0, JumpAnnotation* annotation) { - uint32_t options = instOptions() | forcedInstOptions(); - RegOnly extra = extraReg(); - const char* comment = inlineComment(); - - resetInstOptions(); - resetInlineComment(); - resetExtraReg(); - - JumpNode* node; - ASMJIT_PROPAGATE(newJumpNode(&node, instId, options, o0, annotation)); - - node->setExtraReg(extra); - if (comment) - node->setInlineComment(static_cast(_dataZone.dup(comment, strlen(comment), true))); - - addNode(node); - return kErrorOk; -} - -JumpAnnotation* BaseCompiler::newJumpAnnotation() { - if (_jumpAnnotations.grow(&_allocator, 1) != kErrorOk) { - reportError(DebugUtils::errored(kErrorOutOfMemory)); - return nullptr; - } - - uint32_t id = _jumpAnnotations.size(); - JumpAnnotation* jumpAnnotation = _allocator.newT(this, id); - - if (!jumpAnnotation) { - reportError(DebugUtils::errored(kErrorOutOfMemory)); - return nullptr; - } - - _jumpAnnotations.appendUnsafe(jumpAnnotation); - return jumpAnnotation; -} - -// ============================================================================ -// [asmjit::BaseCompiler - Events] -// ============================================================================ - -Error BaseCompiler::onAttach(CodeHolder* code) noexcept { - ASMJIT_PROPAGATE(Base::onAttach(code)); - - Error err = addPassT(); - if (ASMJIT_UNLIKELY(err)) { - onDetach(code); - return err; - } - - return kErrorOk; -} - -Error BaseCompiler::onDetach(CodeHolder* code) noexcept { - _func = nullptr; - _localConstPool = nullptr; - _globalConstPool = nullptr; - - _vRegArray.reset(); - _vRegZone.reset(); - - return Base::onDetach(code); -} - -// ============================================================================ -// [asmjit::FuncPass - Construction / Destruction] -// ============================================================================ - -FuncPass::FuncPass(const char* name) noexcept - : Pass(name) {} - -// ============================================================================ -// [asmjit::FuncPass - Run] -// ============================================================================ - -Error FuncPass::run(Zone* zone, Logger* logger) { - BaseNode* node = cb()->firstNode(); - if (!node) return kErrorOk; - - do { - if (node->type() == BaseNode::kNodeFunc) { - FuncNode* func = node->as(); - node = func->endNode(); - ASMJIT_PROPAGATE(runOnFunction(zone, logger, func)); - } - - // Find a function by skipping all nodes that are not `kNodeFunc`. - do { - node = node->next(); - } while (node && node->type() != BaseNode::kNodeFunc); - } while (node); - - return kErrorOk; -} - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_COMPILER diff --git a/ext/asmjit-master/src/asmjit/core/compiler.h b/ext/asmjit-master/src/asmjit/core/compiler.h deleted file mode 100644 index 71f89ec7..00000000 --- a/ext/asmjit-master/src/asmjit/core/compiler.h +++ /dev/null @@ -1,816 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_COMPILER_H_INCLUDED -#define ASMJIT_CORE_COMPILER_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_COMPILER - -#include "../core/assembler.h" -#include "../core/builder.h" -#include "../core/constpool.h" -#include "../core/func.h" -#include "../core/inst.h" -#include "../core/operand.h" -#include "../core/support.h" -#include "../core/zone.h" -#include "../core/zonevector.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -struct RATiedReg; -class RAWorkReg; - -class JumpAnnotation; - -class JumpNode; -class FuncNode; -class FuncRetNode; -class InvokeNode; - -//! \addtogroup asmjit_compiler -//! \{ - -// ============================================================================ -// [asmjit::VirtReg] -// ============================================================================ - -//! Virtual register data, managed by \ref BaseCompiler. -class VirtReg { -public: - ASMJIT_NONCOPYABLE(VirtReg) - - //! Virtual register id. - uint32_t _id; - //! Virtual register info (signature). - RegInfo _info; - //! Virtual register size (can be smaller than `regInfo._size`). - uint32_t _virtSize; - //! Virtual register alignment (for spilling). - uint8_t _alignment; - //! Type-id. - uint8_t _typeId; - //! Virtual register weight for alloc/spill decisions. - uint8_t _weight; - //! True if this is a fixed register, never reallocated. - uint8_t _isFixed : 1; - //! True if the virtual register is only used as a stack (never accessed as register). - uint8_t _isStack : 1; - uint8_t _reserved : 6; - - //! Virtual register name (user provided or automatically generated). - ZoneString<16> _name; - - // ------------------------------------------------------------------------- - // The following members are used exclusively by RAPass. They are initialized - // when the VirtReg is created to NULL pointers and then changed during RAPass - // execution. RAPass sets them back to NULL before it returns. - // ------------------------------------------------------------------------- - - //! Reference to `RAWorkReg`, used during register allocation. - RAWorkReg* _workReg; - - //! \name Construction & Destruction - //! \{ - - inline VirtReg(uint32_t id, uint32_t signature, uint32_t virtSize, uint32_t alignment, uint32_t typeId) noexcept - : _id(id), - _virtSize(virtSize), - _alignment(uint8_t(alignment)), - _typeId(uint8_t(typeId)), - _weight(1), - _isFixed(false), - _isStack(false), - _reserved(0), - _name(), - _workReg(nullptr) { _info._signature = signature; } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the virtual register id. - inline uint32_t id() const noexcept { return _id; } - - //! Returns the virtual register name. - inline const char* name() const noexcept { return _name.data(); } - //! Returns the size of the virtual register name. - inline uint32_t nameSize() const noexcept { return _name.size(); } - - //! Returns a register information that wraps the register signature. - inline const RegInfo& info() const noexcept { return _info; } - //! Returns a virtual register type (maps to the physical register type as well). - inline uint32_t type() const noexcept { return _info.type(); } - //! Returns a virtual register group (maps to the physical register group as well). - inline uint32_t group() const noexcept { return _info.group(); } - - //! Returns a real size of the register this virtual register maps to. - //! - //! For example if this is a 128-bit SIMD register used for a scalar single - //! precision floating point value then its virtSize would be 4, however, the - //! `regSize` would still say 16 (128-bits), because it's the smallest size - //! of that register type. - inline uint32_t regSize() const noexcept { return _info.size(); } - - //! Returns a register signature of this virtual register. - inline uint32_t signature() const noexcept { return _info.signature(); } - - //! Returns the virtual register size. - //! - //! The virtual register size describes how many bytes the virtual register - //! needs to store its content. It can be smaller than the physical register - //! size, see `regSize()`. - inline uint32_t virtSize() const noexcept { return _virtSize; } - - //! Returns the virtual register alignment. - inline uint32_t alignment() const noexcept { return _alignment; } - - //! Returns the virtual register type id, see `Type::Id`. - inline uint32_t typeId() const noexcept { return _typeId; } - - //! Returns the virtual register weight - the register allocator can use it - //! as explicit hint for alloc/spill decisions. - inline uint32_t weight() const noexcept { return _weight; } - //! Sets the virtual register weight (0 to 255) - the register allocator can - //! use it as explicit hint for alloc/spill decisions and initial bin-packing. - inline void setWeight(uint32_t weight) noexcept { _weight = uint8_t(weight); } - - //! Returns whether the virtual register is always allocated to a fixed - //! physical register (and never reallocated). - //! - //! \note This is only used for special purposes and it's mostly internal. - inline bool isFixed() const noexcept { return bool(_isFixed); } - - //! Returns whether the virtual register is indeed a stack that only uses - //! the virtual register id for making it accessible. - //! - //! \note It's an error if a stack is accessed as a register. - inline bool isStack() const noexcept { return bool(_isStack); } - - inline bool hasWorkReg() const noexcept { return _workReg != nullptr; } - inline RAWorkReg* workReg() const noexcept { return _workReg; } - inline void setWorkReg(RAWorkReg* workReg) noexcept { _workReg = workReg; } - inline void resetWorkReg() noexcept { _workReg = nullptr; } - - //! \} -}; - -// ============================================================================ -// [asmjit::BaseCompiler] -// ============================================================================ - -//! Code emitter that uses virtual registers and performs register allocation. -//! -//! Compiler is a high-level code-generation tool that provides register -//! allocation and automatic handling of function calling conventions. It was -//! primarily designed for merging multiple parts of code into a function -//! without worrying about registers and function calling conventions. -//! -//! BaseCompiler can be used, with a minimum effort, to handle 32-bit and -//! 64-bit code generation within a single code base. -//! -//! BaseCompiler is based on BaseBuilder and contains all the features it -//! provides. It means that the code it stores can be modified (removed, added, -//! injected) and analyzed. When the code is finalized the compiler can emit -//! the code into an Assembler to translate the abstract representation into a -//! machine code. -//! -//! Check out architecture specific compilers for more details and examples: -//! -//! - \ref x86::Compiler - X86/X64 compiler implementation. -class ASMJIT_VIRTAPI BaseCompiler : public BaseBuilder { -public: - ASMJIT_NONCOPYABLE(BaseCompiler) - typedef BaseBuilder Base; - - //! Current function. - FuncNode* _func; - //! Allocates `VirtReg` objects. - Zone _vRegZone; - //! Stores array of `VirtReg` pointers. - ZoneVector _vRegArray; - //! Stores jump annotations. - ZoneVector _jumpAnnotations; - - //! Local constant pool, flushed at the end of each function. - ConstPoolNode* _localConstPool; - //! Global constant pool, flushed by `finalize()`. - ConstPoolNode* _globalConstPool; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `BaseCompiler` instance. - ASMJIT_API BaseCompiler() noexcept; - //! Destroys the `BaseCompiler` instance. - ASMJIT_API virtual ~BaseCompiler() noexcept; - - //! \} - - //! \name Function Management - //! \{ - - //! Returns the current function. - inline FuncNode* func() const noexcept { return _func; } - - //! Creates a new \ref FuncNode. - ASMJIT_API Error _newFuncNode(FuncNode** out, const FuncSignature& signature); - //! Creates a new \ref FuncNode adds it to the compiler. - ASMJIT_API Error _addFuncNode(FuncNode** out, const FuncSignature& signature); - - //! Creates a new \ref FuncRetNode. - ASMJIT_API Error _newRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1); - //! Creates a new \ref FuncRetNode and adds it to the compiler. - ASMJIT_API Error _addRetNode(FuncRetNode** out, const Operand_& o0, const Operand_& o1); - - //! Creates a new \ref FuncNode with the given `signature` and returns it. - inline FuncNode* newFunc(const FuncSignature& signature) { - FuncNode* node; - _newFuncNode(&node, signature); - return node; - } - - //! Creates a new \ref FuncNode with the given `signature`, adds it to the - //! compiler by using the \ref addFunc(FuncNode*) overload, and returns it. - inline FuncNode* addFunc(const FuncSignature& signature) { - FuncNode* node; - _addFuncNode(&node, signature); - return node; - } - - //! Adds a function `node` to the instruction stream. - ASMJIT_API FuncNode* addFunc(FuncNode* func); - //! Emits a sentinel that marks the end of the current function. - ASMJIT_API Error endFunc(); - - //! Sets a function argument at `argIndex` to `reg`. - ASMJIT_API Error setArg(uint32_t argIndex, const BaseReg& reg); - - inline FuncRetNode* newRet(const Operand_& o0, const Operand_& o1) { - FuncRetNode* node; - _newRetNode(&node, o0, o1); - return node; - } - - inline FuncRetNode* addRet(const Operand_& o0, const Operand_& o1) { - FuncRetNode* node; - _addRetNode(&node, o0, o1); - return node; - } - - //! \} - - //! \name Function Invocation - //! \{ - - //! Creates a new \ref InvokeNode. - ASMJIT_API Error _newInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature); - //! Creates a new \ref InvokeNode and adds it to Compiler. - ASMJIT_API Error _addInvokeNode(InvokeNode** out, uint32_t instId, const Operand_& o0, const FuncSignature& signature); - - //! Creates a new `InvokeNode`. - inline InvokeNode* newCall(uint32_t instId, const Operand_& o0, const FuncSignature& signature) { - InvokeNode* node; - _newInvokeNode(&node, instId, o0, signature); - return node; - } - - //! Adds a new `InvokeNode`. - inline InvokeNode* addCall(uint32_t instId, const Operand_& o0, const FuncSignature& signature) { - InvokeNode* node; - _addInvokeNode(&node, instId, o0, signature); - return node; - } - - //! \} - - //! \name Virtual Registers - //! \{ - - //! Creates a new virtual register representing the given `typeId` and `signature`. - //! - //! \note This function is public, but it's not generally recommended to be used - //! by AsmJit users, use architecture-specific `newReg()` functionality instead - //! or functions like \ref _newReg() and \ref _newRegFmt(). - ASMJIT_API Error newVirtReg(VirtReg** out, uint32_t typeId, uint32_t signature, const char* name); - - //! Creates a new virtual register of the given `typeId` and stores it to `out` operand. - ASMJIT_API Error _newReg(BaseReg* out, uint32_t typeId, const char* name = nullptr); - - //! Creates a new virtual register of the given `typeId` and stores it to `out` operand. - //! - //! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments. - ASMJIT_API Error _newRegFmt(BaseReg* out, uint32_t typeId, const char* fmt, ...); - - //! Creates a new virtual register compatible with the provided reference register `ref`. - ASMJIT_API Error _newReg(BaseReg* out, const BaseReg& ref, const char* name = nullptr); - - //! Creates a new virtual register compatible with the provided reference register `ref`. - //! - //! \note This version accepts a snprintf() format `fmt` followed by a variadic arguments. - ASMJIT_API Error _newRegFmt(BaseReg* out, const BaseReg& ref, const char* fmt, ...); - - //! Tests whether the given `id` is a valid virtual register id. - inline bool isVirtIdValid(uint32_t id) const noexcept { - uint32_t index = Operand::virtIdToIndex(id); - return index < _vRegArray.size(); - } - //! Tests whether the given `reg` is a virtual register having a valid id. - inline bool isVirtRegValid(const BaseReg& reg) const noexcept { - return isVirtIdValid(reg.id()); - } - - //! Returns \ref VirtReg associated with the given `id`. - inline VirtReg* virtRegById(uint32_t id) const noexcept { - ASMJIT_ASSERT(isVirtIdValid(id)); - return _vRegArray[Operand::virtIdToIndex(id)]; - } - - //! Returns \ref VirtReg associated with the given `reg`. - inline VirtReg* virtRegByReg(const BaseReg& reg) const noexcept { return virtRegById(reg.id()); } - - //! Returns \ref VirtReg associated with the given virtual register `index`. - //! - //! \note This is not the same as virtual register id. The conversion between - //! id and its index is implemented by \ref Operand_::virtIdToIndex() and \ref - //! Operand_::indexToVirtId() functions. - inline VirtReg* virtRegByIndex(uint32_t index) const noexcept { return _vRegArray[index]; } - - //! Returns an array of all virtual registers managed by the Compiler. - inline const ZoneVector& virtRegs() const noexcept { return _vRegArray; } - - //! \name Stack - //! \{ - - //! Creates a new stack of the given `size` and `alignment` and stores it to `out`. - //! - //! \note `name` can be used to give the stack a name, for debugging purposes. - ASMJIT_API Error _newStack(BaseMem* out, uint32_t size, uint32_t alignment, const char* name = nullptr); - - //! Updates the stack size of a stack created by `_newStack()` by its `virtId`. - ASMJIT_API Error setStackSize(uint32_t virtId, uint32_t newSize, uint32_t newAlignment = 0); - - //! Updates the stack size of a stack created by `_newStack()`. - inline Error setStackSize(const BaseMem& mem, uint32_t newSize, uint32_t newAlignment = 0) { - return setStackSize(mem.id(), newSize, newAlignment); - } - - //! \} - - //! \name Constants - //! \{ - - //! Creates a new constant of the given `scope` (see \ref ConstPool::Scope). - //! - //! This function adds a constant of the given `size` to the built-in \ref - //! ConstPool and stores the reference to that constant to the `out` operand. - ASMJIT_API Error _newConst(BaseMem* out, uint32_t scope, const void* data, size_t size); - - //! \} - - //! \name Miscellaneous - //! \{ - - //! Rename the given virtual register `reg` to a formatted string `fmt`. - ASMJIT_API void rename(const BaseReg& reg, const char* fmt, ...); - - //! \} - - //! \name Jump Annotations - //! \{ - - inline const ZoneVector& jumpAnnotations() const noexcept { - return _jumpAnnotations; - } - - ASMJIT_API Error newJumpNode(JumpNode** out, uint32_t instId, uint32_t instOptions, const Operand_& o0, JumpAnnotation* annotation); - ASMJIT_API Error emitAnnotatedJump(uint32_t instId, const Operand_& o0, JumpAnnotation* annotation); - - //! Returns a new `JumpAnnotation` instance, which can be used to aggregate - //! possible targets of a jump where the target is not a label, for example - //! to implement jump tables. - ASMJIT_API JumpAnnotation* newJumpAnnotation(); - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("alloc() has no effect, it will be removed in the future") - inline void alloc(BaseReg&) {} - ASMJIT_DEPRECATED("spill() has no effect, it will be removed in the future") - inline void spill(BaseReg&) {} -#endif // !ASMJIT_NO_DEPRECATED - - //! \name Events - //! \{ - - ASMJIT_API Error onAttach(CodeHolder* code) noexcept override; - ASMJIT_API Error onDetach(CodeHolder* code) noexcept override; - - //! \} -}; - -// ============================================================================ -// [asmjit::JumpAnnotation] -// ============================================================================ - -//! Jump annotation used to annotate jumps. -//! -//! \ref BaseCompiler allows to emit jumps where the target is either register -//! or memory operand. Such jumps cannot be trivially inspected, so instead of -//! doing heuristics AsmJit allows to annotate such jumps with possible targets. -//! Register allocator then use the annotation to construct control-flow, which -//! is then used by liveness analysis and other tools to prepare ground for -//! register allocation. -class JumpAnnotation { -public: - ASMJIT_NONCOPYABLE(JumpAnnotation) - - //! Compiler that owns this JumpAnnotation. - BaseCompiler* _compiler; - //! Annotation identifier. - uint32_t _annotationId; - //! Vector of label identifiers, see \ref labelIds(). - ZoneVector _labelIds; - - inline JumpAnnotation(BaseCompiler* compiler, uint32_t annotationId) noexcept - : _compiler(compiler), - _annotationId(annotationId) {} - - //! Returns the compiler that owns this JumpAnnotation. - inline BaseCompiler* compiler() const noexcept { return _compiler; } - //! Returns the annotation id. - inline uint32_t annotationId() const noexcept { return _annotationId; } - //! Returns a vector of label identifiers that lists all targets of the jump. - const ZoneVector& labelIds() const noexcept { return _labelIds; } - - //! Tests whether the given `label` is a target of this JumpAnnotation. - inline bool hasLabel(const Label& label) const noexcept { return hasLabelId(label.id()); } - //! Tests whether the given `labelId` is a target of this JumpAnnotation. - inline bool hasLabelId(uint32_t labelId) const noexcept { return _labelIds.contains(labelId); } - - //! Adds the `label` to the list of targets of this JumpAnnotation. - inline Error addLabel(const Label& label) noexcept { return addLabelId(label.id()); } - //! Adds the `labelId` to the list of targets of this JumpAnnotation. - inline Error addLabelId(uint32_t labelId) noexcept { return _labelIds.append(&_compiler->_allocator, labelId); } -}; - -// ============================================================================ -// [asmjit::JumpNode] -// ============================================================================ - -//! Jump instruction with \ref JumpAnnotation. -//! -//! \note This node should be only used to represent jump where the jump target -//! cannot be deduced by examining instruction operands. For example if the jump -//! target is register or memory location. This pattern is often used to perform -//! indirect jumps that use jump table, e.g. to implement `switch{}` statement. -class JumpNode : public InstNode { -public: - ASMJIT_NONCOPYABLE(JumpNode) - - JumpAnnotation* _annotation; - - //! \name Construction & Destruction - //! \{ - - ASMJIT_INLINE JumpNode(BaseCompiler* cc, uint32_t instId, uint32_t options, uint32_t opCount, JumpAnnotation* annotation) noexcept - : InstNode(cc, instId, options, opCount, kBaseOpCapacity), - _annotation(annotation) { - setType(kNodeJump); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether this JumpNode has associated a \ref JumpAnnotation. - inline bool hasAnnotation() const noexcept { return _annotation != nullptr; } - //! Returns the \ref JumpAnnotation associated with this jump, or `nullptr`. - inline JumpAnnotation* annotation() const noexcept { return _annotation; } - //! Sets the \ref JumpAnnotation associated with this jump to `annotation`. - inline void setAnnotation(JumpAnnotation* annotation) noexcept { _annotation = annotation; } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncNode] -// ============================================================================ - -//! Function node represents a function used by \ref BaseCompiler. -//! -//! A function is composed of the following: -//! -//! - Function entry, \ref FuncNode acts as a label, so the entry is implicit. -//! To get the entry, simply use \ref FuncNode::label(), which is the same -//! as \ref LabelNode::label(). -//! -//! - Function exit, which is represented by \ref FuncNode::exitNode(). A -//! helper function \ref FuncNode::exitLabel() exists and returns an exit -//! label instead of node. -//! -//! - Function \ref FuncNode::endNode() sentinel. This node marks the end of -//! a function - there should be no code that belongs to the function after -//! this node, but the Compiler doesn't enforce that at the moment. -//! -//! - Function detail, see \ref FuncNode::detail(). -//! -//! - Function frame, see \ref FuncNode::frame(). -//! -//! - Function arguments mapped to virtual registers, see \ref FuncNode::args(). -//! -//! In a node list, the function and its body looks like the following: -//! -//! \code{.unparsed} -//! [...] - Anything before the function. -//! -//! [FuncNode] - Entry point of the function, acts as a label as well. -//! - Prolog inserted by the register allocator. -//! {...} - Function body - user code basically. -//! [ExitLabel] - Exit label -//! - Epilog inserted by the register allocator. -//! - Return inserted by the register allocator. -//! {...} - Can contain data or user code (error handling, special cases, ...). -//! [FuncEnd] - End sentinel -//! -//! [...] - Anything after the function. -//! \endcode -//! -//! When a function is added to the compiler by \ref BaseCompiler::addFunc() it -//! actually inserts 3 nodes (FuncNode, ExitLabel, and FuncEnd) and sets the -//! current cursor to be FuncNode. When \ref BaseCompiler::endFunc() is called -//! the cursor is set to FuncEnd. This guarantees that user can use ExitLabel -//! as a marker after additional code or data can be placed, and it's a common -//! practice. -class FuncNode : public LabelNode { -public: - ASMJIT_NONCOPYABLE(FuncNode) - - //! Function detail. - FuncDetail _funcDetail; - //! Function frame. - FuncFrame _frame; - //! Function exit label. - LabelNode* _exitNode; - //! Function end (sentinel). - SentinelNode* _end; - //! Arguments array as `VirtReg`. - VirtReg** _args; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `FuncNode` instance. - //! - //! Always use `BaseCompiler::addFunc()` to create `FuncNode`. - ASMJIT_INLINE FuncNode(BaseBuilder* cb) noexcept - : LabelNode(cb), - _funcDetail(), - _frame(), - _exitNode(nullptr), - _end(nullptr), - _args(nullptr) { - setType(kNodeFunc); - } - - //! \} - - //! \{ - //! \name Accessors - - //! Returns function exit `LabelNode`. - inline LabelNode* exitNode() const noexcept { return _exitNode; } - //! Returns function exit label. - inline Label exitLabel() const noexcept { return _exitNode->label(); } - - //! Returns "End of Func" sentinel. - inline SentinelNode* endNode() const noexcept { return _end; } - - //! Returns function declaration. - inline FuncDetail& detail() noexcept { return _funcDetail; } - //! Returns function declaration. - inline const FuncDetail& detail() const noexcept { return _funcDetail; } - - //! Returns function frame. - inline FuncFrame& frame() noexcept { return _frame; } - //! Returns function frame. - inline const FuncFrame& frame() const noexcept { return _frame; } - - //! Returns arguments count. - inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); } - //! Returns returns count. - inline uint32_t retCount() const noexcept { return _funcDetail.retCount(); } - - //! Returns arguments list. - inline VirtReg** args() const noexcept { return _args; } - - //! Returns argument at `i`. - inline VirtReg* arg(uint32_t i) const noexcept { - ASMJIT_ASSERT(i < argCount()); - return _args[i]; - } - - //! Sets argument at `i`. - inline void setArg(uint32_t i, VirtReg* vReg) noexcept { - ASMJIT_ASSERT(i < argCount()); - _args[i] = vReg; - } - - //! Resets argument at `i`. - inline void resetArg(uint32_t i) noexcept { - ASMJIT_ASSERT(i < argCount()); - _args[i] = nullptr; - } - - //! Returns function attributes. - inline uint32_t attributes() const noexcept { return _frame.attributes(); } - //! Adds `attrs` to the function attributes. - inline void addAttributes(uint32_t attrs) noexcept { _frame.addAttributes(attrs); } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncRetNode] -// ============================================================================ - -//! Function return, used by \ref BaseCompiler. -class FuncRetNode : public InstNode { -public: - ASMJIT_NONCOPYABLE(FuncRetNode) - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `FuncRetNode` instance. - inline FuncRetNode(BaseBuilder* cb) noexcept : InstNode(cb, BaseInst::kIdAbstract, 0, 0) { - _any._nodeType = kNodeFuncRet; - } - - //! \} -}; - -// ============================================================================ -// [asmjit::InvokeNode] -// ============================================================================ - -//! Function invocation, used by \ref BaseCompiler. -class InvokeNode : public InstNode { -public: - ASMJIT_NONCOPYABLE(InvokeNode) - - //! Function detail. - FuncDetail _funcDetail; - //! Returns. - Operand_ _rets[2]; - //! Arguments. - Operand_* _args; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `InvokeNode` instance. - inline InvokeNode(BaseBuilder* cb, uint32_t instId, uint32_t options) noexcept - : InstNode(cb, instId, options, kBaseOpCapacity), - _funcDetail(), - _args(nullptr) { - setType(kNodeInvoke); - _resetOps(); - _rets[0].reset(); - _rets[1].reset(); - addFlags(kFlagIsRemovable); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets the function signature. - inline Error init(const FuncSignature& signature, const Environment& environment) noexcept { - return _funcDetail.init(signature, environment); - } - - //! Returns the function detail. - inline FuncDetail& detail() noexcept { return _funcDetail; } - //! Returns the function detail. - inline const FuncDetail& detail() const noexcept { return _funcDetail; } - - //! Returns the target operand. - inline Operand& target() noexcept { return _opArray[0].as(); } - //! \overload - inline const Operand& target() const noexcept { return _opArray[0].as(); } - - //! Returns the number of function arguments. - inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); } - //! Returns the number of function return values. - inline uint32_t retCount() const noexcept { return _funcDetail.retCount(); } - - //! Returns the return value at `i`. - inline Operand& ret(uint32_t i = 0) noexcept { - ASMJIT_ASSERT(i < 2); - return _rets[i].as(); - } - //! \overload - inline const Operand& ret(uint32_t i = 0) const noexcept { - ASMJIT_ASSERT(i < 2); - return _rets[i].as(); - } - - //! Returns the function argument at `i`. - inline Operand& arg(uint32_t i) noexcept { - ASMJIT_ASSERT(i < kFuncArgCountLoHi); - return _args[i].as(); - } - //! \overload - inline const Operand& arg(uint32_t i) const noexcept { - ASMJIT_ASSERT(i < kFuncArgCountLoHi); - return _args[i].as(); - } - - //! Sets the function argument at `i` to `op`. - ASMJIT_API bool _setArg(uint32_t i, const Operand_& op) noexcept; - //! Sets the function return value at `i` to `op`. - ASMJIT_API bool _setRet(uint32_t i, const Operand_& op) noexcept; - - //! Sets the function argument at `i` to `reg`. - inline bool setArg(uint32_t i, const BaseReg& reg) noexcept { return _setArg(i, reg); } - //! Sets the function argument at `i` to `imm`. - inline bool setArg(uint32_t i, const Imm& imm) noexcept { return _setArg(i, imm); } - - //! Sets the function return value at `i` to `var`. - inline bool setRet(uint32_t i, const BaseReg& reg) noexcept { return _setRet(i, reg); } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncPass] -// ============================================================================ - -//! Function pass extends \ref Pass with \ref FuncPass::runOnFunction(). -class ASMJIT_VIRTAPI FuncPass : public Pass { -public: - ASMJIT_NONCOPYABLE(FuncPass) - typedef Pass Base; - - //! \name Construction & Destruction - //! \{ - - ASMJIT_API FuncPass(const char* name) noexcept; - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the associated `BaseCompiler`. - inline BaseCompiler* cc() const noexcept { return static_cast(_cb); } - - //! \} - - //! \name Run - //! \{ - - //! Calls `runOnFunction()` on each `FuncNode` node found. - ASMJIT_API Error run(Zone* zone, Logger* logger) override; - - //! Called once per `FuncNode`. - virtual Error runOnFunction(Zone* zone, Logger* logger, FuncNode* func) = 0; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_COMPILER -#endif // ASMJIT_CORE_COMPILER_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/constpool.cpp b/ext/asmjit-master/src/asmjit/core/constpool.cpp deleted file mode 100644 index 4db68e2e..00000000 --- a/ext/asmjit-master/src/asmjit/core/constpool.cpp +++ /dev/null @@ -1,375 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/constpool.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::ConstPool - Construction / Destruction] -// ============================================================================ - -ConstPool::ConstPool(Zone* zone) noexcept { reset(zone); } -ConstPool::~ConstPool() noexcept {} - -// ============================================================================ -// [asmjit::ConstPool - Reset] -// ============================================================================ - -void ConstPool::reset(Zone* zone) noexcept { - _zone = zone; - - size_t dataSize = 1; - for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_tree); i++) { - _tree[i].reset(); - _tree[i].setDataSize(dataSize); - _gaps[i] = nullptr; - dataSize <<= 1; - } - - _gapPool = nullptr; - _size = 0; - _alignment = 0; -} - -// ============================================================================ -// [asmjit::ConstPool - Ops] -// ============================================================================ - -static ASMJIT_INLINE ConstPool::Gap* ConstPool_allocGap(ConstPool* self) noexcept { - ConstPool::Gap* gap = self->_gapPool; - if (!gap) - return self->_zone->allocT(); - - self->_gapPool = gap->_next; - return gap; -} - -static ASMJIT_INLINE void ConstPool_freeGap(ConstPool* self, ConstPool::Gap* gap) noexcept { - gap->_next = self->_gapPool; - self->_gapPool = gap; -} - -static void ConstPool_addGap(ConstPool* self, size_t offset, size_t size) noexcept { - ASMJIT_ASSERT(size > 0); - - while (size > 0) { - size_t gapIndex; - size_t gapSize; - - if (size >= 16 && Support::isAligned(offset, 16)) { - gapIndex = ConstPool::kIndex16; - gapSize = 16; - } - else if (size >= 8 && Support::isAligned(offset, 8)) { - gapIndex = ConstPool::kIndex8; - gapSize = 8; - } - else if (size >= 4 && Support::isAligned(offset, 4)) { - gapIndex = ConstPool::kIndex4; - gapSize = 4; - } - else if (size >= 2 && Support::isAligned(offset, 2)) { - gapIndex = ConstPool::kIndex2; - gapSize = 2; - } - else { - gapIndex = ConstPool::kIndex1; - gapSize = 1; - } - - // We don't have to check for errors here, if this failed nothing really - // happened (just the gap won't be visible) and it will fail again at - // place where the same check would generate `kErrorOutOfMemory` error. - ConstPool::Gap* gap = ConstPool_allocGap(self); - if (!gap) - return; - - gap->_next = self->_gaps[gapIndex]; - self->_gaps[gapIndex] = gap; - - gap->_offset = offset; - gap->_size = gapSize; - - offset += gapSize; - size -= gapSize; - } -} - -Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept { - size_t treeIndex; - - if (size == 32) - treeIndex = kIndex32; - else if (size == 16) - treeIndex = kIndex16; - else if (size == 8) - treeIndex = kIndex8; - else if (size == 4) - treeIndex = kIndex4; - else if (size == 2) - treeIndex = kIndex2; - else if (size == 1) - treeIndex = kIndex1; - else - return DebugUtils::errored(kErrorInvalidArgument); - - ConstPool::Node* node = _tree[treeIndex].get(data); - if (node) { - dstOffset = node->_offset; - return kErrorOk; - } - - // Before incrementing the current offset try if there is a gap that can - // be used for the requested data. - size_t offset = ~size_t(0); - size_t gapIndex = treeIndex; - - while (gapIndex != kIndexCount - 1) { - ConstPool::Gap* gap = _gaps[treeIndex]; - - // Check if there is a gap. - if (gap) { - size_t gapOffset = gap->_offset; - size_t gapSize = gap->_size; - - // Destroy the gap for now. - _gaps[treeIndex] = gap->_next; - ConstPool_freeGap(this, gap); - - offset = gapOffset; - ASMJIT_ASSERT(Support::isAligned(offset, size)); - - gapSize -= size; - if (gapSize > 0) - ConstPool_addGap(this, gapOffset, gapSize); - } - - gapIndex++; - } - - if (offset == ~size_t(0)) { - // Get how many bytes have to be skipped so the address is aligned accordingly - // to the 'size'. - size_t diff = Support::alignUpDiff(_size, size); - - if (diff != 0) { - ConstPool_addGap(this, _size, diff); - _size += diff; - } - - offset = _size; - _size += size; - } - - // Add the initial node to the right index. - node = ConstPool::Tree::_newNode(_zone, data, size, offset, false); - if (!node) return DebugUtils::errored(kErrorOutOfMemory); - - _tree[treeIndex].insert(node); - _alignment = Support::max(_alignment, size); - - dstOffset = offset; - - // Now create a bunch of shared constants that are based on the data pattern. - // We stop at size 4, it probably doesn't make sense to split constants down - // to 1 byte. - size_t pCount = 1; - while (size > 4) { - size >>= 1; - pCount <<= 1; - - ASMJIT_ASSERT(treeIndex != 0); - treeIndex--; - - const uint8_t* pData = static_cast(data); - for (size_t i = 0; i < pCount; i++, pData += size) { - node = _tree[treeIndex].get(pData); - if (node) continue; - - node = ConstPool::Tree::_newNode(_zone, pData, size, offset + (i * size), true); - _tree[treeIndex].insert(node); - } - } - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::ConstPool - Reset] -// ============================================================================ - -struct ConstPoolFill { - inline ConstPoolFill(uint8_t* dst, size_t dataSize) noexcept : - _dst(dst), - _dataSize(dataSize) {} - - inline void operator()(const ConstPool::Node* node) noexcept { - if (!node->_shared) - memcpy(_dst + node->_offset, node->data(), _dataSize); - } - - uint8_t* _dst; - size_t _dataSize; -}; - -void ConstPool::fill(void* dst) const noexcept { - // Clears possible gaps, asmjit should never emit garbage to the output. - memset(dst, 0, _size); - - ConstPoolFill filler(static_cast(dst), 1); - for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_tree); i++) { - _tree[i].forEach(filler); - filler._dataSize <<= 1; - } -} - -// ============================================================================ -// [asmjit::ConstPool - Unit] -// ============================================================================ - -#if defined(ASMJIT_TEST) -UNIT(const_pool) { - Zone zone(32384 - Zone::kBlockOverhead); - ConstPool pool(&zone); - - uint32_t i; - uint32_t kCount = BrokenAPI::hasArg("--quick") ? 1000 : 1000000; - - INFO("Adding %u constants to the pool.", kCount); - { - size_t prevOffset; - size_t curOffset; - uint64_t c = 0x0101010101010101u; - - EXPECT(pool.add(&c, 8, prevOffset) == kErrorOk); - EXPECT(prevOffset == 0); - - for (i = 1; i < kCount; i++) { - c++; - EXPECT(pool.add(&c, 8, curOffset) == kErrorOk); - EXPECT(prevOffset + 8 == curOffset); - EXPECT(pool.size() == (i + 1) * 8); - prevOffset = curOffset; - } - - EXPECT(pool.alignment() == 8); - } - - INFO("Retrieving %u constants from the pool.", kCount); - { - uint64_t c = 0x0101010101010101u; - - for (i = 0; i < kCount; i++) { - size_t offset; - EXPECT(pool.add(&c, 8, offset) == kErrorOk); - EXPECT(offset == i * 8); - c++; - } - } - - INFO("Checking if the constants were split into 4-byte patterns"); - { - uint32_t c = 0x01010101; - for (i = 0; i < kCount; i++) { - size_t offset; - EXPECT(pool.add(&c, 4, offset) == kErrorOk); - EXPECT(offset == i * 8); - c++; - } - } - - INFO("Adding 2 byte constant to misalign the current offset"); - { - uint16_t c = 0xFFFF; - size_t offset; - - EXPECT(pool.add(&c, 2, offset) == kErrorOk); - EXPECT(offset == kCount * 8); - EXPECT(pool.alignment() == 8); - } - - INFO("Adding 8 byte constant to check if pool gets aligned again"); - { - uint64_t c = 0xFFFFFFFFFFFFFFFFu; - size_t offset; - - EXPECT(pool.add(&c, 8, offset) == kErrorOk); - EXPECT(offset == kCount * 8 + 8); - } - - INFO("Adding 2 byte constant to verify the gap is filled"); - { - uint16_t c = 0xFFFE; - size_t offset; - - EXPECT(pool.add(&c, 2, offset) == kErrorOk); - EXPECT(offset == kCount * 8 + 2); - EXPECT(pool.alignment() == 8); - } - - INFO("Checking reset functionality"); - { - pool.reset(&zone); - zone.reset(); - - EXPECT(pool.size() == 0); - EXPECT(pool.alignment() == 0); - } - - INFO("Checking pool alignment when combined constants are added"); - { - uint8_t bytes[32] = { 0 }; - size_t offset; - - pool.add(bytes, 1, offset); - EXPECT(pool.size() == 1); - EXPECT(pool.alignment() == 1); - EXPECT(offset == 0); - - pool.add(bytes, 2, offset); - EXPECT(pool.size() == 4); - EXPECT(pool.alignment() == 2); - EXPECT(offset == 2); - - pool.add(bytes, 4, offset); - EXPECT(pool.size() == 8); - EXPECT(pool.alignment() == 4); - EXPECT(offset == 4); - - pool.add(bytes, 4, offset); - EXPECT(pool.size() == 8); - EXPECT(pool.alignment() == 4); - EXPECT(offset == 4); - - pool.add(bytes, 32, offset); - EXPECT(pool.size() == 64); - EXPECT(pool.alignment() == 32); - EXPECT(offset == 32); - } -} -#endif - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/constpool.h b/ext/asmjit-master/src/asmjit/core/constpool.h deleted file mode 100644 index d9ac5895..00000000 --- a/ext/asmjit-master/src/asmjit/core/constpool.h +++ /dev/null @@ -1,262 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_CONSTPOOL_H_INCLUDED -#define ASMJIT_CORE_CONSTPOOL_H_INCLUDED - -#include "../core/support.h" -#include "../core/zone.h" -#include "../core/zonetree.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_utilities -//! \{ - -// ============================================================================ -// [asmjit::ConstPool] -// ============================================================================ - -//! Constant pool. -class ConstPool { -public: - ASMJIT_NONCOPYABLE(ConstPool) - - //! Constant pool scope. - enum Scope : uint32_t { - //! Local constant, always embedded right after the current function. - kScopeLocal = 0, - //! Global constant, embedded at the end of the currently compiled code. - kScopeGlobal = 1 - }; - - //! \cond INTERNAL - - //! Index of a given size in const-pool table. - enum Index : uint32_t { - kIndex1 = 0, - kIndex2 = 1, - kIndex4 = 2, - kIndex8 = 3, - kIndex16 = 4, - kIndex32 = 5, - kIndexCount = 6 - }; - - //! Zone-allocated const-pool gap created by two differently aligned constants. - struct Gap { - //! Pointer to the next gap - Gap* _next; - //! Offset of the gap. - size_t _offset; - //! Remaining bytes of the gap (basically a gap size). - size_t _size; - }; - - //! Zone-allocated const-pool node. - class Node : public ZoneTreeNodeT { - public: - ASMJIT_NONCOPYABLE(Node) - - //! If this constant is shared with another. - uint32_t _shared : 1; - //! Data offset from the beginning of the pool. - uint32_t _offset; - - inline Node(size_t offset, bool shared) noexcept - : ZoneTreeNodeT(), - _shared(shared), - _offset(uint32_t(offset)) {} - - inline void* data() const noexcept { - return static_cast(const_cast(this) + 1); - } - }; - - //! Data comparer used internally. - class Compare { - public: - size_t _dataSize; - - inline Compare(size_t dataSize) noexcept - : _dataSize(dataSize) {} - - inline int operator()(const Node& a, const Node& b) const noexcept { - return ::memcmp(a.data(), b.data(), _dataSize); - } - - inline int operator()(const Node& a, const void* data) const noexcept { - return ::memcmp(a.data(), data, _dataSize); - } - }; - - //! Zone-allocated const-pool tree. - struct Tree { - //! RB tree. - ZoneTree _tree; - //! Size of the tree (number of nodes). - size_t _size; - //! Size of the data. - size_t _dataSize; - - inline explicit Tree(size_t dataSize = 0) noexcept - : _tree(), - _size(0), - _dataSize(dataSize) {} - - inline void reset() noexcept { - _tree.reset(); - _size = 0; - } - - inline bool empty() const noexcept { return _size == 0; } - inline size_t size() const noexcept { return _size; } - - inline void setDataSize(size_t dataSize) noexcept { - ASMJIT_ASSERT(empty()); - _dataSize = dataSize; - } - - inline Node* get(const void* data) noexcept { - Compare cmp(_dataSize); - return _tree.get(data, cmp); - } - - inline void insert(Node* node) noexcept { - Compare cmp(_dataSize); - _tree.insert(node, cmp); - _size++; - } - - template - inline void forEach(Visitor& visitor) const noexcept { - Node* node = _tree.root(); - if (!node) return; - - Node* stack[Globals::kMaxTreeHeight]; - size_t top = 0; - - for (;;) { - Node* left = node->left(); - if (left != nullptr) { - ASMJIT_ASSERT(top != Globals::kMaxTreeHeight); - stack[top++] = node; - - node = left; - continue; - } - - for (;;) { - visitor(node); - node = node->right(); - - if (node != nullptr) - break; - - if (top == 0) - return; - - node = stack[--top]; - } - } - } - - static inline Node* _newNode(Zone* zone, const void* data, size_t size, size_t offset, bool shared) noexcept { - Node* node = zone->allocT(sizeof(Node) + size); - if (ASMJIT_UNLIKELY(!node)) return nullptr; - - node = new(node) Node(offset, shared); - memcpy(node->data(), data, size); - return node; - } - }; - - //! \endcond - - //! Zone allocator. - Zone* _zone; - //! Tree per size. - Tree _tree[kIndexCount]; - //! Gaps per size. - Gap* _gaps[kIndexCount]; - //! Gaps pool - Gap* _gapPool; - - //! Size of the pool (in bytes). - size_t _size; - //! Required pool alignment. - size_t _alignment; - - //! \name Construction & Destruction - //! \{ - - ASMJIT_API ConstPool(Zone* zone) noexcept; - ASMJIT_API ~ConstPool() noexcept; - - ASMJIT_API void reset(Zone* zone) noexcept; - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether the constant-pool is empty. - inline bool empty() const noexcept { return _size == 0; } - //! Returns the size of the constant-pool in bytes. - inline size_t size() const noexcept { return _size; } - //! Returns minimum alignment. - inline size_t alignment() const noexcept { return _alignment; } - - //! \} - - //! \name Utilities - //! \{ - - //! Adds a constant to the constant pool. - //! - //! The constant must have known size, which is 1, 2, 4, 8, 16 or 32 bytes. - //! The constant is added to the pool only if it doesn't not exist, otherwise - //! cached value is returned. - //! - //! AsmJit is able to subdivide added constants, so for example if you add - //! 8-byte constant 0x1122334455667788 it will create the following slots: - //! - //! 8-byte: 0x1122334455667788 - //! 4-byte: 0x11223344, 0x55667788 - //! - //! The reason is that when combining MMX/SSE/AVX code some patterns are used - //! frequently. However, AsmJit is not able to reallocate a constant that has - //! been already added. For example if you try to add 4-byte constant and then - //! 8-byte constant having the same 4-byte pattern as the previous one, two - //! independent slots will be generated by the pool. - ASMJIT_API Error add(const void* data, size_t size, size_t& dstOffset) noexcept; - - //! Fills the destination with the content of this constant pool. - ASMJIT_API void fill(void* dst) const noexcept; -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_CONSTPOOL_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/cpuinfo.cpp b/ext/asmjit-master/src/asmjit/core/cpuinfo.cpp deleted file mode 100644 index edc7d172..00000000 --- a/ext/asmjit-master/src/asmjit/core/cpuinfo.cpp +++ /dev/null @@ -1,97 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/cpuinfo.h" - -#if !defined(_WIN32) - #include - #include - #include -#endif - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::CpuInfo - Detect - CPU NumThreads] -// ============================================================================ - -#if defined(_WIN32) -static inline uint32_t detectHWThreadCount() noexcept { - SYSTEM_INFO info; - ::GetSystemInfo(&info); - return info.dwNumberOfProcessors; -} -#elif defined(_SC_NPROCESSORS_ONLN) -static inline uint32_t detectHWThreadCount() noexcept { - long res = ::sysconf(_SC_NPROCESSORS_ONLN); - return res <= 0 ? uint32_t(1) : uint32_t(res); -} -#else -static inline uint32_t detectHWThreadCount() noexcept { - return 1; -} -#endif - -// ============================================================================ -// [asmjit::CpuInfo - Detect - CPU Features] -// ============================================================================ - -#if defined(ASMJIT_BUILD_X86) && ASMJIT_ARCH_X86 -namespace x86 { void detectCpu(CpuInfo& cpu) noexcept; } -#endif - -#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM -namespace arm { void detectCpu(CpuInfo& cpu) noexcept; } -#endif - -// ============================================================================ -// [asmjit::CpuInfo - Detect - Static Initializer] -// ============================================================================ - -static uint32_t cpuInfoInitialized; -static CpuInfo cpuInfoGlobal(Globals::NoInit); - -const CpuInfo& CpuInfo::host() noexcept { - // This should never cause a problem as the resulting information should - // always be the same. - if (!cpuInfoInitialized) { - CpuInfo cpuInfoLocal; - -#if defined(ASMJIT_BUILD_X86) && ASMJIT_ARCH_X86 - x86::detectCpu(cpuInfoLocal); -#endif - -#if defined(ASMJIT_BUILD_ARM) && ASMJIT_ARCH_ARM - arm::detectCpu(cpuInfoLocal); -#endif - - cpuInfoLocal._hwThreadCount = detectHWThreadCount(); - cpuInfoGlobal = cpuInfoLocal; - cpuInfoInitialized = 1; - } - - return cpuInfoGlobal; -} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/cpuinfo.h b/ext/asmjit-master/src/asmjit/core/cpuinfo.h deleted file mode 100644 index ee2c9e55..00000000 --- a/ext/asmjit-master/src/asmjit/core/cpuinfo.h +++ /dev/null @@ -1,154 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_CPUINFO_H_INCLUDED -#define ASMJIT_CORE_CPUINFO_H_INCLUDED - -#include "../core/arch.h" -#include "../core/features.h" -#include "../core/globals.h" -#include "../core/string.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::CpuInfo] -// ============================================================================ - -//! CPU information. -class CpuInfo { -public: - //! Architecture. - uint8_t _arch; - //! Sub-architecture. - uint8_t _subArch; - //! Reserved for future use. - uint16_t _reserved; - //! CPU family ID. - uint32_t _familyId; - //! CPU model ID. - uint32_t _modelId; - //! CPU brand ID. - uint32_t _brandId; - //! CPU stepping. - uint32_t _stepping; - //! Processor type. - uint32_t _processorType; - //! Maximum number of addressable IDs for logical processors. - uint32_t _maxLogicalProcessors; - //! Cache line size (in bytes). - uint32_t _cacheLineSize; - //! Number of hardware threads. - uint32_t _hwThreadCount; - - //! CPU vendor string. - FixedString<16> _vendor; - //! CPU brand string. - FixedString<64> _brand; - //! CPU features. - BaseFeatures _features; - - //! \name Construction & Destruction - //! \{ - - inline CpuInfo() noexcept { reset(); } - inline CpuInfo(const CpuInfo& other) noexcept = default; - - inline explicit CpuInfo(Globals::NoInit_) noexcept - : _features(Globals::NoInit) {}; - - //! Returns the host CPU information. - ASMJIT_API static const CpuInfo& host() noexcept; - - //! Initializes CpuInfo to the given architecture, see \ref Environment. - inline void initArch(uint32_t arch, uint32_t subArch = 0u) noexcept { - _arch = uint8_t(arch); - _subArch = uint8_t(subArch); - } - - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline CpuInfo& operator=(const CpuInfo& other) noexcept = default; - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the CPU architecture id, see \ref Environment::Arch. - inline uint32_t arch() const noexcept { return _arch; } - //! Returns the CPU architecture sub-id, see \ref Environment::SubArch. - inline uint32_t subArch() const noexcept { return _subArch; } - - //! Returns the CPU family ID. - inline uint32_t familyId() const noexcept { return _familyId; } - //! Returns the CPU model ID. - inline uint32_t modelId() const noexcept { return _modelId; } - //! Returns the CPU brand id. - inline uint32_t brandId() const noexcept { return _brandId; } - //! Returns the CPU stepping. - inline uint32_t stepping() const noexcept { return _stepping; } - //! Returns the processor type. - inline uint32_t processorType() const noexcept { return _processorType; } - //! Returns the number of maximum logical processors. - inline uint32_t maxLogicalProcessors() const noexcept { return _maxLogicalProcessors; } - - //! Returns the size of a cache line flush. - inline uint32_t cacheLineSize() const noexcept { return _cacheLineSize; } - //! Returns number of hardware threads available. - inline uint32_t hwThreadCount() const noexcept { return _hwThreadCount; } - - //! Returns the CPU vendor. - inline const char* vendor() const noexcept { return _vendor.str; } - //! Tests whether the CPU vendor is equal to `s`. - inline bool isVendor(const char* s) const noexcept { return _vendor.eq(s); } - - //! Returns the CPU brand string. - inline const char* brand() const noexcept { return _brand.str; } - - //! Returns all CPU features as `BaseFeatures`, cast to your arch-specific class - //! if needed. - template - inline const T& features() const noexcept { return _features.as(); } - - //! Tests whether the CPU has the given `feature`. - inline bool hasFeature(uint32_t featureId) const noexcept { return _features.has(featureId); } - //! Adds the given CPU `feature` to the list of this CpuInfo features. - inline CpuInfo& addFeature(uint32_t featureId) noexcept { _features.add(featureId); return *this; } - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_CPUINFO_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/datatypes.h b/ext/asmjit-master/src/asmjit/core/datatypes.h deleted file mode 100644 index 2f6cc1e5..00000000 --- a/ext/asmjit-master/src/asmjit/core/datatypes.h +++ /dev/null @@ -1,1071 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_DATATYPES_H_INCLUDED -#define ASMJIT_CORE_DATATYPES_H_INCLUDED - -#include "../core/globals.h" - -#ifndef ASMJIT_NO_DEPRECATED - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::Data64] -// ============================================================================ - -//! 64-bit data useful for creating SIMD constants. -union ASMJIT_DEPRECATED_STRUCT("Data64 is deprecated and will be removed in the future") Data64 { - //! Array of eight 8-bit signed integers. - int8_t sb[8]; - //! Array of eight 8-bit unsigned integers. - uint8_t ub[8]; - //! Array of four 16-bit signed integers. - int16_t sw[4]; - //! Array of four 16-bit unsigned integers. - uint16_t uw[4]; - //! Array of two 32-bit signed integers. - int32_t sd[2]; - //! Array of two 32-bit unsigned integers. - uint32_t ud[2]; - //! Array of one 64-bit signed integer. - int64_t sq[1]; - //! Array of one 64-bit unsigned integer. - uint64_t uq[1]; - - //! Array of two SP-FP values. - float sf[2]; - //! Array of one DP-FP value. - double df[1]; - - //! \name Construction & Destruction - //! \{ - - //! Sets all eight 8-bit signed integers. - static inline Data64 fromI8(int8_t x0) noexcept { - Data64 self; - self.setI8(x0); - return self; - } - - //! Sets all eight 8-bit unsigned integers. - static inline Data64 fromU8(uint8_t x0) noexcept { - Data64 self; - self.setU8(x0); - return self; - } - - //! Sets all eight 8-bit signed integers. - static inline Data64 fromI8( - int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7) noexcept { - - Data64 self; - self.setI8(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all eight 8-bit unsigned integers. - static inline Data64 fromU8( - uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) noexcept { - - Data64 self; - self.setU8(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four 16-bit signed integers. - static inline Data64 fromI16(int16_t x0) noexcept { - Data64 self; - self.setI16(x0); - return self; - } - - //! Sets all four 16-bit unsigned integers. - static inline Data64 fromU16(uint16_t x0) noexcept { - Data64 self; - self.setU16(x0); - return self; - } - - //! Sets all four 16-bit signed integers. - static inline Data64 fromI16(int16_t x0, int16_t x1, int16_t x2, int16_t x3) noexcept { - Data64 self; - self.setI16(x0, x1, x2, x3); - return self; - } - - //! Sets all four 16-bit unsigned integers. - static inline Data64 fromU16(uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3) noexcept { - Data64 self; - self.setU16(x0, x1, x2, x3); - return self; - } - - //! Sets all two 32-bit signed integers. - static inline Data64 fromI32(int32_t x0) noexcept { - Data64 self; - self.setI32(x0); - return self; - } - - //! Sets all two 32-bit unsigned integers. - static inline Data64 fromU32(uint32_t x0) noexcept { - Data64 self; - self.setU32(x0); - return self; - } - - //! Sets all two 32-bit signed integers. - static inline Data64 fromI32(int32_t x0, int32_t x1) noexcept { - Data64 self; - self.setI32(x0, x1); - return self; - } - - //! Sets all two 32-bit unsigned integers. - static inline Data64 fromU32(uint32_t x0, uint32_t x1) noexcept { - Data64 self; - self.setU32(x0, x1); - return self; - } - - //! Sets 64-bit signed integer. - static inline Data64 fromI64(int64_t x0) noexcept { - Data64 self; - self.setI64(x0); - return self; - } - - //! Sets 64-bit unsigned integer. - static inline Data64 fromU64(uint64_t x0) noexcept { - Data64 self; - self.setU64(x0); - return self; - } - - //! Sets all two SP-FP values. - static inline Data64 fromF32(float x0) noexcept { - Data64 self; - self.setF32(x0); - return self; - } - - //! Sets all two SP-FP values. - static inline Data64 fromF32(float x0, float x1) noexcept { - Data64 self; - self.setF32(x0, x1); - return self; - } - - //! Sets all two SP-FP values. - static inline Data64 fromF64(double x0) noexcept { - Data64 self; - self.setF64(x0); - return self; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets all eight 8-bit signed integers. - inline void setI8(int8_t x0) noexcept { - setU8(uint8_t(x0)); - } - - //! Sets all eight 8-bit unsigned integers. - inline void setU8(uint8_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0101010101010101u; - uq[0] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x01010101u; - ud[0] = xd; - ud[1] = xd; - } - } - - //! Sets all eight 8-bit signed integers. - inline void setI8( - int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7) noexcept { - - sb[0] = x0; sb[1] = x1; sb[2] = x2; sb[3] = x3; - sb[4] = x4; sb[5] = x5; sb[6] = x6; sb[7] = x7; - } - - //! Sets all eight 8-bit unsigned integers. - inline void setU8( - uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) noexcept { - - ub[0] = x0; ub[1] = x1; ub[2] = x2; ub[3] = x3; - ub[4] = x4; ub[5] = x5; ub[6] = x6; ub[7] = x7; - } - - //! Sets all four 16-bit signed integers. - inline void setI16(int16_t x0) noexcept { - setU16(uint16_t(x0)); - } - - //! Sets all four 16-bit unsigned integers. - inline void setU16(uint16_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0001000100010001u; - uq[0] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x00010001u; - ud[0] = xd; - ud[1] = xd; - } - } - - //! Sets all four 16-bit signed integers. - inline void setI16(int16_t x0, int16_t x1, int16_t x2, int16_t x3) noexcept { - sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; - } - - //! Sets all four 16-bit unsigned integers. - inline void setU16(uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3) noexcept { - uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; - } - - //! Sets all two 32-bit signed integers. - inline void setI32(int32_t x0) noexcept { - sd[0] = x0; sd[1] = x0; - } - - //! Sets all two 32-bit unsigned integers. - inline void setU32(uint32_t x0) noexcept { - ud[0] = x0; ud[1] = x0; - } - - //! Sets all two 32-bit signed integers. - inline void setI32(int32_t x0, int32_t x1) noexcept { - sd[0] = x0; sd[1] = x1; - } - - //! Sets all two 32-bit unsigned integers. - inline void setU32(uint32_t x0, uint32_t x1) noexcept { - ud[0] = x0; ud[1] = x1; - } - - //! Sets 64-bit signed integer. - inline void setI64(int64_t x0) noexcept { - sq[0] = x0; - } - - //! Sets 64-bit unsigned integer. - inline void setU64(uint64_t x0) noexcept { - uq[0] = x0; - } - - //! Sets all two SP-FP values. - inline void setF32(float x0) noexcept { - sf[0] = x0; sf[1] = x0; - } - - //! Sets all two SP-FP values. - inline void setF32(float x0, float x1) noexcept { - sf[0] = x0; sf[1] = x1; - } - - //! Sets all two SP-FP values. - inline void setF64(double x0) noexcept { - df[0] = x0; - } -}; - -// ============================================================================ -// [asmjit::Data128] -// ============================================================================ - -//! 128-bit data useful for creating SIMD constants. -union ASMJIT_DEPRECATED_STRUCT("Data128 is deprecated and will be removed in the future") Data128 { - //! Array of sixteen 8-bit signed integers. - int8_t sb[16]; - //! Array of sixteen 8-bit unsigned integers. - uint8_t ub[16]; - //! Array of eight 16-bit signed integers. - int16_t sw[8]; - //! Array of eight 16-bit unsigned integers. - uint16_t uw[8]; - //! Array of four 32-bit signed integers. - int32_t sd[4]; - //! Array of four 32-bit unsigned integers. - uint32_t ud[4]; - //! Array of two 64-bit signed integers. - int64_t sq[2]; - //! Array of two 64-bit unsigned integers. - uint64_t uq[2]; - - //! Array of four 32-bit single precision floating points. - float sf[4]; - //! Array of two 64-bit double precision floating points. - double df[2]; - - //! \name Construction & Destruction - //! \{ - - //! Sets all sixteen 8-bit signed integers. - static inline Data128 fromI8(int8_t x0) noexcept { - Data128 self; - self.setI8(x0); - return self; - } - - //! Sets all sixteen 8-bit unsigned integers. - static inline Data128 fromU8(uint8_t x0) noexcept { - Data128 self; - self.setU8(x0); - return self; - } - - //! Sets all sixteen 8-bit signed integers. - static inline Data128 fromI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15) noexcept { - - Data128 self; - self.setI8(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all sixteen 8-bit unsigned integers. - static inline Data128 fromU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15) noexcept { - - Data128 self; - self.setU8(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all eight 16-bit signed integers. - static inline Data128 fromI16(int16_t x0) noexcept { - Data128 self; - self.setI16(x0); - return self; - } - - //! Sets all eight 16-bit unsigned integers. - static inline Data128 fromU16(uint16_t x0) noexcept { - Data128 self; - self.setU16(x0); - return self; - } - - //! Sets all eight 16-bit signed integers. - static inline Data128 fromI16( - int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7) noexcept { - - Data128 self; - self.setI16(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all eight 16-bit unsigned integers. - static inline Data128 fromU16( - uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7) noexcept { - - Data128 self; - self.setU16(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four 32-bit signed integers. - static inline Data128 fromI32(int32_t x0) noexcept { - Data128 self; - self.setI32(x0); - return self; - } - - //! Sets all four 32-bit unsigned integers. - static inline Data128 fromU32(uint32_t x0) noexcept { - Data128 self; - self.setU32(x0); - return self; - } - - //! Sets all four 32-bit signed integers. - static inline Data128 fromI32(int32_t x0, int32_t x1, int32_t x2, int32_t x3) noexcept { - Data128 self; - self.setI32(x0, x1, x2, x3); - return self; - } - - //! Sets all four 32-bit unsigned integers. - static inline Data128 fromU32(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) noexcept { - Data128 self; - self.setU32(x0, x1, x2, x3); - return self; - } - - //! Sets all two 64-bit signed integers. - static inline Data128 fromI64(int64_t x0) noexcept { - Data128 self; - self.setI64(x0); - return self; - } - - //! Sets all two 64-bit unsigned integers. - static inline Data128 fromU64(uint64_t x0) noexcept { - Data128 self; - self.setU64(x0); - return self; - } - - //! Sets all two 64-bit signed integers. - static inline Data128 fromI64(int64_t x0, int64_t x1) noexcept { - Data128 self; - self.setI64(x0, x1); - return self; - } - - //! Sets all two 64-bit unsigned integers. - static inline Data128 fromU64(uint64_t x0, uint64_t x1) noexcept { - Data128 self; - self.setU64(x0, x1); - return self; - } - - //! Sets all four SP-FP floats. - static inline Data128 fromF32(float x0) noexcept { - Data128 self; - self.setF32(x0); - return self; - } - - //! Sets all four SP-FP floats. - static inline Data128 fromF32(float x0, float x1, float x2, float x3) noexcept { - Data128 self; - self.setF32(x0, x1, x2, x3); - return self; - } - - //! Sets all two DP-FP floats. - static inline Data128 fromF64(double x0) noexcept { - Data128 self; - self.setF64(x0); - return self; - } - - //! Sets all two DP-FP floats. - static inline Data128 fromF64(double x0, double x1) noexcept { - Data128 self; - self.setF64(x0, x1); - return self; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets all sixteen 8-bit signed integers. - inline void setI8(int8_t x0) noexcept { - setU8(uint8_t(x0)); - } - - //! Sets all sixteen 8-bit unsigned integers. - inline void setU8(uint8_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0101010101010101u; - uq[0] = xq; - uq[1] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x01010101u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - } - } - - //! Sets all sixteen 8-bit signed integers. - inline void setI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15) noexcept { - - sb[0 ] = x0 ; sb[1 ] = x1 ; sb[2 ] = x2 ; sb[3 ] = x3 ; - sb[4 ] = x4 ; sb[5 ] = x5 ; sb[6 ] = x6 ; sb[7 ] = x7 ; - sb[8 ] = x8 ; sb[9 ] = x9 ; sb[10] = x10; sb[11] = x11; - sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15; - } - - //! Sets all sixteen 8-bit unsigned integers. - inline void setU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15) noexcept { - - ub[0 ] = x0 ; ub[1 ] = x1 ; ub[2 ] = x2 ; ub[3 ] = x3 ; - ub[4 ] = x4 ; ub[5 ] = x5 ; ub[6 ] = x6 ; ub[7 ] = x7 ; - ub[8 ] = x8 ; ub[9 ] = x9 ; ub[10] = x10; ub[11] = x11; - ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15; - } - - //! Sets all eight 16-bit signed integers. - inline void setI16(int16_t x0) noexcept { - setU16(uint16_t(x0)); - } - - //! Sets all eight 16-bit unsigned integers. - inline void setU16(uint16_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0001000100010001u; - uq[0] = xq; - uq[1] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x00010001u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - } - } - - //! Sets all eight 16-bit signed integers. - inline void setI16( - int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7) noexcept { - - sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; - sw[4] = x4; sw[5] = x5; sw[6] = x6; sw[7] = x7; - } - - //! Sets all eight 16-bit unsigned integers. - inline void setU16( - uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7) noexcept { - - uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; - uw[4] = x4; uw[5] = x5; uw[6] = x6; uw[7] = x7; - } - - //! Sets all four 32-bit signed integers. - inline void setI32(int32_t x0) noexcept { - setU32(uint32_t(x0)); - } - - //! Sets all four 32-bit unsigned integers. - inline void setU32(uint32_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t t = (uint64_t(x0) << 32) + x0; - uq[0] = t; - uq[1] = t; - } - else { - ud[0] = x0; - ud[1] = x0; - ud[2] = x0; - ud[3] = x0; - } - } - - //! Sets all four 32-bit signed integers. - inline void setI32(int32_t x0, int32_t x1, int32_t x2, int32_t x3) noexcept { - sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3; - } - - //! Sets all four 32-bit unsigned integers. - inline void setU32(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) noexcept { - ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3; - } - - //! Sets all two 64-bit signed integers. - inline void setI64(int64_t x0) noexcept { - sq[0] = x0; sq[1] = x0; - } - - //! Sets all two 64-bit unsigned integers. - inline void setU64(uint64_t x0) noexcept { - uq[0] = x0; uq[1] = x0; - } - - //! Sets all two 64-bit signed integers. - inline void setI64(int64_t x0, int64_t x1) noexcept { - sq[0] = x0; sq[1] = x1; - } - - //! Sets all two 64-bit unsigned integers. - inline void setU64(uint64_t x0, uint64_t x1) noexcept { - uq[0] = x0; uq[1] = x1; - } - - //! Sets all four SP-FP floats. - inline void setF32(float x0) noexcept { - sf[0] = x0; sf[1] = x0; sf[2] = x0; sf[3] = x0; - } - - //! Sets all four SP-FP floats. - inline void setF32(float x0, float x1, float x2, float x3) noexcept { - sf[0] = x0; sf[1] = x1; sf[2] = x2; sf[3] = x3; - } - - //! Sets all two DP-FP floats. - inline void setF64(double x0) noexcept { - df[0] = x0; df[1] = x0; - } - - //! Sets all two DP-FP floats. - inline void setF64(double x0, double x1) noexcept { - df[0] = x0; df[1] = x1; - } -}; - -// ============================================================================ -// [asmjit::Data256] -// ============================================================================ - -//! 256-bit data useful for creating SIMD constants. -union ASMJIT_DEPRECATED_STRUCT("Data256 is deprecated and will be removed in the future") Data256 { - //! Array of thirty two 8-bit signed integers. - int8_t sb[32]; - //! Array of thirty two 8-bit unsigned integers. - uint8_t ub[32]; - //! Array of sixteen 16-bit signed integers. - int16_t sw[16]; - //! Array of sixteen 16-bit unsigned integers. - uint16_t uw[16]; - //! Array of eight 32-bit signed integers. - int32_t sd[8]; - //! Array of eight 32-bit unsigned integers. - uint32_t ud[8]; - //! Array of four 64-bit signed integers. - int64_t sq[4]; - //! Array of four 64-bit unsigned integers. - uint64_t uq[4]; - - //! Array of eight 32-bit single precision floating points. - float sf[8]; - //! Array of four 64-bit double precision floating points. - double df[4]; - - //! \name Construction & Destruction - //! \{ - - //! Sets all thirty two 8-bit signed integers. - static inline Data256 fromI8(int8_t x0) noexcept { - Data256 self; - self.setI8(x0); - return self; - } - - //! Sets all thirty two 8-bit unsigned integers. - static inline Data256 fromU8(uint8_t x0) noexcept { - Data256 self; - self.setU8(x0); - return self; - } - - //! Sets all thirty two 8-bit signed integers. - static inline Data256 fromI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15, - int8_t x16, int8_t x17, int8_t x18, int8_t x19, - int8_t x20, int8_t x21, int8_t x22, int8_t x23, - int8_t x24, int8_t x25, int8_t x26, int8_t x27, - int8_t x28, int8_t x29, int8_t x30, int8_t x31) noexcept { - - Data256 self; - self.setI8( - x0, x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9 , x10, x11, x12, x13, x14, x15, - x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31); - return self; - } - - //! Sets all thirty two 8-bit unsigned integers. - static inline Data256 fromU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15, - uint8_t x16, uint8_t x17, uint8_t x18, uint8_t x19, - uint8_t x20, uint8_t x21, uint8_t x22, uint8_t x23, - uint8_t x24, uint8_t x25, uint8_t x26, uint8_t x27, - uint8_t x28, uint8_t x29, uint8_t x30, uint8_t x31) noexcept { - - Data256 self; - self.setU8( - x0, x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9 , x10, x11, x12, x13, x14, x15, - x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31); - return self; - } - - //! Sets all sixteen 16-bit signed integers. - static inline Data256 fromI16(int16_t x0) noexcept { - Data256 self; - self.setI16(x0); - return self; - } - - //! Sets all sixteen 16-bit unsigned integers. - static inline Data256 fromU16(uint16_t x0) noexcept { - Data256 self; - self.setU16(x0); - return self; - } - - //! Sets all sixteen 16-bit signed integers. - static inline Data256 fromI16( - int16_t x0, int16_t x1, int16_t x2 , int16_t x3 , int16_t x4 , int16_t x5 , int16_t x6 , int16_t x7 , - int16_t x8, int16_t x9, int16_t x10, int16_t x11, int16_t x12, int16_t x13, int16_t x14, int16_t x15) noexcept { - - Data256 self; - self.setI16(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all sixteen 16-bit unsigned integers. - static inline Data256 fromU16( - uint16_t x0, uint16_t x1, uint16_t x2 , uint16_t x3 , uint16_t x4 , uint16_t x5 , uint16_t x6 , uint16_t x7 , - uint16_t x8, uint16_t x9, uint16_t x10, uint16_t x11, uint16_t x12, uint16_t x13, uint16_t x14, uint16_t x15) noexcept { - - Data256 self; - self.setU16(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15); - return self; - } - - //! Sets all eight 32-bit signed integers. - static inline Data256 fromI32(int32_t x0) noexcept { - Data256 self; - self.setI32(x0); - return self; - } - - //! Sets all eight 32-bit unsigned integers. - static inline Data256 fromU32(uint32_t x0) noexcept { - Data256 self; - self.setU32(x0); - return self; - } - - //! Sets all eight 32-bit signed integers. - static inline Data256 fromI32( - int32_t x0, int32_t x1, int32_t x2, int32_t x3, - int32_t x4, int32_t x5, int32_t x6, int32_t x7) noexcept { - - Data256 self; - self.setI32(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all eight 32-bit unsigned integers. - static inline Data256 fromU32( - uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, - uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) noexcept { - - Data256 self; - self.setU32(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four 64-bit signed integers. - static inline Data256 fromI64(int64_t x0) noexcept { - Data256 self; - self.setI64(x0); - return self; - } - - //! Sets all four 64-bit unsigned integers. - static inline Data256 fromU64(uint64_t x0) noexcept { - Data256 self; - self.setU64(x0); - return self; - } - - //! Sets all four 64-bit signed integers. - static inline Data256 fromI64(int64_t x0, int64_t x1, int64_t x2, int64_t x3) noexcept { - Data256 self; - self.setI64(x0, x1, x2, x3); - return self; - } - - //! Sets all four 64-bit unsigned integers. - static inline Data256 fromU64(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3) noexcept { - Data256 self; - self.setU64(x0, x1, x2, x3); - return self; - } - - //! Sets all eight SP-FP floats. - static inline Data256 fromF32(float x0) noexcept { - Data256 self; - self.setF32(x0); - return self; - } - - //! Sets all eight SP-FP floats. - static inline Data256 fromF32( - float x0, float x1, float x2, float x3, - float x4, float x5, float x6, float x7) noexcept { - - Data256 self; - self.setF32(x0, x1, x2, x3, x4, x5, x6, x7); - return self; - } - - //! Sets all four DP-FP floats. - static inline Data256 fromF64(double x0) noexcept { - Data256 self; - self.setF64(x0); - return self; - } - - //! Sets all four DP-FP floats. - static inline Data256 fromF64(double x0, double x1, double x2, double x3) noexcept { - Data256 self; - self.setF64(x0, x1, x2, x3); - return self; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets all thirty two 8-bit signed integers. - inline void setI8(int8_t x0) noexcept { - setU8(uint8_t(x0)); - } - - //! Sets all thirty two 8-bit unsigned integers. - inline void setU8(uint8_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0101010101010101u; - uq[0] = xq; - uq[1] = xq; - uq[2] = xq; - uq[3] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x01010101u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - ud[4] = xd; - ud[5] = xd; - ud[6] = xd; - ud[7] = xd; - } - } - - //! Sets all thirty two 8-bit signed integers. - inline void setI8( - int8_t x0 , int8_t x1 , int8_t x2 , int8_t x3 , - int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , - int8_t x8 , int8_t x9 , int8_t x10, int8_t x11, - int8_t x12, int8_t x13, int8_t x14, int8_t x15, - int8_t x16, int8_t x17, int8_t x18, int8_t x19, - int8_t x20, int8_t x21, int8_t x22, int8_t x23, - int8_t x24, int8_t x25, int8_t x26, int8_t x27, - int8_t x28, int8_t x29, int8_t x30, int8_t x31) noexcept { - - sb[0 ] = x0 ; sb[1 ] = x1 ; sb[2 ] = x2 ; sb[3 ] = x3 ; - sb[4 ] = x4 ; sb[5 ] = x5 ; sb[6 ] = x6 ; sb[7 ] = x7 ; - sb[8 ] = x8 ; sb[9 ] = x9 ; sb[10] = x10; sb[11] = x11; - sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15; - sb[16] = x16; sb[17] = x17; sb[18] = x18; sb[19] = x19; - sb[20] = x20; sb[21] = x21; sb[22] = x22; sb[23] = x23; - sb[24] = x24; sb[25] = x25; sb[26] = x26; sb[27] = x27; - sb[28] = x28; sb[29] = x29; sb[30] = x30; sb[31] = x31; - } - - //! Sets all thirty two 8-bit unsigned integers. - inline void setU8( - uint8_t x0 , uint8_t x1 , uint8_t x2 , uint8_t x3 , - uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , - uint8_t x8 , uint8_t x9 , uint8_t x10, uint8_t x11, - uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15, - uint8_t x16, uint8_t x17, uint8_t x18, uint8_t x19, - uint8_t x20, uint8_t x21, uint8_t x22, uint8_t x23, - uint8_t x24, uint8_t x25, uint8_t x26, uint8_t x27, - uint8_t x28, uint8_t x29, uint8_t x30, uint8_t x31) noexcept { - - ub[0 ] = x0 ; ub[1 ] = x1 ; ub[2 ] = x2 ; ub[3 ] = x3 ; - ub[4 ] = x4 ; ub[5 ] = x5 ; ub[6 ] = x6 ; ub[7 ] = x7 ; - ub[8 ] = x8 ; ub[9 ] = x9 ; ub[10] = x10; ub[11] = x11; - ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15; - ub[16] = x16; ub[17] = x17; ub[18] = x18; ub[19] = x19; - ub[20] = x20; ub[21] = x21; ub[22] = x22; ub[23] = x23; - ub[24] = x24; ub[25] = x25; ub[26] = x26; ub[27] = x27; - ub[28] = x28; ub[29] = x29; ub[30] = x30; ub[31] = x31; - } - - //! Sets all sixteen 16-bit signed integers. - inline void setI16(int16_t x0) noexcept { - setU16(uint16_t(x0)); - } - - //! Sets all eight 16-bit unsigned integers. - inline void setU16(uint16_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = uint64_t(x0) * 0x0001000100010001u; - uq[0] = xq; - uq[1] = xq; - uq[2] = xq; - uq[3] = xq; - } - else { - uint32_t xd = uint32_t(x0) * 0x00010001u; - ud[0] = xd; - ud[1] = xd; - ud[2] = xd; - ud[3] = xd; - ud[4] = xd; - ud[5] = xd; - ud[6] = xd; - ud[7] = xd; - } - } - - //! Sets all sixteen 16-bit signed integers. - inline void setI16( - int16_t x0, int16_t x1, int16_t x2 , int16_t x3 , int16_t x4 , int16_t x5 , int16_t x6 , int16_t x7, - int16_t x8, int16_t x9, int16_t x10, int16_t x11, int16_t x12, int16_t x13, int16_t x14, int16_t x15) noexcept { - - sw[0 ] = x0 ; sw[1 ] = x1 ; sw[2 ] = x2 ; sw[3 ] = x3 ; - sw[4 ] = x4 ; sw[5 ] = x5 ; sw[6 ] = x6 ; sw[7 ] = x7 ; - sw[8 ] = x8 ; sw[9 ] = x9 ; sw[10] = x10; sw[11] = x11; - sw[12] = x12; sw[13] = x13; sw[14] = x14; sw[15] = x15; - } - - //! Sets all sixteen 16-bit unsigned integers. - inline void setU16( - uint16_t x0, uint16_t x1, uint16_t x2 , uint16_t x3 , uint16_t x4 , uint16_t x5 , uint16_t x6 , uint16_t x7, - uint16_t x8, uint16_t x9, uint16_t x10, uint16_t x11, uint16_t x12, uint16_t x13, uint16_t x14, uint16_t x15) noexcept { - - uw[0 ] = x0 ; uw[1 ] = x1 ; uw[2 ] = x2 ; uw[3 ] = x3 ; - uw[4 ] = x4 ; uw[5 ] = x5 ; uw[6 ] = x6 ; uw[7 ] = x7 ; - uw[8 ] = x8 ; uw[9 ] = x9 ; uw[10] = x10; uw[11] = x11; - uw[12] = x12; uw[13] = x13; uw[14] = x14; uw[15] = x15; - } - - //! Sets all eight 32-bit signed integers. - inline void setI32(int32_t x0) noexcept { - setU32(uint32_t(x0)); - } - - //! Sets all eight 32-bit unsigned integers. - inline void setU32(uint32_t x0) noexcept { - if (ASMJIT_ARCH_BITS >= 64) { - uint64_t xq = (uint64_t(x0) << 32) + x0; - uq[0] = xq; - uq[1] = xq; - uq[2] = xq; - uq[3] = xq; - } - else { - ud[0] = x0; - ud[1] = x0; - ud[2] = x0; - ud[3] = x0; - ud[4] = x0; - ud[5] = x0; - ud[6] = x0; - ud[7] = x0; - } - } - - //! Sets all eight 32-bit signed integers. - inline void setI32( - int32_t x0, int32_t x1, int32_t x2, int32_t x3, - int32_t x4, int32_t x5, int32_t x6, int32_t x7) noexcept { - - sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3; - sd[4] = x4; sd[5] = x5; sd[6] = x6; sd[7] = x7; - } - - //! Sets all eight 32-bit unsigned integers. - inline void setU32( - uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, - uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) noexcept { - - ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3; - ud[4] = x4; ud[5] = x5; ud[6] = x6; ud[7] = x7; - } - - //! Sets all four 64-bit signed integers. - inline void setI64(int64_t x0) noexcept { - sq[0] = x0; sq[1] = x0; sq[2] = x0; sq[3] = x0; - } - - //! Sets all four 64-bit unsigned integers. - inline void setU64(uint64_t x0) noexcept { - uq[0] = x0; uq[1] = x0; uq[2] = x0; uq[3] = x0; - } - - //! Sets all four 64-bit signed integers. - inline void setI64(int64_t x0, int64_t x1, int64_t x2, int64_t x3) noexcept { - sq[0] = x0; sq[1] = x1; sq[2] = x2; sq[3] = x3; - } - - //! Sets all four 64-bit unsigned integers. - inline void setU64(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3) noexcept { - uq[0] = x0; uq[1] = x1; uq[2] = x2; uq[3] = x3; - } - - //! Sets all eight SP-FP floats. - inline void setF32(float x0) noexcept { - sf[0] = x0; sf[1] = x0; sf[2] = x0; sf[3] = x0; - sf[4] = x0; sf[5] = x0; sf[6] = x0; sf[7] = x0; - } - - //! Sets all eight SP-FP floats. - inline void setF32( - float x0, float x1, float x2, float x3, - float x4, float x5, float x6, float x7) noexcept { - - sf[0] = x0; sf[1] = x1; sf[2] = x2; sf[3] = x3; - sf[4] = x4; sf[5] = x5; sf[6] = x6; sf[7] = x7; - } - - //! Sets all four DP-FP floats. - inline void setF64(double x0) noexcept { - df[0] = x0; df[1] = x0; df[2] = x0; df[3] = x0; - } - - //! Sets all four DP-FP floats. - inline void setF64(double x0, double x1, double x2, double x3) noexcept { - df[0] = x0; df[1] = x1; df[2] = x2; df[3] = x3; - } - - //! \} -}; - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_DEPRECATED -#endif // ASMJIT_CORE_DATATYPES_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/emitter.cpp b/ext/asmjit-master/src/asmjit/core/emitter.cpp deleted file mode 100644 index b6ecc3d3..00000000 --- a/ext/asmjit-master/src/asmjit/core/emitter.cpp +++ /dev/null @@ -1,392 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/emitterutils_p.h" -#include "../core/errorhandler.h" -#include "../core/logger.h" -#include "../core/support.h" - -#ifdef ASMJIT_BUILD_X86 - #include "../x86/x86internal_p.h" - #include "../x86/x86instdb_p.h" -#endif // ASMJIT_BUILD_X86 - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/arminternal_p.h" - #include "../arm/arminstdb.h" -#endif // ASMJIT_BUILD_ARM - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::BaseEmitter - Construction / Destruction] -// ============================================================================ - -BaseEmitter::BaseEmitter(uint32_t emitterType) noexcept - : _emitterType(uint8_t(emitterType)), - _emitterFlags(0), - _validationFlags(0), - _validationOptions(0), - _encodingOptions(0), - _forcedInstOptions(BaseInst::kOptionReserved), - _privateData(0), - _code(nullptr), - _logger(nullptr), - _errorHandler(nullptr), - _environment(), - _gpRegInfo(), - _instOptions(0), - _extraReg(), - _inlineComment(nullptr) {} - -BaseEmitter::~BaseEmitter() noexcept { - if (_code) { - _addEmitterFlags(kFlagDestroyed); - _code->detach(this); - } -} - -// ============================================================================ -// [asmjit::BaseEmitter - Finalize] -// ============================================================================ - -Error BaseEmitter::finalize() { - // Does nothing by default, overridden by `BaseBuilder` and `BaseCompiler`. - return kErrorOk; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Internals] -// ============================================================================ - -static constexpr uint32_t kEmitterPreservedFlags = - BaseEmitter::kFlagOwnLogger | - BaseEmitter::kFlagOwnErrorHandler ; - -static ASMJIT_NOINLINE void BaseEmitter_updateForcedOptions(BaseEmitter* self) noexcept { - bool hasLogger = self->_logger != nullptr; - bool hasValidationOptions; - - if (self->emitterType() == BaseEmitter::kTypeAssembler) - hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionAssembler); - else - hasValidationOptions = self->hasValidationOption(BaseEmitter::kValidationOptionIntermediate); - - self->_forcedInstOptions &= ~BaseInst::kOptionReserved; - if (hasLogger || hasValidationOptions) - self->_forcedInstOptions |= BaseInst::kOptionReserved; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Validation Options] -// ============================================================================ - -void BaseEmitter::addValidationOptions(uint32_t options) noexcept { - _validationOptions = uint8_t(_validationOptions | options); - BaseEmitter_updateForcedOptions(this); -} - -void BaseEmitter::clearValidationOptions(uint32_t options) noexcept { - _validationOptions = uint8_t(_validationOptions | options); - BaseEmitter_updateForcedOptions(this); -} - -// ============================================================================ -// [asmjit::BaseEmitter - Logging] -// ============================================================================ - -void BaseEmitter::setLogger(Logger* logger) noexcept { -#ifndef ASMJIT_NO_LOGGING - if (logger) { - _logger = logger; - _addEmitterFlags(kFlagOwnLogger); - } - else { - _logger = nullptr; - _clearEmitterFlags(kFlagOwnLogger); - if (_code) - _logger = _code->logger(); - } - BaseEmitter_updateForcedOptions(this); -#else - DebugUtils::unused(logger); -#endif -} - -// ============================================================================ -// [asmjit::BaseEmitter - Error Handling] -// ============================================================================ - -void BaseEmitter::setErrorHandler(ErrorHandler* errorHandler) noexcept { - if (errorHandler) { - _errorHandler = errorHandler; - _addEmitterFlags(kFlagOwnErrorHandler); - } - else { - _errorHandler = nullptr; - _clearEmitterFlags(kFlagOwnErrorHandler); - if (_code) - _errorHandler = _code->errorHandler(); - } -} - -Error BaseEmitter::reportError(Error err, const char* message) { - ErrorHandler* eh = _errorHandler; - if (eh) { - if (!message) - message = DebugUtils::errorAsString(err); - eh->handleError(err, message, this); - } - return err; -} - -// ============================================================================ -// [asmjit::BaseEmitter - Labels] -// ============================================================================ - -Label BaseEmitter::labelByName(const char* name, size_t nameSize, uint32_t parentId) noexcept { - return Label(_code ? _code->labelIdByName(name, nameSize, parentId) : uint32_t(Globals::kInvalidId)); -} - -bool BaseEmitter::isLabelValid(uint32_t labelId) const noexcept { - return _code && labelId < _code->labelCount(); -} - -// ============================================================================ -// [asmjit::BaseEmitter - Emit (Low-Level)] -// ============================================================================ - -using EmitterUtils::noExt; - -Error BaseEmitter::_emitI(uint32_t instId) { - return _emit(instId, noExt[0], noExt[1], noExt[2], noExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0) { - return _emit(instId, o0, noExt[1], noExt[2], noExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1) { - return _emit(instId, o0, o1, noExt[2], noExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2) { - return _emit(instId, o0, o1, o2, noExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3) { - Operand_ opExt[3] = { o3 }; - return _emit(instId, o0, o1, o2, opExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4) { - Operand_ opExt[3] = { o3, o4 }; - return _emit(instId, o0, o1, o2, opExt); -} - -Error BaseEmitter::_emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5) { - Operand_ opExt[3] = { o3, o4, o5 }; - return _emit(instId, o0, o1, o2, opExt); -} - -Error BaseEmitter::_emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount) { - const Operand_* op = operands; - - Operand_ opExt[3]; - - switch (opCount) { - case 0: - return _emit(instId, noExt[0], noExt[1], noExt[2], noExt); - - case 1: - return _emit(instId, op[0], noExt[1], noExt[2], noExt); - - case 2: - return _emit(instId, op[0], op[1], noExt[2], noExt); - - case 3: - return _emit(instId, op[0], op[1], op[2], noExt); - - case 4: - opExt[0] = op[3]; - opExt[1].reset(); - opExt[2].reset(); - return _emit(instId, op[0], op[1], op[2], opExt); - - case 5: - opExt[0] = op[3]; - opExt[1] = op[4]; - opExt[2].reset(); - return _emit(instId, op[0], op[1], op[2], opExt); - - case 6: - return _emit(instId, op[0], op[1], op[2], op + 3); - - default: - return DebugUtils::errored(kErrorInvalidArgument); - } -} - -// ============================================================================ -// [asmjit::BaseEmitter - Emit (High-Level)] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error BaseEmitter::emitProlog(const FuncFrame& frame) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - -#ifdef ASMJIT_BUILD_X86 - if (environment().isFamilyX86()) - return x86::X86Internal::emitProlog(as(), frame); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment().isFamilyARM()) - return arm::ArmInternal::emitProlog(as(), frame); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} - -ASMJIT_FAVOR_SIZE Error BaseEmitter::emitEpilog(const FuncFrame& frame) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - -#ifdef ASMJIT_BUILD_X86 - if (environment().isFamilyX86()) - return x86::X86Internal::emitEpilog(as(), frame); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment().isFamilyARM()) - return arm::ArmInternal::emitEpilog(as(), frame); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} - -ASMJIT_FAVOR_SIZE Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - -#ifdef ASMJIT_BUILD_X86 - if (environment().isFamilyX86()) - return x86::X86Internal::emitArgsAssignment(as(), frame, args); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment().isFamilyARM()) - return arm::ArmInternal::emitArgsAssignment(as(), frame, args); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} - -// ============================================================================ -// [asmjit::BaseEmitter - Comment] -// ============================================================================ - -Error BaseEmitter::commentf(const char* fmt, ...) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - -#ifndef ASMJIT_NO_LOGGING - va_list ap; - va_start(ap, fmt); - Error err = commentv(fmt, ap); - va_end(ap); - return err; -#else - DebugUtils::unused(fmt); - return kErrorOk; -#endif -} - -Error BaseEmitter::commentv(const char* fmt, va_list ap) { - if (ASMJIT_UNLIKELY(!_code)) - return DebugUtils::errored(kErrorNotInitialized); - -#ifndef ASMJIT_NO_LOGGING - StringTmp<1024> sb; - Error err = sb.appendVFormat(fmt, ap); - - if (ASMJIT_UNLIKELY(err)) - return err; - - return comment(sb.data(), sb.size()); -#else - DebugUtils::unused(fmt, ap); - return kErrorOk; -#endif -} - -// ============================================================================ -// [asmjit::BaseEmitter - Events] -// ============================================================================ - -Error BaseEmitter::onAttach(CodeHolder* code) noexcept { - _code = code; - _environment = code->environment(); - - onSettingsUpdated(); - return kErrorOk; -} - -Error BaseEmitter::onDetach(CodeHolder* code) noexcept { - DebugUtils::unused(code); - - _clearEmitterFlags(~kEmitterPreservedFlags); - _forcedInstOptions = BaseInst::kOptionReserved; - _privateData = 0; - - if (!hasOwnLogger()) - _logger = nullptr; - - if (!hasOwnErrorHandler()) - _errorHandler = nullptr; - - _environment.reset(); - _gpRegInfo.reset(); - - _instOptions = 0; - _extraReg.reset(); - _inlineComment = nullptr; - - return kErrorOk; -} - -void BaseEmitter::onSettingsUpdated() noexcept { - // Only called when attached to CodeHolder by CodeHolder. - ASMJIT_ASSERT(_code != nullptr); - - if (!hasOwnLogger()) - _logger = _code->logger(); - - if (!hasOwnErrorHandler()) - _errorHandler = _code->errorHandler(); - - BaseEmitter_updateForcedOptions(this); -} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/emitter.h b/ext/asmjit-master/src/asmjit/core/emitter.h deleted file mode 100644 index 0fd09f73..00000000 --- a/ext/asmjit-master/src/asmjit/core/emitter.h +++ /dev/null @@ -1,714 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_EMITTER_H_INCLUDED -#define ASMJIT_CORE_EMITTER_H_INCLUDED - -#include "../core/arch.h" -#include "../core/codeholder.h" -#include "../core/inst.h" -#include "../core/operand.h" -#include "../core/type.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class ConstPool; -class FuncFrame; -class FuncArgsAssignment; - -// ============================================================================ -// [asmjit::BaseEmitter] -// ============================================================================ - -//! Provides a base foundation to emit code - specialized by `Assembler` and -//! `BaseBuilder`. -class ASMJIT_VIRTAPI BaseEmitter { -public: - ASMJIT_BASE_CLASS(BaseEmitter) - - //! See \ref EmitterType. - uint8_t _emitterType; - //! See \ref BaseEmitter::EmitterFlags. - uint8_t _emitterFlags; - //! Validation flags in case validation is used, see \ref InstAPI::ValidationFlags. - //! - //! \note Validation flags are specific to the emitter and they are setup at - //! construction time and then never changed. - uint8_t _validationFlags; - //! Validation options, see \ref ValidationOptions. - uint8_t _validationOptions; - - //! Encoding options, see \ref EncodingOptions. - uint32_t _encodingOptions; - - //! Forced instruction options, combined with \ref _instOptions by \ref emit(). - uint32_t _forcedInstOptions; - //! Internal private data used freely by any emitter. - uint32_t _privateData; - - //! CodeHolder the emitter is attached to. - CodeHolder* _code; - //! Attached \ref Logger. - Logger* _logger; - //! Attached \ref ErrorHandler. - ErrorHandler* _errorHandler; - - //! Describes the target environment, matches \ref CodeHolder::environment(). - Environment _environment; - //! Native GP register signature and signature related information. - RegInfo _gpRegInfo; - - //! Next instruction options (affects the next instruction). - uint32_t _instOptions; - //! Extra register (op-mask {k} on AVX-512) (affects the next instruction). - RegOnly _extraReg; - //! Inline comment of the next instruction (affects the next instruction). - const char* _inlineComment; - - //! Emitter type. - enum EmitterType : uint32_t { - //! Unknown or uninitialized. - kTypeNone = 0, - //! Emitter inherits from \ref BaseAssembler. - kTypeAssembler = 1, - //! Emitter inherits from \ref BaseBuilder. - kTypeBuilder = 2, - //! Emitter inherits from \ref BaseCompiler. - kTypeCompiler = 3, - - //! Count of emitter types. - kTypeCount = 4 - }; - - //! Emitter flags. - enum EmitterFlags : uint32_t { - //! The emitter has its own \ref Logger (not propagated from \ref CodeHolder). - kFlagOwnLogger = 0x10u, - //! The emitter has its own \ref ErrorHandler (not propagated from \ref CodeHolder). - kFlagOwnErrorHandler = 0x20u, - //! The emitter was finalized. - kFlagFinalized = 0x40u, - //! The emitter was destroyed. - kFlagDestroyed = 0x80u - }; - - //! Encoding options. - enum EncodingOptions : uint32_t { - //! Emit instructions that are optimized for size, if possible. - //! - //! Default: false. - //! - //! X86 Specific - //! ------------ - //! - //! When this option is set it the assembler will try to fix instructions - //! if possible into operation equivalent instructions that take less bytes - //! by taking advantage of implicit zero extension. For example instruction - //! like `mov r64, imm` and `and r64, imm` can be translated to `mov r32, imm` - //! and `and r32, imm` when the immediate constant is lesser than `2^31`. - kEncodingOptionOptimizeForSize = 0x00000001u, - - //! Emit optimized code-alignment sequences. - //! - //! Default: false. - //! - //! X86 Specific - //! ------------ - //! - //! Default align sequence used by X86 architecture is one-byte (0x90) - //! opcode that is often shown by disassemblers as NOP. However there are - //! more optimized align sequences for 2-11 bytes that may execute faster - //! on certain CPUs. If this feature is enabled AsmJit will generate - //! specialized sequences for alignment between 2 to 11 bytes. - kEncodingOptionOptimizedAlign = 0x00000002u, - - //! Emit jump-prediction hints. - //! - //! Default: false. - //! - //! X86 Specific - //! ------------ - //! - //! Jump prediction is usually based on the direction of the jump. If the - //! jump is backward it is usually predicted as taken; and if the jump is - //! forward it is usually predicted as not-taken. The reason is that loops - //! generally use backward jumps and conditions usually use forward jumps. - //! However this behavior can be overridden by using instruction prefixes. - //! If this option is enabled these hints will be emitted. - //! - //! This feature is disabled by default, because the only processor that - //! used to take into consideration prediction hints was P4. Newer processors - //! implement heuristics for branch prediction and ignore static hints. This - //! means that this feature can be only used for annotation purposes. - kEncodingOptionPredictedJumps = 0x00000010u - }; - -#ifndef ASMJIT_NO_DEPRECATED - enum EmitterOptions : uint32_t { - kOptionOptimizedForSize = kEncodingOptionOptimizeForSize, - kOptionOptimizedAlign = kEncodingOptionOptimizedAlign, - kOptionPredictedJumps = kEncodingOptionPredictedJumps - }; -#endif - - //! Validation options are used to tell emitters to perform strict validation - //! of instructions passed to \ref emit(). - //! - //! \ref BaseAssembler implementation perform by default only basic checks - //! that are necessary to identify all variations of an instruction so the - //! correct encoding can be selected. This is fine for production-ready code - //! as the assembler doesn't have to perform checks that would slow it down. - //! However, sometimes these checks are beneficial especially when the project - //! that uses AsmJit is in a development phase, in which mistakes happen often. - //! To make the experience of using AsmJit seamless it offers validation - //! features that can be controlled by `ValidationOptions`. - enum ValidationOptions : uint32_t { - //! Perform strict validation in \ref BaseAssembler::emit() implementations. - //! - //! This flag ensures that each instruction is checked before it's encoded - //! into a binary representation. This flag is only relevant for \ref - //! BaseAssembler implementations, but can be set in any other emitter type, - //! in that case if that emitter needs to create an assembler on its own, - //! for the purpose of \ref finalize() it would propagate this flag to such - //! assembler so all instructions passed to it are explicitly validated. - //! - //! Default: false. - kValidationOptionAssembler = 0x00000001u, - - //! Perform strict validation in \ref BaseBuilder::emit() and \ref - //! BaseCompiler::emit() implementations. - //! - //! This flag ensures that each instruction is checked before an \ref - //! InstNode representing the instruction is created by Builder or Compiler. - //! - //! Default: false. - kValidationOptionIntermediate = 0x00000002u - }; - - //! \name Construction & Destruction - //! \{ - - ASMJIT_API explicit BaseEmitter(uint32_t emitterType) noexcept; - ASMJIT_API virtual ~BaseEmitter() noexcept; - - //! \} - - //! \name Cast - //! \{ - - template - inline T* as() noexcept { return reinterpret_cast(this); } - - template - inline const T* as() const noexcept { return reinterpret_cast(this); } - - //! \} - - //! \name Emitter Type & Flags - //! \{ - - //! Returns the type of this emitter, see `EmitterType`. - inline uint32_t emitterType() const noexcept { return _emitterType; } - //! Returns emitter flags , see `Flags`. - inline uint32_t emitterFlags() const noexcept { return _emitterFlags; } - - //! Tests whether the emitter inherits from `BaseAssembler`. - inline bool isAssembler() const noexcept { return _emitterType == kTypeAssembler; } - //! Tests whether the emitter inherits from `BaseBuilder`. - //! - //! \note Both Builder and Compiler emitters would return `true`. - inline bool isBuilder() const noexcept { return _emitterType >= kTypeBuilder; } - //! Tests whether the emitter inherits from `BaseCompiler`. - inline bool isCompiler() const noexcept { return _emitterType == kTypeCompiler; } - - //! Tests whether the emitter has the given `flag` enabled. - inline bool hasEmitterFlag(uint32_t flag) const noexcept { return (_emitterFlags & flag) != 0; } - //! Tests whether the emitter is finalized. - inline bool isFinalized() const noexcept { return hasEmitterFlag(kFlagFinalized); } - //! Tests whether the emitter is destroyed (only used during destruction). - inline bool isDestroyed() const noexcept { return hasEmitterFlag(kFlagDestroyed); } - - inline void _addEmitterFlags(uint32_t flags) noexcept { _emitterFlags = uint8_t(_emitterFlags | flags); } - inline void _clearEmitterFlags(uint32_t flags) noexcept { _emitterFlags = uint8_t(_emitterFlags & ~flags); } - - //! \} - - //! \name Target Information - //! \{ - - //! Returns the CodeHolder this emitter is attached to. - inline CodeHolder* code() const noexcept { return _code; } - - //! Returns the target environment, see \ref Environment. - //! - //! The returned \ref Environment reference matches \ref CodeHolder::environment(). - inline const Environment& environment() const noexcept { return _environment; } - - //! Tests whether the target architecture is 32-bit. - inline bool is32Bit() const noexcept { return environment().is32Bit(); } - //! Tests whether the target architecture is 64-bit. - inline bool is64Bit() const noexcept { return environment().is64Bit(); } - - //! Returns the target architecture type. - inline uint32_t arch() const noexcept { return environment().arch(); } - //! Returns the target architecture sub-type. - inline uint32_t subArch() const noexcept { return environment().subArch(); } - - //! Returns the target architecture's GP register size (4 or 8 bytes). - inline uint32_t registerSize() const noexcept { return environment().registerSize(); } - - //! \} - - //! \name Initialization & Finalization - //! \{ - - //! Tests whether the emitter is initialized (i.e. attached to \ref CodeHolder). - inline bool isInitialized() const noexcept { return _code != nullptr; } - - //! Finalizes this emitter. - //! - //! Materializes the content of the emitter by serializing it to the attached - //! \ref CodeHolder through an architecture specific \ref BaseAssembler. This - //! function won't do anything if the emitter inherits from \ref BaseAssembler - //! as assemblers emit directly to a \ref CodeBuffer held by \ref CodeHolder. - //! However, if this is an emitter that inherits from \ref BaseBuilder or \ref - //! BaseCompiler then these emitters need the materialization phase as they - //! store their content in a representation not visible to \ref CodeHolder. - ASMJIT_API virtual Error finalize(); - - //! \} - - //! \name Logging - //! \{ - - //! Tests whether the emitter has a logger. - inline bool hasLogger() const noexcept { return _logger != nullptr; } - - //! Tests whether the emitter has its own logger. - //! - //! Own logger means that it overrides the possible logger that may be used - //! by \ref CodeHolder this emitter is attached to. - inline bool hasOwnLogger() const noexcept { return hasEmitterFlag(kFlagOwnLogger); } - - //! Returns the logger this emitter uses. - //! - //! The returned logger is either the emitter's own logger or it's logger - //! used by \ref CodeHolder this emitter is attached to. - inline Logger* logger() const noexcept { return _logger; } - - //! Sets or resets the logger of the emitter. - //! - //! If the `logger` argument is non-null then the logger will be considered - //! emitter's own logger, see \ref hasOwnLogger() for more details. If the - //! given `logger` is null then the emitter will automatically use logger - //! that is attached to the \ref CodeHolder this emitter is attached to. - ASMJIT_API void setLogger(Logger* logger) noexcept; - - //! Resets the logger of this emitter. - //! - //! The emitter will bail to using a logger attached to \ref CodeHolder this - //! emitter is attached to, or no logger at all if \ref CodeHolder doesn't - //! have one. - inline void resetLogger() noexcept { return setLogger(nullptr); } - - //! \} - - //! \name Error Handling - //! \{ - - //! Tests whether the emitter has an error handler attached. - inline bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; } - - //! Tests whether the emitter has its own error handler. - //! - //! Own error handler means that it overrides the possible error handler that - //! may be used by \ref CodeHolder this emitter is attached to. - inline bool hasOwnErrorHandler() const noexcept { return hasEmitterFlag(kFlagOwnErrorHandler); } - - //! Returns the error handler this emitter uses. - //! - //! The returned error handler is either the emitter's own error handler or - //! it's error handler used by \ref CodeHolder this emitter is attached to. - inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; } - - //! Sets or resets the error handler of the emitter. - ASMJIT_API void setErrorHandler(ErrorHandler* errorHandler) noexcept; - - //! Resets the error handler. - inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); } - - //! Handles the given error in the following way: - //! 1. If the emitter has \ref ErrorHandler attached, it calls its - //! \ref ErrorHandler::handleError() member function first, and - //! then returns the error. The `handleError()` function may throw. - //! 2. if the emitter doesn't have \ref ErrorHandler, the error is - //! simply returned. - ASMJIT_API Error reportError(Error err, const char* message = nullptr); - - //! \} - - //! \name Encoding Options - //! \{ - - //! Returns encoding options, see \ref EncodingOptions. - inline uint32_t encodingOptions() const noexcept { return _encodingOptions; } - //! Tests whether the encoding `option` is set. - inline bool hasEncodingOption(uint32_t option) const noexcept { return (_encodingOptions & option) != 0; } - - //! Enables the given encoding `options`, see \ref EncodingOptions. - inline void addEncodingOptions(uint32_t options) noexcept { _encodingOptions |= options; } - //! Disables the given encoding `options`, see \ref EncodingOptions. - inline void clearEncodingOptions(uint32_t options) noexcept { _encodingOptions &= ~options; } - - //! \} - - //! \name Validation Options - //! \{ - - //! Returns the emitter's validation options, see \ref ValidationOptions. - inline uint32_t validationOptions() const noexcept { - return _validationOptions; - } - - //! Tests whether the given `option` is present in validation options. - inline bool hasValidationOption(uint32_t option) const noexcept { - return (_validationOptions & option) != 0; - } - - //! Activates the given validation `options`, see \ref ValidationOptions. - //! - //! This function is used to activate explicit validation options that will - //! be then used by all emitter implementations. There are in general two - //! possibilities: - //! - //! - Architecture specific assembler is used. In this case a - //! \ref kValidationOptionAssembler can be used to turn on explicit - //! validation that will be used before an instruction is emitted. - //! This means that internally an extra step will be performed to - //! make sure that the instruction is correct. This is needed, because - //! by default assemblers prefer speed over strictness. - //! - //! This option should be used in debug builds as it's pretty expensive. - //! - //! - Architecture specific builder or compiler is used. In this case - //! the user can turn on \ref kValidationOptionIntermediate option - //! that adds explicit validation step before the Builder or Compiler - //! creates an \ref InstNode to represent an emitted instruction. Error - //! will be returned if the instruction is ill-formed. In addition, - //! also \ref kValidationOptionAssembler can be used, which would not be - //! consumed by Builder / Compiler directly, but it would be propagated - //! to an architecture specific \ref BaseAssembler implementation it - //! creates during \ref BaseEmitter::finalize(). - ASMJIT_API void addValidationOptions(uint32_t options) noexcept; - - //! Deactivates the given validation `options`. - //! - //! See \ref addValidationOptions() and \ref ValidationOptions for more details. - ASMJIT_API void clearValidationOptions(uint32_t options) noexcept; - - //! \} - - //! \name Instruction Options - //! \{ - - //! Returns forced instruction options. - //! - //! Forced instruction options are merged with next instruction options before - //! the instruction is encoded. These options have some bits reserved that are - //! used by error handling, logging, and instruction validation purposes. Other - //! options are globals that affect each instruction. - inline uint32_t forcedInstOptions() const noexcept { return _forcedInstOptions; } - - //! Returns options of the next instruction. - inline uint32_t instOptions() const noexcept { return _instOptions; } - //! Returns options of the next instruction. - inline void setInstOptions(uint32_t options) noexcept { _instOptions = options; } - //! Adds options of the next instruction. - inline void addInstOptions(uint32_t options) noexcept { _instOptions |= options; } - //! Resets options of the next instruction. - inline void resetInstOptions() noexcept { _instOptions = 0; } - - //! Tests whether the extra register operand is valid. - inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); } - //! Returns an extra operand that will be used by the next instruction (architecture specific). - inline const RegOnly& extraReg() const noexcept { return _extraReg; } - //! Sets an extra operand that will be used by the next instruction (architecture specific). - inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); } - //! Sets an extra operand that will be used by the next instruction (architecture specific). - inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); } - //! Resets an extra operand that will be used by the next instruction (architecture specific). - inline void resetExtraReg() noexcept { _extraReg.reset(); } - - //! Returns comment/annotation of the next instruction. - inline const char* inlineComment() const noexcept { return _inlineComment; } - //! Sets comment/annotation of the next instruction. - //! - //! \note This string is set back to null by `_emit()`, but until that it has - //! to remain valid as the Emitter is not required to make a copy of it (and - //! it would be slow to do that for each instruction). - inline void setInlineComment(const char* s) noexcept { _inlineComment = s; } - //! Resets the comment/annotation to nullptr. - inline void resetInlineComment() noexcept { _inlineComment = nullptr; } - - //! \} - - //! \name Sections - //! \{ - - virtual Error section(Section* section) = 0; - - //! \} - - //! \name Labels - //! \{ - - //! Creates a new label. - virtual Label newLabel() = 0; - //! Creates a new named label. - virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, uint32_t type = Label::kTypeGlobal, uint32_t parentId = Globals::kInvalidId) = 0; - - //! Returns `Label` by `name`. - //! - //! Returns invalid Label in case that the name is invalid or label was not found. - //! - //! \note This function doesn't trigger ErrorHandler in case the name is invalid - //! or no such label exist. You must always check the validity of the `Label` returned. - ASMJIT_API Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept; - - //! Binds the `label` to the current position of the current section. - //! - //! \note Attempt to bind the same label multiple times will return an error. - virtual Error bind(const Label& label) = 0; - - //! Tests whether the label `id` is valid (i.e. registered). - ASMJIT_API bool isLabelValid(uint32_t labelId) const noexcept; - //! Tests whether the `label` is valid (i.e. registered). - inline bool isLabelValid(const Label& label) const noexcept { return isLabelValid(label.id()); } - - //! \} - - //! \name Emit - //! \{ - - // NOTE: These `emit()` helpers are designed to address a code-bloat generated - // by C++ compilers to call a function having many arguments. Each parameter to - // `_emit()` requires some code to pass it, which means that if we default to - // 5 arguments in `_emit()` and instId the C++ compiler would have to generate - // a virtual function call having 5 parameters and additional `this` argument, - // which is quite a lot. Since by default most instructions have 2 to 3 operands - // it's better to introduce helpers that pass from 0 to 6 operands that help to - // reduce the size of emit(...) function call. - - //! Emits an instruction (internal). - ASMJIT_API Error _emitI(uint32_t instId); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4); - //! \overload - ASMJIT_API Error _emitI(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5); - - //! Emits an instruction `instId` with the given `operands`. - template - ASMJIT_INLINE Error emit(uint32_t instId, Args&&... operands) { - return _emitI(instId, Support::ForwardOp::forward(operands)...); - } - - inline Error emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount) { - return _emitOpArray(instId, operands, opCount); - } - - inline Error emitInst(const BaseInst& inst, const Operand_* operands, size_t opCount) { - setInstOptions(inst.options()); - setExtraReg(inst.extraReg()); - return _emitOpArray(inst.id(), operands, opCount); - } - - //! \cond INTERNAL - //! Emits an instruction - all 6 operands must be defined. - virtual Error _emit(uint32_t instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt) = 0; - //! Emits instruction having operands stored in array. - virtual Error _emitOpArray(uint32_t instId, const Operand_* operands, size_t opCount); - //! \endcond - - //! \} - - //! \name Emit Utilities - //! \{ - - ASMJIT_API Error emitProlog(const FuncFrame& frame); - ASMJIT_API Error emitEpilog(const FuncFrame& frame); - ASMJIT_API Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args); - - //! \} - - //! \name Align - //! \{ - - //! Aligns the current CodeBuffer position to the `alignment` specified. - //! - //! The sequence that is used to fill the gap between the aligned location - //! and the current location depends on the align `mode`, see \ref AlignMode. - virtual Error align(uint32_t alignMode, uint32_t alignment) = 0; - - //! \} - - //! \name Embed - //! \{ - - //! Embeds raw data into the \ref CodeBuffer. - virtual Error embed(const void* data, size_t dataSize) = 0; - - //! Embeds a typed data array. - //! - //! This is the most flexible function for embedding data as it allows to: - //! - Assign a `typeId` to the data, so the emitter knows the type of - //! items stored in `data`. Binary data should use \ref Type::kIdU8. - //! - Repeat the given data `repeatCount` times, so the data can be used - //! as a fill pattern for example, or as a pattern used by SIMD instructions. - virtual Error embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1) = 0; - - //! Embeds int8_t `value` repeated by `repeatCount`. - inline Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI8, &value, 1, repeatCount); } - //! Embeds uint8_t `value` repeated by `repeatCount`. - inline Error embedUInt8(uint8_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU8, &value, 1, repeatCount); } - //! Embeds int16_t `value` repeated by `repeatCount`. - inline Error embedInt16(int16_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI16, &value, 1, repeatCount); } - //! Embeds uint16_t `value` repeated by `repeatCount`. - inline Error embedUInt16(uint16_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU16, &value, 1, repeatCount); } - //! Embeds int32_t `value` repeated by `repeatCount`. - inline Error embedInt32(int32_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI32, &value, 1, repeatCount); } - //! Embeds uint32_t `value` repeated by `repeatCount`. - inline Error embedUInt32(uint32_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU32, &value, 1, repeatCount); } - //! Embeds int64_t `value` repeated by `repeatCount`. - inline Error embedInt64(int64_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdI64, &value, 1, repeatCount); } - //! Embeds uint64_t `value` repeated by `repeatCount`. - inline Error embedUInt64(uint64_t value, size_t repeatCount = 1) { return embedDataArray(Type::kIdU64, &value, 1, repeatCount); } - //! Embeds a floating point `value` repeated by `repeatCount`. - inline Error embedFloat(float value, size_t repeatCount = 1) { return embedDataArray(Type::kIdF32, &value, 1, repeatCount); } - //! Embeds a floating point `value` repeated by `repeatCount`. - inline Error embedDouble(double value, size_t repeatCount = 1) { return embedDataArray(Type::IdOfT::kTypeId, &value, 1, repeatCount); } - - //! Embeds a constant pool at the current offset by performing the following: - //! 1. Aligns by using kAlignData to the minimum `pool` alignment. - //! 2. Binds the ConstPool label so it's bound to an aligned location. - //! 3. Emits ConstPool content. - virtual Error embedConstPool(const Label& label, const ConstPool& pool) = 0; - - //! Embeds an absolute `label` address as data. - //! - //! The `dataSize` is an optional argument that can be used to specify the - //! size of the address data. If it's zero (default) the address size is - //! deduced from the target architecture (either 4 or 8 bytes). - virtual Error embedLabel(const Label& label, size_t dataSize = 0) = 0; - - //! Embeds a delta (distance) between the `label` and `base` calculating it - //! as `label - base`. This function was designed to make it easier to embed - //! lookup tables where each index is a relative distance of two labels. - virtual Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) = 0; - - //! \} - - //! \name Comment - //! \{ - - //! Emits a comment stored in `data` with an optional `size` parameter. - virtual Error comment(const char* data, size_t size = SIZE_MAX) = 0; - - //! Emits a formatted comment specified by `fmt` and variable number of arguments. - ASMJIT_API Error commentf(const char* fmt, ...); - //! Emits a formatted comment specified by `fmt` and `ap`. - ASMJIT_API Error commentv(const char* fmt, va_list ap); - - //! \} - - //! \name Events - //! \{ - - //! Called after the emitter was attached to `CodeHolder`. - virtual Error onAttach(CodeHolder* code) noexcept = 0; - //! Called after the emitter was detached from `CodeHolder`. - virtual Error onDetach(CodeHolder* code) noexcept = 0; - - //! Called when \ref CodeHolder has updated an important setting, which - //! involves the following: - //! - //! - \ref Logger has been changed (\ref CodeHolder::setLogger() has been - //! called). - //! - \ref ErrorHandler has been changed (\ref CodeHolder::setErrorHandler() - //! has been called). - //! - //! This function ensures that the settings are properly propagated from - //! \ref CodeHolder to the emitter. - //! - //! \note This function is virtual and can be overridden, however, if you - //! do so, always call \ref BaseEmitter::onSettingsUpdated() within your - //! own implementation to ensure that the emitter is in a consisten state. - ASMJIT_API virtual void onSettingsUpdated() noexcept; - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use environment() instead") - inline CodeInfo codeInfo() const noexcept { - return CodeInfo(_environment, _code ? _code->baseAddress() : Globals::kNoBaseAddress); - } - - ASMJIT_DEPRECATED("Use arch() instead") - inline uint32_t archId() const noexcept { return arch(); } - - ASMJIT_DEPRECATED("Use registerSize() instead") - inline uint32_t gpSize() const noexcept { return registerSize(); } - - ASMJIT_DEPRECATED("Use encodingOptions() instead") - inline uint32_t emitterOptions() const noexcept { return encodingOptions(); } - - ASMJIT_DEPRECATED("Use addEncodingOptions() instead") - inline void addEmitterOptions(uint32_t options) noexcept { addEncodingOptions(options); } - - ASMJIT_DEPRECATED("Use clearEncodingOptions() instead") - inline void clearEmitterOptions(uint32_t options) noexcept { clearEncodingOptions(options); } - - ASMJIT_DEPRECATED("Use forcedInstOptions() instead") - inline uint32_t globalInstOptions() const noexcept { return forcedInstOptions(); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_EMITTER_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/emitterutils.cpp b/ext/asmjit-master/src/asmjit/core/emitterutils.cpp deleted file mode 100644 index 1115934e..00000000 --- a/ext/asmjit-master/src/asmjit/core/emitterutils.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/assembler.h" -#include "../core/emitterutils_p.h" -#include "../core/formatter.h" -#include "../core/logger.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::EmitterUtils] -// ============================================================================ - -namespace EmitterUtils { - -#ifndef ASMJIT_NO_LOGGING - -Error formatLine(String& sb, const uint8_t* binData, size_t binSize, size_t dispSize, size_t immSize, const char* comment) noexcept { - size_t currentSize = sb.size(); - size_t commentSize = comment ? Support::strLen(comment, Globals::kMaxCommentSize) : 0; - - ASMJIT_ASSERT(binSize >= dispSize); - const size_t kNoBinSize = SIZE_MAX; - - if ((binSize != 0 && binSize != kNoBinSize) || commentSize) { - size_t align = kMaxInstLineSize; - char sep = ';'; - - for (size_t i = (binSize == kNoBinSize); i < 2; i++) { - size_t begin = sb.size(); - ASMJIT_PROPAGATE(sb.padEnd(align)); - - if (sep) { - ASMJIT_PROPAGATE(sb.append(sep)); - ASMJIT_PROPAGATE(sb.append(' ')); - } - - // Append binary data or comment. - if (i == 0) { - ASMJIT_PROPAGATE(sb.appendHex(binData, binSize - dispSize - immSize)); - ASMJIT_PROPAGATE(sb.appendChars('.', dispSize * 2)); - ASMJIT_PROPAGATE(sb.appendHex(binData + binSize - immSize, immSize)); - if (commentSize == 0) break; - } - else { - ASMJIT_PROPAGATE(sb.append(comment, commentSize)); - } - - currentSize += sb.size() - begin; - align += kMaxBinarySize; - sep = '|'; - } - } - - return sb.append('\n'); -} - -void logLabelBound(BaseAssembler* self, const Label& label) noexcept { - Logger* logger = self->logger(); - - StringTmp<512> sb; - size_t binSize = logger->hasFlag(FormatOptions::kFlagMachineCode) ? size_t(0) : SIZE_MAX; - - sb.appendChars(' ', logger->indentation(FormatOptions::kIndentationLabel)); - Formatter::formatLabel(sb, logger->flags(), self, label.id()); - sb.append(':'); - EmitterUtils::formatLine(sb, nullptr, binSize, 0, 0, self->_inlineComment); - logger->log(sb.data(), sb.size()); -} - -void logInstructionEmitted( - BaseAssembler* self, - uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt, - uint32_t relSize, uint32_t immSize, uint8_t* afterCursor) { - - Logger* logger = self->logger(); - ASMJIT_ASSERT(logger != nullptr); - - StringTmp<256> sb; - uint32_t flags = logger->flags(); - - uint8_t* beforeCursor = self->bufferPtr(); - intptr_t emittedSize = (intptr_t)(afterCursor - beforeCursor); - - Operand_ opArray[Globals::kMaxOpCount]; - EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - - sb.appendChars(' ', logger->indentation(FormatOptions::kIndentationCode)); - Formatter::formatInstruction(sb, flags, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); - - if ((flags & FormatOptions::kFlagMachineCode) != 0) - EmitterUtils::formatLine(sb, self->bufferPtr(), size_t(emittedSize), relSize, immSize, self->inlineComment()); - else - EmitterUtils::formatLine(sb, nullptr, SIZE_MAX, 0, 0, self->inlineComment()); - logger->log(sb); -} - -Error logInstructionFailed( - BaseAssembler* self, - Error err, - uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) { - - StringTmp<256> sb; - sb.append(DebugUtils::errorAsString(err)); - sb.append(": "); - - Operand_ opArray[Globals::kMaxOpCount]; - EmitterUtils::opArrayFromEmitArgs(opArray, o0, o1, o2, opExt); - - Formatter::formatInstruction(sb, 0, self, self->arch(), BaseInst(instId, options, self->extraReg()), opArray, Globals::kMaxOpCount); - - if (self->inlineComment()) { - sb.append(" ; "); - sb.append(self->inlineComment()); - } - - self->resetInstOptions(); - self->resetExtraReg(); - self->resetInlineComment(); - return self->reportError(err, sb.data()); -} - -#endif - -} // {EmitterUtils} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/emitterutils_p.h b/ext/asmjit-master/src/asmjit/core/emitterutils_p.h deleted file mode 100644 index 7e222d3a..00000000 --- a/ext/asmjit-master/src/asmjit/core/emitterutils_p.h +++ /dev/null @@ -1,109 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_EMITTERUTILS_P_H_INCLUDED -#define ASMJIT_CORE_EMITTERUTILS_P_H_INCLUDED - -#include "../core/emitter.h" -#include "../core/operand.h" - -ASMJIT_BEGIN_NAMESPACE - -class BaseAssembler; - -//! \cond INTERNAL -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::EmitterUtils] -// ============================================================================ - -namespace EmitterUtils { - -static const Operand_ noExt[3] {}; - -enum kOpIndex { - kOp3 = 0, - kOp4 = 1, - kOp5 = 2 -}; - -static ASMJIT_INLINE uint32_t opCountFromEmitArgs(const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) noexcept { - uint32_t opCount = 0; - - if (opExt[kOp3].isNone()) { - if (!o0.isNone()) opCount = 1; - if (!o1.isNone()) opCount = 2; - if (!o2.isNone()) opCount = 3; - } - else { - opCount = 4; - if (!opExt[kOp4].isNone()) { - opCount = 5 + uint32_t(!opExt[kOp5].isNone()); - } - } - - return opCount; -} - -static ASMJIT_INLINE void opArrayFromEmitArgs(Operand_ dst[Globals::kMaxOpCount], const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt) noexcept { - dst[0].copyFrom(o0); - dst[1].copyFrom(o1); - dst[2].copyFrom(o2); - dst[3].copyFrom(opExt[kOp3]); - dst[4].copyFrom(opExt[kOp4]); - dst[5].copyFrom(opExt[kOp5]); -} - -#ifndef ASMJIT_NO_LOGGING -enum : uint32_t { - // Has to be big to be able to hold all metadata compiler can assign to a - // single instruction. - kMaxInstLineSize = 44, - kMaxBinarySize = 26 -}; - -Error formatLine(String& sb, const uint8_t* binData, size_t binSize, size_t dispSize, size_t immSize, const char* comment) noexcept; - -void logLabelBound(BaseAssembler* self, const Label& label) noexcept; - -void logInstructionEmitted( - BaseAssembler* self, - uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt, - uint32_t relSize, uint32_t immSize, uint8_t* afterCursor); - -Error logInstructionFailed( - BaseAssembler* self, - Error err, uint32_t instId, uint32_t options, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* opExt); -#endif - -} - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_EMITTERUTILS_P_H_INCLUDED - diff --git a/ext/asmjit-master/src/asmjit/core/environment.cpp b/ext/asmjit-master/src/asmjit/core/environment.cpp deleted file mode 100644 index 3be2b15a..00000000 --- a/ext/asmjit-master/src/asmjit/core/environment.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/environment.h" - -ASMJIT_BEGIN_NAMESPACE - -// X86 Target -// ---------- -// -// - 32-bit - Linux, OSX, BSD, and apparently also Haiku guarantee 16-byte -// stack alignment. Other operating systems are assumed to have -// 4-byte alignment by default for safety reasons. -// - 64-bit - stack must be aligned to 16 bytes. -// -// ARM Target -// ---------- -// -// - 32-bit - Stack must be aligned to 8 bytes. -// - 64-bit - Stack must be aligned to 16 bytes (hardware requirement). -uint32_t Environment::stackAlignment() const noexcept { - if (is64Bit()) { - // Assume 16-byte alignment on any 64-bit target. - return 16; - } - else { - // The following platforms use 16-byte alignment in 32-bit mode. - if (isPlatformLinux() || - isPlatformBSD() || - isPlatformApple() || - isPlatformHaiku()) { - return 16u; - } - - if (isFamilyARM()) - return 8; - - // Bail to 4-byte alignment if we don't know. - return 4; - } -} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/environment.h b/ext/asmjit-master/src/asmjit/core/environment.h deleted file mode 100644 index 99b34ec9..00000000 --- a/ext/asmjit-master/src/asmjit/core/environment.h +++ /dev/null @@ -1,591 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_ENVIRONMENT_H_INCLUDED -#define ASMJIT_CORE_ENVIRONMENT_H_INCLUDED - -#include "../core/globals.h" - -#if defined(__APPLE__) - #include -#endif - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::Environment] -// ============================================================================ - -//! Represents an environment, which is usually related to a \ref Target. -//! -//! Environment has usually an 'arch-subarch-vendor-os-abi' format, which is -//! sometimes called "Triple" (historically it used to be 3 only parts) or -//! "Tuple", which is a convention used by Debian Linux. -//! -//! AsmJit doesn't support all possible combinations or architectures and ABIs, -//! however, it models the environment similarly to other compilers for future -//! extensibility. -class Environment { -public: - //! Architecture type, see \ref Arch. - uint8_t _arch; - //! Sub-architecture type, see \ref SubArch. - uint8_t _subArch; - //! Vendor type, see \ref Vendor. - uint8_t _vendor; - //! Platform type, see \ref Platform. - uint8_t _platform; - //! ABI type, see \ref Abi. - uint8_t _abi; - //! Object format, see \ref Format. - uint8_t _format; - //! Reserved for future use, must be zero. - uint16_t _reserved; - - //! Architecture. - enum Arch : uint32_t { - //! Unknown or uninitialized architecture. - kArchUnknown = 0, - - //! Mask used by 32-bit architectures (odd are 32-bit, even are 64-bit). - kArch32BitMask = 0x01, - //! Mask used by big-endian architectures. - kArchBigEndianMask = 0x80u, - - //! 32-bit X86 architecture. - kArchX86 = 1, - //! 64-bit X86 architecture also known as X86_64 and AMD64. - kArchX64 = 2, - - //! 32-bit RISC-V architecture. - kArchRISCV32 = 3, - //! 64-bit RISC-V architecture. - kArchRISCV64 = 4, - - //! 32-bit ARM architecture (little endian). - kArchARM = 5, - //! 32-bit ARM architecture (big endian). - kArchARM_BE = kArchARM | kArchBigEndianMask, - //! 64-bit ARM architecture in (little endian). - kArchAArch64 = 6, - //! 64-bit ARM architecture in (big endian). - kArchAArch64_BE = kArchAArch64 | kArchBigEndianMask, - //! 32-bit ARM in Thumb mode (little endian). - kArchThumb = 7, - //! 32-bit ARM in Thumb mode (big endian). - kArchThumb_BE = kArchThumb | kArchBigEndianMask, - - // 8 is not used, even numbers are 64-bit architectures. - - //! 32-bit MIPS architecture in (little endian). - kArchMIPS_LE = 9, - //! 32-bit MIPS architecture in (big endian). - kArchMIPS_BE = kArchMIPS_LE | kArchBigEndianMask, - //! 64-bit MIPS architecture in (little endian). - kArchMIPS64_LE = 10, - //! 64-bit MIPS architecture in (big endian). - kArchMIPS64_BE = kArchMIPS64_LE | kArchBigEndianMask, - - //! Count of architectures. - kArchCount - }; - - //! Sub-architecture. - enum SubArch : uint32_t { - //! Unknown or uninitialized architecture sub-type. - kSubArchUnknown = 0, - - //! Count of sub-architectures. - kSubArchCount - }; - - //! Vendor. - //! - //! \note AsmJit doesn't use vendor information at the moment. It's provided - //! for future use, if required. - enum Vendor : uint32_t { - //! Unknown or uninitialized vendor. - kVendorUnknown = 0, - - //! Count of vendor identifiers. - kVendorCount - }; - - //! Platform / OS. - enum Platform : uint32_t { - //! Unknown or uninitialized platform. - kPlatformUnknown = 0, - - //! Windows OS. - kPlatformWindows, - - //! Other platform, most likely POSIX based. - kPlatformOther, - - //! Linux OS. - kPlatformLinux, - //! GNU/Hurd OS. - kPlatformHurd, - - //! FreeBSD OS. - kPlatformFreeBSD, - //! OpenBSD OS. - kPlatformOpenBSD, - //! NetBSD OS. - kPlatformNetBSD, - //! DragonFly BSD OS. - kPlatformDragonFlyBSD, - - //! Haiku OS. - kPlatformHaiku, - - //! Apple OSX. - kPlatformOSX, - //! Apple iOS. - kPlatformIOS, - //! Apple TVOS. - kPlatformTVOS, - //! Apple WatchOS. - kPlatformWatchOS, - - //! Emscripten platform. - kPlatformEmscripten, - - //! Count of platform identifiers. - kPlatformCount - }; - - //! ABI. - enum Abi : uint32_t { - //! Unknown or uninitialied environment. - kAbiUnknown = 0, - //! Microsoft ABI. - kAbiMSVC, - //! GNU ABI. - kAbiGNU, - //! Android Environment / ABI. - kAbiAndroid, - //! Cygwin ABI. - kAbiCygwin, - - //! Count of known ABI types. - kAbiCount - }; - - //! Object format. - //! - //! \note AsmJit doesn't really use anything except \ref kFormatUnknown and - //! \ref kFormatJIT at the moment. Object file formats are provided for - //! future extensibility and a possibility to generate object files at some - //! point. - enum Format : uint32_t { - //! Unknown or uninitialized object format. - kFormatUnknown = 0, - - //! JIT code generation object, most likely \ref JitRuntime or a custom - //! \ref Target implementation. - kFormatJIT, - - //! Executable and linkable format (ELF). - kFormatELF, - //! Common object file format. - kFormatCOFF, - //! Extended COFF object format. - kFormatXCOFF, - //! Mach object file format. - kFormatMachO, - - //! Count of object format types. - kFormatCount - }; - - //! \name Environment Detection - //! \{ - -#ifdef _DOXYGEN - //! Architecture detected at compile-time (architecture of the host). - static constexpr Arch kArchHost = DETECTED_AT_COMPILE_TIME; - //! Sub-architecture detected at compile-time (sub-architecture of the host). - static constexpr SubArch kSubArchHost = DETECTED_AT_COMPILE_TIME; - //! Vendor detected at compile-time (vendor of the host). - static constexpr Vendor kVendorHost = DETECTED_AT_COMPILE_TIME; - //! Platform detected at compile-time (platform of the host). - static constexpr Platform kPlatformHost = DETECTED_AT_COMPILE_TIME; - //! ABI detected at compile-time (ABI of the host). - static constexpr Abi kAbiHost = DETECTED_AT_COMPILE_TIME; -#else - static constexpr Arch kArchHost = - ASMJIT_ARCH_X86 == 32 ? kArchX86 : - ASMJIT_ARCH_X86 == 64 ? kArchX64 : - - ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_LE ? kArchARM : - ASMJIT_ARCH_ARM == 32 && ASMJIT_ARCH_BE ? kArchARM_BE : - ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_LE ? kArchAArch64 : - ASMJIT_ARCH_ARM == 64 && ASMJIT_ARCH_BE ? kArchAArch64_BE : - - ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_LE ? kArchMIPS_LE : - ASMJIT_ARCH_MIPS == 32 && ASMJIT_ARCH_BE ? kArchMIPS_BE : - ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_LE ? kArchMIPS64_LE : - ASMJIT_ARCH_MIPS == 64 && ASMJIT_ARCH_BE ? kArchMIPS64_BE : - - kArchUnknown; - - static constexpr SubArch kSubArchHost = - kSubArchUnknown; - - static constexpr Vendor kVendorHost = - kVendorUnknown; - - static constexpr Platform kPlatformHost = -#if defined(__EMSCRIPTEN__) - kPlatformEmscripten -#elif defined(_WIN32) - kPlatformWindows -#elif defined(__linux__) - kPlatformLinux -#elif defined(__gnu_hurd__) - kPlatformHurd -#elif defined(__FreeBSD__) - kPlatformFreeBSD -#elif defined(__OpenBSD__) - kPlatformOpenBSD -#elif defined(__NetBSD__) - kPlatformNetBSD -#elif defined(__DragonFly__) - kPlatformDragonFlyBSD -#elif defined(__HAIKU__) - kPlatformHaiku -#elif defined(__APPLE__) && TARGET_OS_OSX - kPlatformOSX -#elif defined(__APPLE__) && TARGET_OS_TV - kPlatformTVOS -#elif defined(__APPLE__) && TARGET_OS_WATCH - kPlatformWatchOS -#elif defined(__APPLE__) && TARGET_OS_IPHONE - kPlatformIOS -#else - kPlatformOther -#endif - ; - - static constexpr Abi kAbiHost = -#if defined(_MSC_VER) - kAbiMSVC -#elif defined(__CYGWIN__) - kAbiCygwin -#elif defined(__MINGW32__) || defined(__GLIBC__) - kAbiGNU -#elif defined(__ANDROID__) - kAbiAndroid -#else - kAbiUnknown -#endif - ; - -#endif - - //! \} - - //! \name Construction / Destruction - //! \{ - - inline Environment() noexcept : - _arch(uint8_t(kArchUnknown)), - _subArch(uint8_t(kSubArchUnknown)), - _vendor(uint8_t(kVendorUnknown)), - _platform(uint8_t(kPlatformUnknown)), - _abi(uint8_t(kAbiUnknown)), - _format(uint8_t(kFormatUnknown)), - _reserved(0) {} - - inline Environment(const Environment& other) noexcept = default; - - inline explicit Environment(uint32_t arch, - uint32_t subArch = kSubArchUnknown, - uint32_t vendor = kVendorUnknown, - uint32_t platform = kPlatformUnknown, - uint32_t abi = kAbiUnknown, - uint32_t format = kFormatUnknown) noexcept { - init(arch, subArch, vendor, platform, abi, format); - } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline Environment& operator=(const Environment& other) noexcept = default; - - inline bool operator==(const Environment& other) const noexcept { return equals(other); } - inline bool operator!=(const Environment& other) const noexcept { return !equals(other); } - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether the environment is not set up. - //! - //! Returns true if all members are zero, and thus unknown. - inline bool empty() const noexcept { - // Unfortunately compilers won't optimize fields are checked one by one... - return _packed() == 0; - } - - //! Tests whether the environment is intialized, which means it must have - //! a valid architecture. - inline bool isInitialized() const noexcept { - return _arch != kArchUnknown; - } - - inline uint64_t _packed() const noexcept { - uint64_t x; - memcpy(&x, this, 8); - return x; - } - - //! Resets all members of the environment to zero / unknown. - inline void reset() noexcept { - _arch = uint8_t(kArchUnknown); - _subArch = uint8_t(kSubArchUnknown); - _vendor = uint8_t(kVendorUnknown); - _platform = uint8_t(kPlatformUnknown); - _abi = uint8_t(kAbiUnknown); - _format = uint8_t(kFormatUnknown); - _reserved = 0; - } - - inline bool equals(const Environment& other) const noexcept { - return _packed() == other._packed(); - } - - //! Returns the architecture, see \ref Arch. - inline uint32_t arch() const noexcept { return _arch; } - //! Returns the sub-architecture, see \ref SubArch. - inline uint32_t subArch() const noexcept { return _subArch; } - //! Returns vendor, see \ref Vendor. - inline uint32_t vendor() const noexcept { return _vendor; } - //! Returns target's platform or operating system, see \ref Platform. - inline uint32_t platform() const noexcept { return _platform; } - //! Returns target's ABI, see \ref Abi. - inline uint32_t abi() const noexcept { return _abi; } - //! Returns target's object format, see \ref Format. - inline uint32_t format() const noexcept { return _format; } - - inline void init(uint32_t arch, - uint32_t subArch = kSubArchUnknown, - uint32_t vendor = kVendorUnknown, - uint32_t platform = kPlatformUnknown, - uint32_t abi = kAbiUnknown, - uint32_t format = kFormatUnknown) noexcept { - _arch = uint8_t(arch); - _subArch = uint8_t(subArch); - _vendor = uint8_t(vendor); - _platform = uint8_t(platform); - _abi = uint8_t(abi); - _format = uint8_t(format); - _reserved = 0; - } - - //! Tests whether the architecture is 32-bit. - inline bool is32Bit() const noexcept { return is32Bit(_arch); } - //! Tests whether the architecture is 64-bit. - inline bool is64Bit() const noexcept { return is64Bit(_arch); } - - //! Tests whether the architecture is little endian. - inline bool isLittleEndian() const noexcept { return isLittleEndian(_arch); } - //! Tests whether the architecture is big endian. - inline bool isBigEndian() const noexcept { return isBigEndian(_arch); } - - //! Tests whether this architecture is of X86 family. - inline bool isFamilyX86() const noexcept { return isFamilyX86(_arch); } - //! Tests whether this architecture is of ARM family. - inline bool isFamilyRISCV() const noexcept { return isFamilyRISCV(_arch); } - //! Tests whether this architecture is of ARM family. - inline bool isFamilyARM() const noexcept { return isFamilyARM(_arch); } - //! Tests whether this architecture is of ARM family. - inline bool isFamilyMIPS() const noexcept { return isFamilyMIPS(_arch); } - - //! Tests whether the environment platform is Windows. - inline bool isPlatformWindows() const noexcept { return _platform == kPlatformWindows; } - - //! Tests whether the environment platform is Linux. - inline bool isPlatformLinux() const noexcept { return _platform == kPlatformLinux; } - - //! Tests whether the environment platform is Hurd. - inline bool isPlatformHurd() const noexcept { return _platform == kPlatformHurd; } - - //! Tests whether the environment platform is Haiku. - inline bool isPlatformHaiku() const noexcept { return _platform == kPlatformHaiku; } - - //! Tests whether the environment platform is any BSD. - inline bool isPlatformBSD() const noexcept { - return _platform == kPlatformFreeBSD || - _platform == kPlatformOpenBSD || - _platform == kPlatformNetBSD || - _platform == kPlatformDragonFlyBSD; - } - - //! Tests whether the environment platform is any Apple platform (OSX, iOS, TVOS, WatchOS). - inline bool isPlatformApple() const noexcept { - return _platform == kPlatformOSX || - _platform == kPlatformIOS || - _platform == kPlatformTVOS || - _platform == kPlatformWatchOS; - } - - //! Tests whether the ABI is MSVC. - inline bool isAbiMSVC() const noexcept { return _abi == kAbiMSVC; } - //! Tests whether the ABI is GNU. - inline bool isAbiGNU() const noexcept { return _abi == kAbiGNU; } - - //! Returns a calculated stack alignment for this environment. - ASMJIT_API uint32_t stackAlignment() const noexcept; - - //! Returns a native register size of this architecture. - uint32_t registerSize() const noexcept { return registerSizeFromArch(_arch); } - - //! Sets the architecture to `arch`. - inline void setArch(uint32_t arch) noexcept { _arch = uint8_t(arch); } - //! Sets the sub-architecture to `subArch`. - inline void setSubArch(uint32_t subArch) noexcept { _subArch = uint8_t(subArch); } - //! Sets the vendor to `vendor`. - inline void setVendor(uint32_t vendor) noexcept { _vendor = uint8_t(vendor); } - //! Sets the platform to `platform`. - inline void setPlatform(uint32_t platform) noexcept { _platform = uint8_t(platform); } - //! Sets the ABI to `abi`. - inline void setAbi(uint32_t abi) noexcept { _abi = uint8_t(abi); } - //! Sets the object format to `format`. - inline void setFormat(uint32_t format) noexcept { _format = uint8_t(format); } - - //! \} - - //! \name Static Utilities - //! \{ - - //! Tests whether the given architecture `arch` is 32-bit. - static inline bool is32Bit(uint32_t arch) noexcept { - return (arch & kArch32BitMask) == kArch32BitMask; - } - - //! Tests whether the given architecture `arch` is 64-bit. - static inline bool is64Bit(uint32_t arch) noexcept { - return (arch & kArch32BitMask) == 0; - } - - //! Tests whether the given architecture `arch` is little endian. - static inline bool isLittleEndian(uint32_t arch) noexcept { - return (arch & kArchBigEndianMask) == 0; - } - - //! Tests whether the given architecture `arch` is big endian. - static inline bool isBigEndian(uint32_t arch) noexcept { - return (arch & kArchBigEndianMask) == kArchBigEndianMask; - } - - //! Tests whether the given architecture family is X86 or X64. - static inline bool isFamilyX86(uint32_t arch) noexcept { - return arch == kArchX86 || - arch == kArchX64; - } - - //! Tests whether the given architecture family is RISC-V (both 32-bit and 64-bit). - static inline bool isFamilyRISCV(uint32_t arch) noexcept { - return arch == kArchRISCV32 || - arch == kArchRISCV64; - } - - //! Tests whether the given architecture family is ARM, Thumb, or AArch64. - static inline bool isFamilyARM(uint32_t arch) noexcept { - arch &= ~kArchBigEndianMask; - return arch == kArchARM || - arch == kArchAArch64 || - arch == kArchThumb; - } - - //! Tests whether the given architecture family is MISP or MIPS64. - static inline bool isFamilyMIPS(uint32_t arch) noexcept { - arch &= ~kArchBigEndianMask; - return arch == kArchMIPS_LE || - arch == kArchMIPS64_LE; - } - - //! Returns a native general purpose register size from the given architecture. - static uint32_t registerSizeFromArch(uint32_t arch) noexcept { - return is32Bit(arch) ? 4u : 8u; - } - - //! \} -}; - -//! Returns the host environment constructed from preprocessor macros defined -//! by the compiler. -//! -//! The returned environment should precisely match the target host architecture, -//! sub-architecture, platform, and ABI. -static ASMJIT_INLINE Environment hostEnvironment() noexcept { - return Environment(Environment::kArchHost, - Environment::kSubArchHost, - Environment::kVendorHost, - Environment::kPlatformHost, - Environment::kAbiHost, - Environment::kFormatUnknown); -} - -static_assert(sizeof(Environment) == 8, - "Environment must occupy exactly 8 bytes."); - -//! \} - -#ifndef ASMJIT_NO_DEPRECATED -class ASMJIT_DEPRECATED_STRUCT("Use Environment instead") ArchInfo : public Environment { -public: - inline ArchInfo() noexcept : Environment() {} - - inline ArchInfo(const Environment& other) noexcept : Environment(other) {} - inline explicit ArchInfo(uint32_t arch, uint32_t subArch = kSubArchUnknown) noexcept - : Environment(arch, subArch) {} - - enum Id : uint32_t { - kIdNone = Environment::kArchUnknown, - kIdX86 = Environment::kArchX86, - kIdX64 = Environment::kArchX64, - kIdA32 = Environment::kArchARM, - kIdA64 = Environment::kArchAArch64, - kIdHost = Environment::kArchHost - }; - - enum SubType : uint32_t { - kSubIdNone = Environment::kSubArchUnknown - }; - - static inline ArchInfo host() noexcept { return ArchInfo(hostEnvironment()); } -}; -#endif // !ASMJIT_NO_DEPRECATED - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_ENVIRONMENT_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/errorhandler.cpp b/ext/asmjit-master/src/asmjit/core/errorhandler.cpp deleted file mode 100644 index 8372d75a..00000000 --- a/ext/asmjit-master/src/asmjit/core/errorhandler.cpp +++ /dev/null @@ -1,37 +0,0 @@ - -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/errorhandler.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::ErrorHandler] -// ============================================================================ - -ErrorHandler::ErrorHandler() noexcept {} -ErrorHandler::~ErrorHandler() noexcept {} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/errorhandler.h b/ext/asmjit-master/src/asmjit/core/errorhandler.h deleted file mode 100644 index 2337cd8d..00000000 --- a/ext/asmjit-master/src/asmjit/core/errorhandler.h +++ /dev/null @@ -1,267 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_ERRORHANDLER_H_INCLUDED -#define ASMJIT_CORE_ERRORHANDLER_H_INCLUDED - -#include "../core/globals.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_error_handling -//! \{ - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class BaseEmitter; - -// ============================================================================ -// [asmjit::ErrorHandler] -// ============================================================================ - -//! Error handler can be used to override the default behavior of error handling. -//! -//! It's available to all classes that inherit `BaseEmitter`. Override -//! \ref ErrorHandler::handleError() to implement your own error handler. -//! -//! The following use-cases are supported: -//! -//! - Record the error and continue code generation. This is the simplest -//! approach that can be used to at least log possible errors. -//! - Throw an exception. AsmJit doesn't use exceptions and is completely -//! exception-safe, but it's perfectly legal to throw an exception from -//! the error handler. -//! - Use plain old C's `setjmp()` and `longjmp()`. Asmjit always puts Assembler, -//! Builder and Compiler to a consistent state before calling \ref handleError(), -//! so `longjmp()` can be used without issues to cancel the code-generation if -//! an error occurred. This method can be used if exception handling in your -//! project is turned off and you still want some comfort. In most cases it -//! should be safe as AsmJit uses \ref Zone memory and the ownership of memory -//! it allocates always ends with the instance that allocated it. If using this -//! approach please never jump outside the life-time of \ref CodeHolder and -//! \ref BaseEmitter. -//! -//! \ref ErrorHandler can be attached to \ref CodeHolder or \ref BaseEmitter, -//! which has a priority. The example below uses error handler that just prints -//! the error, but lets AsmJit continue: -//! -//! ``` -//! // Error Handling #1 - Logging and returing Error. -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! // Error handler that just prints the error and lets AsmJit ignore it. -//! class SimpleErrorHandler : public ErrorHandler { -//! public: -//! Error err; -//! -//! inline SimpleErrorHandler() : err(kErrorOk) {} -//! -//! void handleError(Error err, const char* message, BaseEmitter* origin) override { -//! this->err = err; -//! fprintf(stderr, "ERROR: %s\n", message); -//! } -//! }; -//! -//! int main() { -//! JitRuntime rt; -//! SimpleErrorHandler eh; -//! -//! CodeHolder code; -//! code.init(rt.environment()); -//! code.setErrorHandler(&eh); -//! -//! // Try to emit instruction that doesn't exist. -//! x86::Assembler a(&code); -//! a.emit(x86::Inst::kIdMov, x86::xmm0, x86::xmm1); -//! -//! if (eh.err) { -//! // Assembler failed! -//! return 1; -//! } -//! -//! return 0; -//! } -//! ``` -//! -//! If error happens during instruction emitting / encoding the assembler behaves -//! transactionally - the output buffer won't advance if encoding failed, thus -//! either a fully encoded instruction or nothing is emitted. The error handling -//! shown above is useful, but it's still not the best way of dealing with errors -//! in AsmJit. The following example shows how to use exception handling to handle -//! errors in a more C++ way: -//! -//! ``` -//! // Error Handling #2 - Throwing an exception. -//! #include -//! #include -//! #include -//! #include -//! -//! using namespace asmjit; -//! -//! // Error handler that throws a user-defined `AsmJitException`. -//! class AsmJitException : public std::exception { -//! public: -//! Error err; -//! std::string message; -//! -//! AsmJitException(Error err, const char* message) noexcept -//! : err(err), -//! message(message) {} -//! -//! const char* what() const noexcept override { return message.c_str(); } -//! }; -//! -//! class ThrowableErrorHandler : public ErrorHandler { -//! public: -//! // Throw is possible, functions that use ErrorHandler are never 'noexcept'. -//! void handleError(Error err, const char* message, BaseEmitter* origin) override { -//! throw AsmJitException(err, message); -//! } -//! }; -//! -//! int main() { -//! JitRuntime rt; -//! ThrowableErrorHandler eh; -//! -//! CodeHolder code; -//! code.init(rt.environment()); -//! code.setErrorHandler(&eh); -//! -//! x86::Assembler a(&code); -//! -//! // Try to emit instruction that doesn't exist. -//! try { -//! a.emit(x86::Inst::kIdMov, x86::xmm0, x86::xmm1); -//! } -//! catch (const AsmJitException& ex) { -//! printf("EXCEPTION THROWN: %s\n", ex.what()); -//! return 1; -//! } -//! -//! return 0; -//! } -//! ``` -//! -//! If C++ exceptions are not what you like or your project turns off them -//! completely there is still a way of reducing the error handling to a minimum -//! by using a standard setjmp/longjmp approach. AsmJit is exception-safe and -//! cleans up everything before calling the ErrorHandler, so any approach is -//! safe. You can simply jump from the error handler without causing any -//! side-effects or memory leaks. The following example demonstrates how it -//! could be done: -//! -//! ``` -//! // Error Handling #3 - Using setjmp/longjmp if exceptions are not allowed. -//! #include -//! #include -//! #include -//! -//! class LongJmpErrorHandler : public asmjit::ErrorHandler { -//! public: -//! inline LongJmpErrorHandler() : err(asmjit::kErrorOk) {} -//! -//! void handleError(asmjit::Error err, const char* message, asmjit::BaseEmitter* origin) override { -//! this->err = err; -//! longjmp(state, 1); -//! } -//! -//! jmp_buf state; -//! asmjit::Error err; -//! }; -//! -//! int main(int argc, char* argv[]) { -//! using namespace asmjit; -//! -//! JitRuntime rt; -//! LongJmpErrorHandler eh; -//! -//! CodeHolder code; -//! code.init(rt.rt.environment()); -//! code.setErrorHandler(&eh); -//! -//! x86::Assembler a(&code); -//! -//! if (!setjmp(eh.state)) { -//! // Try to emit instruction that doesn't exist. -//! a.emit(x86::Inst::kIdMov, x86::xmm0, x86::xmm1); -//! } -//! else { -//! Error err = eh.err; -//! printf("ASMJIT ERROR: 0x%08X [%s]\n", err, DebugUtils::errorAsString(err)); -//! } -//! -//! return 0; -//! } -//! ``` -class ASMJIT_VIRTAPI ErrorHandler { -public: - ASMJIT_BASE_CLASS(ErrorHandler) - - // -------------------------------------------------------------------------- - // [Construction / Destruction] - // -------------------------------------------------------------------------- - - //! Creates a new `ErrorHandler` instance. - ASMJIT_API ErrorHandler() noexcept; - //! Destroys the `ErrorHandler` instance. - ASMJIT_API virtual ~ErrorHandler() noexcept; - - // -------------------------------------------------------------------------- - // [Handle Error] - // -------------------------------------------------------------------------- - - //! Error handler (must be reimplemented). - //! - //! Error handler is called after an error happened and before it's propagated - //! to the caller. There are multiple ways how the error handler can be used: - //! - //! 1. User-based error handling without throwing exception or using C's - //! `longjmp()`. This is for users that don't use exceptions and want - //! customized error handling. - //! - //! 2. Throwing an exception. AsmJit doesn't use exceptions and is completely - //! exception-safe, but you can throw exception from your error handler if - //! this way is the preferred way of handling errors in your project. - //! - //! 3. Using plain old C's `setjmp()` and `longjmp()`. Asmjit always puts - //! `BaseEmitter` to a consistent state before calling `handleError()` - //! so `longjmp()` can be used without any issues to cancel the code - //! generation if an error occurred. There is no difference between - //! exceptions and `longjmp()` from AsmJit's perspective, however, - //! never jump outside of `CodeHolder` and `BaseEmitter` scope as you - //! would leak memory. - virtual void handleError(Error err, const char* message, BaseEmitter* origin) = 0; -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_ERRORHANDLER_H_INCLUDED - diff --git a/ext/asmjit-master/src/asmjit/core/features.h b/ext/asmjit-master/src/asmjit/core/features.h deleted file mode 100644 index fd28472c..00000000 --- a/ext/asmjit-master/src/asmjit/core/features.h +++ /dev/null @@ -1,186 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_FEATURES_H_INCLUDED -#define ASMJIT_CORE_FEATURES_H_INCLUDED - -#include "../core/globals.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_core -//! \{ - -// ============================================================================ -// [asmjit::BaseFeatures] -// ============================================================================ - -//! Base class that provides information about CPU features. -//! -//! Internally each feature is repreesnted by a single bit in an embedded -//! bit-array, however, feature bits are defined by an architecture specific -//! implementations, like \ref x86::Features. -class BaseFeatures { -public: - typedef Support::BitWord BitWord; - typedef Support::BitVectorIterator Iterator; - - enum : uint32_t { - kMaxFeatures = 128, - kNumBitWords = kMaxFeatures / Support::kBitWordSizeInBits - }; - - BitWord _bits[kNumBitWords]; - - //! \name Construction & Destruction - //! \{ - - inline BaseFeatures() noexcept { reset(); } - inline BaseFeatures(const BaseFeatures& other) noexcept = default; - inline explicit BaseFeatures(Globals::NoInit_) noexcept {} - - inline void reset() noexcept { - for (size_t i = 0; i < kNumBitWords; i++) - _bits[i] = 0; - } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline BaseFeatures& operator=(const BaseFeatures& other) noexcept = default; - - inline bool operator==(const BaseFeatures& other) noexcept { return eq(other); } - inline bool operator!=(const BaseFeatures& other) noexcept { return !eq(other); } - - //! \} - - //! \name Cast - //! \{ - - //! Casts this base class into a derived type `T`. - template - inline T& as() noexcept { return static_cast(*this); } - - //! Casts this base class into a derived type `T` (const). - template - inline const T& as() const noexcept { return static_cast(*this); } - - //! \} - - //! \name Accessors - //! \{ - - inline bool empty() const noexcept { - for (uint32_t i = 0; i < kNumBitWords; i++) - if (_bits[i]) - return false; - return true; - } - - //! Returns all features as array of bitwords (see \ref Support::BitWord). - inline BitWord* bits() noexcept { return _bits; } - //! Returns all features as array of bitwords (const). - inline const BitWord* bits() const noexcept { return _bits; } - - //! Returns the number of BitWords returned by \ref bits(). - inline size_t bitWordCount() const noexcept { return kNumBitWords; } - - //! Returns \ref Support::BitVectorIterator, that can be used to iterate - //! all features efficiently - inline Iterator iterator() const noexcept { - return Iterator(_bits, kNumBitWords); - } - - //! Tests whether the feature `featureId` is present. - inline bool has(uint32_t featureId) const noexcept { - ASMJIT_ASSERT(featureId < kMaxFeatures); - - uint32_t idx = featureId / Support::kBitWordSizeInBits; - uint32_t bit = featureId % Support::kBitWordSizeInBits; - - return bool((_bits[idx] >> bit) & 0x1); - } - - //! Tests whether all features as defined by `other` are present. - inline bool hasAll(const BaseFeatures& other) const noexcept { - for (uint32_t i = 0; i < kNumBitWords; i++) - if ((_bits[i] & other._bits[i]) != other._bits[i]) - return false; - return true; - } - - //! \} - - //! \name Utilities - //! \{ - - //! Adds the given CPU `featureId` to the list of features. - inline void add(uint32_t featureId) noexcept { - ASMJIT_ASSERT(featureId < kMaxFeatures); - - uint32_t idx = featureId / Support::kBitWordSizeInBits; - uint32_t bit = featureId % Support::kBitWordSizeInBits; - - _bits[idx] |= BitWord(1) << bit; - } - - template - inline void add(uint32_t featureId, Args... otherIds) noexcept { - add(featureId); - add(otherIds...); - } - - //! Removes the given CPU `featureId` from the list of features. - inline void remove(uint32_t featureId) noexcept { - ASMJIT_ASSERT(featureId < kMaxFeatures); - - uint32_t idx = featureId / Support::kBitWordSizeInBits; - uint32_t bit = featureId % Support::kBitWordSizeInBits; - - _bits[idx] &= ~(BitWord(1) << bit); - } - - template - inline void remove(uint32_t featureId, Args... otherIds) noexcept { - remove(featureId); - remove(otherIds...); - } - - inline bool eq(const BaseFeatures& other) const noexcept { - for (size_t i = 0; i < kNumBitWords; i++) - if (_bits[i] != other._bits[i]) - return false; - return true; - } - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_FEATURES_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/formatter.cpp b/ext/asmjit-master/src/asmjit/core/formatter.cpp deleted file mode 100644 index 404edaf3..00000000 --- a/ext/asmjit-master/src/asmjit/core/formatter.cpp +++ /dev/null @@ -1,469 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_LOGGING - -#include "../core/builder.h" -#include "../core/codeholder.h" -#include "../core/compiler.h" -#include "../core/emitter.h" -#include "../core/formatter.h" -#include "../core/string.h" -#include "../core/support.h" -#include "../core/type.h" - -#ifdef ASMJIT_BUILD_X86 - #include "../x86/x86formatter_p.h" -#endif - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/armformatter_p.h" -#endif - -ASMJIT_BEGIN_NAMESPACE - -#if defined(ASMJIT_NO_COMPILER) -class VirtReg; -#endif - -// ============================================================================ -// [asmjit::Formatter] -// ============================================================================ - -namespace Formatter { - -Error formatTypeId(String& sb, uint32_t typeId) noexcept { - if (typeId == Type::kIdVoid) - return sb.append("void"); - - if (!Type::isValid(typeId)) - return sb.append("unknown"); - - const char* typeName = "unknown"; - uint32_t typeSize = Type::sizeOf(typeId); - - uint32_t baseId = Type::baseOf(typeId); - switch (baseId) { - case Type::kIdIntPtr : typeName = "iptr" ; break; - case Type::kIdUIntPtr: typeName = "uptr" ; break; - case Type::kIdI8 : typeName = "i8" ; break; - case Type::kIdU8 : typeName = "u8" ; break; - case Type::kIdI16 : typeName = "i16" ; break; - case Type::kIdU16 : typeName = "u16" ; break; - case Type::kIdI32 : typeName = "i32" ; break; - case Type::kIdU32 : typeName = "u32" ; break; - case Type::kIdI64 : typeName = "i64" ; break; - case Type::kIdU64 : typeName = "u64" ; break; - case Type::kIdF32 : typeName = "f32" ; break; - case Type::kIdF64 : typeName = "f64" ; break; - case Type::kIdF80 : typeName = "f80" ; break; - case Type::kIdMask8 : typeName = "mask8" ; break; - case Type::kIdMask16 : typeName = "mask16"; break; - case Type::kIdMask32 : typeName = "mask32"; break; - case Type::kIdMask64 : typeName = "mask64"; break; - case Type::kIdMmx32 : typeName = "mmx32" ; break; - case Type::kIdMmx64 : typeName = "mmx64" ; break; - } - - uint32_t baseSize = Type::sizeOf(baseId); - if (typeSize > baseSize) { - uint32_t count = typeSize / baseSize; - return sb.appendFormat("%sx%u", typeName, unsigned(count)); - } - else { - return sb.append(typeName); - } -} - -Error formatFeature( - String& sb, - uint32_t arch, - uint32_t featureId) noexcept { - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::FormatterInternal::formatFeature(sb, featureId); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::FormatterInternal::formatFeature(sb, featureId); -#endif - - return kErrorInvalidArch; -} - -Error formatLabel( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t labelId) noexcept { - - DebugUtils::unused(formatFlags); - - const LabelEntry* le = emitter->code()->labelEntry(labelId); - if (ASMJIT_UNLIKELY(!le)) - return sb.appendFormat("", labelId); - - if (le->hasName()) { - if (le->hasParent()) { - uint32_t parentId = le->parentId(); - const LabelEntry* pe = emitter->code()->labelEntry(parentId); - - if (ASMJIT_UNLIKELY(!pe)) - ASMJIT_PROPAGATE(sb.appendFormat("", labelId)); - else if (ASMJIT_UNLIKELY(!pe->hasName())) - ASMJIT_PROPAGATE(sb.appendFormat("L%u", parentId)); - else - ASMJIT_PROPAGATE(sb.append(pe->name())); - - ASMJIT_PROPAGATE(sb.append('.')); - } - return sb.append(le->name()); - } - else { - return sb.appendFormat("L%u", labelId); - } -} - -Error formatRegister( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - uint32_t regType, - uint32_t regId) noexcept { - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::FormatterInternal::formatRegister(sb, formatFlags, emitter, arch, regType, regId); -#endif - - return kErrorInvalidArch; -} - -Error formatOperand( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - const Operand_& op) noexcept { - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::FormatterInternal::formatOperand(sb, formatFlags, emitter, arch, op); -#endif - - return kErrorInvalidArch; -} - -Error formatInstruction( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept { - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::FormatterInternal::formatInstruction(sb, formatFlags, emitter, arch, inst, operands, opCount); -#endif - - return kErrorInvalidArch; -} - -#ifndef ASMJIT_NO_BUILDER -static Error formatFuncValue(String& sb, uint32_t formatFlags, const BaseEmitter* emitter, FuncValue value) noexcept { - uint32_t typeId = value.typeId(); - ASMJIT_PROPAGATE(formatTypeId(sb, typeId)); - - if (value.isAssigned()) { - ASMJIT_PROPAGATE(sb.append('@')); - - if (value.isIndirect()) - ASMJIT_PROPAGATE(sb.append('[')); - - // NOTE: It should be either reg or stack, but never both. We - // use two IFs on purpose so if the FuncValue is both it would - // show in logs. - if (value.isReg()) { - ASMJIT_PROPAGATE(formatRegister(sb, formatFlags, emitter, emitter->arch(), value.regType(), value.regId())); - } - - if (value.isStack()) { - ASMJIT_PROPAGATE(sb.appendFormat("[%d]", int(value.stackOffset()))); - } - - if (value.isIndirect()) - ASMJIT_PROPAGATE(sb.append(']')); - } - - return kErrorOk; -} - -static Error formatFuncRets( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - const FuncDetail& fd, - VirtReg* const* vRegs) noexcept { - - if (!fd.hasRet()) - return sb.append("void"); - - for (uint32_t i = 0; i < fd.retCount(); i++) { - if (i) ASMJIT_PROPAGATE(sb.append(", ")); - ASMJIT_PROPAGATE(formatFuncValue(sb, formatFlags, emitter, fd.ret(i))); - -#ifndef ASMJIT_NO_COMPILER - if (vRegs) { - static const char nullRet[] = ""; - ASMJIT_PROPAGATE(sb.appendFormat(" %s", vRegs[i] ? vRegs[i]->name() : nullRet)); - } -#else - DebugUtils::unused(vRegs); -#endif - } - - return kErrorOk; -} - -static Error formatFuncArgs( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - const FuncDetail& fd, - VirtReg* const* vRegs) noexcept { - - uint32_t count = fd.argCount(); - if (!count) - return sb.append("void"); - - for (uint32_t i = 0; i < count; i++) { - if (i) - ASMJIT_PROPAGATE(sb.append(", ")); - - ASMJIT_PROPAGATE(formatFuncValue(sb, formatFlags, emitter, fd.arg(i))); - -#ifndef ASMJIT_NO_COMPILER - if (vRegs) { - static const char nullArg[] = ""; - ASMJIT_PROPAGATE(sb.appendFormat(" %s", vRegs[i] ? vRegs[i]->name() : nullArg)); - } -#else - DebugUtils::unused(vRegs); -#endif - } - - return kErrorOk; -} - -Error formatNode( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder, - const BaseNode* node) noexcept { - - if (node->hasPosition() && (formatFlags & FormatOptions::kFlagPositions) != 0) - ASMJIT_PROPAGATE(sb.appendFormat("<%05u> ", node->position())); - - switch (node->type()) { - case BaseNode::kNodeInst: - case BaseNode::kNodeJump: { - const InstNode* instNode = node->as(); - ASMJIT_PROPAGATE( - formatInstruction(sb, formatFlags, builder, - builder->arch(), - instNode->baseInst(), instNode->operands(), instNode->opCount())); - break; - } - - case BaseNode::kNodeSection: { - const SectionNode* sectionNode = node->as(); - if (builder->_code->isSectionValid(sectionNode->id())) { - const Section* section = builder->_code->sectionById(sectionNode->id()); - ASMJIT_PROPAGATE(sb.appendFormat(".section %s", section->name())); - } - break; - } - - case BaseNode::kNodeLabel: { - const LabelNode* labelNode = node->as(); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, labelNode->labelId())); - ASMJIT_PROPAGATE(sb.append(":")); - break; - } - - case BaseNode::kNodeAlign: { - const AlignNode* alignNode = node->as(); - ASMJIT_PROPAGATE( - sb.appendFormat("align %u (%s)", - alignNode->alignment(), - alignNode->alignMode() == kAlignCode ? "code" : "data")); - break; - } - - case BaseNode::kNodeEmbedData: { - const EmbedDataNode* embedNode = node->as(); - ASMJIT_PROPAGATE(sb.append("embed ")); - if (embedNode->repeatCount() != 1) - ASMJIT_PROPAGATE(sb.appendFormat("[repeat=%zu] ", size_t(embedNode->repeatCount()))); - ASMJIT_PROPAGATE(sb.appendFormat("%u bytes", embedNode->dataSize())); - break; - } - - case BaseNode::kNodeEmbedLabel: { - const EmbedLabelNode* embedNode = node->as(); - ASMJIT_PROPAGATE(sb.append(".label ")); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->labelId())); - break; - } - - case BaseNode::kNodeEmbedLabelDelta: { - const EmbedLabelDeltaNode* embedNode = node->as(); - ASMJIT_PROPAGATE(sb.append(".label (")); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->labelId())); - ASMJIT_PROPAGATE(sb.append(" - ")); - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, embedNode->baseLabelId())); - ASMJIT_PROPAGATE(sb.append(")")); - break; - } - - case BaseNode::kNodeComment: { - const CommentNode* commentNode = node->as(); - ASMJIT_PROPAGATE(sb.appendFormat("; %s", commentNode->inlineComment())); - break; - } - - case BaseNode::kNodeSentinel: { - const SentinelNode* sentinelNode = node->as(); - const char* sentinelName = nullptr; - - switch (sentinelNode->sentinelType()) { - case SentinelNode::kSentinelFuncEnd: - sentinelName = "[FuncEnd]"; - break; - - default: - sentinelName = "[Sentinel]"; - break; - } - - ASMJIT_PROPAGATE(sb.append(sentinelName)); - break; - } - -#ifndef ASMJIT_NO_COMPILER - case BaseNode::kNodeFunc: { - const FuncNode* funcNode = node->as(); - - ASMJIT_PROPAGATE(formatLabel(sb, formatFlags, builder, funcNode->labelId())); - ASMJIT_PROPAGATE(sb.append(": ")); - - ASMJIT_PROPAGATE(formatFuncRets(sb, formatFlags, builder, funcNode->detail(), nullptr)); - ASMJIT_PROPAGATE(sb.append(" Func(")); - ASMJIT_PROPAGATE(formatFuncArgs(sb, formatFlags, builder, funcNode->detail(), funcNode->args())); - ASMJIT_PROPAGATE(sb.append(")")); - break; - } - - case BaseNode::kNodeFuncRet: { - const FuncRetNode* retNode = node->as(); - ASMJIT_PROPAGATE(sb.append("[FuncRet]")); - - for (uint32_t i = 0; i < 2; i++) { - const Operand_& op = retNode->_opArray[i]; - if (!op.isNone()) { - ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", ")); - ASMJIT_PROPAGATE(formatOperand(sb, formatFlags, builder, builder->arch(), op)); - } - } - break; - } - - case BaseNode::kNodeInvoke: { - const InvokeNode* invokeNode = node->as(); - ASMJIT_PROPAGATE( - formatInstruction(sb, formatFlags, builder, - builder->arch(), - invokeNode->baseInst(), invokeNode->operands(), invokeNode->opCount())); - break; - } -#endif - - default: { - ASMJIT_PROPAGATE(sb.appendFormat("[UserNode:%u]", node->type())); - break; - } - } - - return kErrorOk; -} - - -Error formatNodeList( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder) noexcept { - - return formatNodeList(sb, formatFlags, builder, builder->firstNode(), nullptr); -} - -Error formatNodeList( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder, - const BaseNode* begin, - const BaseNode* end) noexcept { - - const BaseNode* node = begin; - while (node != end) { - ASMJIT_PROPAGATE(formatNode(sb, formatFlags, builder, node)); - ASMJIT_PROPAGATE(sb.append('\n')); - node = node->next(); - } - return kErrorOk; -} -#endif - -} // {Formatter} - -ASMJIT_END_NAMESPACE - -#endif diff --git a/ext/asmjit-master/src/asmjit/core/formatter.h b/ext/asmjit-master/src/asmjit/core/formatter.h deleted file mode 100644 index 81d1c77c..00000000 --- a/ext/asmjit-master/src/asmjit/core/formatter.h +++ /dev/null @@ -1,252 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_FORMATTER_H_INCLUDED -#define ASMJIT_CORE_FORMATTER_H_INCLUDED - -#include "../core/inst.h" -#include "../core/string.h" - -#ifndef ASMJIT_NO_LOGGING - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_logging -//! \{ - -// ============================================================================ -// [Forward Declarations] -// ============================================================================ - -class BaseEmitter; -struct Operand_; - -#ifndef ASMJIT_NO_BUILDER -class BaseBuilder; -class BaseNode; -#endif - -// ============================================================================ -// [asmjit::FormatOptions] -// ============================================================================ - -//! Formatting options used by \ref Logger and \ref Formatter. -class FormatOptions { -public: - //! Format flags, see \ref Flags. - uint32_t _flags; - //! Indentation by type, see \ref IndentationType. - uint8_t _indentation[4]; - - //! Flags can enable a logging feature. - enum Flags : uint32_t { - //! No flags. - kNoFlags = 0u, - - //! Show also binary form of each logged instruction (Assembler). - kFlagMachineCode = 0x00000001u, - //! Show a text explanation of some immediate values. - kFlagExplainImms = 0x00000002u, - //! Use hexadecimal notation of immediate values. - kFlagHexImms = 0x00000004u, - //! Use hexadecimal notation of address offsets. - kFlagHexOffsets = 0x00000008u, - //! Show casts between virtual register types (Compiler). - kFlagRegCasts = 0x00000010u, - //! Show positions associated with nodes (Compiler). - kFlagPositions = 0x00000020u, - //! Annotate nodes that are lowered by passes. - kFlagAnnotations = 0x00000040u, - - // TODO: These must go, keep this only for formatting. - //! Show an additional output from passes. - kFlagDebugPasses = 0x00000080u, - //! Show an additional output from RA. - kFlagDebugRA = 0x00000100u - }; - - //! Describes indentation type of code, label, or comment in logger output. - enum IndentationType : uint32_t { - //! Indentation used for instructions and directives. - kIndentationCode = 0u, - //! Indentation used for labels and function nodes. - kIndentationLabel = 1u, - //! Indentation used for comments (not inline comments). - kIndentationComment = 2u, - //! \cond INTERNAL - //! Reserved for future use. - kIndentationReserved = 3u - //! \endcond - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a default-initialized FormatOptions. - constexpr FormatOptions() noexcept - : _flags(0), - _indentation { 0, 0, 0, 0 } {} - - constexpr FormatOptions(const FormatOptions& other) noexcept = default; - inline FormatOptions& operator=(const FormatOptions& other) noexcept = default; - - //! Resets FormatOptions to its default initialized state. - inline void reset() noexcept { - _flags = 0; - _indentation[0] = 0; - _indentation[1] = 0; - _indentation[2] = 0; - _indentation[3] = 0; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns format flags. - constexpr uint32_t flags() const noexcept { return _flags; } - //! Tests whether the given `flag` is set in format flags. - constexpr bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; } - //! Resets all format flags to `flags`. - inline void setFlags(uint32_t flags) noexcept { _flags = flags; } - //! Adds `flags` to format flags. - inline void addFlags(uint32_t flags) noexcept { _flags |= flags; } - //! Removes `flags` from format flags. - inline void clearFlags(uint32_t flags) noexcept { _flags &= ~flags; } - - //! Returns indentation for the given `type`, see \ref IndentationType. - constexpr uint8_t indentation(uint32_t type) const noexcept { return _indentation[type]; } - //! Sets indentation for the given `type`, see \ref IndentationType. - inline void setIndentation(uint32_t type, uint32_t n) noexcept { _indentation[type] = uint8_t(n); } - //! Resets indentation for the given `type` to zero. - inline void resetIndentation(uint32_t type) noexcept { _indentation[type] = uint8_t(0); } - - //! \} -}; - -// ============================================================================ -// [asmjit::Formatter] -// ============================================================================ - -//! Provides formatting functionality to format operands, instructions, and nodes. -namespace Formatter { - -//! Appends a formatted `typeId` to the output string `sb`. -ASMJIT_API Error formatTypeId( - String& sb, - uint32_t typeId) noexcept; - -//! Appends a formatted `featureId` to the output string `sb`. -//! -//! See \ref BaseFeatures. -ASMJIT_API Error formatFeature( - String& sb, - uint32_t arch, - uint32_t featureId) noexcept; - -//! Appends a formatted register to the output string `sb`. -//! -//! \note Emitter is optional, but it's required to format virtual registers, -//! which won't be formatted properly if the `emitter` is not provided. -ASMJIT_API Error formatRegister( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - uint32_t regType, - uint32_t regId) noexcept; - -//! Appends a formatted label to the output string `sb`. -//! -//! \note Emitter is optional, but it's required to format named labels -//! properly, otherwise the formatted as it is an anonymous label. -ASMJIT_API Error formatLabel( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t labelId) noexcept; - -//! Appends a formatted operand to the output string `sb`. -//! -//! \note Emitter is optional, but it's required to format named labels and -//! virtual registers. See \ref formatRegister() and \ref formatLabel() for -//! more details. -ASMJIT_API Error formatOperand( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - const Operand_& op) noexcept; - -//! Appends a formatted instruction to the output string `sb`. -//! -//! \note Emitter is optional, but it's required to format named labels and -//! virtual registers. See \ref formatRegister() and \ref formatLabel() for -//! more details. -ASMJIT_API Error formatInstruction( - String& sb, - uint32_t formatFlags, - const BaseEmitter* emitter, - uint32_t arch, - const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept; - -#ifndef ASMJIT_NO_BUILDER -//! Appends a formatted node to the output string `sb`. -//! -//! The `node` must belong to the provided `builder`. -ASMJIT_API Error formatNode( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder, - const BaseNode* node) noexcept; - -//! Appends formatted nodes to the output string `sb`. -//! -//! All nodes that are part of the given `builder` will be appended. -ASMJIT_API Error formatNodeList( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder) noexcept; - -//! Appends formatted nodes to the output string `sb`. -//! -//! This function works the same as \ref formatNode(), but appends more nodes -//! to the output string, separating each node with a newline '\n' character. -ASMJIT_API Error formatNodeList( - String& sb, - uint32_t formatFlags, - const BaseBuilder* builder, - const BaseNode* begin, - const BaseNode* end) noexcept; -#endif - -} // {Formatter} - -//! \} - -ASMJIT_END_NAMESPACE - -#endif - -#endif // ASMJIT_CORE_FORMATTER_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/func.cpp b/ext/asmjit-master/src/asmjit/core/func.cpp deleted file mode 100644 index 514ae9db..00000000 --- a/ext/asmjit-master/src/asmjit/core/func.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/arch.h" -#include "../core/func.h" -#include "../core/type.h" - -#ifdef ASMJIT_BUILD_X86 - #include "../x86/x86internal_p.h" - #include "../x86/x86operand.h" -#endif - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/arminternal_p.h" - #include "../arm/armoperand.h" -#endif - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::FuncDetail - Init / Reset] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error FuncDetail::init(const FuncSignature& signature, const Environment& environment) noexcept { - uint32_t ccId = signature.callConv(); - uint32_t argCount = signature.argCount(); - - if (ASMJIT_UNLIKELY(argCount > Globals::kMaxFuncArgs)) - return DebugUtils::errored(kErrorInvalidArgument); - - CallConv& cc = _callConv; - ASMJIT_PROPAGATE(cc.init(ccId, environment)); - - uint32_t registerSize = Environment::registerSizeFromArch(cc.arch()); - uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize); - - const uint8_t* args = signature.args(); - for (uint32_t i = 0; i < argCount; i++) { - FuncValue& arg = _args[i]; - arg.initTypeId(Type::deabstract(args[i], deabstractDelta)); - } - _argCount = uint8_t(argCount); - _vaIndex = uint8_t(signature.vaIndex()); - - uint32_t ret = signature.ret(); - if (ret != Type::kIdVoid) { - _rets[0].initTypeId(Type::deabstract(ret, deabstractDelta)); - _retCount = 1; - } - -#ifdef ASMJIT_BUILD_X86 - if (environment.isFamilyX86()) - return x86::X86Internal::initFuncDetail(*this, signature, registerSize); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (environment.isFamilyARM()) - return arm::ArmInternal::initFuncDetail(*this, signature, registerSize); -#endif - - // We should never bubble here as if `cc.init()` succeeded then there has to - // be an implementation for the current architecture. However, stay safe. - return DebugUtils::errored(kErrorInvalidArgument); -} - -// ============================================================================ -// [asmjit::FuncFrame - Init / Reset / Finalize] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error FuncFrame::init(const FuncDetail& func) noexcept { -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(func.callConv().arch())) - return x86::X86Internal::initFuncFrame(*this, func); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(func.callConv().arch())) - return arm::ArmInternal::initFuncFrame(*this, func); -#endif - - return DebugUtils::errored(kErrorInvalidArgument); -} - -ASMJIT_FAVOR_SIZE Error FuncFrame::finalize() noexcept { -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch())) - return x86::X86Internal::finalizeFuncFrame(*this); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch())) - return arm::ArmInternal::finalizeFuncFrame(*this); -#endif - - return DebugUtils::errored(kErrorInvalidArgument); -} - -// ============================================================================ -// [asmjit::FuncArgsAssignment] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error FuncArgsAssignment::updateFuncFrame(FuncFrame& frame) const noexcept { - uint32_t arch = frame.arch(); - const FuncDetail* func = funcDetail(); - - if (!func) - return DebugUtils::errored(kErrorInvalidState); - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::X86Internal::argsToFuncFrame(*this, frame); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::ArmInternal::argsToFuncFrame(*this, frame); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/func.h b/ext/asmjit-master/src/asmjit/core/func.h deleted file mode 100644 index 9c45c1f8..00000000 --- a/ext/asmjit-master/src/asmjit/core/func.h +++ /dev/null @@ -1,976 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_FUNC_H_INCLUDED -#define ASMJIT_CORE_FUNC_H_INCLUDED - -#include "../core/arch.h" -#include "../core/callconv.h" -#include "../core/environment.h" -#include "../core/operand.h" -#include "../core/type.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_function -//! \{ - -// ============================================================================ -// [asmjit::FuncArgIndex] -// ============================================================================ - -//! Function argument index (lo/hi). -enum FuncArgIndex : uint32_t { - //! Maximum number of function arguments supported by AsmJit. - kFuncArgCount = Globals::kMaxFuncArgs, - //! Extended maximum number of arguments (used internally). - kFuncArgCountLoHi = kFuncArgCount * 2, - - //! Index to the LO part of function argument (default). - //! - //! This value is typically omitted and added only if there is HI argument - //! accessed. - kFuncArgLo = 0, - - //! Index to the HI part of function argument. - //! - //! HI part of function argument depends on target architecture. On x86 it's - //! typically used to transfer 64-bit integers (they form a pair of 32-bit - //! integers). - kFuncArgHi = kFuncArgCount -}; - -// ============================================================================ -// [asmjit::FuncSignature] -// ============================================================================ - -//! Function signature. -//! -//! Contains information about function return type, count of arguments and -//! their TypeIds. Function signature is a low level structure which doesn't -//! contain platform specific or calling convention specific information. -struct FuncSignature { - //! Calling convention id. - uint8_t _callConv; - //! Count of arguments. - uint8_t _argCount; - //! Index of a first VA or `kNoVarArgs`. - uint8_t _vaIndex; - //! Return value TypeId. - uint8_t _ret; - //! Function arguments TypeIds. - const uint8_t* _args; - - enum : uint8_t { - //! Doesn't have variable number of arguments (`...`). - kNoVarArgs = 0xFF - }; - - //! \name Initializtion & Reset - //! \{ - - //! Initializes the function signature. - inline void init(uint32_t ccId, uint32_t vaIndex, uint32_t ret, const uint8_t* args, uint32_t argCount) noexcept { - ASMJIT_ASSERT(ccId <= 0xFF); - ASMJIT_ASSERT(argCount <= 0xFF); - - _callConv = uint8_t(ccId); - _argCount = uint8_t(argCount); - _vaIndex = uint8_t(vaIndex); - _ret = uint8_t(ret); - _args = args; - } - - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the calling convention. - inline uint32_t callConv() const noexcept { return _callConv; } - //! Sets the calling convention to `ccId`; - inline void setCallConv(uint32_t ccId) noexcept { _callConv = uint8_t(ccId); } - - //! Tests whether the function has variable number of arguments (...). - inline bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; } - //! Returns the variable arguments (...) index, `kNoVarArgs` if none. - inline uint32_t vaIndex() const noexcept { return _vaIndex; } - //! Sets the variable arguments (...) index to `index`. - inline void setVaIndex(uint32_t index) noexcept { _vaIndex = uint8_t(index); } - //! Resets the variable arguments index (making it a non-va function). - inline void resetVaIndex() noexcept { _vaIndex = kNoVarArgs; } - - //! Returns the number of function arguments. - inline uint32_t argCount() const noexcept { return _argCount; } - - inline bool hasRet() const noexcept { return _ret != Type::kIdVoid; } - //! Returns the return value type. - inline uint32_t ret() const noexcept { return _ret; } - - //! Returns the type of the argument at index `i`. - inline uint32_t arg(uint32_t i) const noexcept { - ASMJIT_ASSERT(i < _argCount); - return _args[i]; - } - //! Returns the array of function arguments' types. - inline const uint8_t* args() const noexcept { return _args; } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncSignatureT] -// ============================================================================ - -template -class FuncSignatureT : public FuncSignature { -public: - inline FuncSignatureT(uint32_t ccId = CallConv::kIdHost, uint32_t vaIndex = kNoVarArgs) noexcept { - static const uint8_t ret_args[] = { (uint8_t(Type::IdOfT::kTypeId))... }; - init(ccId, vaIndex, ret_args[0], ret_args + 1, uint32_t(ASMJIT_ARRAY_SIZE(ret_args) - 1)); - } -}; - -// ============================================================================ -// [asmjit::FuncSignatureBuilder] -// ============================================================================ - -//! Function signature builder. -class FuncSignatureBuilder : public FuncSignature { -public: - uint8_t _builderArgList[kFuncArgCount]; - - //! \name Initializtion & Reset - //! \{ - - inline FuncSignatureBuilder(uint32_t ccId = CallConv::kIdHost, uint32_t vaIndex = kNoVarArgs) noexcept { - init(ccId, vaIndex, Type::kIdVoid, _builderArgList, 0); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Sets the return type to `retType`. - inline void setRet(uint32_t retType) noexcept { _ret = uint8_t(retType); } - //! Sets the return type based on `T`. - template - inline void setRetT() noexcept { setRet(Type::IdOfT::kTypeId); } - - //! Sets the argument at index `index` to `argType`. - inline void setArg(uint32_t index, uint32_t argType) noexcept { - ASMJIT_ASSERT(index < _argCount); - _builderArgList[index] = uint8_t(argType); - } - //! Sets the argument at index `i` to the type based on `T`. - template - inline void setArgT(uint32_t index) noexcept { setArg(index, Type::IdOfT::kTypeId); } - - //! Appends an argument of `type` to the function prototype. - inline void addArg(uint32_t type) noexcept { - ASMJIT_ASSERT(_argCount < kFuncArgCount); - _builderArgList[_argCount++] = uint8_t(type); - } - //! Appends an argument of type based on `T` to the function prototype. - template - inline void addArgT() noexcept { addArg(Type::IdOfT::kTypeId); } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncValue] -// ============================================================================ - -//! Argument or return value as defined by `FuncSignature`, but with register -//! or stack address (and other metadata) assigned to it. -struct FuncValue { - uint32_t _data; - - enum Parts : uint32_t { - kTypeIdShift = 0, //!< TypeId shift. - kTypeIdMask = 0x000000FFu, //!< TypeId mask. - - kFlagIsReg = 0x00000100u, //!< Passed by register. - kFlagIsStack = 0x00000200u, //!< Passed by stack. - kFlagIsIndirect = 0x00000400u, //!< Passed indirectly by reference (internally a pointer). - kFlagIsDone = 0x00000800u, //!< Used internally by arguments allocator. - - kStackOffsetShift = 12, //!< Stack offset shift. - kStackOffsetMask = 0xFFFFF000u, //!< Stack offset mask (must occupy MSB bits). - - kRegIdShift = 16, //!< RegId shift. - kRegIdMask = 0x00FF0000u, //!< RegId mask. - - kRegTypeShift = 24, //!< RegType shift. - kRegTypeMask = 0xFF000000u //!< RegType mask. - }; - - //! \name Initializtion & Reset - //! \{ - - // These initialize the whole `FuncValue` to either register or stack. Useful - // when you know all of these properties and wanna just set it up. - - //! Initializes the `typeId` of this `FuncValue`. - inline void initTypeId(uint32_t typeId) noexcept { - _data = typeId << kTypeIdShift; - } - - inline void initReg(uint32_t regType, uint32_t regId, uint32_t typeId, uint32_t flags = 0) noexcept { - _data = (regType << kRegTypeShift) | (regId << kRegIdShift) | (typeId << kTypeIdShift) | kFlagIsReg | flags; - } - - inline void initStack(int32_t offset, uint32_t typeId) noexcept { - _data = (uint32_t(offset) << kStackOffsetShift) | (typeId << kTypeIdShift) | kFlagIsStack; - } - - //! Resets the value to its unassigned state. - inline void reset() noexcept { _data = 0; } - - //! \} - - //! \name Assign - //! \{ - - // These initialize only part of `FuncValue`, useful when building `FuncValue` - // incrementally. The caller should first init the type-id by caliing `initTypeId` - // and then continue building either register or stack. - - inline void assignRegData(uint32_t regType, uint32_t regId) noexcept { - ASMJIT_ASSERT((_data & (kRegTypeMask | kRegIdMask)) == 0); - _data |= (regType << kRegTypeShift) | (regId << kRegIdShift) | kFlagIsReg; - } - - inline void assignStackOffset(int32_t offset) noexcept { - ASMJIT_ASSERT((_data & kStackOffsetMask) == 0); - _data |= (uint32_t(offset) << kStackOffsetShift) | kFlagIsStack; - } - - //! \} - - //! \name Accessors - //! \{ - - inline void _replaceValue(uint32_t mask, uint32_t value) noexcept { _data = (_data & ~mask) | value; } - - //! Tests whether the `FuncValue` has a flag `flag` set. - inline bool hasFlag(uint32_t flag) const noexcept { return (_data & flag) != 0; } - //! Adds `flags` to `FuncValue`. - inline void addFlags(uint32_t flags) noexcept { _data |= flags; } - //! Clears `flags` of `FuncValue`. - inline void clearFlags(uint32_t flags) noexcept { _data &= ~flags; } - - //! Tests whether the value is initialized (i.e. contains a valid data). - inline bool isInitialized() const noexcept { return _data != 0; } - //! Tests whether the argument is passed by register. - inline bool isReg() const noexcept { return hasFlag(kFlagIsReg); } - //! Tests whether the argument is passed by stack. - inline bool isStack() const noexcept { return hasFlag(kFlagIsStack); } - //! Tests whether the argument is passed by register. - inline bool isAssigned() const noexcept { return hasFlag(kFlagIsReg | kFlagIsStack); } - //! Tests whether the argument is passed through a pointer (used by WIN64 to pass XMM|YMM|ZMM). - inline bool isIndirect() const noexcept { return hasFlag(kFlagIsIndirect); } - - //! Tests whether the argument was already processed (used internally). - inline bool isDone() const noexcept { return hasFlag(kFlagIsDone); } - - //! Returns a register type of the register used to pass function argument or return value. - inline uint32_t regType() const noexcept { return (_data & kRegTypeMask) >> kRegTypeShift; } - //! Sets a register type of the register used to pass function argument or return value. - inline void setRegType(uint32_t regType) noexcept { _replaceValue(kRegTypeMask, regType << kRegTypeShift); } - - //! Returns a physical id of the register used to pass function argument or return value. - inline uint32_t regId() const noexcept { return (_data & kRegIdMask) >> kRegIdShift; } - //! Sets a physical id of the register used to pass function argument or return value. - inline void setRegId(uint32_t regId) noexcept { _replaceValue(kRegIdMask, regId << kRegIdShift); } - - //! Returns a stack offset of this argument. - inline int32_t stackOffset() const noexcept { return int32_t(_data & kStackOffsetMask) >> kStackOffsetShift; } - //! Sets a stack offset of this argument. - inline void setStackOffset(int32_t offset) noexcept { _replaceValue(kStackOffsetMask, uint32_t(offset) << kStackOffsetShift); } - - //! Tests whether the argument or return value has associated `Type::Id`. - inline bool hasTypeId() const noexcept { return (_data & kTypeIdMask) != 0; } - //! Returns a TypeId of this argument or return value. - inline uint32_t typeId() const noexcept { return (_data & kTypeIdMask) >> kTypeIdShift; } - //! Sets a TypeId of this argument or return value. - inline void setTypeId(uint32_t typeId) noexcept { _replaceValue(kTypeIdMask, typeId << kTypeIdShift); } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncDetail] -// ============================================================================ - -//! Function detail - CallConv and expanded FuncSignature. -//! -//! Function detail is architecture and OS dependent representation of a function. -//! It contains calling convention and expanded function signature so all -//! arguments have assigned either register type & id or stack address. -class FuncDetail { -public: - //! Calling convention. - CallConv _callConv; - //! Number of function arguments. - uint8_t _argCount; - //! Number of function return values. - uint8_t _retCount; - //! Variable arguments index of `kNoVarArgs`. - uint8_t _vaIndex; - //! Reserved for future use. - uint8_t _reserved; - //! Registers that contains arguments. - uint32_t _usedRegs[BaseReg::kGroupVirt]; - //! Size of arguments passed by stack. - uint32_t _argStackSize; - //! Function return values. - FuncValue _rets[2]; - //! Function arguments. - FuncValue _args[kFuncArgCountLoHi]; - - enum : uint8_t { - //! Doesn't have variable number of arguments (`...`). - kNoVarArgs = 0xFF - }; - - //! \name Construction & Destruction - //! \{ - - inline FuncDetail() noexcept { reset(); } - inline FuncDetail(const FuncDetail& other) noexcept = default; - - //! Initializes this `FuncDetail` to the given signature. - ASMJIT_API Error init(const FuncSignature& signature, const Environment& environment) noexcept; - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the function's calling convention, see `CallConv`. - inline const CallConv& callConv() const noexcept { return _callConv; } - - //! Returns the associated calling convention flags, see `CallConv::Flags`. - inline uint32_t flags() const noexcept { return _callConv.flags(); } - //! Checks whether a CallConv `flag` is set, see `CallConv::Flags`. - inline bool hasFlag(uint32_t ccFlag) const noexcept { return _callConv.hasFlag(ccFlag); } - - //! Returns count of function return values. - inline uint32_t retCount() const noexcept { return _retCount; } - //! Returns the number of function arguments. - inline uint32_t argCount() const noexcept { return _argCount; } - - //! Tests whether the function has a return value. - inline bool hasRet() const noexcept { return _retCount != 0; } - //! Returns function return value associated with the given `index`. - inline FuncValue& ret(uint32_t index = 0) noexcept { - ASMJIT_ASSERT(index < ASMJIT_ARRAY_SIZE(_rets)); - return _rets[index]; - } - //! Returns function return value associated with the given `index` (const). - inline const FuncValue& ret(uint32_t index = 0) const noexcept { - ASMJIT_ASSERT(index < ASMJIT_ARRAY_SIZE(_rets)); - return _rets[index]; - } - - //! Returns function arguments array. - inline FuncValue* args() noexcept { return _args; } - //! Returns function arguments array (const). - inline const FuncValue* args() const noexcept { return _args; } - - inline bool hasArg(uint32_t index) const noexcept { - ASMJIT_ASSERT(index < kFuncArgCountLoHi); - return _args[index].isInitialized(); - } - - //! Returns function argument at the given `index`. - inline FuncValue& arg(uint32_t index) noexcept { - ASMJIT_ASSERT(index < kFuncArgCountLoHi); - return _args[index]; - } - - //! Returnsfunction argument at the given index `index` (const). - inline const FuncValue& arg(uint32_t index) const noexcept { - ASMJIT_ASSERT(index < kFuncArgCountLoHi); - return _args[index]; - } - - inline void resetArg(uint32_t index) noexcept { - ASMJIT_ASSERT(index < kFuncArgCountLoHi); - _args[index].reset(); - } - - inline bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; } - inline uint32_t vaIndex() const noexcept { return _vaIndex; } - - //! Tests whether the function passes one or more argument by stack. - inline bool hasStackArgs() const noexcept { return _argStackSize != 0; } - //! Returns stack size needed for function arguments passed on the stack. - inline uint32_t argStackSize() const noexcept { return _argStackSize; } - - inline uint32_t redZoneSize() const noexcept { return _callConv.redZoneSize(); } - inline uint32_t spillZoneSize() const noexcept { return _callConv.spillZoneSize(); } - inline uint32_t naturalStackAlignment() const noexcept { return _callConv.naturalStackAlignment(); } - - inline uint32_t passedRegs(uint32_t group) const noexcept { return _callConv.passedRegs(group); } - inline uint32_t preservedRegs(uint32_t group) const noexcept { return _callConv.preservedRegs(group); } - - inline uint32_t usedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _usedRegs[group]; - } - - inline void addUsedRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - _usedRegs[group] |= regs; - } - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncFrame] -// ============================================================================ - -//! Function frame. -//! -//! Function frame is used directly by prolog and epilog insertion (PEI) utils. -//! It provides information necessary to insert a proper and ABI comforming -//! prolog and epilog. Function frame calculation is based on `CallConv` and -//! other function attributes. -//! -//! Function Frame Structure -//! ------------------------ -//! -//! Various properties can contribute to the size and structure of the function -//! frame. The function frame in most cases won't use all of the properties -//! illustrated (for example Spill Zone and Red Zone are never used together). -//! -//! ``` -//! +-----------------------------+ -//! | Arguments Passed by Stack | -//! +-----------------------------+ -//! | Spill Zone | -//! +-----------------------------+ <- Stack offset (args) starts from here. -//! | Return Address, if Pushed | -//! +-----------------------------+ <- Stack pointer (SP) upon entry. -//! | Save/Restore Stack. | -//! +-----------------------------+-----------------------------+ -//! | Local Stack | | -//! +-----------------------------+ Final Stack | -//! | Call Stack | | -//! +-----------------------------+-----------------------------+ <- SP after prolog. -//! | Red Zone | -//! +-----------------------------+ -//! ``` -class FuncFrame { -public: - enum Tag : uint32_t { - //! Tag used to inform that some offset is invalid. - kTagInvalidOffset = 0xFFFFFFFFu - }; - - //! Attributes are designed in a way that all are initially false, and user - //! or FuncFrame finalizer adds them when necessary. - enum Attributes : uint32_t { - //! Function has variable number of arguments. - kAttrHasVarArgs = 0x00000001u, - //! Preserve frame pointer (don't omit FP). - kAttrHasPreservedFP = 0x00000010u, - //! Function calls other functions (is not leaf). - kAttrHasFuncCalls = 0x00000020u, - - //! Use AVX instead of SSE for all operations (X86). - kAttrX86AvxEnabled = 0x00010000u, - //! Emit VZEROUPPER instruction in epilog (X86). - kAttrX86AvxCleanup = 0x00020000u, - //! Emit EMMS instruction in epilog (X86). - kAttrX86MmxCleanup = 0x00040000u, - - //! Function has aligned save/restore of vector registers. - kAttrAlignedVecSR = 0x40000000u, - //! FuncFrame is finalized and can be used by PEI. - kAttrIsFinalized = 0x80000000u - }; - - //! Function attributes. - uint32_t _attributes; - - //! Architecture, see \ref Environment::Arch. - uint8_t _arch; - //! SP register ID (to access call stack and local stack). - uint8_t _spRegId; - //! SA register ID (to access stack arguments). - uint8_t _saRegId; - - //! Red zone size (copied from CallConv). - uint8_t _redZoneSize; - //! Spill zone size (copied from CallConv). - uint8_t _spillZoneSize; - //! Natural stack alignment (copied from CallConv). - uint8_t _naturalStackAlignment; - //! Minimum stack alignment to turn on dynamic alignment. - uint8_t _minDynamicAlignment; - - //! Call stack alignment. - uint8_t _callStackAlignment; - //! Local stack alignment. - uint8_t _localStackAlignment; - //! Final stack alignment. - uint8_t _finalStackAlignment; - - //! Adjustment of the stack before returning (X86-STDCALL). - uint16_t _calleeStackCleanup; - - //! Call stack size. - uint32_t _callStackSize; - //! Local stack size. - uint32_t _localStackSize; - //! Final stack size (sum of call stack and local stack). - uint32_t _finalStackSize; - - //! Local stack offset (non-zero only if call stack is used). - uint32_t _localStackOffset; - //! Offset relative to SP that contains previous SP (before alignment). - uint32_t _daOffset; - //! Offset of the first stack argument relative to SP. - uint32_t _saOffsetFromSP; - //! Offset of the first stack argument relative to SA (_saRegId or FP). - uint32_t _saOffsetFromSA; - - //! Local stack adjustment in prolog/epilog. - uint32_t _stackAdjustment; - - //! Registers that are dirty. - uint32_t _dirtyRegs[BaseReg::kGroupVirt]; - //! Registers that must be preserved (copied from CallConv). - uint32_t _preservedRegs[BaseReg::kGroupVirt]; - - //! Final stack size required to save GP regs. - uint16_t _gpSaveSize; - //! Final Stack size required to save other than GP regs. - uint16_t _nonGpSaveSize; - //! Final offset where saved GP regs are stored. - uint32_t _gpSaveOffset; - //! Final offset where saved other than GP regs are stored. - uint32_t _nonGpSaveOffset; - - //! \name Construction & Destruction - //! \{ - - inline FuncFrame() noexcept { reset(); } - inline FuncFrame(const FuncFrame& other) noexcept = default; - - ASMJIT_API Error init(const FuncDetail& func) noexcept; - - inline void reset() noexcept { - memset(this, 0, sizeof(FuncFrame)); - _spRegId = BaseReg::kIdBad; - _saRegId = BaseReg::kIdBad; - _daOffset = kTagInvalidOffset; - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the target architecture of the function frame. - inline uint32_t arch() const noexcept { return _arch; } - - //! Returns function frame attributes, see `Attributes`. - inline uint32_t attributes() const noexcept { return _attributes; } - //! Checks whether the FuncFame contains an attribute `attr`. - inline bool hasAttribute(uint32_t attr) const noexcept { return (_attributes & attr) != 0; } - //! Adds attributes `attrs` to the FuncFrame. - inline void addAttributes(uint32_t attrs) noexcept { _attributes |= attrs; } - //! Clears attributes `attrs` from the FrameFrame. - inline void clearAttributes(uint32_t attrs) noexcept { _attributes &= ~attrs; } - - //! Tests whether the function has variable number of arguments. - inline bool hasVarArgs() const noexcept { return hasAttribute(kAttrHasVarArgs); } - //! Sets the variable arguments flag. - inline void setVarArgs() noexcept { addAttributes(kAttrHasVarArgs); } - //! Resets variable arguments flag. - inline void resetVarArgs() noexcept { clearAttributes(kAttrHasVarArgs); } - - //! Tests whether the function preserves frame pointer (EBP|ESP on X86). - inline bool hasPreservedFP() const noexcept { return hasAttribute(kAttrHasPreservedFP); } - //! Enables preserved frame pointer. - inline void setPreservedFP() noexcept { addAttributes(kAttrHasPreservedFP); } - //! Disables preserved frame pointer. - inline void resetPreservedFP() noexcept { clearAttributes(kAttrHasPreservedFP); } - - //! Tests whether the function calls other functions. - inline bool hasFuncCalls() const noexcept { return hasAttribute(kAttrHasFuncCalls); } - //! Sets `kFlagHasCalls` to true. - inline void setFuncCalls() noexcept { addAttributes(kAttrHasFuncCalls); } - //! Sets `kFlagHasCalls` to false. - inline void resetFuncCalls() noexcept { clearAttributes(kAttrHasFuncCalls); } - - //! Tests whether the function contains AVX cleanup - 'vzeroupper' instruction in epilog. - inline bool hasAvxCleanup() const noexcept { return hasAttribute(kAttrX86AvxCleanup); } - //! Enables AVX cleanup. - inline void setAvxCleanup() noexcept { addAttributes(kAttrX86AvxCleanup); } - //! Disables AVX cleanup. - inline void resetAvxCleanup() noexcept { clearAttributes(kAttrX86AvxCleanup); } - - //! Tests whether the function contains AVX cleanup - 'vzeroupper' instruction in epilog. - inline bool isAvxEnabled() const noexcept { return hasAttribute(kAttrX86AvxEnabled); } - //! Enables AVX cleanup. - inline void setAvxEnabled() noexcept { addAttributes(kAttrX86AvxEnabled); } - //! Disables AVX cleanup. - inline void resetAvxEnabled() noexcept { clearAttributes(kAttrX86AvxEnabled); } - - //! Tests whether the function contains MMX cleanup - 'emms' instruction in epilog. - inline bool hasMmxCleanup() const noexcept { return hasAttribute(kAttrX86MmxCleanup); } - //! Enables MMX cleanup. - inline void setMmxCleanup() noexcept { addAttributes(kAttrX86MmxCleanup); } - //! Disables MMX cleanup. - inline void resetMmxCleanup() noexcept { clearAttributes(kAttrX86MmxCleanup); } - - //! Tests whether the function uses call stack. - inline bool hasCallStack() const noexcept { return _callStackSize != 0; } - //! Tests whether the function uses local stack. - inline bool hasLocalStack() const noexcept { return _localStackSize != 0; } - //! Tests whether vector registers can be saved and restored by using aligned reads and writes. - inline bool hasAlignedVecSR() const noexcept { return hasAttribute(kAttrAlignedVecSR); } - //! Tests whether the function has to align stack dynamically. - inline bool hasDynamicAlignment() const noexcept { return _finalStackAlignment >= _minDynamicAlignment; } - - //! Tests whether the calling convention specifies 'RedZone'. - inline bool hasRedZone() const noexcept { return _redZoneSize != 0; } - //! Tests whether the calling convention specifies 'SpillZone'. - inline bool hasSpillZone() const noexcept { return _spillZoneSize != 0; } - - //! Returns the size of 'RedZone'. - inline uint32_t redZoneSize() const noexcept { return _redZoneSize; } - //! Returns the size of 'SpillZone'. - inline uint32_t spillZoneSize() const noexcept { return _spillZoneSize; } - //! Returns natural stack alignment (guaranteed stack alignment upon entry). - inline uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; } - //! Returns natural stack alignment (guaranteed stack alignment upon entry). - inline uint32_t minDynamicAlignment() const noexcept { return _minDynamicAlignment; } - - //! Tests whether the callee must adjust SP before returning (X86-STDCALL only) - inline bool hasCalleeStackCleanup() const noexcept { return _calleeStackCleanup != 0; } - //! Returns home many bytes of the stack the the callee must adjust before returning (X86-STDCALL only) - inline uint32_t calleeStackCleanup() const noexcept { return _calleeStackCleanup; } - - //! Returns call stack alignment. - inline uint32_t callStackAlignment() const noexcept { return _callStackAlignment; } - //! Returns local stack alignment. - inline uint32_t localStackAlignment() const noexcept { return _localStackAlignment; } - //! Returns final stack alignment (the maximum value of call, local, and natural stack alignments). - inline uint32_t finalStackAlignment() const noexcept { return _finalStackAlignment; } - - //! Sets call stack alignment. - //! - //! \note This also updates the final stack alignment. - inline void setCallStackAlignment(uint32_t alignment) noexcept { - _callStackAlignment = uint8_t(alignment); - _finalStackAlignment = Support::max(_naturalStackAlignment, _callStackAlignment, _localStackAlignment); - } - - //! Sets local stack alignment. - //! - //! \note This also updates the final stack alignment. - inline void setLocalStackAlignment(uint32_t value) noexcept { - _localStackAlignment = uint8_t(value); - _finalStackAlignment = Support::max(_naturalStackAlignment, _callStackAlignment, _localStackAlignment); - } - - //! Combines call stack alignment with `alignment`, updating it to the greater value. - //! - //! \note This also updates the final stack alignment. - inline void updateCallStackAlignment(uint32_t alignment) noexcept { - _callStackAlignment = uint8_t(Support::max(_callStackAlignment, alignment)); - _finalStackAlignment = Support::max(_finalStackAlignment, _callStackAlignment); - } - - //! Combines local stack alignment with `alignment`, updating it to the greater value. - //! - //! \note This also updates the final stack alignment. - inline void updateLocalStackAlignment(uint32_t alignment) noexcept { - _localStackAlignment = uint8_t(Support::max(_localStackAlignment, alignment)); - _finalStackAlignment = Support::max(_finalStackAlignment, _localStackAlignment); - } - - //! Returns call stack size. - inline uint32_t callStackSize() const noexcept { return _callStackSize; } - //! Returns local stack size. - inline uint32_t localStackSize() const noexcept { return _localStackSize; } - - //! Sets call stack size. - inline void setCallStackSize(uint32_t size) noexcept { _callStackSize = size; } - //! Sets local stack size. - inline void setLocalStackSize(uint32_t size) noexcept { _localStackSize = size; } - - //! Combines call stack size with `size`, updating it to the greater value. - inline void updateCallStackSize(uint32_t size) noexcept { _callStackSize = Support::max(_callStackSize, size); } - //! Combines local stack size with `size`, updating it to the greater value. - inline void updateLocalStackSize(uint32_t size) noexcept { _localStackSize = Support::max(_localStackSize, size); } - - //! Returns final stack size (only valid after the FuncFrame is finalized). - inline uint32_t finalStackSize() const noexcept { return _finalStackSize; } - - //! Returns an offset to access the local stack (non-zero only if call stack is used). - inline uint32_t localStackOffset() const noexcept { return _localStackOffset; } - - //! Tests whether the function prolog/epilog requires a memory slot for storing unaligned SP. - inline bool hasDAOffset() const noexcept { return _daOffset != kTagInvalidOffset; } - //! Returns a memory offset used to store DA (dynamic alignment) slot (relative to SP). - inline uint32_t daOffset() const noexcept { return _daOffset; } - - inline uint32_t saOffset(uint32_t regId) const noexcept { - return regId == _spRegId ? saOffsetFromSP() - : saOffsetFromSA(); - } - - inline uint32_t saOffsetFromSP() const noexcept { return _saOffsetFromSP; } - inline uint32_t saOffsetFromSA() const noexcept { return _saOffsetFromSA; } - - //! Returns mask of registers of the given register `group` that are modified - //! by the function. The engine would then calculate which registers must be - //! saved & restored by the function by using the data provided by the calling - //! convention. - inline uint32_t dirtyRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _dirtyRegs[group]; - } - - //! Sets which registers (as a mask) are modified by the function. - //! - //! \remarks Please note that this will completely overwrite the existing - //! register mask, use `addDirtyRegs()` to modify the existing register - //! mask. - inline void setDirtyRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - _dirtyRegs[group] = regs; - } - - //! Adds which registers (as a mask) are modified by the function. - inline void addDirtyRegs(uint32_t group, uint32_t regs) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - _dirtyRegs[group] |= regs; - } - - //! \overload - inline void addDirtyRegs(const BaseReg& reg) noexcept { - ASMJIT_ASSERT(reg.id() < Globals::kMaxPhysRegs); - addDirtyRegs(reg.group(), Support::bitMask(reg.id())); - } - - //! \overload - template - ASMJIT_INLINE void addDirtyRegs(const BaseReg& reg, Args&&... args) noexcept { - addDirtyRegs(reg); - addDirtyRegs(std::forward(args)...); - } - - inline void setAllDirty() noexcept { - for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_dirtyRegs); i++) - _dirtyRegs[i] = 0xFFFFFFFFu; - } - - inline void setAllDirty(uint32_t group) noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - _dirtyRegs[group] = 0xFFFFFFFFu; - } - - //! Returns a calculated mask of registers of the given `group` that will be - //! saved and restored in the function's prolog and epilog, respectively. The - //! register mask is calculated from both `dirtyRegs` (provided by user) and - //! `preservedMask` (provided by the calling convention). - inline uint32_t savedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _dirtyRegs[group] & _preservedRegs[group]; - } - - //! Returns the mask of preserved registers of the given register `group`. - //! - //! Preserved registers are those that must survive the function call - //! unmodified. The function can only modify preserved registers it they - //! are saved and restored in funciton's prolog and epilog, respectively. - inline uint32_t preservedRegs(uint32_t group) const noexcept { - ASMJIT_ASSERT(group < BaseReg::kGroupVirt); - return _preservedRegs[group]; - } - - inline bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; } - inline uint32_t saRegId() const noexcept { return _saRegId; } - inline void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); } - inline void resetSARegId() { setSARegId(BaseReg::kIdBad); } - - //! Returns stack size required to save GP registers. - inline uint32_t gpSaveSize() const noexcept { return _gpSaveSize; } - //! Returns stack size required to save other than GP registers (MM, XMM|YMM|ZMM, K, VFP, etc...). - inline uint32_t nonGpSaveSize() const noexcept { return _nonGpSaveSize; } - - //! Returns an offset to the stack where general purpose registers are saved. - inline uint32_t gpSaveOffset() const noexcept { return _gpSaveOffset; } - //! Returns an offset to the stack where other than GP registers are saved. - inline uint32_t nonGpSaveOffset() const noexcept { return _nonGpSaveOffset; } - - //! Tests whether the functions contains stack adjustment. - inline bool hasStackAdjustment() const noexcept { return _stackAdjustment != 0; } - //! Returns function's stack adjustment used in function's prolog and epilog. - //! - //! If the returned value is zero it means that the stack is not adjusted. - //! This can mean both that the stack is not used and/or the stack is only - //! adjusted by instructions that pust/pop registers into/from stack. - inline uint32_t stackAdjustment() const noexcept { return _stackAdjustment; } - - //! \} - - //! \name Finaliztion - //! \{ - - ASMJIT_API Error finalize() noexcept; - - //! \} -}; - -// ============================================================================ -// [asmjit::FuncArgsAssignment] -// ============================================================================ - -//! A helper class that can be used to assign a physical register for each -//! function argument. Use with `BaseEmitter::emitArgsAssignment()`. -class FuncArgsAssignment { -public: - //! Function detail. - const FuncDetail* _funcDetail; - //! Register that can be used to access arguments passed by stack. - uint8_t _saRegId; - //! Reserved for future use. - uint8_t _reserved[3]; - //! Mapping of each function argument. - FuncValue _args[kFuncArgCountLoHi]; - - //! \name Construction & Destruction - //! \{ - - inline explicit FuncArgsAssignment(const FuncDetail* fd = nullptr) noexcept { reset(fd); } - - inline FuncArgsAssignment(const FuncArgsAssignment& other) noexcept { - memcpy(this, &other, sizeof(*this)); - } - - inline void reset(const FuncDetail* fd = nullptr) noexcept { - _funcDetail = fd; - _saRegId = uint8_t(BaseReg::kIdBad); - memset(_reserved, 0, sizeof(_reserved)); - memset(_args, 0, sizeof(_args)); - } - - //! \} - - //! \name Accessors - //! \{ - - inline const FuncDetail* funcDetail() const noexcept { return _funcDetail; } - inline void setFuncDetail(const FuncDetail* fd) noexcept { _funcDetail = fd; } - - inline bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; } - inline uint32_t saRegId() const noexcept { return _saRegId; } - inline void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); } - inline void resetSARegId() { _saRegId = uint8_t(BaseReg::kIdBad); } - - inline FuncValue& arg(uint32_t index) noexcept { - ASMJIT_ASSERT(index < ASMJIT_ARRAY_SIZE(_args)); - return _args[index]; - } - inline const FuncValue& arg(uint32_t index) const noexcept { - ASMJIT_ASSERT(index < ASMJIT_ARRAY_SIZE(_args)); - return _args[index]; - } - - inline bool isAssigned(uint32_t argIndex) const noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_args)); - return _args[argIndex].isAssigned(); - } - - inline void assignReg(uint32_t argIndex, const BaseReg& reg, uint32_t typeId = Type::kIdVoid) noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_args)); - ASMJIT_ASSERT(reg.isPhysReg()); - _args[argIndex].initReg(reg.type(), reg.id(), typeId); - } - - inline void assignReg(uint32_t argIndex, uint32_t regType, uint32_t regId, uint32_t typeId = Type::kIdVoid) noexcept { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_args)); - _args[argIndex].initReg(regType, regId, typeId); - } - - inline void assignStack(uint32_t argIndex, int32_t offset, uint32_t typeId = Type::kIdVoid) { - ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_args)); - _args[argIndex].initStack(offset, typeId); - } - - // NOTE: All `assignAll()` methods are shortcuts to assign all arguments at - // once, however, since registers are passed all at once these initializers - // don't provide any way to pass TypeId and/or to keep any argument between - // the arguments passed unassigned. - inline void _assignAllInternal(uint32_t argIndex, const BaseReg& reg) noexcept { - assignReg(argIndex, reg); - } - - template - inline void _assignAllInternal(uint32_t argIndex, const BaseReg& reg, Args&&... args) noexcept { - assignReg(argIndex, reg); - _assignAllInternal(argIndex + 1, std::forward(args)...); - } - - template - inline void assignAll(Args&&... args) noexcept { - _assignAllInternal(0, std::forward(args)...); - } - - //! \} - - //! \name Utilities - //! \{ - - //! Update `FuncFrame` based on function's arguments assignment. - //! - //! \note You MUST call this in orher to use `BaseEmitter::emitArgsAssignment()`, - //! otherwise the FuncFrame would not contain the information necessary to - //! assign all arguments into the registers and/or stack specified. - ASMJIT_API Error updateFuncFrame(FuncFrame& frame) const noexcept; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_FUNC_H_INCLUDED - diff --git a/ext/asmjit-master/src/asmjit/core/globals.cpp b/ext/asmjit-master/src/asmjit/core/globals.cpp deleted file mode 100644 index 7ec66283..00000000 --- a/ext/asmjit-master/src/asmjit/core/globals.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/globals.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::DebugUtils] -// ============================================================================ - -ASMJIT_FAVOR_SIZE const char* DebugUtils::errorAsString(Error err) noexcept { -#ifndef ASMJIT_NO_TEXT - // @EnumStringBegin{"enum": "ErrorCode", "output": "sError", "strip": "kError"}@ - static const char sErrorString[] = - "Ok\0" - "OutOfMemory\0" - "InvalidArgument\0" - "InvalidState\0" - "InvalidArch\0" - "NotInitialized\0" - "AlreadyInitialized\0" - "FeatureNotEnabled\0" - "TooManyHandles\0" - "TooLarge\0" - "NoCodeGenerated\0" - "InvalidDirective\0" - "InvalidLabel\0" - "TooManyLabels\0" - "LabelAlreadyBound\0" - "LabelAlreadyDefined\0" - "LabelNameTooLong\0" - "InvalidLabelName\0" - "InvalidParentLabel\0" - "NonLocalLabelCannotHaveParent\0" - "InvalidSection\0" - "TooManySections\0" - "InvalidSectionName\0" - "TooManyRelocations\0" - "InvalidRelocEntry\0" - "RelocOffsetOutOfRange\0" - "InvalidAssignment\0" - "InvalidInstruction\0" - "InvalidRegType\0" - "InvalidRegGroup\0" - "InvalidPhysId\0" - "InvalidVirtId\0" - "InvalidPrefixCombination\0" - "InvalidLockPrefix\0" - "InvalidXAcquirePrefix\0" - "InvalidXReleasePrefix\0" - "InvalidRepPrefix\0" - "InvalidRexPrefix\0" - "InvalidExtraReg\0" - "InvalidKMaskUse\0" - "InvalidKZeroUse\0" - "InvalidBroadcast\0" - "InvalidEROrSAE\0" - "InvalidAddress\0" - "InvalidAddressIndex\0" - "InvalidAddressScale\0" - "InvalidAddress64Bit\0" - "InvalidAddress64BitZeroExtension\0" - "InvalidDisplacement\0" - "InvalidSegment\0" - "InvalidImmediate\0" - "InvalidOperandSize\0" - "AmbiguousOperandSize\0" - "OperandSizeMismatch\0" - "InvalidOption\0" - "OptionAlreadyDefined\0" - "InvalidTypeId\0" - "InvalidUseOfGpbHi\0" - "InvalidUseOfGpq\0" - "InvalidUseOfF80\0" - "NotConsecutiveRegs\0" - "IllegalVirtReg\0" - "TooManyVirtRegs\0" - "NoMorePhysRegs\0" - "OverlappedRegs\0" - "OverlappingStackRegWithRegArg\0" - "ExpressionLabelNotBound\0" - "ExpressionOverflow\0" - "\0"; - - static const uint16_t sErrorIndex[] = { - 0, 3, 15, 31, 44, 56, 71, 90, 108, 123, 132, 148, 165, 178, 192, 210, 230, - 247, 264, 283, 313, 328, 344, 363, 382, 400, 422, 440, 459, 474, 490, 504, - 518, 543, 561, 583, 605, 622, 639, 655, 671, 687, 704, 719, 734, 754, 774, - 794, 827, 847, 862, 879, 898, 919, 939, 953, 974, 988, 1006, 1022, 1038, - 1057, 1072, 1088, 1103, 1118, 1148, 1172, 1191 - }; - // @EnumStringEnd@ - - return sErrorString + sErrorIndex[Support::min(err, kErrorCount)]; -#else - DebugUtils::unused(err); - static const char noMessage[] = ""; - return noMessage; -#endif -} - -ASMJIT_FAVOR_SIZE void DebugUtils::debugOutput(const char* str) noexcept { -#if defined(_WIN32) - ::OutputDebugStringA(str); -#else - ::fputs(str, stderr); -#endif -} - -ASMJIT_FAVOR_SIZE void DebugUtils::assertionFailed(const char* file, int line, const char* msg) noexcept { - char str[1024]; - - snprintf(str, 1024, - "[asmjit] Assertion failed at %s (line %d):\n" - "[asmjit] %s\n", file, line, msg); - - debugOutput(str); - ::abort(); -} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/globals.h b/ext/asmjit-master/src/asmjit/core/globals.h deleted file mode 100644 index 67a8769a..00000000 --- a/ext/asmjit-master/src/asmjit/core/globals.h +++ /dev/null @@ -1,453 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_GLOBALS_H_INCLUDED -#define ASMJIT_CORE_GLOBALS_H_INCLUDED - -#include "../core/api-config.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::Support] -// ============================================================================ - -//! \cond INTERNAL -//! \addtogroup asmjit_utilities -//! \{ -namespace Support { - //! Cast designed to cast between function and void* pointers. - template - static inline Dst ptr_cast_impl(Src p) noexcept { return (Dst)p; } -} // {Support} - -#if defined(ASMJIT_NO_STDCXX) -namespace Support { - ASMJIT_INLINE void* operatorNew(size_t n) noexcept { return malloc(n); } - ASMJIT_INLINE void operatorDelete(void* p) noexcept { if (p) free(p); } -} // {Support} - -#define ASMJIT_BASE_CLASS(TYPE) \ - ASMJIT_INLINE void* operator new(size_t n) noexcept { \ - return Support::operatorNew(n); \ - } \ - \ - ASMJIT_INLINE void operator delete(void* p) noexcept { \ - Support::operatorDelete(p); \ - } \ - \ - ASMJIT_INLINE void* operator new(size_t, void* p) noexcept { return p; } \ - ASMJIT_INLINE void operator delete(void*, void*) noexcept {} -#else -#define ASMJIT_BASE_CLASS(TYPE) -#endif - -//! \} -//! \endcond - -// ============================================================================ -// [asmjit::Globals] -// ============================================================================ - -//! \addtogroup asmjit_core -//! \{ - -//! Contains typedefs, constants, and variables used globally by AsmJit. -namespace Globals { - -// ============================================================================ -// [asmjit::Globals::] -// ============================================================================ - -//! Host memory allocator overhead. -constexpr uint32_t kAllocOverhead = uint32_t(sizeof(intptr_t) * 4); - -//! Host memory allocator alignment. -constexpr uint32_t kAllocAlignment = 8; - -//! Aggressive growing strategy threshold. -constexpr uint32_t kGrowThreshold = 1024 * 1024 * 16; - -//! Maximum depth of RB-Tree is: -//! -//! `2 * log2(n + 1)` -//! -//! Size of RB node is at least two pointers (without data), -//! so a theoretical architecture limit would be: -//! -//! `2 * log2(addressableMemorySize / sizeof(Node) + 1)` -//! -//! Which yields 30 on 32-bit arch and 61 on 64-bit arch. -//! The final value was adjusted by +1 for safety reasons. -constexpr uint32_t kMaxTreeHeight = (ASMJIT_ARCH_BITS == 32 ? 30 : 61) + 1; - -//! Maximum number of operands per a single instruction. -constexpr uint32_t kMaxOpCount = 6; - -//! Maximum arguments of a function supported by the Compiler / Function API. -constexpr uint32_t kMaxFuncArgs = 16; - -//! Maximum number of physical registers AsmJit can use per register group. -constexpr uint32_t kMaxPhysRegs = 32; - -//! Maximum alignment. -constexpr uint32_t kMaxAlignment = 64; - -//! Maximum label or symbol size in bytes. -constexpr uint32_t kMaxLabelNameSize = 2048; - -//! Maximum section name size. -constexpr uint32_t kMaxSectionNameSize = 35; - -//! Maximum size of comment. -constexpr uint32_t kMaxCommentSize = 1024; - -//! Invalid identifier. -constexpr uint32_t kInvalidId = 0xFFFFFFFFu; - -//! Returned by `indexOf()` and similar when working with containers that use 32-bit index/size. -constexpr uint32_t kNotFound = 0xFFFFFFFFu; - -//! Invalid base address. -constexpr uint64_t kNoBaseAddress = ~uint64_t(0); - -// ============================================================================ -// [asmjit::Globals::ResetPolicy] -// ============================================================================ - -//! Reset policy used by most `reset()` functions. -enum ResetPolicy : uint32_t { - //! Soft reset, doesn't deallocate memory (default). - kResetSoft = 0, - //! Hard reset, releases all memory used, if any. - kResetHard = 1 -}; - -// ============================================================================ -// [asmjit::Globals::Link] -// ============================================================================ - -enum Link : uint32_t { - kLinkLeft = 0, - kLinkRight = 1, - - kLinkPrev = 0, - kLinkNext = 1, - - kLinkFirst = 0, - kLinkLast = 1, - - kLinkCount = 2 -}; - -struct Init_ {}; -struct NoInit_ {}; - -static const constexpr Init_ Init {}; -static const constexpr NoInit_ NoInit {}; - -} // {Globals} - -// ============================================================================ -// [asmjit::ByteOrder] -// ============================================================================ - -//! Byte order. -namespace ByteOrder { - enum : uint32_t { - kLE = 0, - kBE = 1, - kNative = ASMJIT_ARCH_LE ? kLE : kBE, - kSwapped = ASMJIT_ARCH_LE ? kBE : kLE - }; -} - -// ============================================================================ -// [asmjit::ptr_as_func / func_as_ptr] -// ============================================================================ - -template -static inline Func ptr_as_func(void* func) noexcept { return Support::ptr_cast_impl(func); } - -template -static inline void* func_as_ptr(Func func) noexcept { return Support::ptr_cast_impl(func); } - -//! \} - -// ============================================================================ -// [asmjit::Error] -// ============================================================================ - -//! \addtogroup asmjit_error_handling -//! \{ - -//! AsmJit error type (uint32_t). -typedef uint32_t Error; - -//! AsmJit error codes. -enum ErrorCode : uint32_t { - // @EnumValuesBegin{"enum": "ErrorCode"}@ - - //! No error (success). - kErrorOk = 0, - - //! Out of memory. - kErrorOutOfMemory, - - //! Invalid argument. - kErrorInvalidArgument, - - //! Invalid state. - //! - //! If this error is returned it means that either you are doing something - //! wrong or AsmJit caught itself by doing something wrong. This error should - //! never be ignored. - kErrorInvalidState, - - //! Invalid or incompatible architecture. - kErrorInvalidArch, - - //! The object is not initialized. - kErrorNotInitialized, - //! The object is already initialized. - kErrorAlreadyInitialized, - - //! Built-in feature was disabled at compile time and it's not available. - kErrorFeatureNotEnabled, - - //! Too many handles (Windows) or file descriptors (Unix/Posix). - kErrorTooManyHandles, - //! Code generated is larger than allowed. - kErrorTooLarge, - - //! No code generated. - //! - //! Returned by runtime if the \ref CodeHolder contains no code. - kErrorNoCodeGenerated, - - //! Invalid directive. - kErrorInvalidDirective, - //! Attempt to use uninitialized label. - kErrorInvalidLabel, - //! Label index overflow - a single \ref BaseAssembler instance can hold - //! almost 2^32 (4 billion) labels. If there is an attempt to create more - //! labels then this error is returned. - kErrorTooManyLabels, - //! Label is already bound. - kErrorLabelAlreadyBound, - //! Label is already defined (named labels). - kErrorLabelAlreadyDefined, - //! Label name is too long. - kErrorLabelNameTooLong, - //! Label must always be local if it's anonymous (without a name). - kErrorInvalidLabelName, - //! Parent id passed to \ref CodeHolder::newNamedLabelEntry() was invalid. - kErrorInvalidParentLabel, - //! Parent id specified for a non-local (global) label. - kErrorNonLocalLabelCannotHaveParent, - - //! Invalid section. - kErrorInvalidSection, - //! Too many sections (section index overflow). - kErrorTooManySections, - //! Invalid section name (most probably too long). - kErrorInvalidSectionName, - - //! Relocation index overflow (too many relocations). - kErrorTooManyRelocations, - //! Invalid relocation entry. - kErrorInvalidRelocEntry, - //! Reloc entry contains address that is out of range (unencodable). - kErrorRelocOffsetOutOfRange, - - //! Invalid assignment to a register, function argument, or function return value. - kErrorInvalidAssignment, - //! Invalid instruction. - kErrorInvalidInstruction, - //! Invalid register type. - kErrorInvalidRegType, - //! Invalid register group. - kErrorInvalidRegGroup, - //! Invalid physical register id. - kErrorInvalidPhysId, - //! Invalid virtual register id. - kErrorInvalidVirtId, - //! Invalid prefix combination. - kErrorInvalidPrefixCombination, - //! Invalid LOCK prefix. - kErrorInvalidLockPrefix, - //! Invalid XACQUIRE prefix. - kErrorInvalidXAcquirePrefix, - //! Invalid XRELEASE prefix. - kErrorInvalidXReleasePrefix, - //! Invalid REP prefix. - kErrorInvalidRepPrefix, - //! Invalid REX prefix. - kErrorInvalidRexPrefix, - //! Invalid {...} register. - kErrorInvalidExtraReg, - //! Invalid {k} use (not supported by the instruction). - kErrorInvalidKMaskUse, - //! Invalid {k}{z} use (not supported by the instruction). - kErrorInvalidKZeroUse, - //! Invalid broadcast - Currently only related to invalid use of AVX-512 {1tox}. - kErrorInvalidBroadcast, - //! Invalid 'embedded-rounding' {er} or 'suppress-all-exceptions' {sae} (AVX-512). - kErrorInvalidEROrSAE, - //! Invalid address used (not encodable). - kErrorInvalidAddress, - //! Invalid index register used in memory address (not encodable). - kErrorInvalidAddressIndex, - //! Invalid address scale (not encodable). - kErrorInvalidAddressScale, - //! Invalid use of 64-bit address. - kErrorInvalidAddress64Bit, - //! Invalid use of 64-bit address that require 32-bit zero-extension (X64). - kErrorInvalidAddress64BitZeroExtension, - //! Invalid displacement (not encodable). - kErrorInvalidDisplacement, - //! Invalid segment (X86). - kErrorInvalidSegment, - - //! Invalid immediate (out of bounds on X86 and invalid pattern on ARM). - kErrorInvalidImmediate, - - //! Invalid operand size. - kErrorInvalidOperandSize, - //! Ambiguous operand size (memory has zero size while it's required to determine the operation type. - kErrorAmbiguousOperandSize, - //! Mismatching operand size (size of multiple operands doesn't match the operation size). - kErrorOperandSizeMismatch, - - //! Invalid option. - kErrorInvalidOption, - //! Option already defined. - kErrorOptionAlreadyDefined, - - //! Invalid TypeId. - kErrorInvalidTypeId, - //! Invalid use of a 8-bit GPB-HIGH register. - kErrorInvalidUseOfGpbHi, - //! Invalid use of a 64-bit GPQ register in 32-bit mode. - kErrorInvalidUseOfGpq, - //! Invalid use of an 80-bit float (\ref Type::kIdF80). - kErrorInvalidUseOfF80, - //! Some registers in the instruction muse be consecutive (some ARM and AVX512 - //! neural-net instructions). - kErrorNotConsecutiveRegs, - - //! Illegal virtual register - reported by instruction validation. - kErrorIllegalVirtReg, - //! AsmJit cannot create more virtual registers. - kErrorTooManyVirtRegs, - - //! AsmJit requires a physical register, but no one is available. - kErrorNoMorePhysRegs, - //! A variable has been assigned more than once to a function argument (BaseCompiler). - kErrorOverlappedRegs, - //! Invalid register to hold stack arguments offset. - kErrorOverlappingStackRegWithRegArg, - - //! Unbound label cannot be evaluated by expression. - kErrorExpressionLabelNotBound, - //! Arithmetic overflow during expression evaluation. - kErrorExpressionOverflow, - - // @EnumValuesEnd@ - - //! Count of AsmJit error codes. - kErrorCount -}; - -// ============================================================================ -// [asmjit::DebugUtils] -// ============================================================================ - -//! Debugging utilities. -namespace DebugUtils { - -//! \cond INTERNAL -//! Used to silence warnings about unused arguments or variables. -template -static ASMJIT_INLINE void unused(Args&&...) noexcept {} -//! \endcond - -//! Returns the error `err` passed. -//! -//! Provided for debugging purposes. Putting a breakpoint inside `errored` can -//! help with tracing the origin of any error reported / returned by AsmJit. -static constexpr Error errored(Error err) noexcept { return err; } - -//! Returns a printable version of `asmjit::Error` code. -ASMJIT_API const char* errorAsString(Error err) noexcept; - -//! Called to output debugging message(s). -ASMJIT_API void debugOutput(const char* str) noexcept; - -//! Called on assertion failure. -//! -//! \param file Source file name where it happened. -//! \param line Line in the source file. -//! \param msg Message to display. -//! -//! If you have problems with assertion failures a breakpoint can be put -//! at \ref assertionFailed() function (asmjit/core/globals.cpp). A call stack -//! will be available when such assertion failure is triggered. AsmJit always -//! returns errors on failures, assertions are a last resort and usually mean -//! unrecoverable state due to out of range array access or totally invalid -//! arguments like nullptr where a valid pointer should be provided, etc... -ASMJIT_API void ASMJIT_NORETURN assertionFailed(const char* file, int line, const char* msg) noexcept; - -} // {DebugUtils} - -//! \def ASMJIT_ASSERT(...) -//! -//! AsmJit's own assert macro used in AsmJit code-base. -#if defined(ASMJIT_BUILD_DEBUG) -#define ASMJIT_ASSERT(...) \ - do { \ - if (ASMJIT_LIKELY(__VA_ARGS__)) \ - break; \ - ::asmjit::DebugUtils::assertionFailed(__FILE__, __LINE__, #__VA_ARGS__); \ - } while (0) -#else -#define ASMJIT_ASSERT(...) ((void)0) -#endif - -//! \def ASMJIT_PROPAGATE(...) -//! -//! Propagates a possible `Error` produced by `...` to the caller by returning -//! the error immediately. Used by AsmJit internally, but kept public for users -//! that want to use the same technique to propagate errors to the caller. -#define ASMJIT_PROPAGATE(...) \ - do { \ - ::asmjit::Error _err = __VA_ARGS__; \ - if (ASMJIT_UNLIKELY(_err)) \ - return _err; \ - } while (0) - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_GLOBALS_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/inst.cpp b/ext/asmjit-master/src/asmjit/core/inst.cpp deleted file mode 100644 index a233b938..00000000 --- a/ext/asmjit-master/src/asmjit/core/inst.cpp +++ /dev/null @@ -1,139 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifdef ASMJIT_BUILD_X86 - -#include "../core/arch.h" -#include "../core/inst.h" - -#ifdef ASMJIT_BUILD_X86 - #include "../x86/x86instapi_p.h" -#endif - -#ifdef ASMJIT_BUILD_ARM - #include "../arm/arminstapi_p.h" -#endif - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::InstAPI - Text] -// ============================================================================ - -#ifndef ASMJIT_NO_TEXT -Error InstAPI::instIdToString(uint32_t arch, uint32_t instId, String& output) noexcept { -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::instIdToString(arch, instId, output); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::InstInternal::instIdToString(arch, instId, output); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} - -uint32_t InstAPI::stringToInstId(uint32_t arch, const char* s, size_t len) noexcept { -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::stringToInstId(arch, s, len); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::InstInternal::stringToInstId(arch, s, len); -#endif - - return 0; -} -#endif // !ASMJIT_NO_TEXT - -// ============================================================================ -// [asmjit::InstAPI - Validate] -// ============================================================================ - -#ifndef ASMJIT_NO_VALIDATION -Error InstAPI::validate(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, uint32_t validationFlags) noexcept { -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::validate(arch, inst, operands, opCount, validationFlags); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::InstInternal::validate(arch, inst, operands, opCount, validationFlags); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} -#endif // !ASMJIT_NO_VALIDATION - -// ============================================================================ -// [asmjit::InstAPI - QueryRWInfo] -// ============================================================================ - -#ifndef ASMJIT_NO_INTROSPECTION -Error InstAPI::queryRWInfo(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept { - if (ASMJIT_UNLIKELY(opCount > Globals::kMaxOpCount)) - return DebugUtils::errored(kErrorInvalidArgument); - -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::queryRWInfo(arch, inst, operands, opCount, out); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::InstInternal::queryRWInfo(arch, inst, operands, opCount, out); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} -#endif // !ASMJIT_NO_INTROSPECTION - -// ============================================================================ -// [asmjit::InstAPI - QueryFeatures] -// ============================================================================ - -#ifndef ASMJIT_NO_INTROSPECTION -Error InstAPI::queryFeatures(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, BaseFeatures* out) noexcept { -#ifdef ASMJIT_BUILD_X86 - if (Environment::isFamilyX86(arch)) - return x86::InstInternal::queryFeatures(arch, inst, operands, opCount, out); -#endif - -#ifdef ASMJIT_BUILD_ARM - if (Environment::isFamilyARM(arch)) - return arm::InstInternal::queryFeatures(arch, inst, operands, opCount, out); -#endif - - return DebugUtils::errored(kErrorInvalidArch); -} -#endif // !ASMJIT_NO_INTROSPECTION - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_BUILD_X86 diff --git a/ext/asmjit-master/src/asmjit/core/inst.h b/ext/asmjit-master/src/asmjit/core/inst.h deleted file mode 100644 index e34f93c8..00000000 --- a/ext/asmjit-master/src/asmjit/core/inst.h +++ /dev/null @@ -1,555 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_INST_H_INCLUDED -#define ASMJIT_CORE_INST_H_INCLUDED - -#include "../core/cpuinfo.h" -#include "../core/operand.h" -#include "../core/string.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_instruction_db -//! \{ - -// ============================================================================ -// [asmjit::BaseInst] -// ============================================================================ - -//! Instruction id, options, and extraReg in a single structure. This structure -//! exists mainly to simplify analysis and validation API that requires `BaseInst` -//! and `Operand[]` array. -class BaseInst { -public: - //! Instruction id, see \ref BaseInst::Id or {arch-specific}::Inst::Id. - uint32_t _id; - //! Instruction options, see \ref BaseInst::Options or {arch-specific}::Inst::Options. - uint32_t _options; - //! Extra register used by instruction (either REP register or AVX-512 selector). - RegOnly _extraReg; - - enum Id : uint32_t { - //! Invalid or uninitialized instruction id. - kIdNone = 0x00000000u, - //! Abstract instruction (BaseBuilder and BaseCompiler). - kIdAbstract = 0x80000000u - }; - - enum Options : uint32_t { - //! Used internally by emitters for handling errors and rare cases. - kOptionReserved = 0x00000001u, - - //! Prevents following a jump during compilation (BaseCompiler). - kOptionUnfollow = 0x00000010u, - - //! Overwrite the destination operand(s) (BaseCompiler). - //! - //! Hint that is important for register liveness analysis. It tells the - //! compiler that the destination operand will be overwritten now or by - //! adjacent instructions. BaseCompiler knows when a register is completely - //! overwritten by a single instruction, for example you don't have to - //! mark "movaps" or "pxor x, x", however, if a pair of instructions is - //! used and the first of them doesn't completely overwrite the content - //! of the destination, BaseCompiler fails to mark that register as dead. - //! - //! X86 Specific - //! ------------ - //! - //! - All instructions that always overwrite at least the size of the - //! register the virtual-register uses , for example "mov", "movq", - //! "movaps" don't need the overwrite option to be used - conversion, - //! shuffle, and other miscellaneous instructions included. - //! - //! - All instructions that clear the destination register if all operands - //! are the same, for example "xor x, x", "pcmpeqb x x", etc... - //! - //! - Consecutive instructions that partially overwrite the variable until - //! there is no old content require `BaseCompiler::overwrite()` to be used. - //! Some examples (not always the best use cases thought): - //! - //! - `movlps xmm0, ?` followed by `movhps xmm0, ?` and vice versa - //! - `movlpd xmm0, ?` followed by `movhpd xmm0, ?` and vice versa - //! - `mov al, ?` followed by `and ax, 0xFF` - //! - `mov al, ?` followed by `mov ah, al` - //! - `pinsrq xmm0, ?, 0` followed by `pinsrq xmm0, ?, 1` - //! - //! - If allocated variable is used temporarily for scalar operations. For - //! example if you allocate a full vector like `x86::Compiler::newXmm()` - //! and then use that vector for scalar operations you should use - //! `overwrite()` directive: - //! - //! - `sqrtss x, y` - only LO element of `x` is changed, if you don't - //! use HI elements, use `compiler.overwrite().sqrtss(x, y)`. - kOptionOverwrite = 0x00000020u, - - //! Emit short-form of the instruction. - kOptionShortForm = 0x00000040u, - //! Emit long-form of the instruction. - kOptionLongForm = 0x00000080u, - - //! Conditional jump is likely to be taken. - kOptionTaken = 0x00000100u, - //! Conditional jump is unlikely to be taken. - kOptionNotTaken = 0x00000200u - }; - - //! Control type. - enum ControlType : uint32_t { - //! No control type (doesn't jump). - kControlNone = 0u, - //! Unconditional jump. - kControlJump = 1u, - //! Conditional jump (branch). - kControlBranch = 2u, - //! Function call. - kControlCall = 3u, - //! Function return. - kControlReturn = 4u - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new BaseInst instance with `id` and `options` set. - //! - //! Default values of `id` and `options` are zero, which means none instruciton. - //! Such instruction is guaranteed to never exist for any architecture supported - //! by AsmJit. - inline explicit BaseInst(uint32_t id = 0, uint32_t options = 0) noexcept - : _id(id), - _options(options), - _extraReg() {} - - inline BaseInst(uint32_t id, uint32_t options, const RegOnly& extraReg) noexcept - : _id(id), - _options(options), - _extraReg(extraReg) {} - - inline BaseInst(uint32_t id, uint32_t options, const BaseReg& extraReg) noexcept - : _id(id), - _options(options), - _extraReg { extraReg.signature(), extraReg.id() } {} - - //! \} - - //! \name Instruction ID - //! \{ - - //! Returns the instruction id. - inline uint32_t id() const noexcept { return _id; } - //! Sets the instruction id to the given `id`. - inline void setId(uint32_t id) noexcept { _id = id; } - //! Resets the instruction id to zero, see \ref kIdNone. - inline void resetId() noexcept { _id = 0; } - - //! \} - - //! \name Instruction Options - //! \{ - - inline uint32_t options() const noexcept { return _options; } - inline bool hasOption(uint32_t option) const noexcept { return (_options & option) != 0; } - inline void setOptions(uint32_t options) noexcept { _options = options; } - inline void addOptions(uint32_t options) noexcept { _options |= options; } - inline void clearOptions(uint32_t options) noexcept { _options &= ~options; } - inline void resetOptions() noexcept { _options = 0; } - - //! \} - - //! \name Extra Register - //! \{ - - inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); } - inline RegOnly& extraReg() noexcept { return _extraReg; } - inline const RegOnly& extraReg() const noexcept { return _extraReg; } - inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); } - inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); } - inline void resetExtraReg() noexcept { _extraReg.reset(); } - - //! \} -}; - -// ============================================================================ -// [asmjit::OpRWInfo] -// ============================================================================ - -//! Read/Write information related to a single operand, used by \ref InstRWInfo. -struct OpRWInfo { - //! Read/Write flags, see \ref OpRWInfo::Flags. - uint32_t _opFlags; - //! Physical register index, if required. - uint8_t _physId; - //! Size of a possible memory operand that can replace a register operand. - uint8_t _rmSize; - //! Reserved for future use. - uint8_t _reserved[2]; - //! Read bit-mask where each bit represents one byte read from Reg/Mem. - uint64_t _readByteMask; - //! Write bit-mask where each bit represents one byte written to Reg/Mem. - uint64_t _writeByteMask; - //! Zero/Sign extend bit-mask where each bit represents one byte written to Reg/Mem. - uint64_t _extendByteMask; - - //! Flags describe how the operand is accessed and some additional information. - enum Flags : uint32_t { - //! Operand is read. - kRead = 0x00000001u, - - //! Operand is written. - kWrite = 0x00000002u, - - //! Operand is both read and written. - kRW = 0x00000003u, - - //! Register operand can be replaced by a memory operand. - kRegMem = 0x00000004u, - - //! The `extendByteMask()` represents a zero extension. - kZExt = 0x00000010u, - - //! Register operand must use \ref physId(). - kRegPhysId = 0x00000100u, - //! Base register of a memory operand must use \ref physId(). - kMemPhysId = 0x00000200u, - - //! This memory operand is only used to encode registers and doesn't access memory. - //! - //! X86 Specific - //! ------------ - //! - //! Instructions that use such feature include BNDLDX, BNDSTX, and LEA. - kMemFake = 0x000000400u, - - //! Base register of the memory operand will be read. - kMemBaseRead = 0x00001000u, - //! Base register of the memory operand will be written. - kMemBaseWrite = 0x00002000u, - //! Base register of the memory operand will be read & written. - kMemBaseRW = 0x00003000u, - - //! Index register of the memory operand will be read. - kMemIndexRead = 0x00004000u, - //! Index register of the memory operand will be written. - kMemIndexWrite = 0x00008000u, - //! Index register of the memory operand will be read & written. - kMemIndexRW = 0x0000C000u, - - //! Base register of the memory operand will be modified before the operation. - kMemBasePreModify = 0x00010000u, - //! Base register of the memory operand will be modified after the operation. - kMemBasePostModify = 0x00020000u - }; - - // Don't remove these asserts. Read/Write flags are used extensively - // by Compiler and they must always be compatible with constants below. - static_assert(kRead == 0x1, "OpRWInfo::kRead flag must be 0x1"); - static_assert(kWrite == 0x2, "OpRWInfo::kWrite flag must be 0x2"); - static_assert(kRegMem == 0x4, "OpRWInfo::kRegMem flag must be 0x4"); - - //! \name Reset - //! \{ - - //! Resets this operand information to all zeros. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! Resets this operand info (resets all members) and set common information - //! to the given `opFlags`, `regSize`, and possibly `physId`. - inline void reset(uint32_t opFlags, uint32_t regSize, uint32_t physId = BaseReg::kIdBad) noexcept { - _opFlags = opFlags; - _physId = uint8_t(physId); - _rmSize = uint8_t((opFlags & kRegMem) ? regSize : uint32_t(0)); - _resetReserved(); - - uint64_t mask = Support::lsbMask(regSize); - _readByteMask = opFlags & kRead ? mask : uint64_t(0); - _writeByteMask = opFlags & kWrite ? mask : uint64_t(0); - _extendByteMask = 0; - } - - inline void _resetReserved() noexcept { - memset(_reserved, 0, sizeof(_reserved)); - } - - //! \} - - //! \name Operand Flags - //! \{ - - //! Returns operand flags, see \ref Flags. - inline uint32_t opFlags() const noexcept { return _opFlags; } - //! Tests whether operand flags contain the given `flag`. - inline bool hasOpFlag(uint32_t flag) const noexcept { return (_opFlags & flag) != 0; } - - //! Adds the given `flags` to operand flags. - inline void addOpFlags(uint32_t flags) noexcept { _opFlags |= flags; } - //! Removes the given `flags` from operand flags. - inline void clearOpFlags(uint32_t flags) noexcept { _opFlags &= ~flags; } - - //! Tests whether this operand is read from. - inline bool isRead() const noexcept { return hasOpFlag(kRead); } - //! Tests whether this operand is written to. - inline bool isWrite() const noexcept { return hasOpFlag(kWrite); } - //! Tests whether this operand is both read and write. - inline bool isReadWrite() const noexcept { return (_opFlags & kRW) == kRW; } - //! Tests whether this operand is read only. - inline bool isReadOnly() const noexcept { return (_opFlags & kRW) == kRead; } - //! Tests whether this operand is write only. - inline bool isWriteOnly() const noexcept { return (_opFlags & kRW) == kWrite; } - - //! Tests whether this operand is Reg/Mem - //! - //! Reg/Mem operands can use either register or memory. - inline bool isRm() const noexcept { return hasOpFlag(kRegMem); } - - //! Tests whether the operand will be zero extended. - inline bool isZExt() const noexcept { return hasOpFlag(kZExt); } - - //! \} - - //! \name Memory Flags - //! \{ - - //! Tests whether this is a fake memory operand, which is only used, because - //! of encoding. Fake memory operands do not access any memory, they are only - //! used to encode registers. - inline bool isMemFake() const noexcept { return hasOpFlag(kMemFake); } - - //! Tests whether the instruction reads from its BASE registers. - inline bool isMemBaseRead() const noexcept { return hasOpFlag(kMemBaseRead); } - //! Tests whether the instruction writes to its BASE registers. - inline bool isMemBaseWrite() const noexcept { return hasOpFlag(kMemBaseWrite); } - //! Tests whether the instruction reads and writes from/to its BASE registers. - inline bool isMemBaseReadWrite() const noexcept { return (_opFlags & kMemBaseRW) == kMemBaseRW; } - //! Tests whether the instruction only reads from its BASE registers. - inline bool isMemBaseReadOnly() const noexcept { return (_opFlags & kMemBaseRW) == kMemBaseRead; } - //! Tests whether the instruction only writes to its BASE registers. - inline bool isMemBaseWriteOnly() const noexcept { return (_opFlags & kMemBaseRW) == kMemBaseWrite; } - - //! Tests whether the instruction modifies the BASE register before it uses - //! it to calculate the target address. - inline bool isMemBasePreModify() const noexcept { return hasOpFlag(kMemBasePreModify); } - //! Tests whether the instruction modifies the BASE register after it uses - //! it to calculate the target address. - inline bool isMemBasePostModify() const noexcept { return hasOpFlag(kMemBasePostModify); } - - //! Tests whether the instruction reads the INDEX registers. - inline bool isMemIndexRead() const noexcept { return hasOpFlag(kMemIndexRead); } - //! Tests whether the instruction writes to its INDEX registers. - inline bool isMemIndexWrite() const noexcept { return hasOpFlag(kMemIndexWrite); } - //! Tests whether the instruction reads and writes from/to its INDEX registers. - inline bool isMemIndexReadWrite() const noexcept { return (_opFlags & kMemIndexRW) == kMemIndexRW; } - //! Tests whether the instruction only reads from its INDEX registers. - inline bool isMemIndexReadOnly() const noexcept { return (_opFlags & kMemIndexRW) == kMemIndexRead; } - //! Tests whether the instruction only writes to its INDEX registers. - inline bool isMemIndexWriteOnly() const noexcept { return (_opFlags & kMemIndexRW) == kMemIndexWrite; } - - //! \} - - //! \name Physical Register ID - //! \{ - - //! Returns a physical id of the register that is fixed for this operand. - //! - //! Returns \ref BaseReg::kIdBad if any register can be used. - inline uint32_t physId() const noexcept { return _physId; } - //! Tests whether \ref physId() would return a valid physical register id. - inline bool hasPhysId() const noexcept { return _physId != BaseReg::kIdBad; } - //! Sets physical register id, which would be fixed for this operand. - inline void setPhysId(uint32_t physId) noexcept { _physId = uint8_t(physId); } - - //! \} - - //! \name Reg/Mem Information - //! \{ - - //! Returns Reg/Mem size of the operand. - inline uint32_t rmSize() const noexcept { return _rmSize; } - //! Sets Reg/Mem size of the operand. - inline void setRmSize(uint32_t rmSize) noexcept { _rmSize = uint8_t(rmSize); } - - //! \} - - //! \name Read & Write Masks - //! \{ - - //! Returns read mask. - inline uint64_t readByteMask() const noexcept { return _readByteMask; } - //! Returns write mask. - inline uint64_t writeByteMask() const noexcept { return _writeByteMask; } - //! Returns extend mask. - inline uint64_t extendByteMask() const noexcept { return _extendByteMask; } - - //! Sets read mask. - inline void setReadByteMask(uint64_t mask) noexcept { _readByteMask = mask; } - //! Sets write mask. - inline void setWriteByteMask(uint64_t mask) noexcept { _writeByteMask = mask; } - //! Sets externd mask. - inline void setExtendByteMask(uint64_t mask) noexcept { _extendByteMask = mask; } - - //! \} -}; - -// ============================================================================ -// [asmjit::InstRWInfo] -// ============================================================================ - -//! Read/Write information of an instruction. -struct InstRWInfo { - //! Instruction flags (there are no flags at the moment, this field is reserved). - uint32_t _instFlags; - //! Mask of CPU flags read. - uint32_t _readFlags; - //! Mask of CPU flags written. - uint32_t _writeFlags; - //! Count of operands. - uint8_t _opCount; - //! CPU feature required for replacing register operand with memory operand. - uint8_t _rmFeature; - //! Reserved for future use. - uint8_t _reserved[18]; - //! Read/Write onfo of extra register (rep{} or kz{}). - OpRWInfo _extraReg; - //! Read/Write info of instruction operands. - OpRWInfo _operands[Globals::kMaxOpCount]; - - //! \name Commons - //! \{ - - //! Resets this RW information to all zeros. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - - //! \} - - //! \name Instruction Flags - //! - //! \{ - - inline uint32_t instFlags() const noexcept { return _instFlags; } - inline bool hasInstFlag(uint32_t flag) const noexcept { return (_instFlags & flag) != 0; } - - //! } - - //! \name CPU Flags Read/Write Information - //! \{ - - //! Returns read flags of the instruction. - inline uint32_t readFlags() const noexcept { return _readFlags; } - //! Returns write flags of the instruction. - inline uint32_t writeFlags() const noexcept { return _writeFlags; } - - //! \} - - //! \name Reg/Mem Information - //! \{ - - //! Returns the CPU feature required to replace a register operand with memory - //! operand. If the returned feature is zero (none) then this instruction - //! either doesn't provide memory operand combination or there is no extra - //! CPU feature required. - //! - //! X86 Specific - //! ------------ - //! - //! Some AVX+ instructions may require extra features for replacing registers - //! with memory operands, for example VPSLLDQ instruction only supports - //! 'reg/reg/imm' combination on AVX/AVX2 capable CPUs and requires AVX-512 for - //! 'reg/mem/imm' combination. - inline uint32_t rmFeature() const noexcept { return _rmFeature; } - - //! \} - - //! \name Operand Read/Write Information - //! \{ - - //! Returns RW information of extra register operand (extraReg). - inline const OpRWInfo& extraReg() const noexcept { return _extraReg; } - - //! Returns RW information of all instruction's operands. - inline const OpRWInfo* operands() const noexcept { return _operands; } - - //! Returns RW information of the operand at the given `index`. - inline const OpRWInfo& operand(size_t index) const noexcept { - ASMJIT_ASSERT(index < Globals::kMaxOpCount); - return _operands[index]; - } - - //! Returns the number of operands this instruction has. - inline uint32_t opCount() const noexcept { return _opCount; } - - //! \} -}; - -// ============================================================================ -// [asmjit::InstAPI] -// ============================================================================ - -//! Instruction API. -namespace InstAPI { - -//! Validation flags that can be used with \ref InstAPI::validate(). -enum ValidationFlags : uint32_t { - //! Allow virtual registers in the instruction. - kValidationFlagVirtRegs = 0x01u -}; - -#ifndef ASMJIT_NO_TEXT -//! Appends the name of the instruction specified by `instId` and `instOptions` -//! into the `output` string. -//! -//! \note Instruction options would only affect instruction prefix & suffix, -//! other options would be ignored. If `instOptions` is zero then only raw -//! instruction name (without any additional text) will be appended. -ASMJIT_API Error instIdToString(uint32_t arch, uint32_t instId, String& output) noexcept; - -//! Parses an instruction name in the given string `s`. Length is specified -//! by `len` argument, which can be `SIZE_MAX` if `s` is known to be null -//! terminated. -//! -//! Returns the parsed instruction id or \ref BaseInst::kIdNone if no such -//! instruction exists. -ASMJIT_API uint32_t stringToInstId(uint32_t arch, const char* s, size_t len) noexcept; -#endif // !ASMJIT_NO_TEXT - -#ifndef ASMJIT_NO_VALIDATION -//! Validates the given instruction considering the validation `flags`, see -//! \ref ValidationFlags. -ASMJIT_API Error validate(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, uint32_t validationFlags = 0) noexcept; -#endif // !ASMJIT_NO_VALIDATION - -#ifndef ASMJIT_NO_INTROSPECTION -//! Gets Read/Write information of the given instruction. -ASMJIT_API Error queryRWInfo(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept; - -//! Gets CPU features required by the given instruction. -ASMJIT_API Error queryFeatures(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount, BaseFeatures* out) noexcept; -#endif // !ASMJIT_NO_INTROSPECTION - -} // {InstAPI} - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_INST_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/jitallocator.cpp b/ext/asmjit-master/src/asmjit/core/jitallocator.cpp deleted file mode 100644 index b2285113..00000000 --- a/ext/asmjit-master/src/asmjit/core/jitallocator.cpp +++ /dev/null @@ -1,1152 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_JIT - -#include "../core/arch.h" -#include "../core/jitallocator.h" -#include "../core/osutils_p.h" -#include "../core/support.h" -#include "../core/virtmem.h" -#include "../core/zone.h" -#include "../core/zonelist.h" -#include "../core/zonetree.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::JitAllocator - Constants] -// ============================================================================ - -enum JitAllocatorConstants : uint32_t { - //! Number of pools to use when `JitAllocator::kOptionUseMultiplePools` is set. - //! - //! Each pool increases granularity twice to make memory management more - //! efficient. Ideal number of pools appears to be 3 to 4 as it distributes - //! small and large functions properly. - kJitAllocatorMultiPoolCount = 3, - - //! Minimum granularity (and the default granularity for pool #0). - kJitAllocatorBaseGranularity = 64, - - //! Maximum block size (16MB). - kJitAllocatorMaxBlockSize = 1024 * 1024 * 16 -}; - -static inline uint32_t JitAllocator_defaultFillPattern() noexcept { - // X86 and X86_64 - 4x 'int3' instruction. - if (ASMJIT_ARCH_X86) - return 0xCCCCCCCCu; - - // Unknown... - return 0u; -} - -// ============================================================================ -// [asmjit::JitAllocator - BitFlipIterator] -// ============================================================================ - -//! BitWord[] iterator used by `JitAllocator` that can flip the search pattern -//! during iteration. -template -class BitFlipIterator { -public: - ASMJIT_INLINE BitFlipIterator(const T* data, size_t numBitWords, size_t start = 0, T xorMask = 0) noexcept { - init(data, numBitWords, start, xorMask); - } - - ASMJIT_INLINE void init(const T* data, size_t numBitWords, size_t start = 0, T xorMask = 0) noexcept { - const T* ptr = data + (start / Support::bitSizeOf()); - size_t idx = Support::alignDown(start, Support::bitSizeOf()); - size_t end = numBitWords * Support::bitSizeOf(); - - T bitWord = T(0); - if (idx < end) { - bitWord = (*ptr++ ^ xorMask) & (Support::allOnes() << (start % Support::bitSizeOf())); - while (!bitWord && (idx += Support::bitSizeOf()) < end) - bitWord = *ptr++ ^ xorMask; - } - - _ptr = ptr; - _idx = idx; - _end = end; - _current = bitWord; - _xorMask = xorMask; - } - - ASMJIT_INLINE bool hasNext() const noexcept { - return _current != T(0); - } - - ASMJIT_INLINE size_t next() noexcept { - T bitWord = _current; - ASMJIT_ASSERT(bitWord != T(0)); - - uint32_t bit = Support::ctz(bitWord); - bitWord ^= T(1u) << bit; - - size_t n = _idx + bit; - while (!bitWord && (_idx += Support::bitSizeOf()) < _end) - bitWord = *_ptr++ ^ _xorMask; - - _current = bitWord; - return n; - } - - ASMJIT_INLINE size_t nextAndFlip() noexcept { - T bitWord = _current; - ASMJIT_ASSERT(bitWord != T(0)); - - uint32_t bit = Support::ctz(bitWord); - bitWord ^= Support::allOnes() << bit; - _xorMask ^= Support::allOnes(); - - size_t n = _idx + bit; - while (!bitWord && (_idx += Support::bitSizeOf()) < _end) - bitWord = *_ptr++ ^ _xorMask; - - _current = bitWord; - return n; - } - - ASMJIT_INLINE size_t peekNext() const noexcept { - ASMJIT_ASSERT(_current != T(0)); - return _idx + Support::ctz(_current); - } - - const T* _ptr; - size_t _idx; - size_t _end; - T _current; - T _xorMask; -}; - -// ============================================================================ -// [asmjit::JitAllocator - Pool] -// ============================================================================ - -class JitAllocatorBlock; - -class JitAllocatorPool { -public: - ASMJIT_NONCOPYABLE(JitAllocatorPool) - - inline JitAllocatorPool(uint32_t granularity) noexcept - : blocks(), - cursor(nullptr), - blockCount(0), - granularity(uint16_t(granularity)), - granularityLog2(uint8_t(Support::ctz(granularity))), - emptyBlockCount(0), - totalAreaSize(0), - totalAreaUsed(0), - totalOverheadBytes(0) {} - - inline void reset() noexcept { - blocks.reset(); - cursor = nullptr; - blockCount = 0; - totalAreaSize = 0; - totalAreaUsed = 0; - totalOverheadBytes = 0; - } - - inline size_t byteSizeFromAreaSize(uint32_t areaSize) const noexcept { return size_t(areaSize) * granularity; } - inline uint32_t areaSizeFromByteSize(size_t size) const noexcept { return uint32_t((size + granularity - 1) >> granularityLog2); } - - inline size_t bitWordCountFromAreaSize(uint32_t areaSize) const noexcept { - using namespace Support; - return alignUp(areaSize, kBitWordSizeInBits) / kBitWordSizeInBits; - } - - //! Double linked list of blocks. - ZoneList blocks; - //! Where to start looking first. - JitAllocatorBlock* cursor; - - //! Count of blocks. - uint32_t blockCount; - //! Allocation granularity. - uint16_t granularity; - //! Log2(granularity). - uint8_t granularityLog2; - //! Count of empty blocks (either 0 or 1 as we won't keep more blocks empty). - uint8_t emptyBlockCount; - - //! Number of bits reserved across all blocks. - size_t totalAreaSize; - //! Number of bits used across all blocks. - size_t totalAreaUsed; - //! Overhead of all blocks (in bytes). - size_t totalOverheadBytes; -}; - -// ============================================================================ -// [asmjit::JitAllocator - Block] -// ============================================================================ - -class JitAllocatorBlock : public ZoneTreeNodeT, - public ZoneListNode { -public: - ASMJIT_NONCOPYABLE(JitAllocatorBlock) - - enum Flags : uint32_t { - //! Block is empty. - kFlagEmpty = 0x00000001u, - //! Block is dirty (largestUnusedArea, searchStart, searchEnd). - kFlagDirty = 0x00000002u, - //! Block is dual-mapped. - kFlagDualMapped = 0x00000004u - }; - - inline JitAllocatorBlock( - JitAllocatorPool* pool, - VirtMem::DualMapping mapping, - size_t blockSize, - uint32_t blockFlags, - Support::BitWord* usedBitVector, - Support::BitWord* stopBitVector, - uint32_t areaSize) noexcept - : ZoneTreeNodeT(), - pool(pool), - mapping(mapping), - blockSize(blockSize), - flags(blockFlags), - areaSize(areaSize), - areaUsed(0), - largestUnusedArea(areaSize), - searchStart(0), - searchEnd(areaSize), - usedBitVector(usedBitVector), - stopBitVector(stopBitVector) {} - - inline uint8_t* roPtr() const noexcept { return static_cast(mapping.ro); } - inline uint8_t* rwPtr() const noexcept { return static_cast(mapping.rw); } - - inline bool hasFlag(uint32_t f) const noexcept { return (flags & f) != 0; } - inline void addFlags(uint32_t f) noexcept { flags |= f; } - inline void clearFlags(uint32_t f) noexcept { flags &= ~f; } - - inline uint32_t areaAvailable() const noexcept { return areaSize - areaUsed; } - - inline void increaseUsedArea(uint32_t value) noexcept { - areaUsed += value; - pool->totalAreaUsed += value; - } - - inline void decreaseUsedArea(uint32_t value) noexcept { - areaUsed -= value; - pool->totalAreaUsed -= value; - } - - // RBTree default CMP uses '<' and '>' operators. - inline bool operator<(const JitAllocatorBlock& other) const noexcept { return roPtr() < other.roPtr(); } - inline bool operator>(const JitAllocatorBlock& other) const noexcept { return roPtr() > other.roPtr(); } - - // Special implementation for querying blocks by `key`, which must be in `[BlockPtr, BlockPtr + BlockSize)` range. - inline bool operator<(const uint8_t* key) const noexcept { return roPtr() + blockSize <= key; } - inline bool operator>(const uint8_t* key) const noexcept { return roPtr() > key; } - - //! Link to the pool that owns this block. - JitAllocatorPool* pool; - //! Virtual memory mapping - either single mapping (both pointers equal) or - //! dual mapping, where one pointer is Read+Execute and the second Read+Write. - VirtMem::DualMapping mapping; - //! Virtual memory size (block size) [bytes]. - size_t blockSize; - - //! Block flags. - uint32_t flags; - //! Size of the whole block area (bit-vector size). - uint32_t areaSize; - //! Used area (number of bits in bit-vector used). - uint32_t areaUsed; - //! The largest unused continuous area in the bit-vector (or `areaSize` to initiate rescan). - uint32_t largestUnusedArea; - //! Start of a search range (for unused bits). - uint32_t searchStart; - //! End of a search range (for unused bits). - uint32_t searchEnd; - - //! Used bit-vector (0 = unused, 1 = used). - Support::BitWord* usedBitVector; - //! Stop bit-vector (0 = don't care, 1 = stop). - Support::BitWord* stopBitVector; -}; - -// ============================================================================ -// [asmjit::JitAllocator - PrivateImpl] -// ============================================================================ - -class JitAllocatorPrivateImpl : public JitAllocator::Impl { -public: - inline JitAllocatorPrivateImpl(JitAllocatorPool* pools, size_t poolCount) noexcept - : JitAllocator::Impl {}, - pools(pools), - poolCount(poolCount) {} - inline ~JitAllocatorPrivateImpl() noexcept {} - - //! Lock for thread safety. - mutable Lock lock; - //! System page size (also a minimum block size). - uint32_t pageSize; - - //! Blocks from all pools in RBTree. - ZoneTree tree; - //! Allocator pools. - JitAllocatorPool* pools; - //! Number of allocator pools. - size_t poolCount; -}; - -static const JitAllocator::Impl JitAllocatorImpl_none {}; -static const JitAllocator::CreateParams JitAllocatorParams_none {}; - -// ============================================================================ -// [asmjit::JitAllocator - Utilities] -// ============================================================================ - -static inline JitAllocatorPrivateImpl* JitAllocatorImpl_new(const JitAllocator::CreateParams* params) noexcept { - VirtMem::Info vmInfo = VirtMem::info(); - - if (!params) - params = &JitAllocatorParams_none; - - uint32_t options = params->options; - uint32_t blockSize = params->blockSize; - uint32_t granularity = params->granularity; - uint32_t fillPattern = params->fillPattern; - - // Setup pool count to [1..3]. - size_t poolCount = 1; - if (options & JitAllocator::kOptionUseMultiplePools) - poolCount = kJitAllocatorMultiPoolCount;; - - // Setup block size [64kB..256MB]. - if (blockSize < 64 * 1024 || blockSize > 256 * 1024 * 1024 || !Support::isPowerOf2(blockSize)) - blockSize = vmInfo.pageGranularity; - - // Setup granularity [64..256]. - if (granularity < 64 || granularity > 256 || !Support::isPowerOf2(granularity)) - granularity = kJitAllocatorBaseGranularity; - - // Setup fill-pattern. - if (!(options & JitAllocator::kOptionCustomFillPattern)) - fillPattern = JitAllocator_defaultFillPattern(); - - size_t size = sizeof(JitAllocatorPrivateImpl) + sizeof(JitAllocatorPool) * poolCount; - void* p = ::malloc(size); - if (ASMJIT_UNLIKELY(!p)) - return nullptr; - - JitAllocatorPool* pools = reinterpret_cast((uint8_t*)p + sizeof(JitAllocatorPrivateImpl)); - JitAllocatorPrivateImpl* impl = new(p) JitAllocatorPrivateImpl(pools, poolCount); - - impl->options = options; - impl->blockSize = blockSize; - impl->granularity = granularity; - impl->fillPattern = fillPattern; - impl->pageSize = vmInfo.pageSize; - - for (size_t poolId = 0; poolId < poolCount; poolId++) - new(&pools[poolId]) JitAllocatorPool(granularity << poolId); - - return impl; -} - -static inline void JitAllocatorImpl_destroy(JitAllocatorPrivateImpl* impl) noexcept { - impl->~JitAllocatorPrivateImpl(); - ::free(impl); -} - -static inline size_t JitAllocatorImpl_sizeToPoolId(const JitAllocatorPrivateImpl* impl, size_t size) noexcept { - size_t poolId = impl->poolCount - 1; - size_t granularity = size_t(impl->granularity) << poolId; - - while (poolId) { - if (Support::alignUp(size, granularity) == size) - break; - poolId--; - granularity >>= 1; - } - - return poolId; -} - -static inline size_t JitAllocatorImpl_bitVectorSizeToByteSize(uint32_t areaSize) noexcept { - using Support::kBitWordSizeInBits; - return ((areaSize + kBitWordSizeInBits - 1u) / kBitWordSizeInBits) * sizeof(Support::BitWord); -} - -static inline size_t JitAllocatorImpl_calculateIdealBlockSize(JitAllocatorPrivateImpl* impl, JitAllocatorPool* pool, size_t allocationSize) noexcept { - JitAllocatorBlock* last = pool->blocks.last(); - size_t blockSize = last ? last->blockSize : size_t(impl->blockSize); - - if (blockSize < kJitAllocatorMaxBlockSize) - blockSize *= 2u; - - if (allocationSize > blockSize) { - blockSize = Support::alignUp(allocationSize, impl->blockSize); - if (ASMJIT_UNLIKELY(blockSize < allocationSize)) - return 0; // Overflown. - } - - return blockSize; -} - -ASMJIT_FAVOR_SPEED static void JitAllocatorImpl_fillPattern(void* mem, uint32_t pattern, size_t sizeInBytes) noexcept { - size_t n = sizeInBytes / 4u; - uint32_t* p = static_cast(mem); - - for (size_t i = 0; i < n; i++) - p[i] = pattern; -} - -// Allocate a new `JitAllocatorBlock` for the given `blockSize`. -// -// NOTE: The block doesn't have `kFlagEmpty` flag set, because the new block -// is only allocated when it's actually needed, so it would be cleared anyway. -static JitAllocatorBlock* JitAllocatorImpl_newBlock(JitAllocatorPrivateImpl* impl, JitAllocatorPool* pool, size_t blockSize) noexcept { - using Support::BitWord; - using Support::kBitWordSizeInBits; - - uint32_t areaSize = uint32_t((blockSize + pool->granularity - 1) >> pool->granularityLog2); - uint32_t numBitWords = (areaSize + kBitWordSizeInBits - 1u) / kBitWordSizeInBits; - - JitAllocatorBlock* block = static_cast(::malloc(sizeof(JitAllocatorBlock))); - BitWord* bitWords = nullptr; - VirtMem::DualMapping virtMem {}; - Error err = kErrorOutOfMemory; - - if (block != nullptr) - bitWords = static_cast(::malloc(size_t(numBitWords) * 2 * sizeof(BitWord))); - - uint32_t blockFlags = 0; - if (bitWords != nullptr) { - if (impl->options & JitAllocator::kOptionUseDualMapping) { - err = VirtMem::allocDualMapping(&virtMem, blockSize, VirtMem::kAccessReadWrite | VirtMem::kAccessExecute); - blockFlags |= JitAllocatorBlock::kFlagDualMapped; - } - else { - err = VirtMem::alloc(&virtMem.ro, blockSize, VirtMem::kAccessReadWrite | VirtMem::kAccessExecute); - virtMem.rw = virtMem.ro; - } - } - - // Out of memory. - if (ASMJIT_UNLIKELY(!block || !bitWords || err != kErrorOk)) { - if (bitWords) ::free(bitWords); - if (block) ::free(block); - return nullptr; - } - - // Fill the memory if the secure mode is enabled. - if (impl->options & JitAllocator::kOptionFillUnusedMemory) - JitAllocatorImpl_fillPattern(virtMem.rw, impl->fillPattern, blockSize); - - memset(bitWords, 0, size_t(numBitWords) * 2 * sizeof(BitWord)); - return new(block) JitAllocatorBlock(pool, virtMem, blockSize, blockFlags, bitWords, bitWords + numBitWords, areaSize); -} - -static void JitAllocatorImpl_deleteBlock(JitAllocatorPrivateImpl* impl, JitAllocatorBlock* block) noexcept { - DebugUtils::unused(impl); - - if (block->flags & JitAllocatorBlock::kFlagDualMapped) - VirtMem::releaseDualMapping(&block->mapping, block->blockSize); - else - VirtMem::release(block->mapping.ro, block->blockSize); - - ::free(block->usedBitVector); - ::free(block); -} - -static void JitAllocatorImpl_insertBlock(JitAllocatorPrivateImpl* impl, JitAllocatorBlock* block) noexcept { - JitAllocatorPool* pool = block->pool; - - if (!pool->cursor) - pool->cursor = block; - - // Add to RBTree and List. - impl->tree.insert(block); - pool->blocks.append(block); - - // Update statistics. - pool->blockCount++; - pool->totalAreaSize += block->areaSize; - pool->totalOverheadBytes += sizeof(JitAllocatorBlock) + JitAllocatorImpl_bitVectorSizeToByteSize(block->areaSize) * 2u; -} - -static void JitAllocatorImpl_removeBlock(JitAllocatorPrivateImpl* impl, JitAllocatorBlock* block) noexcept { - JitAllocatorPool* pool = block->pool; - - // Remove from RBTree and List. - if (pool->cursor == block) - pool->cursor = block->hasPrev() ? block->prev() : block->next(); - - impl->tree.remove(block); - pool->blocks.unlink(block); - - // Update statistics. - pool->blockCount--; - pool->totalAreaSize -= block->areaSize; - pool->totalOverheadBytes -= sizeof(JitAllocatorBlock) + JitAllocatorImpl_bitVectorSizeToByteSize(block->areaSize) * 2u; -} - -static void JitAllocatorImpl_wipeOutBlock(JitAllocatorPrivateImpl* impl, JitAllocatorBlock* block) noexcept { - JitAllocatorPool* pool = block->pool; - - if (block->hasFlag(JitAllocatorBlock::kFlagEmpty)) - return; - - uint32_t areaSize = block->areaSize; - uint32_t granularity = pool->granularity; - size_t numBitWords = pool->bitWordCountFromAreaSize(areaSize); - - if (impl->options & JitAllocator::kOptionFillUnusedMemory) { - BitFlipIterator it(block->usedBitVector, numBitWords); - - while (it.hasNext()) { - uint32_t start = uint32_t(it.nextAndFlip()); - uint32_t end = areaSize; - - if (it.hasNext()) - end = uint32_t(it.nextAndFlip()); - - JitAllocatorImpl_fillPattern(block->rwPtr() + start * granularity, impl->fillPattern, (end - start) * granularity); - } - } - - memset(block->usedBitVector, 0, size_t(numBitWords) * sizeof(Support::BitWord)); - memset(block->stopBitVector, 0, size_t(numBitWords) * sizeof(Support::BitWord)); - - block->areaUsed = 0; - block->largestUnusedArea = areaSize; - block->searchStart = 0; - block->searchEnd = areaSize; - block->addFlags(JitAllocatorBlock::kFlagEmpty); - block->clearFlags(JitAllocatorBlock::kFlagDirty); -} - -// ============================================================================ -// [asmjit::JitAllocator - Construction / Destruction] -// ============================================================================ - -JitAllocator::JitAllocator(const CreateParams* params) noexcept { - _impl = JitAllocatorImpl_new(params); - if (ASMJIT_UNLIKELY(!_impl)) - _impl = const_cast(&JitAllocatorImpl_none); -} - -JitAllocator::~JitAllocator() noexcept { - if (_impl == &JitAllocatorImpl_none) - return; - - reset(Globals::kResetHard); - JitAllocatorImpl_destroy(static_cast(_impl)); -} - -// ============================================================================ -// [asmjit::JitAllocator - Reset] -// ============================================================================ - -void JitAllocator::reset(uint32_t resetPolicy) noexcept { - if (_impl == &JitAllocatorImpl_none) - return; - - JitAllocatorPrivateImpl* impl = static_cast(_impl); - impl->tree.reset(); - size_t poolCount = impl->poolCount; - - for (size_t poolId = 0; poolId < poolCount; poolId++) { - JitAllocatorPool& pool = impl->pools[poolId]; - JitAllocatorBlock* block = pool.blocks.first(); - - JitAllocatorBlock* blockToKeep = nullptr; - if (resetPolicy != Globals::kResetHard && !(impl->options & kOptionImmediateRelease)) { - blockToKeep = block; - block = block->next(); - } - - while (block) { - JitAllocatorBlock* next = block->next(); - JitAllocatorImpl_deleteBlock(impl, block); - block = next; - } - - pool.reset(); - - if (blockToKeep) { - blockToKeep->_listNodes[0] = nullptr; - blockToKeep->_listNodes[1] = nullptr; - JitAllocatorImpl_wipeOutBlock(impl, blockToKeep); - JitAllocatorImpl_insertBlock(impl, blockToKeep); - pool.emptyBlockCount = 1; - } - } -} - -// ============================================================================ -// [asmjit::JitAllocator - Statistics] -// ============================================================================ - -JitAllocator::Statistics JitAllocator::statistics() const noexcept { - Statistics statistics; - statistics.reset(); - - if (ASMJIT_LIKELY(_impl != &JitAllocatorImpl_none)) { - JitAllocatorPrivateImpl* impl = static_cast(_impl); - LockGuard guard(impl->lock); - - size_t poolCount = impl->poolCount; - for (size_t poolId = 0; poolId < poolCount; poolId++) { - const JitAllocatorPool& pool = impl->pools[poolId]; - statistics._blockCount += size_t(pool.blockCount); - statistics._reservedSize += size_t(pool.totalAreaSize) * pool.granularity; - statistics._usedSize += size_t(pool.totalAreaUsed) * pool.granularity; - statistics._overheadSize += size_t(pool.totalOverheadBytes); - } - } - - return statistics; -} - -// ============================================================================ -// [asmjit::JitAllocator - Alloc / Release] -// ============================================================================ - -Error JitAllocator::alloc(void** roPtrOut, void** rwPtrOut, size_t size) noexcept { - if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) - return DebugUtils::errored(kErrorNotInitialized); - - JitAllocatorPrivateImpl* impl = static_cast(_impl); - constexpr uint32_t kNoIndex = std::numeric_limits::max(); - - *roPtrOut = nullptr; - *rwPtrOut = nullptr; - - // Align to the minimum granularity by default. - size = Support::alignUp(size, impl->granularity); - if (ASMJIT_UNLIKELY(size == 0)) - return DebugUtils::errored(kErrorInvalidArgument); - - if (ASMJIT_UNLIKELY(size > std::numeric_limits::max() / 2)) - return DebugUtils::errored(kErrorTooLarge); - - LockGuard guard(impl->lock); - JitAllocatorPool* pool = &impl->pools[JitAllocatorImpl_sizeToPoolId(impl, size)]; - - uint32_t areaIndex = kNoIndex; - uint32_t areaSize = uint32_t(pool->areaSizeFromByteSize(size)); - - // Try to find the requested memory area in existing blocks. - JitAllocatorBlock* block = pool->blocks.first(); - if (block) { - JitAllocatorBlock* initial = block; - do { - JitAllocatorBlock* next = block->hasNext() ? block->next() : pool->blocks.first(); - if (block->areaAvailable() >= areaSize) { - if (block->hasFlag(JitAllocatorBlock::kFlagDirty) || block->largestUnusedArea >= areaSize) { - uint32_t blockAreaSize = block->areaSize; - uint32_t searchStart = block->searchStart; - uint32_t searchEnd = block->searchEnd; - - BitFlipIterator it( - block->usedBitVector, - pool->bitWordCountFromAreaSize(searchEnd), - searchStart, - Support::allOnes()); - - // If there is unused area available then there has to be at least one match. - ASMJIT_ASSERT(it.hasNext()); - - uint32_t bestArea = blockAreaSize; - uint32_t largestArea = 0; - uint32_t holeIndex = uint32_t(it.peekNext()); - uint32_t holeEnd = holeIndex; - - searchStart = holeIndex; - do { - holeIndex = uint32_t(it.nextAndFlip()); - if (holeIndex >= searchEnd) break; - - holeEnd = it.hasNext() ? Support::min(searchEnd, uint32_t(it.nextAndFlip())) : searchEnd; - uint32_t holeSize = holeEnd - holeIndex; - - if (holeSize >= areaSize && bestArea >= holeSize) { - largestArea = Support::max(largestArea, bestArea); - bestArea = holeSize; - areaIndex = holeIndex; - } - else { - largestArea = Support::max(largestArea, holeSize); - } - } while (it.hasNext()); - searchEnd = holeEnd; - - // Because we have traversed the entire block, we can now mark the - // largest unused area that can be used to cache the next traversal. - block->searchStart = searchStart; - block->searchEnd = searchEnd; - block->largestUnusedArea = largestArea; - block->clearFlags(JitAllocatorBlock::kFlagDirty); - - if (areaIndex != kNoIndex) { - if (searchStart == areaIndex) - block->searchStart += areaSize; - break; - } - } - } - - block = next; - } while (block != initial); - } - - // Allocate a new block if there is no region of a required width. - if (areaIndex == kNoIndex) { - size_t blockSize = JitAllocatorImpl_calculateIdealBlockSize(impl, pool, size); - if (ASMJIT_UNLIKELY(!blockSize)) - return DebugUtils::errored(kErrorOutOfMemory); - - block = JitAllocatorImpl_newBlock(impl, pool, blockSize); - - if (ASMJIT_UNLIKELY(!block)) - return DebugUtils::errored(kErrorOutOfMemory); - - JitAllocatorImpl_insertBlock(impl, block); - areaIndex = 0; - block->searchStart = areaSize; - block->largestUnusedArea = block->areaSize - areaSize; - } - - // Update statistics. - block->increaseUsedArea(areaSize); - - // Handle special cases. - if (block->hasFlag(JitAllocatorBlock::kFlagEmpty)) { - pool->emptyBlockCount--; - block->clearFlags(JitAllocatorBlock::kFlagEmpty); - } - - if (block->areaAvailable() == 0) { - // The whole block is filled. - block->searchStart = block->areaSize; - block->searchEnd = 0; - block->largestUnusedArea = 0; - block->clearFlags(JitAllocatorBlock::kFlagDirty); - } - - // Mark the newly allocated space as occupied and also the sentinel. - Support::bitVectorFill(block->usedBitVector, areaIndex, areaSize); - Support::bitVectorSetBit(block->stopBitVector, areaIndex + areaSize - 1, true); - - // Return a pointer to the allocated memory. - size_t offset = pool->byteSizeFromAreaSize(areaIndex); - ASMJIT_ASSERT(offset <= block->blockSize - size); - - *roPtrOut = block->roPtr() + offset; - *rwPtrOut = block->rwPtr() + offset; - return kErrorOk; -} - -Error JitAllocator::release(void* ro) noexcept { - if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) - return DebugUtils::errored(kErrorNotInitialized); - - if (ASMJIT_UNLIKELY(!ro)) - return DebugUtils::errored(kErrorInvalidArgument); - - JitAllocatorPrivateImpl* impl = static_cast(_impl); - LockGuard guard(impl->lock); - - JitAllocatorBlock* block = impl->tree.get(static_cast(ro)); - if (ASMJIT_UNLIKELY(!block)) - return DebugUtils::errored(kErrorInvalidState); - - // Offset relative to the start of the block. - JitAllocatorPool* pool = block->pool; - size_t offset = (size_t)((uint8_t*)ro - block->roPtr()); - - // The first bit representing the allocated area and its size. - uint32_t areaIndex = uint32_t(offset >> pool->granularityLog2); - uint32_t areaLast = uint32_t(Support::bitVectorIndexOf(block->stopBitVector, areaIndex, true)); - uint32_t areaSize = areaLast - areaIndex + 1; - - // Update the search region and statistics. - block->searchStart = Support::min(block->searchStart, areaIndex); - block->searchEnd = Support::max(block->searchEnd, areaLast + 1); - block->addFlags(JitAllocatorBlock::kFlagDirty); - block->decreaseUsedArea(areaSize); - - // Clear all occupied bits and also the sentinel. - Support::bitVectorClear(block->usedBitVector, areaIndex, areaSize); - Support::bitVectorSetBit(block->stopBitVector, areaLast, false); - - // Fill the released memory if the secure mode is enabled. - if (impl->options & kOptionFillUnusedMemory) - JitAllocatorImpl_fillPattern(block->rwPtr() + areaIndex * pool->granularity, impl->fillPattern, areaSize * pool->granularity); - - // Release the whole block if it became empty. - if (block->areaUsed == 0) { - if (pool->emptyBlockCount || (impl->options & kOptionImmediateRelease)) { - JitAllocatorImpl_removeBlock(impl, block); - JitAllocatorImpl_deleteBlock(impl, block); - } - else { - pool->emptyBlockCount++; - block->largestUnusedArea = areaSize; - block->searchStart = 0; - block->searchEnd = areaSize; - block->addFlags(JitAllocatorBlock::kFlagEmpty); - block->clearFlags(JitAllocatorBlock::kFlagDirty); - } - } - - return kErrorOk; -} - -Error JitAllocator::shrink(void* ro, size_t newSize) noexcept { - if (ASMJIT_UNLIKELY(_impl == &JitAllocatorImpl_none)) - return DebugUtils::errored(kErrorNotInitialized); - - if (ASMJIT_UNLIKELY(!ro)) - return DebugUtils::errored(kErrorInvalidArgument); - - if (ASMJIT_UNLIKELY(newSize == 0)) - return release(ro); - - JitAllocatorPrivateImpl* impl = static_cast(_impl); - LockGuard guard(impl->lock); - JitAllocatorBlock* block = impl->tree.get(static_cast(ro)); - - if (ASMJIT_UNLIKELY(!block)) - return DebugUtils::errored(kErrorInvalidArgument); - - // Offset relative to the start of the block. - JitAllocatorPool* pool = block->pool; - size_t offset = (size_t)((uint8_t*)ro - block->roPtr()); - - // The first bit representing the allocated area and its size. - uint32_t areaIndex = uint32_t(offset >> pool->granularityLog2); - uint32_t areaOldSize = uint32_t(Support::bitVectorIndexOf(block->stopBitVector, areaIndex, true)) + 1 - areaIndex; - uint32_t areaNewSize = pool->areaSizeFromByteSize(newSize); - - if (ASMJIT_UNLIKELY(areaNewSize > areaOldSize)) - return DebugUtils::errored(kErrorInvalidState); - - uint32_t areaDiff = areaOldSize - areaNewSize; - if (!areaDiff) - return kErrorOk; - - // Update the search region and statistics. - block->searchStart = Support::min(block->searchStart, areaIndex + areaNewSize); - block->searchEnd = Support::max(block->searchEnd, areaIndex + areaOldSize); - block->addFlags(JitAllocatorBlock::kFlagDirty); - block->decreaseUsedArea(areaDiff); - - // Unmark the released space and move the sentinel. - Support::bitVectorClear(block->usedBitVector, areaIndex + areaNewSize, areaDiff); - Support::bitVectorSetBit(block->stopBitVector, areaIndex + areaOldSize - 1, false); - Support::bitVectorSetBit(block->stopBitVector, areaIndex + areaNewSize - 1, true); - - // Fill released memory if the secure mode is enabled. - if (impl->options & kOptionFillUnusedMemory) - JitAllocatorImpl_fillPattern( - block->rwPtr() + (areaIndex + areaOldSize) * pool->granularity, - fillPattern(), - areaDiff * pool->granularity); - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::JitAllocator - Unit] -// ============================================================================ - -#if defined(ASMJIT_TEST) -// A pseudo random number generator based on a paper by Sebastiano Vigna: -// http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf -class Random { -public: - // Constants suggested as `23/18/5`. - enum Steps : uint32_t { - kStep1_SHL = 23, - kStep2_SHR = 18, - kStep3_SHR = 5 - }; - - inline explicit Random(uint64_t seed = 0) noexcept { reset(seed); } - inline Random(const Random& other) noexcept = default; - - inline void reset(uint64_t seed = 0) noexcept { - // The number is arbitrary, it means nothing. - constexpr uint64_t kZeroSeed = 0x1F0A2BE71D163FA0u; - - // Generate the state data by using splitmix64. - for (uint32_t i = 0; i < 2; i++) { - seed += 0x9E3779B97F4A7C15u; - uint64_t x = seed; - x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9u; - x = (x ^ (x >> 27)) * 0x94D049BB133111EBu; - x = (x ^ (x >> 31)); - _state[i] = x != 0 ? x : kZeroSeed; - } - } - - inline uint32_t nextUInt32() noexcept { - return uint32_t(nextUInt64() >> 32); - } - - inline uint64_t nextUInt64() noexcept { - uint64_t x = _state[0]; - uint64_t y = _state[1]; - - x ^= x << kStep1_SHL; - y ^= y >> kStep3_SHR; - x ^= x >> kStep2_SHR; - x ^= y; - - _state[0] = y; - _state[1] = x; - return x + y; - } - - uint64_t _state[2]; -}; - -// Helper class to verify that JitAllocator doesn't return addresses that overlap. -class JitAllocatorWrapper { -public: - inline explicit JitAllocatorWrapper(const JitAllocator::CreateParams* params) noexcept - : _zone(1024 * 1024), - _heap(&_zone), - _allocator(params) {} - - // Address to a memory region of a given size. - class Range { - public: - inline Range(uint8_t* addr, size_t size) noexcept - : addr(addr), - size(size) {} - uint8_t* addr; - size_t size; - }; - - // Based on JitAllocator::Block, serves our purpose well... - class Record : public ZoneTreeNodeT, - public Range { - public: - inline Record(uint8_t* addr, size_t size) - : ZoneTreeNodeT(), - Range(addr, size) {} - - inline bool operator<(const Record& other) const noexcept { return addr < other.addr; } - inline bool operator>(const Record& other) const noexcept { return addr > other.addr; } - - inline bool operator<(const uint8_t* key) const noexcept { return addr + size <= key; } - inline bool operator>(const uint8_t* key) const noexcept { return addr > key; } - }; - - void _insert(void* p_, size_t size) noexcept { - uint8_t* p = static_cast(p_); - uint8_t* pEnd = p + size - 1; - - Record* record; - - record = _records.get(p); - if (record) - EXPECT(record == nullptr, - "Address [%p:%p] collides with a newly allocated [%p:%p]\n", record->addr, record->addr + record->size, p, p + size); - - record = _records.get(pEnd); - if (record) - EXPECT(record == nullptr, - "Address [%p:%p] collides with a newly allocated [%p:%p]\n", record->addr, record->addr + record->size, p, p + size); - - record = _heap.newT(p, size); - EXPECT(record != nullptr, - "Out of memory, cannot allocate 'Record'"); - - _records.insert(record); - } - - void _remove(void* p) noexcept { - Record* record = _records.get(static_cast(p)); - EXPECT(record != nullptr, - "Address [%p] doesn't exist\n", p); - - _records.remove(record); - _heap.release(record, sizeof(Record)); - } - - void* alloc(size_t size) noexcept { - void* roPtr; - void* rwPtr; - - Error err = _allocator.alloc(&roPtr, &rwPtr, size); - EXPECT(err == kErrorOk, - "JitAllocator failed to allocate '%u' bytes\n", unsigned(size)); - - _insert(roPtr, size); - return roPtr; - } - - void release(void* p) noexcept { - _remove(p); - EXPECT(_allocator.release(p) == kErrorOk, - "JitAllocator failed to release '%p'\n", p); - } - - Zone _zone; - ZoneAllocator _heap; - ZoneTree _records; - JitAllocator _allocator; -}; - -static void JitAllocatorTest_shuffle(void** ptrArray, size_t count, Random& prng) noexcept { - for (size_t i = 0; i < count; ++i) - std::swap(ptrArray[i], ptrArray[size_t(prng.nextUInt32() % count)]); -} - -static void JitAllocatorTest_usage(JitAllocator& allocator) noexcept { - JitAllocator::Statistics stats = allocator.statistics(); - INFO(" Block Count : %9llu [Blocks]" , (unsigned long long)(stats.blockCount())); - INFO(" Reserved (VirtMem): %9llu [Bytes]" , (unsigned long long)(stats.reservedSize())); - INFO(" Used (VirtMem): %9llu [Bytes] (%.1f%%)", (unsigned long long)(stats.usedSize()), stats.usedSizeAsPercent()); - INFO(" Overhead (HeapMem): %9llu [Bytes] (%.1f%%)", (unsigned long long)(stats.overheadSize()), stats.overheadSizeAsPercent()); -} - -UNIT(jit_allocator) { - size_t kCount = BrokenAPI::hasArg("--quick") ? 1000 : 100000; - - struct TestParams { - const char* name; - uint32_t options; - uint32_t blockSize; - uint32_t granularity; - }; - - #define OPT(OPTION) JitAllocator::OPTION - static TestParams testParams[] = { - { "Default", 0, 0, 0 }, - { "16MB blocks", 0, 16 * 1024 * 1024, 0 }, - { "256B granularity", 0, 0, 256 }, - { "kOptionUseDualMapping", OPT(kOptionUseDualMapping), 0, 0 }, - { "kOptionUseMultiplePools", OPT(kOptionUseMultiplePools), 0, 0 }, - { "kOptionFillUnusedMemory", OPT(kOptionFillUnusedMemory), 0, 0 }, - { "kOptionImmediateRelease", OPT(kOptionImmediateRelease), 0, 0 }, - { "kOptionUseDualMapping | kOptionFillUnusedMemory", OPT(kOptionUseDualMapping) | OPT(kOptionFillUnusedMemory), 0, 0 } - }; - #undef OPT - - INFO("BitFlipIterator"); - { - static const uint32_t bits[] = { 0x80000000u, 0x80000000u, 0x00000000u, 0x80000000u }; - BitFlipIterator it(bits, ASMJIT_ARRAY_SIZE(bits)); - - EXPECT(it.hasNext()); - EXPECT(it.nextAndFlip() == 31); - EXPECT(it.hasNext()); - EXPECT(it.nextAndFlip() == 32); - EXPECT(it.hasNext()); - EXPECT(it.nextAndFlip() == 63); - EXPECT(it.hasNext()); - EXPECT(it.nextAndFlip() == 64); - EXPECT(it.hasNext()); - EXPECT(it.nextAndFlip() == 127); - EXPECT(!it.hasNext()); - } - - INFO("BitFlipIterator"); - { - static const uint64_t bits[] = { 0xFFFFFFFFFFFFFFFFu, 0xFFFFFFFFFFFFFFFF, 0, 0 }; - BitFlipIterator it(bits, ASMJIT_ARRAY_SIZE(bits)); - - EXPECT(it.hasNext()); - EXPECT(it.nextAndFlip() == 0); - EXPECT(it.hasNext()); - EXPECT(it.nextAndFlip() == 128); - EXPECT(!it.hasNext()); - } - - for (uint32_t testId = 0; testId < ASMJIT_ARRAY_SIZE(testParams); testId++) { - INFO("Testing JitAllocator: %s", testParams[testId].name); - - JitAllocator::CreateParams params {}; - params.options = testParams[testId].options; - params.blockSize = testParams[testId].blockSize; - params.granularity = testParams[testId].granularity; - - JitAllocatorWrapper wrapper(¶ms); - Random prng(100); - - size_t i; - - INFO(" Memory alloc/release test - %d allocations", kCount); - - void** ptrArray = (void**)::malloc(sizeof(void*) * size_t(kCount)); - EXPECT(ptrArray != nullptr, - "Couldn't allocate '%u' bytes for pointer-array", unsigned(sizeof(void*) * size_t(kCount))); - - INFO(" Allocating virtual memory..."); - for (i = 0; i < kCount; i++) - ptrArray[i] = wrapper.alloc((prng.nextUInt32() % 1024) + 8); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Releasing virtual memory..."); - for (i = 0; i < kCount; i++) - wrapper.release(ptrArray[i]); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Allocating virtual memory...", kCount); - for (i = 0; i < kCount; i++) - ptrArray[i] = wrapper.alloc((prng.nextUInt32() % 1024) + 8); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Shuffling..."); - JitAllocatorTest_shuffle(ptrArray, unsigned(kCount), prng); - - INFO(" Releasing 50%% blocks..."); - for (i = 0; i < kCount / 2; i++) - wrapper.release(ptrArray[i]); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Allocating 50%% blocks again..."); - for (i = 0; i < kCount / 2; i++) - ptrArray[i] = wrapper.alloc((prng.nextUInt32() % 1024) + 8); - JitAllocatorTest_usage(wrapper._allocator); - - INFO(" Releasing virtual memory..."); - for (i = 0; i < kCount; i++) - wrapper.release(ptrArray[i]); - JitAllocatorTest_usage(wrapper._allocator); - - ::free(ptrArray); - } -} -#endif - -ASMJIT_END_NAMESPACE - -#endif diff --git a/ext/asmjit-master/src/asmjit/core/jitallocator.h b/ext/asmjit-master/src/asmjit/core/jitallocator.h deleted file mode 100644 index 9cd0a1f7..00000000 --- a/ext/asmjit-master/src/asmjit/core/jitallocator.h +++ /dev/null @@ -1,278 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_JITALLOCATOR_H_INCLUDED -#define ASMJIT_CORE_JITALLOCATOR_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_JIT - -#include "../core/globals.h" -#include "../core/virtmem.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_virtual_memory -//! \{ - -// ============================================================================ -// [asmjit::JitAllocator] -// ============================================================================ - -//! A simple implementation of memory manager that uses `asmjit::VirtMem` -//! functions to manage virtual memory for JIT compiled code. -//! -//! Implementation notes: -//! -//! - Granularity of allocated blocks is different than granularity for a typical -//! C malloc. In addition, the allocator can use several memory pools having a -//! different granularity to minimize the maintenance overhead. Multiple pools -//! feature requires `kFlagUseMultiplePools` flag to be set. -//! -//! - The allocator doesn't store any information in executable memory, instead, -//! the implementation uses two bit-vectors to manage allocated memory of each -//! allocator-block. The first bit-vector called 'used' is used to track used -//! memory (where each bit represents memory size defined by granularity) and -//! the second bit vector called 'stop' is used as a sentinel to mark where -//! the allocated area ends. -//! -//! - Internally, the allocator also uses RB tree to keep track of all blocks -//! across all pools. Each inserted block is added to the tree so it can be -//! matched fast during `release()` and `shrink()`. -class JitAllocator { -public: - ASMJIT_NONCOPYABLE(JitAllocator) - - struct Impl { - //! Allocator options, see \ref JitAllocator::Options. - uint32_t options; - //! Base block size (0 if the allocator is not initialized). - uint32_t blockSize; - //! Base granularity (0 if the allocator is not initialized). - uint32_t granularity; - //! A pattern that is used to fill unused memory if secure mode is enabled. - uint32_t fillPattern; - }; - - //! Allocator implementation (private). - Impl* _impl; - - enum Options : uint32_t { - //! Enables the use of an anonymous memory-mapped memory that is mapped into - //! two buffers having a different pointer. The first buffer has read and - //! execute permissions and the second buffer has read+write permissions. - //! - //! See \ref VirtMem::allocDualMapping() for more details about this feature. - kOptionUseDualMapping = 0x00000001u, - - //! Enables the use of multiple pools with increasing granularity instead of - //! a single pool. This flag would enable 3 internal pools in total having - //! 64, 128, and 256 bytes granularity. - //! - //! This feature is only recommended for users that generate a lot of code - //! and would like to minimize the overhead of `JitAllocator` itself by - //! having blocks of different allocation granularities. Using this feature - //! only for few allocations won't pay off as the allocator may need to - //! create more blocks initially before it can take the advantage of - //! variable block granularity. - kOptionUseMultiplePools = 0x00000002u, - - //! Always fill reserved memory by a fill-pattern. - //! - //! Causes a new block to be cleared by the fill pattern and freshly - //! released memory to be cleared before making it ready for another use. - kOptionFillUnusedMemory = 0x00000004u, - - //! When this flag is set the allocator would immediately release unused - //! blocks during `release()` or `reset()`. When this flag is not set the - //! allocator would keep one empty block in each pool to prevent excessive - //! virtual memory allocations and deallocations in border cases, which - //! involve constantly allocating and deallocating a single block caused - //! by repetitive calling `alloc()` and `release()` when the allocator has - //! either no blocks or have all blocks fully occupied. - kOptionImmediateRelease = 0x00000008u, - - //! Use a custom fill pattern, must be combined with `kFlagFillUnusedMemory`. - kOptionCustomFillPattern = 0x10000000u - }; - - //! \name Construction & Destruction - //! \{ - - //! Parameters that can be passed to `JitAllocator` constructor. - //! - //! Use it like this: - //! - //! ``` - //! // Zero initialize (zero means the default value) and change what you need. - //! JitAllocator::CreateParams params {}; - //! params.blockSize = 1024 * 1024; - //! - //! // Create the allocator. - //! JitAllocator allocator(¶ms); - //! ``` - struct CreateParams { - //! Allocator options, see \ref JitAllocator::Options. - //! - //! No options are used by default. - uint32_t options; - - //! Base size of a single block in bytes (default 64kB). - //! - //! \remarks Block size must be equal or greater to page size and must be - //! power of 2. If the input is not valid then the default block size will - //! be used instead. - uint32_t blockSize; - - //! Base granularity (and also natural alignment) of allocations in bytes - //! (default 64). - //! - //! Since the `JitAllocator` uses bit-arrays to mark used memory the - //! granularity also specifies how many bytes correspond to a single bit in - //! such bit-array. Higher granularity means more waste of virtual memory - //! (as it increases the natural alignment), but smaller bit-arrays as less - //! bits would be required per a single block. - uint32_t granularity; - - //! Patter to use to fill unused memory. - //! - //! Only used if \ref kOptionCustomFillPattern is set. - uint32_t fillPattern; - - // Reset the content of `CreateParams`. - inline void reset() noexcept { memset(this, 0, sizeof(*this)); } - }; - - //! Creates a `JitAllocator` instance. - explicit ASMJIT_API JitAllocator(const CreateParams* params = nullptr) noexcept; - //! Destroys the `JitAllocator` instance and release all blocks held. - ASMJIT_API ~JitAllocator() noexcept; - - inline bool isInitialized() const noexcept { return _impl->blockSize == 0; } - - //! Free all allocated memory - makes all pointers returned by `alloc()` invalid. - //! - //! \remarks This function is not thread-safe as it's designed to be used when - //! nobody else is using allocator. The reason is that there is no point of - //1 calling `reset()` when the allocator is still in use. - ASMJIT_API void reset(uint32_t resetPolicy = Globals::kResetSoft) noexcept; - - //! \} - - //! \name Accessors - //! \{ - - //! Returns allocator options, see `Flags`. - inline uint32_t options() const noexcept { return _impl->options; } - //! Tests whether the allocator has the given `option` set. - inline bool hasOption(uint32_t option) const noexcept { return (_impl->options & option) != 0; } - - //! Returns a base block size (a minimum size of block that the allocator would allocate). - inline uint32_t blockSize() const noexcept { return _impl->blockSize; } - //! Returns granularity of the allocator. - inline uint32_t granularity() const noexcept { return _impl->granularity; } - //! Returns pattern that is used to fill unused memory if `kFlagUseFillPattern` is set. - inline uint32_t fillPattern() const noexcept { return _impl->fillPattern; } - - //! \} - - //! \name Alloc & Release - //! \{ - - //! Allocate `size` bytes of virtual memory. - //! - //! \remarks This function is thread-safe. - ASMJIT_API Error alloc(void** roPtrOut, void** rwPtrOut, size_t size) noexcept; - - //! Release a memory returned by `alloc()`. - //! - //! \remarks This function is thread-safe. - ASMJIT_API Error release(void* ro) noexcept; - - //! Free extra memory allocated with `p` by restricting it to `newSize` size. - //! - //! \remarks This function is thread-safe. - ASMJIT_API Error shrink(void* ro, size_t newSize) noexcept; - - //! \} - - //! \name Statistics - //! \{ - - //! Statistics about `JitAllocator`. - struct Statistics { - //! Number of blocks `JitAllocator` maintains. - size_t _blockCount; - //! How many bytes are currently used / allocated. - size_t _usedSize; - //! How many bytes are currently reserved by the allocator. - size_t _reservedSize; - //! Allocation overhead (in bytes) required to maintain all blocks. - size_t _overheadSize; - - inline void reset() noexcept { - _blockCount = 0; - _usedSize = 0; - _reservedSize = 0; - _overheadSize = 0; - } - - //! Returns count of blocks managed by `JitAllocator` at the moment. - inline size_t blockCount() const noexcept { return _blockCount; } - - //! Returns how many bytes are currently used. - inline size_t usedSize() const noexcept { return _usedSize; } - //! Returns the number of bytes unused by the allocator at the moment. - inline size_t unusedSize() const noexcept { return _reservedSize - _usedSize; } - //! Returns the total number of bytes bytes reserved by the allocator (sum of sizes of all blocks). - inline size_t reservedSize() const noexcept { return _reservedSize; } - //! Returns the number of bytes the allocator needs to manage the allocated memory. - inline size_t overheadSize() const noexcept { return _overheadSize; } - - inline double usedSizeAsPercent() const noexcept { - return (double(usedSize()) / (double(reservedSize()) + 1e-16)) * 100.0; - } - - inline double unusedSizeAsPercent() const noexcept { - return (double(unusedSize()) / (double(reservedSize()) + 1e-16)) * 100.0; - } - - inline double overheadSizeAsPercent() const noexcept { - return (double(overheadSize()) / (double(reservedSize()) + 1e-16)) * 100.0; - } - }; - - //! Returns JIT allocator statistics. - //! - //! \remarks This function is thread-safe. - ASMJIT_API Statistics statistics() const noexcept; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif -#endif diff --git a/ext/asmjit-master/src/asmjit/core/jitruntime.cpp b/ext/asmjit-master/src/asmjit/core/jitruntime.cpp deleted file mode 100644 index 1127c866..00000000 --- a/ext/asmjit-master/src/asmjit/core/jitruntime.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_JIT - -#include "../core/cpuinfo.h" -#include "../core/jitruntime.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::JitRuntime - Utilities] -// ============================================================================ - -// Only useful on non-x86 architectures. -static inline void JitRuntime_flushInstructionCache(const void* p, size_t size) noexcept { -#if defined(_WIN32) && !ASMJIT_ARCH_X86 - // Windows has a built-in support in `kernel32.dll`. - ::FlushInstructionCache(::GetCurrentProcess(), p, size); -#else - DebugUtils::unused(p, size); -#endif -} - -// ============================================================================ -// [asmjit::JitRuntime - Construction / Destruction] -// ============================================================================ - -JitRuntime::JitRuntime(const JitAllocator::CreateParams* params) noexcept - : _allocator(params) { - _environment = hostEnvironment(); - _environment.setFormat(Environment::kFormatJIT); -} - -JitRuntime::~JitRuntime() noexcept {} - -// ============================================================================ -// [asmjit::JitRuntime - Interface] -// ============================================================================ - -Error JitRuntime::_add(void** dst, CodeHolder* code) noexcept { - *dst = nullptr; - - ASMJIT_PROPAGATE(code->flatten()); - ASMJIT_PROPAGATE(code->resolveUnresolvedLinks()); - - size_t estimatedCodeSize = code->codeSize(); - if (ASMJIT_UNLIKELY(estimatedCodeSize == 0)) - return DebugUtils::errored(kErrorNoCodeGenerated); - - uint8_t* ro; - uint8_t* rw; - ASMJIT_PROPAGATE(_allocator.alloc((void**)&ro, (void**)&rw, estimatedCodeSize)); - - // Relocate the code. - Error err = code->relocateToBase(uintptr_t((void*)ro)); - if (ASMJIT_UNLIKELY(err)) { - _allocator.release(ro); - return err; - } - - // Recalculate the final code size and shrink the memory we allocated for it - // in case that some relocations didn't require records in an address table. - size_t codeSize = code->codeSize(); - - for (Section* section : code->_sections) { - size_t offset = size_t(section->offset()); - size_t bufferSize = size_t(section->bufferSize()); - size_t virtualSize = size_t(section->virtualSize()); - - ASMJIT_ASSERT(offset + bufferSize <= codeSize); - memcpy(rw + offset, section->data(), bufferSize); - - if (virtualSize > bufferSize) { - ASMJIT_ASSERT(offset + virtualSize <= codeSize); - memset(rw + offset + bufferSize, 0, virtualSize - bufferSize); - } - } - - if (codeSize < estimatedCodeSize) - _allocator.shrink(ro, codeSize); - - flush(ro, codeSize); - *dst = ro; - - return kErrorOk; -} - -Error JitRuntime::_release(void* p) noexcept { - return _allocator.release(p); -} - -void JitRuntime::flush(const void* p, size_t size) noexcept { - JitRuntime_flushInstructionCache(p, size); -} - -ASMJIT_END_NAMESPACE - -#endif diff --git a/ext/asmjit-master/src/asmjit/core/jitruntime.h b/ext/asmjit-master/src/asmjit/core/jitruntime.h deleted file mode 100644 index 91880e68..00000000 --- a/ext/asmjit-master/src/asmjit/core/jitruntime.h +++ /dev/null @@ -1,126 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_JITRUNTIME_H_INCLUDED -#define ASMJIT_CORE_JITRUNTIME_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_JIT - -#include "../core/codeholder.h" -#include "../core/jitallocator.h" -#include "../core/target.h" - -ASMJIT_BEGIN_NAMESPACE - -class CodeHolder; - -//! \addtogroup asmjit_virtual_memory -//! \{ - -// ============================================================================ -// [asmjit::JitRuntime] -// ============================================================================ - -//! JIT execution runtime is a special `Target` that is designed to store and -//! execute the generated code. -class ASMJIT_VIRTAPI JitRuntime : public Target { -public: - ASMJIT_NONCOPYABLE(JitRuntime) - - //! Virtual memory allocator. - JitAllocator _allocator; - - //! \name Construction & Destruction - //! \{ - - //! Creates a `JitRuntime` instance. - explicit ASMJIT_API JitRuntime(const JitAllocator::CreateParams* params = nullptr) noexcept; - //! Destroys the `JitRuntime` instance. - ASMJIT_API virtual ~JitRuntime() noexcept; - - inline void reset(uint32_t resetPolicy = Globals::kResetSoft) noexcept { - _allocator.reset(resetPolicy); - } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the associated `JitAllocator`. - inline JitAllocator* allocator() const noexcept { return const_cast(&_allocator); } - - //! \} - - //! \name Utilities - //! \{ - - // NOTE: To allow passing function pointers to `add()` and `release()` the - // virtual methods are prefixed with `_` and called from templates instead. - - //! Allocates memory needed for a code stored in the `CodeHolder` and relocates - //! the code to the pointer allocated. - //! - //! The beginning of the memory allocated for the function is returned in `dst`. - //! If failed `Error` code is returned and `dst` is explicitly set to `nullptr` - //! (this means that you don't have to set it to null before calling `add()`). - template - inline Error add(Func* dst, CodeHolder* code) noexcept { - return _add(Support::ptr_cast_impl(dst), code); - } - - //! Releases `p` which was obtained by calling `add()`. - template - inline Error release(Func p) noexcept { - return _release(Support::ptr_cast_impl(p)); - } - - //! Type-unsafe version of `add()`. - ASMJIT_API virtual Error _add(void** dst, CodeHolder* code) noexcept; - - //! Type-unsafe version of `release()`. - ASMJIT_API virtual Error _release(void* p) noexcept; - - //! Flushes an instruction cache. - //! - //! This member function is called after the code has been copied to the - //! destination buffer. It is only useful for JIT code generation as it - //! causes a flush of the processor's cache. - //! - //! Flushing is basically a NOP under X86, but is needed by architectures - //! that do not have a transparent instruction cache like ARM. - //! - //! This function can also be overridden to improve compatibility with tools - //! such as Valgrind, however, it's not an official part of AsmJit. - ASMJIT_API virtual void flush(const void* p, size_t size) noexcept; - - //! \} -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif -#endif diff --git a/ext/asmjit-master/src/asmjit/core/logger.cpp b/ext/asmjit-master/src/asmjit/core/logger.cpp deleted file mode 100644 index 22e0b9af..00000000 --- a/ext/asmjit-master/src/asmjit/core/logger.cpp +++ /dev/null @@ -1,124 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#ifndef ASMJIT_NO_LOGGING - -#include "../core/logger.h" -#include "../core/string.h" -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::Logger - Construction / Destruction] -// ============================================================================ - -Logger::Logger() noexcept - : _options() {} -Logger::~Logger() noexcept {} - -// ============================================================================ -// [asmjit::Logger - Logging] -// ============================================================================ - -Error Logger::logf(const char* fmt, ...) noexcept { - Error err; - va_list ap; - - va_start(ap, fmt); - err = logv(fmt, ap); - va_end(ap); - - return err; -} - -Error Logger::logv(const char* fmt, va_list ap) noexcept { - StringTmp<2048> sb; - ASMJIT_PROPAGATE(sb.appendVFormat(fmt, ap)); - return log(sb); -} - -Error Logger::logBinary(const void* data, size_t size) noexcept { - static const char prefix[] = "db "; - - StringTmp<256> sb; - sb.append(prefix, ASMJIT_ARRAY_SIZE(prefix) - 1); - - size_t i = size; - const uint8_t* s = static_cast(data); - - while (i) { - uint32_t n = uint32_t(Support::min(i, 16)); - sb.truncate(ASMJIT_ARRAY_SIZE(prefix) - 1); - sb.appendHex(s, n); - sb.append('\n'); - ASMJIT_PROPAGATE(log(sb)); - s += n; - i -= n; - } - - return kErrorOk; -} - -// ============================================================================ -// [asmjit::FileLogger - Construction / Destruction] -// ============================================================================ - -FileLogger::FileLogger(FILE* file) noexcept - : _file(file) {} -FileLogger::~FileLogger() noexcept {} - -// ============================================================================ -// [asmjit::FileLogger - Logging] -// ============================================================================ - -Error FileLogger::_log(const char* data, size_t size) noexcept { - if (!_file) - return kErrorOk; - - if (size == SIZE_MAX) - size = strlen(data); - - fwrite(data, 1, size, _file); - return kErrorOk; -} - -// ============================================================================ -// [asmjit::StringLogger - Construction / Destruction] -// ============================================================================ - -StringLogger::StringLogger() noexcept {} -StringLogger::~StringLogger() noexcept {} - -// ============================================================================ -// [asmjit::StringLogger - Logging] -// ============================================================================ - -Error StringLogger::_log(const char* data, size_t size) noexcept { - return _content.append(data, size); -} - -ASMJIT_END_NAMESPACE - -#endif diff --git a/ext/asmjit-master/src/asmjit/core/logger.h b/ext/asmjit-master/src/asmjit/core/logger.h deleted file mode 100644 index 2840869b..00000000 --- a/ext/asmjit-master/src/asmjit/core/logger.h +++ /dev/null @@ -1,228 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_LOGGING_H_INCLUDED -#define ASMJIT_CORE_LOGGING_H_INCLUDED - -#include "../core/inst.h" -#include "../core/string.h" -#include "../core/formatter.h" - -#ifndef ASMJIT_NO_LOGGING - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_logging -//! \{ - -// ============================================================================ -// [asmjit::Logger] -// ============================================================================ - -//! Logging interface. -//! -//! This class can be inherited and reimplemented to fit into your own logging -//! needs. When reimplementing a logger use \ref Logger::_log() method to log -//! customize the output. -//! -//! There are two `Logger` implementations offered by AsmJit: -//! - \ref FileLogger - logs into a `FILE*`. -//! - \ref StringLogger - concatenates all logs into a \ref String. -class ASMJIT_VIRTAPI Logger { -public: - ASMJIT_BASE_CLASS(Logger) - ASMJIT_NONCOPYABLE(Logger) - - //! Format options. - FormatOptions _options; - - //! \name Construction & Destruction - //! \{ - - //! Creates a `Logger` instance. - ASMJIT_API Logger() noexcept; - //! Destroys the `Logger` instance. - ASMJIT_API virtual ~Logger() noexcept; - - //! \} - - //! \name Format Options - //! \{ - - //! Returns \ref FormatOptions of this logger. - inline FormatOptions& options() noexcept { return _options; } - //! \overload - inline const FormatOptions& options() const noexcept { return _options; } - - //! Returns formatting flags, see \ref FormatOptions::Flags. - inline uint32_t flags() const noexcept { return _options.flags(); } - //! Tests whether the logger has the given `flag` enabled. - inline bool hasFlag(uint32_t flag) const noexcept { return _options.hasFlag(flag); } - //! Sets formatting flags to `flags`, see \ref FormatOptions::Flags. - inline void setFlags(uint32_t flags) noexcept { _options.setFlags(flags); } - //! Enables the given formatting `flags`, see \ref FormatOptions::Flags. - inline void addFlags(uint32_t flags) noexcept { _options.addFlags(flags); } - //! Disables the given formatting `flags`, see \ref FormatOptions::Flags. - inline void clearFlags(uint32_t flags) noexcept { _options.clearFlags(flags); } - - //! Returns indentation of `type`, see \ref FormatOptions::IndentationType. - inline uint32_t indentation(uint32_t type) const noexcept { return _options.indentation(type); } - //! Sets indentation of the given indentation `type` to `n` spaces, see \ref - //! FormatOptions::IndentationType. - inline void setIndentation(uint32_t type, uint32_t n) noexcept { _options.setIndentation(type, n); } - //! Resets indentation of the given indentation `type` to 0 spaces. - inline void resetIndentation(uint32_t type) noexcept { _options.resetIndentation(type); } - - //! \} - - //! \name Logging Interface - //! \{ - - //! Logs `str` - must be reimplemented. - //! - //! The function can accept either a null terminated string if `size` is - //! `SIZE_MAX` or a non-null terminated string of the given `size`. The - //! function cannot assume that the data is null terminated and must handle - //! non-null terminated inputs. - virtual Error _log(const char* data, size_t size) noexcept = 0; - - //! Logs string `str`, which is either null terminated or having size `size`. - inline Error log(const char* data, size_t size = SIZE_MAX) noexcept { return _log(data, size); } - //! Logs content of a string `str`. - inline Error log(const String& str) noexcept { return _log(str.data(), str.size()); } - - //! Formats the message by using `snprintf()` and then passes the formatted - //! string to \ref _log(). - ASMJIT_API Error logf(const char* fmt, ...) noexcept; - - //! Formats the message by using `vsnprintf()` and then passes the formatted - //! string to \ref _log(). - ASMJIT_API Error logv(const char* fmt, va_list ap) noexcept; - - //! Logs binary `data` of the given `size`. - ASMJIT_API Error logBinary(const void* data, size_t size) noexcept; - - //! \} -}; - -// ============================================================================ -// [asmjit::FileLogger] -// ============================================================================ - -//! Logger that can log to a `FILE*`. -class ASMJIT_VIRTAPI FileLogger : public Logger { -public: - ASMJIT_NONCOPYABLE(FileLogger) - - FILE* _file; - - //! \name Construction & Destruction - //! \{ - - //! Creates a new `FileLogger` that logs to `FILE*`. - ASMJIT_API FileLogger(FILE* file = nullptr) noexcept; - //! Destroys the `FileLogger`. - ASMJIT_API virtual ~FileLogger() noexcept; - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the logging output stream or null if the logger has no output - //! stream. - inline FILE* file() const noexcept { return _file; } - - //! Sets the logging output stream to `stream` or null. - //! - //! \note If the `file` is null the logging will be disabled. When a logger - //! is attached to `CodeHolder` or any emitter the logging API will always - //! be called regardless of the output file. This means that if you really - //! want to disable logging at emitter level you must not attach a logger - //! to it. - inline void setFile(FILE* file) noexcept { _file = file; } - - //! \} - - ASMJIT_API Error _log(const char* data, size_t size = SIZE_MAX) noexcept override; -}; - -// ============================================================================ -// [asmjit::StringLogger] -// ============================================================================ - -//! Logger that stores everything in an internal string buffer. -class ASMJIT_VIRTAPI StringLogger : public Logger { -public: - ASMJIT_NONCOPYABLE(StringLogger) - - //! Logger data as string. - String _content; - - //! \name Construction & Destruction - //! \{ - - //! Create new `StringLogger`. - ASMJIT_API StringLogger() noexcept; - //! Destroys the `StringLogger`. - ASMJIT_API virtual ~StringLogger() noexcept; - - //! \} - - //! \name Logger Data Accessors - //! \{ - - //! Returns the content of the logger as \ref String. - //! - //! It can be moved, if desired. - inline String& content() noexcept { return _content; } - //! \overload - inline const String& content() const noexcept { return _content; } - - //! Returns aggregated logger data as `char*` pointer. - //! - //! The pointer is owned by `StringLogger`, it can't be modified or freed. - inline const char* data() const noexcept { return _content.data(); } - //! Returns size of the data returned by `data()`. - inline size_t dataSize() const noexcept { return _content.size(); } - - //! \} - - //! \name Logger Data Manipulation - //! \{ - - //! Clears the accumulated logger data. - inline void clear() noexcept { _content.clear(); } - - //! \} - - ASMJIT_API Error _log(const char* data, size_t size = SIZE_MAX) noexcept override; -}; - -//! \} - -ASMJIT_END_NAMESPACE - -#endif - -#endif // ASMJIT_CORE_LOGGER_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/misc_p.h b/ext/asmjit-master/src/asmjit/core/misc_p.h deleted file mode 100644 index b1056f47..00000000 --- a/ext/asmjit-master/src/asmjit/core/misc_p.h +++ /dev/null @@ -1,49 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_MISC_P_H_INCLUDED -#define ASMJIT_CORE_MISC_P_H_INCLUDED - -#include "../core/api-config.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_utilities -//! \{ - -#define ASMJIT_LOOKUP_TABLE_8(T, I) T((I)), T((I+1)), T((I+2)), T((I+3)), T((I+4)), T((I+5)), T((I+6)), T((I+7)) -#define ASMJIT_LOOKUP_TABLE_16(T, I) ASMJIT_LOOKUP_TABLE_8(T, I), ASMJIT_LOOKUP_TABLE_8(T, I + 8) -#define ASMJIT_LOOKUP_TABLE_32(T, I) ASMJIT_LOOKUP_TABLE_16(T, I), ASMJIT_LOOKUP_TABLE_16(T, I + 16) -#define ASMJIT_LOOKUP_TABLE_64(T, I) ASMJIT_LOOKUP_TABLE_32(T, I), ASMJIT_LOOKUP_TABLE_32(T, I + 32) -#define ASMJIT_LOOKUP_TABLE_128(T, I) ASMJIT_LOOKUP_TABLE_64(T, I), ASMJIT_LOOKUP_TABLE_64(T, I + 64) -#define ASMJIT_LOOKUP_TABLE_256(T, I) ASMJIT_LOOKUP_TABLE_128(T, I), ASMJIT_LOOKUP_TABLE_128(T, I + 128) -#define ASMJIT_LOOKUP_TABLE_512(T, I) ASMJIT_LOOKUP_TABLE_256(T, I), ASMJIT_LOOKUP_TABLE_256(T, I + 256) -#define ASMJIT_LOOKUP_TABLE_1024(T, I) ASMJIT_LOOKUP_TABLE_512(T, I), ASMJIT_LOOKUP_TABLE_512(T, I + 512) - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_MISC_P_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/operand.cpp b/ext/asmjit-master/src/asmjit/core/operand.cpp deleted file mode 100644 index 46bb23a2..00000000 --- a/ext/asmjit-master/src/asmjit/core/operand.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/operand.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::Operand - Unit] -// ============================================================================ - -#if defined(ASMJIT_TEST) -UNIT(operand) { - INFO("Checking operand sizes"); - EXPECT(sizeof(Operand) == 16); - EXPECT(sizeof(BaseReg) == 16); - EXPECT(sizeof(BaseMem) == 16); - EXPECT(sizeof(Imm) == 16); - EXPECT(sizeof(Label) == 16); - - INFO("Checking basic functionality of Operand"); - Operand a, b; - Operand dummy; - - EXPECT(a.isNone() == true); - EXPECT(a.isReg() == false); - EXPECT(a.isMem() == false); - EXPECT(a.isImm() == false); - EXPECT(a.isLabel() == false); - EXPECT(a == b); - EXPECT(a._data[0] == 0); - EXPECT(a._data[1] == 0); - - INFO("Checking basic functionality of Label"); - Label label; - EXPECT(label.isValid() == false); - EXPECT(label.id() == Globals::kInvalidId); - - INFO("Checking basic functionality of BaseReg"); - EXPECT(BaseReg().isReg() == true); - EXPECT(BaseReg().isValid() == false); - EXPECT(BaseReg()._data[0] == 0); - EXPECT(BaseReg()._data[1] == 0); - EXPECT(dummy.as().isValid() == false); - - // Create some register (not specific to any architecture). - uint32_t rSig = Operand::kOpReg | (1 << Operand::kSignatureRegTypeShift ) | - (2 << Operand::kSignatureRegGroupShift) | - (8 << Operand::kSignatureSizeShift ) ; - BaseReg r1(rSig, 5); - - EXPECT(r1.isValid() == true); - EXPECT(r1.isReg() == true); - EXPECT(r1.isReg(1) == true); - EXPECT(r1.isPhysReg() == true); - EXPECT(r1.isVirtReg() == false); - EXPECT(r1.signature() == rSig); - EXPECT(r1.type() == 1); - EXPECT(r1.group() == 2); - EXPECT(r1.size() == 8); - EXPECT(r1.id() == 5); - EXPECT(r1.isReg(1, 5) == true); // RegType and Id. - EXPECT(r1._data[0] == 0); - EXPECT(r1._data[1] == 0); - - // The same type of register having different id. - BaseReg r2(r1, 6); - EXPECT(r2.isValid() == true); - EXPECT(r2.isReg() == true); - EXPECT(r2.isReg(1) == true); - EXPECT(r2.isPhysReg() == true); - EXPECT(r2.isVirtReg() == false); - EXPECT(r2.signature() == rSig); - EXPECT(r2.type() == r1.type()); - EXPECT(r2.group() == r1.group()); - EXPECT(r2.size() == r1.size()); - EXPECT(r2.id() == 6); - EXPECT(r2.isReg(1, 6) == true); - - r1.reset(); - EXPECT(!r1.isReg()); - EXPECT(!r1.isValid()); - - INFO("Checking basic functionality of BaseMem"); - BaseMem m; - EXPECT(m.isMem()); - EXPECT(m == BaseMem()); - EXPECT(m.hasBase() == false); - EXPECT(m.hasIndex() == false); - EXPECT(m.hasOffset() == false); - EXPECT(m.isOffset64Bit() == true); - EXPECT(m.offset() == 0); - - m.setOffset(-1); - EXPECT(m.offsetLo32() == -1); - EXPECT(m.offset() == -1); - - int64_t x = int64_t(0xFF00FF0000000001u); - int32_t xHi = int32_t(0xFF00FF00u); - - m.setOffset(x); - EXPECT(m.offset() == x); - EXPECT(m.offsetLo32() == 1); - EXPECT(m.offsetHi32() == xHi); - - INFO("Checking basic functionality of Imm"); - Imm immValue(-42); - EXPECT(Imm(-1).value() == -1); - EXPECT(imm(-1).value() == -1); - EXPECT(immValue.value() == -42); - EXPECT(imm(0xFFFFFFFF).value() == int64_t(0xFFFFFFFF)); -} -#endif - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/operand.h b/ext/asmjit-master/src/asmjit/core/operand.h deleted file mode 100644 index 01cc1eaa..00000000 --- a/ext/asmjit-master/src/asmjit/core/operand.h +++ /dev/null @@ -1,1418 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_OPERAND_H_INCLUDED -#define ASMJIT_CORE_OPERAND_H_INCLUDED - -#include "../core/support.h" - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [Macros] -// ============================================================================ - -//! Adds a template specialization for `REG_TYPE` into the local `RegTraits`. -#define ASMJIT_DEFINE_REG_TRAITS(REG, REG_TYPE, GROUP, SIZE, COUNT, TYPE_ID) \ -template<> \ -struct RegTraits { \ - typedef REG RegT; \ - \ - static constexpr uint32_t kValid = 1; \ - static constexpr uint32_t kCount = COUNT; \ - static constexpr uint32_t kTypeId = TYPE_ID; \ - \ - static constexpr uint32_t kType = REG_TYPE; \ - static constexpr uint32_t kGroup = GROUP; \ - static constexpr uint32_t kSize = SIZE; \ - \ - static constexpr uint32_t kSignature = \ - (Operand::kOpReg << Operand::kSignatureOpShift ) | \ - (kType << Operand::kSignatureRegTypeShift ) | \ - (kGroup << Operand::kSignatureRegGroupShift) | \ - (kSize << Operand::kSignatureSizeShift ) ; \ -} - -//! Adds constructors and member functions to a class that implements abstract -//! register. Abstract register is register that doesn't have type or signature -//! yet, it's a base class like `x86::Reg` or `arm::Reg`. -#define ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ -public: \ - /*! Default constructor that only setups basics. */ \ - constexpr REG() noexcept \ - : BASE(kSignature, kIdBad) {} \ - \ - /*! Makes a copy of the `other` register operand. */ \ - constexpr REG(const REG& other) noexcept \ - : BASE(other) {} \ - \ - /*! Makes a copy of the `other` register having id set to `rId` */ \ - constexpr REG(const BaseReg& other, uint32_t rId) noexcept \ - : BASE(other, rId) {} \ - \ - /*! Creates a register based on `signature` and `rId`. */ \ - constexpr REG(uint32_t signature, uint32_t rId) noexcept \ - : BASE(signature, rId) {} \ - \ - /*! Creates a completely uninitialized REG register operand (garbage). */ \ - inline explicit REG(Globals::NoInit_) noexcept \ - : BASE(Globals::NoInit) {} \ - \ - /*! Creates a new register from register type and id. */ \ - static inline REG fromTypeAndId(uint32_t rType, uint32_t rId) noexcept { \ - return REG(signatureOf(rType), rId); \ - } \ - \ - /*! Clones the register operand. */ \ - constexpr REG clone() const noexcept { return REG(*this); } \ - \ - inline REG& operator=(const REG& other) noexcept = default; - -//! Adds constructors and member functions to a class that implements final -//! register. Final registers MUST HAVE a valid signature. -#define ASMJIT_DEFINE_FINAL_REG(REG, BASE, TRAITS) \ -public: \ - static constexpr uint32_t kThisType = TRAITS::kType; \ - static constexpr uint32_t kThisGroup = TRAITS::kGroup; \ - static constexpr uint32_t kThisSize = TRAITS::kSize; \ - static constexpr uint32_t kSignature = TRAITS::kSignature; \ - \ - ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \ - \ - /*! Creates a register operand having its id set to `rId`. */ \ - constexpr explicit REG(uint32_t rId) noexcept \ - : BASE(kSignature, rId) {} - -//! \addtogroup asmjit_assembler -//! \{ - -// ============================================================================ -// [asmjit::Operand_] -// ============================================================================ - -//! Constructor-less `Operand`. -//! -//! Contains no initialization code and can be used safely to define an array -//! of operands that won't be initialized. This is an `Operand` compatible -//! data structure designed to be statically initialized, static const, or to -//! be used by the user to define an array of operands without having them -//! default initialized. -//! -//! The key difference between `Operand` and `Operand_`: -//! -//! ``` -//! Operand_ xArray[10]; // Not initialized, contains garbage. -//! Operand yArray[10]; // All operands initialized to none. -//! ``` -struct Operand_ { - //! Operand's signature that provides operand type and additional information. - uint32_t _signature; - //! Either base id as used by memory operand or any id as used by others. - uint32_t _baseId; - - //! Data specific to the operand type. - //! - //! The reason we don't use union is that we have `constexpr` constructors that - //! construct operands and other `constexpr` functions that return wither another - //! Operand or something else. These cannot generally work with unions so we also - //! cannot use `union` if we want to be standard compliant. - uint32_t _data[2]; - - //! Indexes to `_data` array. - enum DataIndex : uint32_t { - kDataMemIndexId = 0, - kDataMemOffsetLo = 1, - - kDataImmValueLo = ASMJIT_ARCH_LE ? 0 : 1, - kDataImmValueHi = ASMJIT_ARCH_LE ? 1 : 0 - }; - - //! Operand types that can be encoded in `Operand`. - enum OpType : uint32_t { - //! Not an operand or not initialized. - kOpNone = 0, - //! Operand is a register. - kOpReg = 1, - //! Operand is a memory. - kOpMem = 2, - //! Operand is an immediate value. - kOpImm = 3, - //! Operand is a label. - kOpLabel = 4 - }; - static_assert(kOpMem == kOpReg + 1, "asmjit::Operand requires `kOpMem` to be `kOpReg+1`."); - - //! Label tag. - enum LabelTag { - //! Label tag is used as a sub-type, forming a unique signature across all - //! operand types as 0x1 is never associated with any register type. This - //! means that a memory operand's BASE register can be constructed from - //! virtually any operand (register vs. label) by just assigning its type - //! (register type or label-tag) and operand id. - kLabelTag = 0x1 - }; - - // \cond INTERNAL - enum SignatureBits : uint32_t { - // Operand type (3 least significant bits). - // |........|........|........|.....XXX| - kSignatureOpShift = 0, - kSignatureOpMask = 0x07u << kSignatureOpShift, - - // Register type (5 bits). - // |........|........|........|XXXXX...| - kSignatureRegTypeShift = 3, - kSignatureRegTypeMask = 0x1Fu << kSignatureRegTypeShift, - - // Register group (4 bits). - // |........|........|....XXXX|........| - kSignatureRegGroupShift = 8, - kSignatureRegGroupMask = 0x0Fu << kSignatureRegGroupShift, - - // Memory base type (5 bits). - // |........|........|........|XXXXX...| - kSignatureMemBaseTypeShift = 3, - kSignatureMemBaseTypeMask = 0x1Fu << kSignatureMemBaseTypeShift, - - // Memory index type (5 bits). - // |........|........|...XXXXX|........| - kSignatureMemIndexTypeShift = 8, - kSignatureMemIndexTypeMask = 0x1Fu << kSignatureMemIndexTypeShift, - - // Memory base+index combined (10 bits). - // |........|........|...XXXXX|XXXXX...| - kSignatureMemBaseIndexShift = 3, - kSignatureMemBaseIndexMask = 0x3FFu << kSignatureMemBaseIndexShift, - - // Memory address type (2 bits). - // |........|........|.XX.....|........| - kSignatureMemAddrTypeShift = 13, - kSignatureMemAddrTypeMask = 0x03u << kSignatureMemAddrTypeShift, - - // This memory operand represents a home-slot or stack (BaseCompiler). - // |........|........|X.......|........| - kSignatureMemRegHomeShift = 15, - kSignatureMemRegHomeFlag = 0x01u << kSignatureMemRegHomeShift, - - // Operand size (8 most significant bits). - // |XXXXXXXX|........|........|........| - kSignatureSizeShift = 24, - kSignatureSizeMask = 0xFFu << kSignatureSizeShift - }; - //! \endcond - - //! Constants useful for VirtId <-> Index translation. - enum VirtIdConstants : uint32_t { - //! Minimum valid packed-id. - kVirtIdMin = 256, - //! Maximum valid packed-id, excludes Globals::kInvalidId. - kVirtIdMax = Globals::kInvalidId - 1, - //! Count of valid packed-ids. - kVirtIdCount = uint32_t(kVirtIdMax - kVirtIdMin + 1) - }; - - //! Tests whether the given `id` is a valid virtual register id. Since AsmJit - //! supports both physical and virtual registers it must be able to distinguish - //! between these two. The idea is that physical registers are always limited - //! in size, so virtual identifiers start from `kVirtIdMin` and end at `kVirtIdMax`. - static ASMJIT_INLINE bool isVirtId(uint32_t id) noexcept { return id - kVirtIdMin < uint32_t(kVirtIdCount); } - //! Converts a real-id into a packed-id that can be stored in Operand. - static ASMJIT_INLINE uint32_t indexToVirtId(uint32_t id) noexcept { return id + kVirtIdMin; } - //! Converts a packed-id back to real-id. - static ASMJIT_INLINE uint32_t virtIdToIndex(uint32_t id) noexcept { return id - kVirtIdMin; } - - //! \name Construction & Destruction - //! \{ - - //! \cond INTERNAL - //! Initializes a `BaseReg` operand from `signature` and register `id`. - inline void _initReg(uint32_t signature, uint32_t id) noexcept { - _signature = signature; - _baseId = id; - _data[0] = 0; - _data[1] = 0; - } - //! \endcond - - //! Initializes the operand from `other` operand (used by operator overloads). - inline void copyFrom(const Operand_& other) noexcept { memcpy(this, &other, sizeof(Operand_)); } - - //! Resets the `Operand` to none. - //! - //! None operand is defined the following way: - //! - Its signature is zero (kOpNone, and the rest zero as well). - //! - Its id is `0`. - //! - The reserved8_4 field is set to `0`. - //! - The reserved12_4 field is set to zero. - //! - //! In other words, reset operands have all members set to zero. Reset operand - //! must match the Operand state right after its construction. Alternatively, - //! if you have an array of operands, you can simply use `memset()`. - //! - //! ``` - //! using namespace asmjit; - //! - //! Operand a; - //! Operand b; - //! assert(a == b); - //! - //! b = x86::eax; - //! assert(a != b); - //! - //! b.reset(); - //! assert(a == b); - //! - //! memset(&b, 0, sizeof(Operand)); - //! assert(a == b); - //! ``` - inline void reset() noexcept { - _signature = 0; - _baseId = 0; - _data[0] = 0; - _data[1] = 0; - } - - //! \} - - //! \name Operator Overloads - //! \{ - - //! Tests whether this operand is the same as `other`. - constexpr bool operator==(const Operand_& other) const noexcept { return equals(other); } - //! Tests whether this operand is not the same as `other`. - constexpr bool operator!=(const Operand_& other) const noexcept { return !equals(other); } - - //! \} - - //! \name Cast - //! \{ - - //! Casts this operand to `T` type. - template - inline T& as() noexcept { return static_cast(*this); } - - //! Casts this operand to `T` type (const). - template - inline const T& as() const noexcept { return static_cast(*this); } - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether the operand matches the given signature `sign`. - constexpr bool hasSignature(uint32_t signature) const noexcept { return _signature == signature; } - //! Tests whether the operand matches the signature of the `other` operand. - constexpr bool hasSignature(const Operand_& other) const noexcept { return _signature == other.signature(); } - - //! Returns operand signature as unsigned 32-bit integer. - //! - //! Signature is first 4 bytes of the operand data. It's used mostly for - //! operand checking as it's much faster to check 4 bytes at once than having - //! to check these bytes individually. - constexpr uint32_t signature() const noexcept { return _signature; } - - //! Sets the operand signature, see `signature()`. - //! - //! \note Improper use of `setSignature()` can lead to hard-to-debug errors. - inline void setSignature(uint32_t signature) noexcept { _signature = signature; } - - //! \cond INTERNAL - template - constexpr bool _hasSignaturePart() const noexcept { - return (_signature & mask) != 0; - } - - template - constexpr uint32_t _getSignaturePart() const noexcept { - return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask)); - } - - template - inline void _setSignaturePart(uint32_t value) noexcept { - ASMJIT_ASSERT((value & ~(mask >> Support::constCtz(mask))) == 0); - _signature = (_signature & ~mask) | (value << Support::constCtz(mask)); - } - //! \endcond - - //! Returns the type of the operand, see `OpType`. - constexpr uint32_t opType() const noexcept { return _getSignaturePart(); } - //! Tests whether the operand is none (`kOpNone`). - constexpr bool isNone() const noexcept { return _signature == 0; } - //! Tests whether the operand is a register (`kOpReg`). - constexpr bool isReg() const noexcept { return opType() == kOpReg; } - //! Tests whether the operand is a memory location (`kOpMem`). - constexpr bool isMem() const noexcept { return opType() == kOpMem; } - //! Tests whether the operand is an immediate (`kOpImm`). - constexpr bool isImm() const noexcept { return opType() == kOpImm; } - //! Tests whether the operand is a label (`kOpLabel`). - constexpr bool isLabel() const noexcept { return opType() == kOpLabel; } - - //! Tests whether the operand is a physical register. - constexpr bool isPhysReg() const noexcept { return isReg() && _baseId < 0xFFu; } - //! Tests whether the operand is a virtual register. - constexpr bool isVirtReg() const noexcept { return isReg() && _baseId > 0xFFu; } - - //! Tests whether the operand specifies a size (i.e. the size is not zero). - constexpr bool hasSize() const noexcept { return _hasSignaturePart(); } - //! Tests whether the size of the operand matches `size`. - constexpr bool hasSize(uint32_t s) const noexcept { return size() == s; } - - //! Returns the size of the operand in bytes. - //! - //! The value returned depends on the operand type: - //! * None - Should always return zero size. - //! * Reg - Should always return the size of the register. If the register - //! size depends on architecture (like `x86::CReg` and `x86::DReg`) - //! the size returned should be the greatest possible (so it should - //! return 64-bit size in such case). - //! * Mem - Size is optional and will be in most cases zero. - //! * Imm - Should always return zero size. - //! * Label - Should always return zero size. - constexpr uint32_t size() const noexcept { return _getSignaturePart(); } - - //! Returns the operand id. - //! - //! The value returned should be interpreted accordingly to the operand type: - //! * None - Should be `0`. - //! * Reg - Physical or virtual register id. - //! * Mem - Multiple meanings - BASE address (register or label id), or - //! high value of a 64-bit absolute address. - //! * Imm - Should be `0`. - //! * Label - Label id if it was created by using `newLabel()` or - //! `Globals::kInvalidId` if the label is invalid or not - //! initialized. - constexpr uint32_t id() const noexcept { return _baseId; } - - //! Tests whether the operand is 100% equal to `other` operand. - //! - //! \note This basically performs a binary comparison, if aby bit is - //! different the operands are not equal. - constexpr bool equals(const Operand_& other) const noexcept { - return (_signature == other._signature) & - (_baseId == other._baseId ) & - (_data[0] == other._data[0] ) & - (_data[1] == other._data[1] ) ; - } - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use equals() instead") - constexpr bool isEqual(const Operand_& other) const noexcept { return equals(other); } -#endif //!ASMJIT_NO_DEPRECATED - - //! Tests whether the operand is a register matching `rType`. - constexpr bool isReg(uint32_t rType) const noexcept { - return (_signature & (kSignatureOpMask | kSignatureRegTypeMask)) == - ((kOpReg << kSignatureOpShift) | (rType << kSignatureRegTypeShift)); - } - - //! Tests whether the operand is register and of `rType` and `rId`. - constexpr bool isReg(uint32_t rType, uint32_t rId) const noexcept { - return isReg(rType) && id() == rId; - } - - //! Tests whether the operand is a register or memory. - constexpr bool isRegOrMem() const noexcept { - return Support::isBetween(opType(), kOpReg, kOpMem); - } - - //! \} -}; - -// ============================================================================ -// [asmjit::Operand] -// ============================================================================ - -//! Operand can contain register, memory location, immediate, or label. -class Operand : public Operand_ { -public: - //! \name Construction & Destruction - //! \{ - - //! Creates `kOpNone` operand having all members initialized to zero. - constexpr Operand() noexcept - : Operand_{ kOpNone, 0u, { 0u, 0u }} {} - - //! Creates a cloned `other` operand. - constexpr Operand(const Operand& other) noexcept = default; - - //! Creates a cloned `other` operand. - constexpr explicit Operand(const Operand_& other) - : Operand_(other) {} - - //! Creates an operand initialized to raw `[u0, u1, u2, u3]` values. - constexpr Operand(Globals::Init_, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept - : Operand_{ u0, u1, { u2, u3 }} {} - - //! Creates an uninitialized operand (dangerous). - inline explicit Operand(Globals::NoInit_) noexcept {} - - //! \} - - //! \name Operator Overloads - //! \{ - - inline Operand& operator=(const Operand& other) noexcept = default; - inline Operand& operator=(const Operand_& other) noexcept { return operator=(static_cast(other)); } - - //! \} - - //! \name Utilities - //! \{ - - //! Clones this operand and returns its copy. - constexpr Operand clone() const noexcept { return Operand(*this); } - - //! \} -}; - -static_assert(sizeof(Operand) == 16, "asmjit::Operand must be exactly 16 bytes long"); - -// ============================================================================ -// [asmjit::Label] -// ============================================================================ - -//! Label (jump target or data location). -//! -//! Label represents a location in code typically used as a jump target, but -//! may be also a reference to some data or a static variable. Label has to be -//! explicitly created by BaseEmitter. -//! -//! Example of using labels: -//! -//! ``` -//! // Create some emitter (for example x86::Assembler). -//! x86::Assembler a; -//! -//! // Create Label instance. -//! Label L1 = a.newLabel(); -//! -//! // ... your code ... -//! -//! // Using label. -//! a.jump(L1); -//! -//! // ... your code ... -//! -//! // Bind label to the current position, see `BaseEmitter::bind()`. -//! a.bind(L1); -//! ``` -class Label : public Operand { -public: - //! Type of the Label. - enum LabelType : uint32_t { - //! Anonymous (unnamed) label. - kTypeAnonymous = 0, - //! Local label (always has parentId). - kTypeLocal = 1, - //! Global label (never has parentId). - kTypeGlobal = 2, - //! Number of label types. - kTypeCount = 3 - }; - - //! \name Construction & Destruction - //! \{ - - //! Creates a label operand without ID (you must set the ID to make it valid). - constexpr Label() noexcept - : Operand(Globals::Init, kOpLabel, Globals::kInvalidId, 0, 0) {} - - //! Creates a cloned label operand of `other`. - constexpr Label(const Label& other) noexcept - : Operand(other) {} - - //! Creates a label operand of the given `id`. - constexpr explicit Label(uint32_t id) noexcept - : Operand(Globals::Init, kOpLabel, id, 0, 0) {} - - inline explicit Label(Globals::NoInit_) noexcept - : Operand(Globals::NoInit) {} - - //! Resets the label, will reset all properties and set its ID to `Globals::kInvalidId`. - inline void reset() noexcept { - _signature = kOpLabel; - _baseId = Globals::kInvalidId; - _data[0] = 0; - _data[1] = 0; - } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline Label& operator=(const Label& other) noexcept = default; - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether the label was created by CodeHolder and/or an attached emitter. - constexpr bool isValid() const noexcept { return _baseId != Globals::kInvalidId; } - //! Sets the label `id`. - inline void setId(uint32_t id) noexcept { _baseId = id; } - - //! \} -}; - -// ============================================================================ -// [asmjit::BaseRegTraits] -// ============================================================================ - -//! \cond INTERNAL -//! Default register traits. -struct BaseRegTraits { - //! RegType is not valid by default. - static constexpr uint32_t kValid = 0; - //! Count of registers (0 if none). - static constexpr uint32_t kCount = 0; - //! Everything is void by default. - static constexpr uint32_t kTypeId = 0; - - //! Zero type by default. - static constexpr uint32_t kType = 0; - //! Zero group by default. - static constexpr uint32_t kGroup = 0; - //! No size by default. - static constexpr uint32_t kSize = 0; - - //! Empty signature by default. - static constexpr uint32_t kSignature = Operand::kOpReg; -}; -//! \endcond - -// ============================================================================ -// [asmjit::BaseReg] -// ============================================================================ - -//! Structure that allows to extract a register information based on the signature. -//! -//! This information is compatible with operand's signature (32-bit integer) -//! and `RegInfo` just provides easy way to access it. -struct RegInfo { - inline void reset(uint32_t signature = 0) noexcept { _signature = signature; } - inline void setSignature(uint32_t signature) noexcept { _signature = signature; } - - template - constexpr uint32_t _getSignaturePart() const noexcept { - return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask)); - } - - constexpr bool isValid() const noexcept { return _signature != 0; } - constexpr uint32_t signature() const noexcept { return _signature; } - constexpr uint32_t opType() const noexcept { return _getSignaturePart(); } - constexpr uint32_t group() const noexcept { return _getSignaturePart(); } - constexpr uint32_t type() const noexcept { return _getSignaturePart(); } - constexpr uint32_t size() const noexcept { return _getSignaturePart(); } - - uint32_t _signature; -}; - -//! Physical or virtual register operand. -class BaseReg : public Operand { -public: - //! Architecture neutral register types. - //! - //! These must be reused by any platform that contains that types. All GP - //! and VEC registers are also allowed by design to be part of a BASE|INDEX - //! of a memory operand. - enum RegType : uint32_t { - //! No register - unused, invalid, multiple meanings. - kTypeNone = 0, - - // (1 is used as a LabelTag) - - //! 8-bit low general purpose register (X86). - kTypeGp8Lo = 2, - //! 8-bit high general purpose register (X86). - kTypeGp8Hi = 3, - //! 16-bit general purpose register (X86). - kTypeGp16 = 4, - //! 32-bit general purpose register (X86|ARM). - kTypeGp32 = 5, - //! 64-bit general purpose register (X86|ARM). - kTypeGp64 = 6, - //! 32-bit view of a vector register (ARM). - kTypeVec32 = 7, - //! 64-bit view of a vector register (ARM). - kTypeVec64 = 8, - //! 128-bit view of a vector register (X86|ARM). - kTypeVec128 = 9, - //! 256-bit view of a vector register (X86). - kTypeVec256 = 10, - //! 512-bit view of a vector register (X86). - kTypeVec512 = 11, - //! 1024-bit view of a vector register (future). - kTypeVec1024 = 12, - //! Other0 register, should match `kOther0` group. - kTypeOther0 = 13, - //! Other1 register, should match `kOther1` group. - kTypeOther1 = 14, - //! Universal id of IP/PC register (if separate). - kTypeIP = 15, - //! Start of platform dependent register types (must be honored). - kTypeCustom = 16, - //! Maximum possible register id of all architectures. - kTypeMax = 31 - }; - - //! Register group (architecture neutral), and some limits. - enum RegGroup : uint32_t { - //! General purpose register group compatible with all backends. - kGroupGp = 0, - //! Vector register group compatible with all backends. - kGroupVec = 1, - //! Group that is architecture dependent. - kGroupOther0 = 2, - //! Group that is architecture dependent. - kGroupOther1 = 3, - //! Count of register groups used by virtual registers. - kGroupVirt = 4, - //! Count of register groups used by physical registers. - kGroupCount = 16 - }; - - enum Id : uint32_t { - //! None or any register (mostly internal). - kIdBad = 0xFFu - }; - - static constexpr uint32_t kSignature = kOpReg; - - //! \name Construction & Destruction - //! \{ - - //! Creates a dummy register operand. - constexpr BaseReg() noexcept - : Operand(Globals::Init, kSignature, kIdBad, 0, 0) {} - - //! Creates a new register operand which is the same as `other` . - constexpr BaseReg(const BaseReg& other) noexcept - : Operand(other) {} - - //! Creates a new register operand compatible with `other`, but with a different `rId`. - constexpr BaseReg(const BaseReg& other, uint32_t rId) noexcept - : Operand(Globals::Init, other._signature, rId, 0, 0) {} - - //! Creates a register initialized to `signature` and `rId`. - constexpr BaseReg(uint32_t signature, uint32_t rId) noexcept - : Operand(Globals::Init, signature, rId, 0, 0) {} - - inline explicit BaseReg(Globals::NoInit_) noexcept - : Operand(Globals::NoInit) {} - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline BaseReg& operator=(const BaseReg& other) noexcept = default; - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether this register is the same as `other`. - //! - //! This is just an optimization. Registers by default only use the first - //! 8 bytes of Operand data, so this method takes advantage of this knowledge - //! and only compares these 8 bytes. If both operands were created correctly - //! both \ref equals() and \ref isSame() should give the same answer, however, - //! if any of these two contains garbage or other metadata in the upper 8 - //! bytes then \ref isSame() may return `true` in cases in which \ref equals() - //! returns false. - constexpr bool isSame(const BaseReg& other) const noexcept { - return (_signature == other._signature) & (_baseId == other._baseId); - } - - //! Tests whether the register is valid (either virtual or physical). - constexpr bool isValid() const noexcept { return (_signature != 0) & (_baseId != kIdBad); } - - //! Tests whether this is a physical register. - constexpr bool isPhysReg() const noexcept { return _baseId < kIdBad; } - //! Tests whether this is a virtual register. - constexpr bool isVirtReg() const noexcept { return _baseId > kIdBad; } - - //! Tests whether the register type matches `type` - same as `isReg(type)`, provided for convenience. - constexpr bool isType(uint32_t type) const noexcept { return (_signature & kSignatureRegTypeMask) == (type << kSignatureRegTypeShift); } - //! Tests whether the register group matches `group`. - constexpr bool isGroup(uint32_t group) const noexcept { return (_signature & kSignatureRegGroupMask) == (group << kSignatureRegGroupShift); } - - //! Tests whether the register is a general purpose register (any size). - constexpr bool isGp() const noexcept { return isGroup(kGroupGp); } - //! Tests whether the register is a vector register. - constexpr bool isVec() const noexcept { return isGroup(kGroupVec); } - - using Operand_::isReg; - - //! Same as `isType()`, provided for convenience. - constexpr bool isReg(uint32_t rType) const noexcept { return isType(rType); } - //! Tests whether the register type matches `type` and register id matches `rId`. - constexpr bool isReg(uint32_t rType, uint32_t rId) const noexcept { return isType(rType) && id() == rId; } - - //! Returns the type of the register. - constexpr uint32_t type() const noexcept { return _getSignaturePart(); } - //! Returns the register group. - constexpr uint32_t group() const noexcept { return _getSignaturePart(); } - - //! Clones the register operand. - constexpr BaseReg clone() const noexcept { return BaseReg(*this); } - - //! Casts this register to `RegT` by also changing its signature. - //! - //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. - template - constexpr RegT cloneAs() const noexcept { return RegT(RegT::kSignature, id()); } - - //! Casts this register to `other` by also changing its signature. - //! - //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors. - template - constexpr RegT cloneAs(const RegT& other) const noexcept { return RegT(other.signature(), id()); } - - //! Sets the register id to `rId`. - inline void setId(uint32_t rId) noexcept { _baseId = rId; } - - //! Sets a 32-bit operand signature based on traits of `RegT`. - template - inline void setSignatureT() noexcept { _signature = RegT::kSignature; } - - //! Sets the register `signature` and `rId`. - inline void setSignatureAndId(uint32_t signature, uint32_t rId) noexcept { - _signature = signature; - _baseId = rId; - } - - //! \} - - //! \name Static Functions - //! \{ - - //! Tests whether the `op` operand is a general purpose register. - static inline bool isGp(const Operand_& op) noexcept { - // Check operand type and register group. Not interested in register type and size. - const uint32_t kSgn = (kOpReg << kSignatureOpShift ) | - (kGroupGp << kSignatureRegGroupShift) ; - return (op.signature() & (kSignatureOpMask | kSignatureRegGroupMask)) == kSgn; - } - - //! Tests whether the `op` operand is a vector register. - static inline bool isVec(const Operand_& op) noexcept { - // Check operand type and register group. Not interested in register type and size. - const uint32_t kSgn = (kOpReg << kSignatureOpShift ) | - (kGroupVec << kSignatureRegGroupShift) ; - return (op.signature() & (kSignatureOpMask | kSignatureRegGroupMask)) == kSgn; - } - - //! Tests whether the `op` is a general purpose register of the given `rId`. - static inline bool isGp(const Operand_& op, uint32_t rId) noexcept { return isGp(op) & (op.id() == rId); } - //! Tests whether the `op` is a vector register of the given `rId`. - static inline bool isVec(const Operand_& op, uint32_t rId) noexcept { return isVec(op) & (op.id() == rId); } - - //! \} -}; - -// ============================================================================ -// [asmjit::RegOnly] -// ============================================================================ - -//! RegOnly is 8-byte version of `BaseReg` that allows to store either register -//! or nothing. -//! -//! This class was designed to decrease the space consumed by each extra "operand" -//! in `BaseEmitter` and `InstNode` classes. -struct RegOnly { - //! Type of the operand, either `kOpNone` or `kOpReg`. - uint32_t _signature; - //! Physical or virtual register id. - uint32_t _id; - - //! \name Construction & Destruction - //! \{ - - //! Initializes the `RegOnly` instance to hold register `signature` and `id`. - inline void init(uint32_t signature, uint32_t id) noexcept { - _signature = signature; - _id = id; - } - - inline void init(const BaseReg& reg) noexcept { init(reg.signature(), reg.id()); } - inline void init(const RegOnly& reg) noexcept { init(reg.signature(), reg.id()); } - - //! Resets the `RegOnly` members to zeros (none). - inline void reset() noexcept { init(0, 0); } - - //! \} - - //! \name Accessors - //! \{ - - //! Tests whether this ExtraReg is none (same as calling `Operand_::isNone()`). - constexpr bool isNone() const noexcept { return _signature == 0; } - //! Tests whether the register is valid (either virtual or physical). - constexpr bool isReg() const noexcept { return _signature != 0; } - - //! Tests whether this is a physical register. - constexpr bool isPhysReg() const noexcept { return _id < BaseReg::kIdBad; } - //! Tests whether this is a virtual register (used by `BaseCompiler`). - constexpr bool isVirtReg() const noexcept { return _id > BaseReg::kIdBad; } - - //! Returns the register signature or 0 if no register is assigned. - constexpr uint32_t signature() const noexcept { return _signature; } - //! Returns the register id. - //! - //! \note Always check whether the register is assigned before using the - //! returned identifier as non-assigned `RegOnly` instance would return - //! zero id, which is still a valid register id. - constexpr uint32_t id() const noexcept { return _id; } - - //! Sets the register id. - inline void setId(uint32_t id) noexcept { _id = id; } - - //! \cond INTERNAL - //! - //! Extracts information from operand's signature. - template - constexpr uint32_t _getSignaturePart() const noexcept { - return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask)); - } - //! \endcond - - //! Returns the type of the register. - constexpr uint32_t type() const noexcept { return _getSignaturePart(); } - //! Returns the register group. - constexpr uint32_t group() const noexcept { return _getSignaturePart(); } - - //! \} - - //! \name Utilities - //! \{ - - //! Converts this ExtraReg to a real `RegT` operand. - template - constexpr RegT toReg() const noexcept { return RegT(_signature, _id); } - - //! \} -}; - -// ============================================================================ -// [asmjit::BaseMem] -// ============================================================================ - -//! Base class for all memory operands. -//! -//! \note It's tricky to pack all possible cases that define a memory operand -//! into just 16 bytes. The `BaseMem` splits data into the following parts: -//! -//! BASE - Base register or label - requires 36 bits total. 4 bits are used to -//! encode the type of the BASE operand (label vs. register type) and -//! the remaining 32 bits define the BASE id, which can be a physical or -//! virtual register index. If BASE type is zero, which is never used as -//! a register-type and label doesn't use it as well then BASE field -//! contains a high DWORD of a possible 64-bit absolute address, which is -//! possible on X64. -//! -//! INDEX - Index register (or theoretically Label, which doesn't make sense). -//! Encoding is similar to BASE - it also requires 36 bits and splits -//! the encoding to INDEX type (4 bits defining the register type) and -//! id (32-bits). -//! -//! OFFSET - A relative offset of the address. Basically if BASE is specified -//! the relative displacement adjusts BASE and an optional INDEX. if -//! BASE is not specified then the OFFSET should be considered as ABSOLUTE -//! address (at least on X86). In that case its low 32 bits are stored in -//! DISPLACEMENT field and the remaining high 32 bits are stored in BASE. -//! -//! OTHER - There is rest 8 bits that can be used for whatever purpose. The -//! x86::Mem operand uses these bits to store segment override prefix and -//! index shift (scale). -class BaseMem : public Operand { -public: - //! Address type. - enum AddrType : uint32_t { - //! Default address type, Assembler will select the best type when necessary. - kAddrTypeDefault = 0, - //! Absolute address type. - kAddrTypeAbs = 1, - //! Relative address type. - kAddrTypeRel = 2 - }; - - // Shortcuts. - enum SignatureMem : uint32_t { - kSignatureMemAbs = kAddrTypeAbs << kSignatureMemAddrTypeShift, - kSignatureMemRel = kAddrTypeRel << kSignatureMemAddrTypeShift - }; - - //! \cond INTERNAL - //! Used internally to construct `BaseMem` operand from decomposed data. - struct Decomposed { - uint32_t baseType; - uint32_t baseId; - uint32_t indexType; - uint32_t indexId; - int32_t offset; - uint32_t size; - uint32_t flags; - }; - //! \endcond - - //! \name Construction & Destruction - //! \{ - - //! Creates a default `BaseMem` operand, that points to [0]. - constexpr BaseMem() noexcept - : Operand(Globals::Init, kOpMem, 0, 0, 0) {} - - //! Creates a `BaseMem` operand that is a clone of `other`. - constexpr BaseMem(const BaseMem& other) noexcept - : Operand(other) {} - - //! \cond INTERNAL - - //! Creates a `BaseMem` operand from 4 integers as used by `Operand_` struct. - constexpr BaseMem(Globals::Init_, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept - : Operand(Globals::Init, u0, u1, u2, u3) {} - - constexpr BaseMem(const Decomposed& d) noexcept - : Operand(Globals::Init, - kOpMem | (d.baseType << kSignatureMemBaseTypeShift ) - | (d.indexType << kSignatureMemIndexTypeShift) - | (d.size << kSignatureSizeShift ) - | d.flags, - d.baseId, - d.indexId, - uint32_t(d.offset)) {} - - //! \endcond - - //! Creates a completely uninitialized `BaseMem` operand. - inline explicit BaseMem(Globals::NoInit_) noexcept - : Operand(Globals::NoInit) {} - - //! Resets the memory operand - after the reset the memory points to [0]. - inline void reset() noexcept { - _signature = kOpMem; - _baseId = 0; - _data[0] = 0; - _data[1] = 0; - } - - //! \} - - //! \name Overloaded Operators - //! \{ - - inline BaseMem& operator=(const BaseMem& other) noexcept { copyFrom(other); return *this; } - - //! \} - - //! \name Accessors - //! \{ - - //! Clones the memory operand. - constexpr BaseMem clone() const noexcept { return BaseMem(*this); } - - //! Returns the address type (see \ref AddrType) of the memory operand. - //! - //! By default, address type of newly created memory operands is always \ref kAddrTypeDefault. - constexpr uint32_t addrType() const noexcept { return _getSignaturePart(); } - //! Sets the address type to `addrType`, see \ref AddrType. - inline void setAddrType(uint32_t addrType) noexcept { _setSignaturePart(addrType); } - //! Resets the address type to \ref kAddrTypeDefault. - inline void resetAddrType() noexcept { _setSignaturePart(0); } - - //! Tests whether the address type is \ref kAddrTypeAbs. - constexpr bool isAbs() const noexcept { return addrType() == kAddrTypeAbs; } - //! Sets the address type to \ref kAddrTypeAbs. - inline void setAbs() noexcept { setAddrType(kAddrTypeAbs); } - - //! Tests whether the address type is \ref kAddrTypeRel. - constexpr bool isRel() const noexcept { return addrType() == kAddrTypeRel; } - //! Sets the address type to \ref kAddrTypeRel. - inline void setRel() noexcept { setAddrType(kAddrTypeRel); } - - //! Tests whether this memory operand is a register home (only used by \ref asmjit_compiler) - constexpr bool isRegHome() const noexcept { return _hasSignaturePart(); } - //! Mark this memory operand as register home (only used by \ref asmjit_compiler). - inline void setRegHome() noexcept { _signature |= kSignatureMemRegHomeFlag; } - //! Marks this operand to not be a register home (only used by \ref asmjit_compiler). - inline void clearRegHome() noexcept { _signature &= ~kSignatureMemRegHomeFlag; } - - //! Tests whether the memory operand has a BASE register or label specified. - constexpr bool hasBase() const noexcept { return (_signature & kSignatureMemBaseTypeMask) != 0; } - //! Tests whether the memory operand has an INDEX register specified. - constexpr bool hasIndex() const noexcept { return (_signature & kSignatureMemIndexTypeMask) != 0; } - //! Tests whether the memory operand has BASE or INDEX register. - constexpr bool hasBaseOrIndex() const noexcept { return (_signature & kSignatureMemBaseIndexMask) != 0; } - //! Tests whether the memory operand has BASE and INDEX register. - constexpr bool hasBaseAndIndex() const noexcept { return (_signature & kSignatureMemBaseTypeMask) != 0 && (_signature & kSignatureMemIndexTypeMask) != 0; } - - //! Tests whether the BASE operand is a register (registers start after `kLabelTag`). - constexpr bool hasBaseReg() const noexcept { return (_signature & kSignatureMemBaseTypeMask) > (Label::kLabelTag << kSignatureMemBaseTypeShift); } - //! Tests whether the BASE operand is a label. - constexpr bool hasBaseLabel() const noexcept { return (_signature & kSignatureMemBaseTypeMask) == (Label::kLabelTag << kSignatureMemBaseTypeShift); } - //! Tests whether the INDEX operand is a register (registers start after `kLabelTag`). - constexpr bool hasIndexReg() const noexcept { return (_signature & kSignatureMemIndexTypeMask) > (Label::kLabelTag << kSignatureMemIndexTypeShift); } - - //! Returns the type of the BASE register (0 if this memory operand doesn't - //! use the BASE register). - //! - //! \note If the returned type is one (a value never associated to a register - //! type) the BASE is not register, but it's a label. One equals to `kLabelTag`. - //! You should always check `hasBaseLabel()` before using `baseId()` result. - constexpr uint32_t baseType() const noexcept { return _getSignaturePart(); } - - //! Returns the type of an INDEX register (0 if this memory operand doesn't - //! use the INDEX register). - constexpr uint32_t indexType() const noexcept { return _getSignaturePart(); } - - //! This is used internally for BASE+INDEX validation. - constexpr uint32_t baseAndIndexTypes() const noexcept { return _getSignaturePart(); } - - //! Returns both BASE (4:0 bits) and INDEX (9:5 bits) types combined into a - //! single value. - //! - //! \remarks Returns id of the BASE register or label (if the BASE was - //! specified as label). - constexpr uint32_t baseId() const noexcept { return _baseId; } - - //! Returns the id of the INDEX register. - constexpr uint32_t indexId() const noexcept { return _data[kDataMemIndexId]; } - - //! Sets the id of the BASE register (without modifying its type). - inline void setBaseId(uint32_t rId) noexcept { _baseId = rId; } - //! Sets the id of the INDEX register (without modifying its type). - inline void setIndexId(uint32_t rId) noexcept { _data[kDataMemIndexId] = rId; } - - //! Sets the base register to type and id of the given `base` operand. - inline void setBase(const BaseReg& base) noexcept { return _setBase(base.type(), base.id()); } - //! Sets the index register to type and id of the given `index` operand. - inline void setIndex(const BaseReg& index) noexcept { return _setIndex(index.type(), index.id()); } - - //! \cond INTERNAL - inline void _setBase(uint32_t rType, uint32_t rId) noexcept { - _setSignaturePart(rType); - _baseId = rId; - } - - inline void _setIndex(uint32_t rType, uint32_t rId) noexcept { - _setSignaturePart(rType); - _data[kDataMemIndexId] = rId; - } - //! \endcond - - //! Resets the memory operand's BASE register or label. - inline void resetBase() noexcept { _setBase(0, 0); } - //! Resets the memory operand's INDEX register. - inline void resetIndex() noexcept { _setIndex(0, 0); } - - //! Sets the memory operand size (in bytes). - inline void setSize(uint32_t size) noexcept { _setSignaturePart(size); } - - //! Tests whether the memory operand has a 64-bit offset or absolute address. - //! - //! If this is true then `hasBase()` must always report false. - constexpr bool isOffset64Bit() const noexcept { return baseType() == 0; } - - //! Tests whether the memory operand has a non-zero offset or absolute address. - constexpr bool hasOffset() const noexcept { - return (_data[kDataMemOffsetLo] | uint32_t(_baseId & Support::bitMaskFromBool(isOffset64Bit()))) != 0; - } - - //! Returns either relative offset or absolute address as 64-bit integer. - constexpr int64_t offset() const noexcept { - return isOffset64Bit() ? int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32)) - : int64_t(int32_t(_data[kDataMemOffsetLo])); // Sign extend 32-bit offset. - } - - //! Returns a 32-bit low part of a 64-bit offset or absolute address. - constexpr int32_t offsetLo32() const noexcept { return int32_t(_data[kDataMemOffsetLo]); } - //! Returns a 32-but high part of a 64-bit offset or absolute address. - //! - //! \note This function is UNSAFE and returns garbage if `isOffset64Bit()` - //! returns false. Never use it blindly without checking it first. - constexpr int32_t offsetHi32() const noexcept { return int32_t(_baseId); } - - //! Sets a 64-bit offset or an absolute address to `offset`. - //! - //! \note This functions attempts to set both high and low parts of a 64-bit - //! offset, however, if the operand has a BASE register it will store only the - //! low 32 bits of the offset / address as there is no way to store both BASE - //! and 64-bit offset, and there is currently no architecture that has such - //! capability targeted by AsmJit. - inline void setOffset(int64_t offset) noexcept { - uint32_t lo = uint32_t(uint64_t(offset) & 0xFFFFFFFFu); - uint32_t hi = uint32_t(uint64_t(offset) >> 32); - uint32_t hiMsk = Support::bitMaskFromBool(isOffset64Bit()); - - _data[kDataMemOffsetLo] = lo; - _baseId = (hi & hiMsk) | (_baseId & ~hiMsk); - } - //! Sets a low 32-bit offset to `offset` (don't use without knowing how BaseMem works). - inline void setOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] = uint32_t(offset); } - - //! Adjusts the offset by `offset`. - //! - //! \note This is a fast function that doesn't use the HI 32-bits of a - //! 64-bit offset. Use it only if you know that there is a BASE register - //! and the offset is only 32 bits anyway. - - //! Adjusts the memory operand offset by a `offset`. - inline void addOffset(int64_t offset) noexcept { - if (isOffset64Bit()) { - int64_t result = offset + int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32)); - _data[kDataMemOffsetLo] = uint32_t(uint64_t(result) & 0xFFFFFFFFu); - _baseId = uint32_t(uint64_t(result) >> 32); - } - else { - _data[kDataMemOffsetLo] += uint32_t(uint64_t(offset) & 0xFFFFFFFFu); - } - } - - //! Adds `offset` to a low 32-bit offset part (don't use without knowing how - //! BaseMem works). - inline void addOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] += uint32_t(offset); } - - //! Resets the memory offset to zero. - inline void resetOffset() noexcept { setOffset(0); } - - //! Resets the lo part of the memory offset to zero (don't use without knowing - //! how BaseMem works). - inline void resetOffsetLo32() noexcept { setOffsetLo32(0); } - - //! \} -}; - -// ============================================================================ -// [asmjit::Imm] -// ============================================================================ - -//! Immediate operand. -//! -//! Immediate operand is usually part of instruction itself. It's inlined after -//! or before the instruction opcode. Immediates can be only signed or unsigned -//! integers. -//! -//! To create an immediate operand use `asmjit::imm()` helper, which can be used -//! with any type, not just the default 64-bit int. -class Imm : public Operand { -public: - //! \name Construction & Destruction - //! \{ - - //! Creates a new immediate value (initial value is 0). - constexpr Imm() noexcept - : Operand(Globals::Init, kOpImm, 0, 0, 0) {} - - //! Creates a new immediate value from `other`. - constexpr Imm(const Imm& other) noexcept - : Operand(other) {} - - //! Creates a new signed immediate value, assigning the value to `val`. - constexpr explicit Imm(int64_t val) noexcept - : Operand(Globals::Init, kOpImm, 0, Support::unpackU32At0(val), Support::unpackU32At1(val)) {} - - inline explicit Imm(Globals::NoInit_) noexcept - : Operand(Globals::NoInit) {} - - //! \} - - //! \name Overloaded Operators - //! \{ - - //! Assigns the value of the `other` operand to this immediate. - inline Imm& operator=(const Imm& other) noexcept { copyFrom(other); return *this; } - - //! \} - - //! \name Accessors - //! \{ - - //! Returns the immediate value as `int64_t`, which is the internal format Imm uses. - constexpr int64_t value() const noexcept { - return int64_t((uint64_t(_data[kDataImmValueHi]) << 32) | _data[kDataImmValueLo]); - } - - //! Tests whether the immediate can be casted to 8-bit signed integer. - constexpr bool isInt8() const noexcept { return Support::isInt8(value()); } - //! Tests whether the immediate can be casted to 8-bit unsigned integer. - constexpr bool isUInt8() const noexcept { return Support::isUInt8(value()); } - //! Tests whether the immediate can be casted to 16-bit signed integer. - constexpr bool isInt16() const noexcept { return Support::isInt16(value()); } - //! Tests whether the immediate can be casted to 16-bit unsigned integer. - constexpr bool isUInt16() const noexcept { return Support::isUInt16(value()); } - //! Tests whether the immediate can be casted to 32-bit signed integer. - constexpr bool isInt32() const noexcept { return Support::isInt32(value()); } - //! Tests whether the immediate can be casted to 32-bit unsigned integer. - constexpr bool isUInt32() const noexcept { return _data[kDataImmValueHi] == 0; } - - //! Returns the immediate value casted to `T`. - //! - //! The value is masked before it's casted to `T` so the returned value is - //! simply the representation of `T` considering the original value's lowest - //! bits. - template - constexpr T valueAs() const noexcept { - return T(uint64_t(value()) & Support::allOnes::type>()); - } - - //! Returns low 32-bit signed integer. - constexpr int32_t int32Lo() const noexcept { return int32_t(_data[kDataImmValueLo]); } - //! Returns high 32-bit signed integer. - constexpr int32_t int32Hi() const noexcept { return int32_t(_data[kDataImmValueHi]); } - //! Returns low 32-bit signed integer. - constexpr uint32_t uint32Lo() const noexcept { return _data[kDataImmValueLo]; } - //! Returns high 32-bit signed integer. - constexpr uint32_t uint32Hi() const noexcept { return _data[kDataImmValueHi]; } - - //! Sets immediate value to `val`, the value is casted to a signed 64-bit integer. - template - inline void setValue(const T& val) noexcept { - int64_t val64 = int64_t(Support::asNormalized(val)); - _data[kDataImmValueHi] = uint32_t(uint64_t(val64) >> 32); - _data[kDataImmValueLo] = uint32_t(uint64_t(val64) & 0xFFFFFFFFu); - } - - inline void setDouble(double d) noexcept { - setValue(Support::bitCast(d)); - } - - //! \} - - //! \name Utilities - //! \{ - - //! Clones the immediate operand. - constexpr Imm clone() const noexcept { return Imm(*this); } - - inline void signExtend8Bits() noexcept { setValue(int64_t(valueAs())); } - inline void signExtend16Bits() noexcept { setValue(int64_t(valueAs())); } - inline void signExtend32Bits() noexcept { setValue(int64_t(valueAs())); } - - inline void zeroExtend8Bits() noexcept { setValue(valueAs()); } - inline void zeroExtend16Bits() noexcept { setValue(valueAs()); } - inline void zeroExtend32Bits() noexcept { _data[kDataImmValueHi] = 0u; } - - //! \} - -#ifndef ASMJIT_NO_DEPRECATED - ASMJIT_DEPRECATED("Use valueAs() instead") - inline int8_t i8() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline uint8_t u8() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline int16_t i16() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline uint16_t u16() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline int32_t i32() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline uint32_t u32() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use value() instead") - inline int64_t i64() const noexcept { return value(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline uint64_t u64() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline intptr_t iptr() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use valueAs() instead") - inline uintptr_t uptr() const noexcept { return valueAs(); } - - ASMJIT_DEPRECATED("Use int32Lo() instead") - inline int32_t i32Lo() const noexcept { return int32Lo(); } - - ASMJIT_DEPRECATED("Use uint32Lo() instead") - inline uint32_t u32Lo() const noexcept { return uint32Lo(); } - - ASMJIT_DEPRECATED("Use int32Hi() instead") - inline int32_t i32Hi() const noexcept { return int32Hi(); } - - ASMJIT_DEPRECATED("Use uint32Hi() instead") - inline uint32_t u32Hi() const noexcept { return uint32Hi(); } -#endif // !ASMJIT_NO_DEPRECATED -}; - -//! Creates a new immediate operand. -//! -//! Using `imm(x)` is much nicer than using `Imm(x)` as this is a template -//! which can accept any integer including pointers and function pointers. -template -static constexpr Imm imm(T val) noexcept { - return Imm(std::is_signed::value ? int64_t(val) : int64_t(uint64_t(val))); -} - -//! \} - -// ============================================================================ -// [asmjit::Globals::none] -// ============================================================================ - -namespace Globals { - //! \ingroup asmjit_assembler - //! - //! A default-constructed operand of `Operand_::kOpNone` type. - static constexpr const Operand none; -} - -// ============================================================================ -// [asmjit::Support::ForwardOp] -// ============================================================================ - -//! \cond INTERNAL -namespace Support { - -template -struct ForwardOpImpl { - static ASMJIT_INLINE const T& forward(const T& value) noexcept { return value; } -}; - -template -struct ForwardOpImpl { - static ASMJIT_INLINE Imm forward(const T& value) noexcept { return Imm(value); } -}; - -//! Either forwards operand T or returns a new operand for T if T is a type -//! convertible to operand. At the moment this is only used to convert integers -//! to \ref Imm operands. -template -struct ForwardOp : public ForwardOpImpl::type>::value> {}; - -} - -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_OPERAND_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/osutils.cpp b/ext/asmjit-master/src/asmjit/core/osutils.cpp deleted file mode 100644 index e2f34efb..00000000 --- a/ext/asmjit-master/src/asmjit/core/osutils.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#include "../core/api-build_p.h" -#include "../core/osutils.h" -#include "../core/support.h" - -#if defined(_WIN32) - #include -#elif defined(__APPLE__) - #include -#else - #include - #include -#endif - -ASMJIT_BEGIN_NAMESPACE - -// ============================================================================ -// [asmjit::OSUtils - GetTickCount] -// ============================================================================ - -uint32_t OSUtils::getTickCount() noexcept { -#if defined(_WIN32) - enum HiResStatus : uint32_t { - kHiResUnknown = 0, - kHiResAvailable = 1, - kHiResNotAvailable = 2 - }; - - static std::atomic _hiResStatus(kHiResUnknown); - static volatile double _hiResFreq(0); - - uint32_t status = _hiResStatus.load(); - LARGE_INTEGER now, qpf; - - if (status != kHiResNotAvailable && ::QueryPerformanceCounter(&now)) { - double freq = _hiResFreq; - if (status == kHiResUnknown) { - // Detects the availability of high resolution counter. - if (::QueryPerformanceFrequency(&qpf)) { - freq = double(qpf.QuadPart) / 1000.0; - _hiResFreq = freq; - _hiResStatus.compare_exchange_strong(status, kHiResAvailable); - status = kHiResAvailable; - } - else { - // High resolution not available. - _hiResStatus.compare_exchange_strong(status, kHiResNotAvailable); - } - } - - if (status == kHiResAvailable) - return uint32_t(uint64_t(int64_t(double(now.QuadPart) / freq)) & 0xFFFFFFFFu); - } - - // Bail to `GetTickCount()` if we cannot use high resolution. - return ::GetTickCount(); -#elif defined(__APPLE__) - // See Apple's QA1398. - static mach_timebase_info_data_t _machTime; - - uint32_t denom = _machTime.denom; - if (ASMJIT_UNLIKELY(!denom)) { - if (mach_timebase_info(&_machTime) != KERN_SUCCESS || !(denom = _machTime.denom)) - return 0; - } - - // `mach_absolute_time()` returns nanoseconds, we want milliseconds. - uint64_t t = mach_absolute_time() / 1000000u; - t = (t * _machTime.numer) / _machTime.denom; - return uint32_t(t & 0xFFFFFFFFu); -#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 - struct timespec ts; - if (ASMJIT_UNLIKELY(clock_gettime(CLOCK_MONOTONIC, &ts) != 0)) - return 0; - - uint64_t t = (uint64_t(ts.tv_sec ) * 1000u) + (uint64_t(ts.tv_nsec) / 1000000u); - return uint32_t(t & 0xFFFFFFFFu); -#else - #pragma message("asmjit::OSUtils::getTickCount() doesn't have implementation for the target OS.") - return 0; -#endif -} - -ASMJIT_END_NAMESPACE diff --git a/ext/asmjit-master/src/asmjit/core/osutils.h b/ext/asmjit-master/src/asmjit/core/osutils.h deleted file mode 100644 index a4691295..00000000 --- a/ext/asmjit-master/src/asmjit/core/osutils.h +++ /dev/null @@ -1,87 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_OSUTILS_H_INCLUDED -#define ASMJIT_CORE_OSUTILS_H_INCLUDED - -#include "../core/globals.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \addtogroup asmjit_utilities -//! \{ - -// ============================================================================ -// [asmjit::OSUtils] -// ============================================================================ - -//! Operating system utilities. -namespace OSUtils { - //! Gets the current CPU tick count, used for benchmarking (1ms resolution). - ASMJIT_API uint32_t getTickCount() noexcept; -}; - -// ============================================================================ -// [asmjit::Lock] -// ============================================================================ - -//! \cond INTERNAL - -//! Lock. -//! -//! Lock is internal, it cannot be used outside of AsmJit, however, its internal -//! layout is exposed as it's used by some other classes, which are public. -class Lock { -public: - ASMJIT_NONCOPYABLE(Lock) - -#if defined(_WIN32) -#pragma pack(push, 8) - struct ASMJIT_MAY_ALIAS Handle { - void* DebugInfo; - long LockCount; - long RecursionCount; - void* OwningThread; - void* LockSemaphore; - unsigned long* SpinCount; - }; - Handle _handle; -#pragma pack(pop) -#elif !defined(__EMSCRIPTEN__) - typedef pthread_mutex_t Handle; - Handle _handle; -#endif - - inline Lock() noexcept; - inline ~Lock() noexcept; - - inline void lock() noexcept; - inline void unlock() noexcept; -}; -//! \endcond - -//! \} - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_OSUTILS_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/osutils_p.h b/ext/asmjit-master/src/asmjit/core/osutils_p.h deleted file mode 100644 index 31db308b..00000000 --- a/ext/asmjit-master/src/asmjit/core/osutils_p.h +++ /dev/null @@ -1,94 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_OSUTILS_P_H_INCLUDED -#define ASMJIT_CORE_OSUTILS_P_H_INCLUDED - -#include "../core/osutils.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_utilities -//! \{ - -// ============================================================================ -// [asmjit::Lock] -// ============================================================================ - -#if defined(_WIN32) - -// Windows implementation. -static_assert(sizeof(Lock::Handle) == sizeof(CRITICAL_SECTION), "asmjit::Lock::Handle layout must match CRITICAL_SECTION"); -static_assert(alignof(Lock::Handle) == alignof(CRITICAL_SECTION), "asmjit::Lock::Handle alignment must match CRITICAL_SECTION"); - -inline Lock::Lock() noexcept { InitializeCriticalSection(reinterpret_cast(&_handle)); } -inline Lock::~Lock() noexcept { DeleteCriticalSection(reinterpret_cast(&_handle)); } -inline void Lock::lock() noexcept { EnterCriticalSection(reinterpret_cast(&_handle)); } -inline void Lock::unlock() noexcept { LeaveCriticalSection(reinterpret_cast(&_handle)); } - -#elif !defined(__EMSCRIPTEN__) - -// PThread implementation. -#ifdef PTHREAD_MUTEX_INITIALIZER -inline Lock::Lock() noexcept : _handle(PTHREAD_MUTEX_INITIALIZER) {} -#else -inline Lock::Lock() noexcept { pthread_mutex_init(&_handle, nullptr); } -#endif -inline Lock::~Lock() noexcept { pthread_mutex_destroy(&_handle); } -inline void Lock::lock() noexcept { pthread_mutex_lock(&_handle); } -inline void Lock::unlock() noexcept { pthread_mutex_unlock(&_handle); } - -#else - -// Dummy implementation - Emscripten or other unsupported platform. -inline Lock::Lock() noexcept {} -inline Lock::~Lock() noexcept {} -inline void Lock::lock() noexcept {} -inline void Lock::unlock() noexcept {} - -#endif - -// ============================================================================ -// [asmjit::LockGuard] -// ============================================================================ - -//! Scoped lock. -class LockGuard { -public: - ASMJIT_NONCOPYABLE(LockGuard) - - Lock& _target; - - inline LockGuard(Lock& target) noexcept - : _target(target) { _target.lock(); } - inline ~LockGuard() noexcept { _target.unlock(); } -}; - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // ASMJIT_CORE_OSUTILS_P_H_INCLUDED - diff --git a/ext/asmjit-master/src/asmjit/core/raassignment_p.h b/ext/asmjit-master/src/asmjit/core/raassignment_p.h deleted file mode 100644 index 2618afd0..00000000 --- a/ext/asmjit-master/src/asmjit/core/raassignment_p.h +++ /dev/null @@ -1,399 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_RAASSIGNMENT_P_H_INCLUDED -#define ASMJIT_CORE_RAASSIGNMENT_P_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_COMPILER - -#include "../core/radefs_p.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_ra -//! \{ - -// ============================================================================ -// [asmjit::RAAssignment] -// ============================================================================ - -class RAAssignment { - ASMJIT_NONCOPYABLE(RAAssignment) - -public: - enum Ids : uint32_t { - kPhysNone = 0xFF, - kWorkNone = RAWorkReg::kIdNone - }; - - enum DirtyBit : uint32_t { - kClean = 0, - kDirty = 1 - }; - - struct Layout { - inline void reset() noexcept { - physIndex.reset(); - physCount.reset(); - physTotal = 0; - workCount = 0; - workRegs = nullptr; - } - - RARegIndex physIndex; //!< Index of architecture registers per group. - RARegCount physCount; //!< Count of architecture registers per group. - uint32_t physTotal; //!< Count of physical registers of all groups. - uint32_t workCount; //!< Count of work registers. - const RAWorkRegs* workRegs; //!< WorkRegs data (vector). - }; - - struct PhysToWorkMap { - static inline size_t sizeOf(uint32_t count) noexcept { - return sizeof(PhysToWorkMap) - sizeof(uint32_t) + size_t(count) * sizeof(uint32_t); - } - - inline void reset(uint32_t count) noexcept { - assigned.reset(); - dirty.reset(); - - for (uint32_t i = 0; i < count; i++) - workIds[i] = kWorkNone; - } - - inline void copyFrom(const PhysToWorkMap* other, uint32_t count) noexcept { - size_t size = sizeOf(count); - memcpy(this, other, size); - } - - RARegMask assigned; //!< Assigned registers (each bit represents one physical reg). - RARegMask dirty; //!< Dirty registers (spill slot out of sync or no spill slot). - uint32_t workIds[1 /* ... */]; //!< PhysReg to WorkReg mapping. - }; - - struct WorkToPhysMap { - static inline size_t sizeOf(uint32_t count) noexcept { - return size_t(count) * sizeof(uint8_t); - } - - inline void reset(uint32_t count) noexcept { - for (uint32_t i = 0; i < count; i++) - physIds[i] = kPhysNone; - } - - inline void copyFrom(const WorkToPhysMap* other, uint32_t count) noexcept { - size_t size = sizeOf(count); - if (ASMJIT_LIKELY(size)) - memcpy(this, other, size); - } - - uint8_t physIds[1 /* ... */]; //!< WorkReg to PhysReg mapping - }; - - //! Physical registers layout. - Layout _layout; - //! WorkReg to PhysReg mapping. - WorkToPhysMap* _workToPhysMap; - //! PhysReg to WorkReg mapping and assigned/dirty bits. - PhysToWorkMap* _physToWorkMap; - //! Optimization to translate PhysRegs to WorkRegs faster. - uint32_t* _physToWorkIds[BaseReg::kGroupVirt]; - - //! \name Construction & Destruction - //! \{ - - inline RAAssignment() noexcept { - _layout.reset(); - resetMaps(); - } - - inline void initLayout(const RARegCount& physCount, const RAWorkRegs& workRegs) noexcept { - // Layout must be initialized before data. - ASMJIT_ASSERT(_physToWorkMap == nullptr); - ASMJIT_ASSERT(_workToPhysMap == nullptr); - - _layout.physIndex.buildIndexes(physCount); - _layout.physCount = physCount; - _layout.physTotal = uint32_t(_layout.physIndex[BaseReg::kGroupVirt - 1]) + - uint32_t(_layout.physCount[BaseReg::kGroupVirt - 1]) ; - _layout.workCount = workRegs.size(); - _layout.workRegs = &workRegs; - } - - inline void initMaps(PhysToWorkMap* physToWorkMap, WorkToPhysMap* workToPhysMap) noexcept { - _physToWorkMap = physToWorkMap; - _workToPhysMap = workToPhysMap; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - _physToWorkIds[group] = physToWorkMap->workIds + _layout.physIndex.get(group); - } - - inline void resetMaps() noexcept { - _physToWorkMap = nullptr; - _workToPhysMap = nullptr; - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - _physToWorkIds[group] = nullptr; - } - - //! \} - - //! \name Accessors - //! \{ - - inline PhysToWorkMap* physToWorkMap() const noexcept { return _physToWorkMap; } - inline WorkToPhysMap* workToPhysMap() const noexcept { return _workToPhysMap; } - - inline RARegMask& assigned() noexcept { return _physToWorkMap->assigned; } - inline const RARegMask& assigned() const noexcept { return _physToWorkMap->assigned; } - inline uint32_t assigned(uint32_t group) const noexcept { return _physToWorkMap->assigned[group]; } - - inline RARegMask& dirty() noexcept { return _physToWorkMap->dirty; } - inline const RARegMask& dirty() const noexcept { return _physToWorkMap->dirty; } - inline uint32_t dirty(uint32_t group) const noexcept { return _physToWorkMap->dirty[group]; } - - inline uint32_t workToPhysId(uint32_t group, uint32_t workId) const noexcept { - DebugUtils::unused(group); - ASMJIT_ASSERT(workId != kWorkNone); - ASMJIT_ASSERT(workId < _layout.workCount); - return _workToPhysMap->physIds[workId]; - } - - inline uint32_t physToWorkId(uint32_t group, uint32_t physId) const noexcept { - ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); - return _physToWorkIds[group][physId]; - } - - inline bool isPhysAssigned(uint32_t group, uint32_t physId) const noexcept { - ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); - return Support::bitTest(_physToWorkMap->assigned[group], physId); - } - - inline bool isPhysDirty(uint32_t group, uint32_t physId) const noexcept { - ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); - return Support::bitTest(_physToWorkMap->dirty[group], physId); - } - - //! \} - - //! \name Assignment - //! \{ - - // These are low-level allocation helpers that are used to update the current - // mappings between physical and virt/work registers and also to update masks - // that represent allocated and dirty registers. These functions don't emit - // any code; they are only used to update and keep all mappings in sync. - - //! Assign [VirtReg/WorkReg] to a physical register. - ASMJIT_INLINE void assign(uint32_t group, uint32_t workId, uint32_t physId, uint32_t dirty) noexcept { - ASMJIT_ASSERT(workToPhysId(group, workId) == kPhysNone); - ASMJIT_ASSERT(physToWorkId(group, physId) == kWorkNone); - ASMJIT_ASSERT(!isPhysAssigned(group, physId)); - ASMJIT_ASSERT(!isPhysDirty(group, physId)); - - _workToPhysMap->physIds[workId] = uint8_t(physId); - _physToWorkIds[group][physId] = workId; - - uint32_t regMask = Support::bitMask(physId); - _physToWorkMap->assigned[group] |= regMask; - _physToWorkMap->dirty[group] |= regMask & Support::bitMaskFromBool(dirty); - - verify(); - } - - //! Reassign [VirtReg/WorkReg] to `dstPhysId` from `srcPhysId`. - ASMJIT_INLINE void reassign(uint32_t group, uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept { - ASMJIT_ASSERT(dstPhysId != srcPhysId); - ASMJIT_ASSERT(workToPhysId(group, workId) == srcPhysId); - ASMJIT_ASSERT(physToWorkId(group, srcPhysId) == workId); - ASMJIT_ASSERT(isPhysAssigned(group, srcPhysId) == true); - ASMJIT_ASSERT(isPhysAssigned(group, dstPhysId) == false); - - _workToPhysMap->physIds[workId] = uint8_t(dstPhysId); - _physToWorkIds[group][srcPhysId] = kWorkNone; - _physToWorkIds[group][dstPhysId] = workId; - - uint32_t srcMask = Support::bitMask(srcPhysId); - uint32_t dstMask = Support::bitMask(dstPhysId); - - uint32_t dirty = (_physToWorkMap->dirty[group] & srcMask) != 0; - uint32_t regMask = dstMask | srcMask; - - _physToWorkMap->assigned[group] ^= regMask; - _physToWorkMap->dirty[group] ^= regMask & Support::bitMaskFromBool(dirty); - - verify(); - } - - ASMJIT_INLINE void swap(uint32_t group, uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept { - ASMJIT_ASSERT(aPhysId != bPhysId); - ASMJIT_ASSERT(workToPhysId(group, aWorkId) == aPhysId); - ASMJIT_ASSERT(workToPhysId(group, bWorkId) == bPhysId); - ASMJIT_ASSERT(physToWorkId(group, aPhysId) == aWorkId); - ASMJIT_ASSERT(physToWorkId(group, bPhysId) == bWorkId); - ASMJIT_ASSERT(isPhysAssigned(group, aPhysId)); - ASMJIT_ASSERT(isPhysAssigned(group, bPhysId)); - - _workToPhysMap->physIds[aWorkId] = uint8_t(bPhysId); - _workToPhysMap->physIds[bWorkId] = uint8_t(aPhysId); - _physToWorkIds[group][aPhysId] = bWorkId; - _physToWorkIds[group][bPhysId] = aWorkId; - - uint32_t aMask = Support::bitMask(aPhysId); - uint32_t bMask = Support::bitMask(bPhysId); - - uint32_t flipMask = Support::bitMaskFromBool( - ((_physToWorkMap->dirty[group] & aMask) != 0) ^ - ((_physToWorkMap->dirty[group] & bMask) != 0)); - - uint32_t regMask = aMask | bMask; - _physToWorkMap->dirty[group] ^= regMask & flipMask; - - verify(); - } - - //! Unassign [VirtReg/WorkReg] from a physical register. - ASMJIT_INLINE void unassign(uint32_t group, uint32_t workId, uint32_t physId) noexcept { - ASMJIT_ASSERT(physId < Globals::kMaxPhysRegs); - ASMJIT_ASSERT(workToPhysId(group, workId) == physId); - ASMJIT_ASSERT(physToWorkId(group, physId) == workId); - ASMJIT_ASSERT(isPhysAssigned(group, physId)); - - _workToPhysMap->physIds[workId] = kPhysNone; - _physToWorkIds[group][physId] = kWorkNone; - - uint32_t regMask = Support::bitMask(physId); - _physToWorkMap->assigned[group] &= ~regMask; - _physToWorkMap->dirty[group] &= ~regMask; - - verify(); - } - - inline void makeClean(uint32_t group, uint32_t workId, uint32_t physId) noexcept { - DebugUtils::unused(workId); - uint32_t regMask = Support::bitMask(physId); - _physToWorkMap->dirty[group] &= ~regMask; - } - - inline void makeDirty(uint32_t group, uint32_t workId, uint32_t physId) noexcept { - DebugUtils::unused(workId); - uint32_t regMask = Support::bitMask(physId); - _physToWorkMap->dirty[group] |= regMask; - } - - //! \} - - //! \name Utilities - //! \{ - - inline void swap(RAAssignment& other) noexcept { - std::swap(_workToPhysMap, other._workToPhysMap); - std::swap(_physToWorkMap, other._physToWorkMap); - - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) - std::swap(_physToWorkIds[group], other._physToWorkIds[group]); - } - - inline void copyFrom(const PhysToWorkMap* physToWorkMap, const WorkToPhysMap* workToPhysMap) noexcept { - memcpy(_physToWorkMap, physToWorkMap, PhysToWorkMap::sizeOf(_layout.physTotal)); - memcpy(_workToPhysMap, workToPhysMap, WorkToPhysMap::sizeOf(_layout.workCount)); - } - - inline void copyFrom(const RAAssignment& other) noexcept { - copyFrom(other.physToWorkMap(), other.workToPhysMap()); - } - - // Not really useful outside of debugging. - bool equals(const RAAssignment& other) const noexcept { - // Layout should always match. - if (_layout.physIndex != other._layout.physIndex || - _layout.physCount != other._layout.physCount || - _layout.physTotal != other._layout.physTotal || - _layout.workCount != other._layout.workCount || - _layout.workRegs != other._layout.workRegs) - return false; - - uint32_t physTotal = _layout.physTotal; - uint32_t workCount = _layout.workCount; - - for (uint32_t physId = 0; physId < physTotal; physId++) { - uint32_t thisWorkId = _physToWorkMap->workIds[physId]; - uint32_t otherWorkId = other._physToWorkMap->workIds[physId]; - if (thisWorkId != otherWorkId) - return false; - } - - for (uint32_t workId = 0; workId < workCount; workId++) { - uint32_t thisPhysId = _workToPhysMap->physIds[workId]; - uint32_t otherPhysId = other._workToPhysMap->physIds[workId]; - if (thisPhysId != otherPhysId) - return false; - } - - if (_physToWorkMap->assigned != other._physToWorkMap->assigned || - _physToWorkMap->dirty != other._physToWorkMap->dirty ) - return false; - - return true; - } - -#if defined(ASMJIT_BUILD_DEBUG) - ASMJIT_NOINLINE void verify() noexcept { - // Verify WorkToPhysMap. - { - for (uint32_t workId = 0; workId < _layout.workCount; workId++) { - uint32_t physId = _workToPhysMap->physIds[workId]; - if (physId != kPhysNone) { - const RAWorkReg* workReg = _layout.workRegs->at(workId); - uint32_t group = workReg->group(); - ASMJIT_ASSERT(_physToWorkIds[group][physId] == workId); - } - } - } - - // Verify PhysToWorkMap. - { - for (uint32_t group = 0; group < BaseReg::kGroupVirt; group++) { - uint32_t physCount = _layout.physCount[group]; - for (uint32_t physId = 0; physId < physCount; physId++) { - uint32_t workId = _physToWorkIds[group][physId]; - if (workId != kWorkNone) { - ASMJIT_ASSERT(_workToPhysMap->physIds[workId] == physId); - } - } - } - } - } -#else - inline void verify() noexcept {} -#endif - - //! \} -}; - -//! \} -//! \endcond - -ASMJIT_END_NAMESPACE - -#endif // !ASMJIT_NO_COMPILER -#endif // ASMJIT_CORE_RAASSIGNMENT_P_H_INCLUDED diff --git a/ext/asmjit-master/src/asmjit/core/rabuilders_p.h b/ext/asmjit-master/src/asmjit/core/rabuilders_p.h deleted file mode 100644 index 50624bf5..00000000 --- a/ext/asmjit-master/src/asmjit/core/rabuilders_p.h +++ /dev/null @@ -1,633 +0,0 @@ -// AsmJit - Machine code generation for C++ -// -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. - -#ifndef ASMJIT_CORE_RABUILDERS_P_H_INCLUDED -#define ASMJIT_CORE_RABUILDERS_P_H_INCLUDED - -#include "../core/api-config.h" -#ifndef ASMJIT_NO_COMPILER - -#include "../core/formatter.h" -#include "../core/rapass_p.h" - -ASMJIT_BEGIN_NAMESPACE - -//! \cond INTERNAL -//! \addtogroup asmjit_ra -//! \{ - -// ============================================================================ -// [asmjit::RACFGBuilder] -// ============================================================================ - -template -class RACFGBuilder { -public: - RAPass* _pass; - BaseCompiler* _cc; - - RABlock* _curBlock; - RABlock* _retBlock; - FuncNode* _funcNode; - RARegsStats _blockRegStats; - uint32_t _exitLabelId; - ZoneVector _sharedAssignmentsMap; - - // Only used by logging, it's fine to be here to prevent more #ifdefs... - bool _hasCode; - RABlock* _lastLoggedBlock; - -#ifndef ASMJIT_NO_LOGGING - Logger* _logger; - uint32_t _logFlags; - StringTmp<512> _sb; -#endif - - static constexpr uint32_t kRootIndentation = 2; - static constexpr uint32_t kCodeIndentation = 4; - - // NOTE: This is a bit hacky. There are some nodes which are processed twice - // (see `onBeforeInvoke()` and `onBeforeRet()`) as they can insert some nodes - // around them. Since we don't have any flags to mark these we just use their - // position that is [at that time] unassigned. - static constexpr uint32_t kNodePositionDidOnBefore = 0xFFFFFFFFu; - - inline RACFGBuilder(RAPass* pass) noexcept - : _pass(pass), - _cc(pass->cc()), - _curBlock(nullptr), - _retBlock(nullptr), - _funcNode(nullptr), - _blockRegStats{}, - _exitLabelId(Globals::kInvalidId), - _hasCode(false), - _lastLoggedBlock(nullptr) { -#ifndef ASMJIT_NO_LOGGING - _logger = _pass->debugLogger(); - _logFlags = FormatOptions::kFlagPositions; - - if (_logger) - _logFlags |= _logger->flags(); -#endif - } - - inline BaseCompiler* cc() const noexcept { return _cc; } - - // -------------------------------------------------------------------------- - // [Run] - // -------------------------------------------------------------------------- - - //! Called per function by an architecture-specific CFG builder. - Error run() noexcept { - log("[RAPass::BuildCFG]\n"); - ASMJIT_PROPAGATE(prepare()); - - logNode(_funcNode, kRootIndentation); - logBlock(_curBlock, kRootIndentation); - - BaseNode* node = _funcNode->next(); - if (ASMJIT_UNLIKELY(!node)) - return DebugUtils::errored(kErrorInvalidState); - - _curBlock->setFirst(node); - _curBlock->setLast(node); - - RAInstBuilder ib; - ZoneVector blocksWithUnknownJumps; - - for (;;) { - BaseNode* next = node->next(); - ASMJIT_ASSERT(node->position() == 0 || node->position() == kNodePositionDidOnBefore); - - if (node->isInst()) { - // Instruction | Jump | Invoke | Return - // ------------------------------------ - - // Handle `InstNode`, `InvokeNode`, and `FuncRetNode`. All of them - // share the same interface that provides operands that have read/write - // semantics. - if (ASMJIT_UNLIKELY(!_curBlock)) { - // Unreachable code has to be removed, we cannot allocate registers - // in such code as we cannot do proper liveness analysis in such case. - removeNode(node); - node = next; - continue; - } - - _hasCode = true; - - if (node->isInvoke() || node->isFuncRet()) { - if (node->position() != kNodePositionDidOnBefore) { - // Call and Reg are complicated as they may insert some surrounding - // code around them. The simplest approach is to get the previous - // node, call the `onBefore()` handlers and then check whether - // anything changed and restart if so. By restart we mean that the - // current `node` would go back to the first possible inserted node - // by `onBeforeInvoke()` or `onBeforeRet()`. - BaseNode* prev = node->prev(); - - if (node->type() == BaseNode::kNodeInvoke) - ASMJIT_PROPAGATE(static_cast(this)->onBeforeInvoke(node->as())); - else - ASMJIT_PROPAGATE(static_cast(this)->onBeforeRet(node->as())); - - if (prev != node->prev()) { - // If this was the first node in the block and something was - // inserted before it then we have to update the first block. - if (_curBlock->first() == node) - _curBlock->setFirst(prev->next()); - - node->setPosition(kNodePositionDidOnBefore); - node = prev->next(); - - // `onBeforeInvoke()` and `onBeforeRet()` can only insert instructions. - ASMJIT_ASSERT(node->isInst()); - } - - // Necessary if something was inserted after `node`, but nothing before. - next = node->next(); - } - else { - // Change the position back to its original value. - node->setPosition(0); - } - } - - InstNode* inst = node->as(); - logNode(inst, kCodeIndentation); - - uint32_t controlType = BaseInst::kControlNone; - ib.reset(); - ASMJIT_PROPAGATE(static_cast(this)->onInst(inst, controlType, ib)); - - if (node->isInvoke()) { - ASMJIT_PROPAGATE(static_cast(this)->onInvoke(inst->as(), ib)); - } - - if (node->isFuncRet()) { - ASMJIT_PROPAGATE(static_cast(this)->onRet(inst->as(), ib)); - controlType = BaseInst::kControlReturn; - } - - if (controlType == BaseInst::kControlJump) { - uint32_t fixedRegCount = 0; - for (RATiedReg& tiedReg : ib) { - RAWorkReg* workReg = _pass->workRegById(tiedReg.workId()); - if (workReg->group() == BaseReg::kGroupGp) { - uint32_t useId = tiedReg.useId(); - if (useId == BaseReg::kIdBad) { - useId = _pass->_scratchRegIndexes[fixedRegCount++]; - tiedReg.setUseId(useId); - } - _curBlock->addExitScratchGpRegs(Support::bitMask(useId)); - } - } - } - - ASMJIT_PROPAGATE(_pass->assignRAInst(inst, _curBlock, ib)); - _blockRegStats.combineWith(ib._stats); - - if (controlType != BaseInst::kControlNone) { - // Support for conditional and unconditional jumps. - if (controlType == BaseInst::kControlJump || controlType == BaseInst::kControlBranch) { - _curBlock->setLast(node); - _curBlock->addFlags(RABlock::kFlagHasTerminator); - _curBlock->makeConstructed(_blockRegStats); - - if (!(inst->instOptions() & BaseInst::kOptionUnfollow)) { - // Jmp/Jcc/Call/Loop/etc... - uint32_t opCount = inst->opCount(); - const Operand* opArray = inst->operands(); - - // Cannot jump anywhere without operands. - if (ASMJIT_UNLIKELY(!opCount)) - return DebugUtils::errored(kErrorInvalidState); - - if (opArray[opCount - 1].isLabel()) { - // Labels are easy for constructing the control flow. - LabelNode* labelNode; - ASMJIT_PROPAGATE(cc()->labelNodeOf(&labelNode, opArray[opCount - 1].as