diff --git a/CMakeLists.txt b/CMakeLists.txt index 696ef71..73d2178 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ if (NOT CMAKE_PROJECT_NAME OR "${CMAKE_PROJECT_NAME}" STREQUAL "asmjit") endif() include(CheckCXXCompilerFlag) +INCLUDE(CheckCXXSourceCompiles) include(GNUInstallDirs) # AsmJit - Deprecated @@ -35,10 +36,12 @@ endif() # AsmJit - Configuration # ====================== +# AsmJit testing. if (NOT DEFINED ASMJIT_TEST) set(ASMJIT_TEST FALSE) endif() +# AsmJit build options if (NOT DEFINED ASMJIT_EMBED) set(ASMJIT_EMBED FALSE) endif() @@ -51,6 +54,15 @@ if (NOT DEFINED ASMJIT_SANITIZE) set(ASMJIT_SANITIZE FALSE) endif() +if (NOT DEFINED ASMJIT_NO_NATVIS) + set(ASMJIT_NO_NATVIS FALSE) +endif() + +if (NOT DEFINED ASMJIT_NO_CUSTOM_FLAGS) + set(ASMJIT_NO_CUSTOM_FLAGS FALSE) +endif() + +# AsmJit backends selection. if (NOT DEFINED ASMJIT_NO_X86) set(ASMJIT_NO_X86 FALSE) endif() @@ -63,12 +75,41 @@ if (NOT DEFINED ASMJIT_NO_FOREIGN) set(ASMJIT_NO_FOREIGN FALSE) endif() -if (NOT DEFINED ASMJIT_NO_NATVIS) - set(ASMJIT_NO_NATVIS FALSE) +# AsmJit features selection. +if (NOT DEFINED ASMJIT_NO_DEPRECATED) + set(ASMJIT_NO_DEPRECATED FALSE) endif() -if (NOT DEFINED ASMJIT_NO_CUSTOM_FLAGS) - set(ASMJIT_NO_CUSTOM_FLAGS FALSE) +if (NOT DEFINED ASMJIT_NO_SHM_OPEN) + set(ASMJIT_NO_SHM_OPEN FALSE) +endif() + +if (NOT DEFINED ASMJIT_NO_JIT) + set(ASMJIT_NO_JIT FALSE) +endif() + +if (NOT DEFINED ASMJIT_NO_TEXT) + set(ASMJIT_NO_TEXT ${ASMJIT_NO_TEXT}) +endif() + +if (NOT DEFINED ASMJIT_NO_LOGGING) + set(ASMJIT_NO_LOGGING FALSE) +endif() + +if (NOT DEFINED ASMJIT_NO_VALIDATION) + set(ASMJIT_NO_VALIDATION ${ASMJIT_NO_VALIDATION}) +endif() + +if (NOT DEFINED ASMJIT_NO_INTROSPECTION) + set(ASMJIT_NO_INTROSPECTION ${ASMJIT_NO_INTROSPECTION}) +endif() + +if (NOT DEFINED ASMJIT_NO_BUILDER) + set(ASMJIT_NO_BUILDER FALSE) +endif() + +if (NOT DEFINED ASMJIT_NO_COMPILER) + set(ASMJIT_NO_BUILDER ${ASMJIT_NO_BUILDER}) endif() # EMBED implies STATIC. @@ -76,16 +117,28 @@ 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_NO_X86 "${ASMJIT_NO_X86}" CACHE BOOL "Disable X86/X64 backend") -set(ASMJIT_NO_AARCH64 "${ASMJIT_NO_AARCH64}" CACHE BOOL "Disable AArch64 backend") -set(ASMJIT_NO_FOREIGN "${ASMJIT_NO_FOREIGN}" CACHE BOOL "Disable all foreign architectures (enables only a native architecture)") -set(ASMJIT_NO_NATVIS "${ASMJIT_NO_NATVIS}" CACHE BOOL "Disable natvis support (embedding asmjit.natvis in PDB)") -set(ASMJIT_NO_CUSTOM_FLAGS "${ASMJIT_NO_CUSTOM_FLAGS}" CACHE BOOL "Disable extra compilation flags added by AsmJit to its targets") +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_NO_NATVIS "${ASMJIT_NO_NATVIS}" CACHE BOOL "Disable natvis support (embedding asmjit.natvis in PDB)") +set(ASMJIT_NO_CUSTOM_FLAGS "${ASMJIT_NO_CUSTOM_FLAGS}" CACHE BOOL "Disable extra compilation flags added by AsmJit to its targets") + +set(ASMJIT_NO_X86 "${ASMJIT_NO_X86}" CACHE BOOL "Disable X86/X64 backend") +set(ASMJIT_NO_AARCH64 "${ASMJIT_NO_AARCH64}" CACHE BOOL "Disable AArch64 backend") +set(ASMJIT_NO_FOREIGN "${ASMJIT_NO_FOREIGN}" CACHE BOOL "Disable all foreign architectures (enables only a target architecture)") + +set(ASMJIT_NO_DEPRECATED "${ASMJIT_NO_DEPRECATED}" CACHE BOOL "Disable deprecated API at build time") +set(ASMJIT_NO_SHM_OPEN "${ASMJIT_NO_SHM_OPEN}" CACHE BOOL "Disable the use of shm_open() even on platforms where it's supported") +set(ASMJIT_NO_JIT "${ASMJIT_NO_JIT}" CACHE BOOL "Disable VirtMem, JitAllocator, and JitRuntime at build time") +set(ASMJIT_NO_TEXT "${ASMJIT_NO_TEXT}" CACHE BOOL "Disable textual representation of instructions, enums, cpu features, ...") +set(ASMJIT_NO_LOGGING "${ASMJIT_NO_LOGGING}" CACHE BOOL "Disable logging features at build time") +set(ASMJIT_NO_VALIDATION "${ASMJIT_NO_VALIDATION}" CACHE BOOL "Disable instruction validation API at build time") +set(ASMJIT_NO_INTROSPECTION "${ASMJIT_NO_INTROSPECTION}" CACHE BOOL "Disable instruction introspection API at build time") +set(ASMJIT_NO_BUILDER "${ASMJIT_NO_BUILDER}" CACHE BOOL "Disable Builder emitter at build time") +set(ASMJIT_NO_COMPILER "${ASMJIT_NO_COMPILER}" CACHE BOOL "Disable Compiler emitter at build time") # AsmJit - Project # ================ @@ -155,7 +208,7 @@ function(asmjit_add_target target target_type) 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}) + foreach(link_flag ${ASMJIT_PRIVATE_LFLAGS}) set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${link_flag}") endforeach() @@ -183,6 +236,7 @@ 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_PRIVATE_LFLAGS "") # Private linker flags. set(ASMJIT_SANITIZE_CFLAGS "") # Compiler flags required by currently enabled sanitizers. set(ASMJIT_SANITIZE_LFLAGS "") # Linker flags required by currently enabled sanitizers. @@ -247,13 +301,44 @@ if (ASMJIT_SANITIZE) endif() endif() -# Do not link to pthread on Android as it's part of C runtime. -if (NOT WIN32 AND NOT ANDROID) - list(APPEND ASMJIT_DEPS pthread) -endif() +if (NOT WIN32) + # Dependency: libc is always required. + list(APPEND ASMJIT_DEPS c) -if ("${CMAKE_SYSTEM_NAME}" MATCHES "Linux" OR "${CMAKE_SYSTEM_NAME}" MATCHES "NetBSD") - list(APPEND ASMJIT_DEPS rt) + # Dependency: pthread (required so AsmJit can use pthread_lock). + if (NOT "${CMAKE_SYSTEM_NAME}" MATCHES "^(Android)$") + check_cxx_source_compiles(" + #include + int main() { + pthread_mutex_t m; + pthread_mutex_init(&m, nullptr); + return pthread_mutex_destroy(&m); + } + " ASMJIT_LIBC_HAS_PTHREAD) + if (ASMJIT_LIBC_HAS_PTHREAD) + message("-- Dependency: pthread provided by libc (not linking to libpthread)") + else () + message("-- Dependency: pthread not provided by libc, linking to libpthread") + list(APPEND ASMJIT_DEPS pthread) + endif() + endif() + + # Dependency: shm_open (required so AsmJit can use shm_open on supported platforms). + if ("${CMAKE_SYSTEM_NAME}" MATCHES "^(Linux|NetBSD)$" AND NOT ASMJIT_NO_SHM_OPEN) + check_cxx_source_compiles(" + #include + int main() { + const char file_name[1] {}; + return shm_open(file_name, 0, 0); + } + " ASMJIT_LIBC_HAS_SHM_OPEN) + if (ASMJIT_LIBC_HAS_SHM_OPEN) + message("-- Dependency: shm_open provided by libc (not linking to librt)") + else () + message("-- Dependency: shm_open not provided by libc, linking to librt") + list(APPEND ASMJIT_DEPS rt) + endif() + endif() endif() set(ASMJIT_LIBS ${ASMJIT_DEPS}) @@ -276,11 +361,12 @@ foreach(build_option ASMJIT_STATIC ASMJIT_NO_FOREIGN # AsmJit features selection. ASMJIT_NO_DEPRECATED + ASMJIT_NO_SHM_OPEN ASMJIT_NO_JIT + ASMJIT_NO_TEXT ASMJIT_NO_LOGGING ASMJIT_NO_BUILDER ASMJIT_NO_COMPILER - ASMJIT_NO_TEXT ASMJIT_NO_VALIDATION ASMJIT_NO_INTROSPECTION) if (${build_option}) diff --git a/src/asmjit/core/builder.h b/src/asmjit/core/builder.h index e967d44..c7aca96 100644 --- a/src/asmjit/core/builder.h +++ b/src/asmjit/core/builder.h @@ -1432,7 +1432,7 @@ public: //! //! 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. - ASMJIT_API virtual Error run(Zone* zone, Logger* logger) = 0; + ASMJIT_API virtual Error run(Zone* zone, Logger* logger); //! \} }; diff --git a/src/asmjit/core/compiler.h b/src/asmjit/core/compiler.h index e0e15c9..5897a1b 100644 --- a/src/asmjit/core/compiler.h +++ b/src/asmjit/core/compiler.h @@ -712,7 +712,7 @@ public: ASMJIT_API Error run(Zone* zone, Logger* logger) override; //! Called once per `FuncNode`. - ASMJIT_API virtual Error runOnFunction(Zone* zone, Logger* logger, FuncNode* func) = 0; + ASMJIT_API virtual Error runOnFunction(Zone* zone, Logger* logger, FuncNode* func); //! \} }; diff --git a/src/asmjit/core/emithelper_p.h b/src/asmjit/core/emithelper_p.h index f597422..0f4a2f3 100644 --- a/src/asmjit/core/emithelper_p.h +++ b/src/asmjit/core/emithelper_p.h @@ -31,12 +31,12 @@ public: //! slot. This function does not handle register conversion. virtual Error emitRegMove( const Operand_& dst_, - const Operand_& src_, TypeId typeId, const char* comment = nullptr) = 0; + const Operand_& src_, TypeId typeId, const char* comment = nullptr); //! Emits swap between two registers. virtual Error emitRegSwap( const BaseReg& a, - const BaseReg& b, const char* comment = nullptr) = 0; + const BaseReg& b, const char* comment = nullptr); //! Emits move from a function argument (either register or stack) to a register. //! @@ -45,7 +45,7 @@ public: //! (for example conversion from K to MMX on X86/X64) will fail. virtual Error emitArgMove( const BaseReg& dst_, TypeId dstTypeId, - const Operand_& src_, TypeId srcTypeId, const char* comment = nullptr) = 0; + const Operand_& src_, TypeId srcTypeId, const char* comment = nullptr); Error emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args); }; diff --git a/src/asmjit/core/emitter.cpp b/src/asmjit/core/emitter.cpp index fd036b1..b9b2f89 100644 --- a/src/asmjit/core/emitter.cpp +++ b/src/asmjit/core/emitter.cpp @@ -289,6 +289,12 @@ Error BaseEmitter::embedDataArray(TypeId typeId, const void* data, size_t itemCo return DebugUtils::errored(kErrorInvalidState); } +// [[pure virtual]] +Error BaseEmitter::embedConstPool(const Label& label, const ConstPool& pool) { + DebugUtils::unused(label, pool); + return DebugUtils::errored(kErrorInvalidState); +} + // [[pure virtual]] Error BaseEmitter::embedLabel(const Label& label, size_t dataSize) { DebugUtils::unused(label, dataSize); @@ -305,7 +311,7 @@ Error BaseEmitter::embedLabelDelta(const Label& label, const Label& base, size_t // ===================== // [[pure virtual]] -Error comment(const char* data, size_t size = SIZE_MAX) { +Error BaseEmitter::comment(const char* data, size_t size) { DebugUtils::unused(data, size); return DebugUtils::errored(kErrorInvalidState); } diff --git a/src/asmjit/core/emitter.h b/src/asmjit/core/emitter.h index e3cdd56..a836790 100644 --- a/src/asmjit/core/emitter.h +++ b/src/asmjit/core/emitter.h @@ -557,7 +557,7 @@ public: //! \name Sections //! \{ - ASMJIT_API virtual Error section(Section* section) = 0; + ASMJIT_API virtual Error section(Section* section); //! \} @@ -565,9 +565,9 @@ public: //! \{ //! Creates a new label. - ASMJIT_API virtual Label newLabel() = 0; + ASMJIT_API virtual Label newLabel(); //! Creates a new named label. - ASMJIT_API virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) = 0; + ASMJIT_API virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId); //! Creates a new anonymous label with a name, which can only be used for debugging purposes. ASMJIT_INLINE_NODEBUG Label newAnonymousLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kAnonymous); } @@ -585,7 +585,7 @@ public: //! Binds the `label` to the current position of the current section. //! //! \note Attempt to bind the same label multiple times will return an error. - ASMJIT_API virtual Error bind(const Label& label) = 0; + ASMJIT_API virtual Error bind(const Label& label); //! Tests whether the label `id` is valid (i.e. registered). ASMJIT_API bool isLabelValid(uint32_t labelId) const noexcept; @@ -637,7 +637,7 @@ public: //! \cond INTERNAL //! Emits an instruction - all 6 operands must be defined. - ASMJIT_API virtual Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt) = 0; + ASMJIT_API virtual Error _emit(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_* oExt); //! Emits instruction having operands stored in array. ASMJIT_API virtual Error _emitOpArray(InstId instId, const Operand_* operands, size_t opCount); //! \endcond @@ -661,7 +661,7 @@ public: //! 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. The `alignment` argument specifies alignment in bytes, so for example when //! it's `32` it means that the code buffer will be aligned to `32` bytes. - ASMJIT_API virtual Error align(AlignMode alignMode, uint32_t alignment) = 0; + ASMJIT_API virtual Error align(AlignMode alignMode, uint32_t alignment); //! \} @@ -669,7 +669,7 @@ public: //! \{ //! Embeds raw data into the \ref CodeBuffer. - ASMJIT_API virtual Error embed(const void* data, size_t dataSize) = 0; + ASMJIT_API virtual Error embed(const void* data, size_t dataSize); //! Embeds a typed data array. //! @@ -680,7 +680,7 @@ public: //! //! - 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. - ASMJIT_API virtual Error embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1) = 0; + ASMJIT_API virtual Error embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1); //! Embeds int8_t `value` repeated by `repeatCount`. ASMJIT_INLINE_NODEBUG Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt8, &value, 1, repeatCount); } @@ -707,17 +707,17 @@ public: //! 1. Aligns by using AlignMode::kData to the minimum `pool` alignment. //! 2. Binds the ConstPool label so it's bound to an aligned location. //! 3. Emits ConstPool content. - ASMJIT_API virtual Error embedConstPool(const Label& label, const ConstPool& pool) = 0; + ASMJIT_API virtual Error embedConstPool(const Label& label, const ConstPool& pool); //! 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). - ASMJIT_API virtual Error embedLabel(const Label& label, size_t dataSize = 0) = 0; + ASMJIT_API virtual Error embedLabel(const Label& label, size_t dataSize = 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. - ASMJIT_API virtual Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0) = 0; + ASMJIT_API virtual Error embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0); //! \} @@ -725,7 +725,7 @@ public: //! \{ //! Emits a comment stored in `data` with an optional `size` parameter. - ASMJIT_API virtual Error comment(const char* data, size_t size = SIZE_MAX) = 0; + ASMJIT_API virtual Error comment(const char* data, size_t size = SIZE_MAX); //! Emits a formatted comment specified by `fmt` and variable number of arguments. ASMJIT_API Error commentf(const char* fmt, ...); diff --git a/src/asmjit/core/errorhandler.h b/src/asmjit/core/errorhandler.h index d2c37b3..a1a2dd2 100644 --- a/src/asmjit/core/errorhandler.h +++ b/src/asmjit/core/errorhandler.h @@ -215,7 +215,7 @@ public: //! 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. - ASMJIT_API virtual void handleError(Error err, const char* message, BaseEmitter* origin) = 0; + ASMJIT_API virtual void handleError(Error err, const char* message, BaseEmitter* origin); //! \} }; diff --git a/src/asmjit/core/logger.h b/src/asmjit/core/logger.h index 0e28823..54c169f 100644 --- a/src/asmjit/core/logger.h +++ b/src/asmjit/core/logger.h @@ -90,7 +90,7 @@ public: //! 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. - ASMJIT_API virtual Error _log(const char* data, size_t size) noexcept = 0; + ASMJIT_API virtual Error _log(const char* data, size_t size) noexcept; //! Logs string `str`, which is either null terminated or having size `size`. ASMJIT_INLINE_NODEBUG Error log(const char* data, size_t size = SIZE_MAX) noexcept { return _log(data, size); } diff --git a/src/asmjit/core/rapass_p.h b/src/asmjit/core/rapass_p.h index 2e81221..90d4ae4 100644 --- a/src/asmjit/core/rapass_p.h +++ b/src/asmjit/core/rapass_p.h @@ -945,7 +945,7 @@ public: //! analysis and register allocation. //! //! Use `RACFGBuilderT` template that provides the necessary boilerplate. - virtual Error buildCFG() noexcept = 0; + virtual Error buildCFG() noexcept; //! Called after the CFG is built. Error initSharedAssignments(const ZoneVector& sharedAssignmentsMap) noexcept; @@ -1133,7 +1133,7 @@ public: //! \{ Error rewrite() noexcept; - virtual Error _rewrite(BaseNode* first, BaseNode* stop) noexcept = 0; + virtual Error _rewrite(BaseNode* first, BaseNode* stop) noexcept; //! \} @@ -1153,13 +1153,13 @@ public: //! \name Emit //! \{ - virtual Error emitMove(uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept = 0; - virtual Error emitSwap(uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept = 0; + virtual Error emitMove(uint32_t workId, uint32_t dstPhysId, uint32_t srcPhysId) noexcept; + virtual Error emitSwap(uint32_t aWorkId, uint32_t aPhysId, uint32_t bWorkId, uint32_t bPhysId) noexcept; - virtual Error emitLoad(uint32_t workId, uint32_t dstPhysId) noexcept = 0; - virtual Error emitSave(uint32_t workId, uint32_t srcPhysId) noexcept = 0; + virtual Error emitLoad(uint32_t workId, uint32_t dstPhysId) noexcept; + virtual Error emitSave(uint32_t workId, uint32_t srcPhysId) noexcept; - virtual Error emitJump(const Label& label) noexcept = 0; + virtual Error emitJump(const Label& label) noexcept; virtual Error emitPreCall(InvokeNode* invokeNode) noexcept; //! \} diff --git a/src/asmjit/core/virtmem.cpp b/src/asmjit/core/virtmem.cpp index d4d966e..e59a890 100644 --- a/src/asmjit/core/virtmem.cpp +++ b/src/asmjit/core/virtmem.cpp @@ -81,7 +81,7 @@ #endif // Android NDK doesn't provide `shm_open()` and `shm_unlink()`. - #if !defined(__BIONIC__) + #if !defined(__BIONIC__) && !defined(ASMJIT_NO_SHM_OPEN) #define ASMJIT_HAS_SHM_OPEN #endif