// This file is part of AsmJit project // // See asmjit.h or LICENSE.md for license and copyright information // SPDX-License-Identifier: Zlib #ifndef ASMJIT_CORE_API_CONFIG_H_INCLUDED #define ASMJIT_CORE_API_CONFIG_H_INCLUDED // AsmJit Library & ABI Version // ============================ //! \addtogroup asmjit_core //! \{ //! AsmJit library version in `(Major << 16) | (Minor << 8) | (Patch)` format. #define ASMJIT_LIBRARY_VERSION 0x010A00 /* 1.10.0 */ //! \def ASMJIT_ABI_NAMESPACE //! //! AsmJit ABI namespace is an inline namespace within \ref asmjit namespace. //! //! It's used to make sure that when user links to an incompatible version of AsmJit, it won't link. It has also some //! additional properties as well. When `ASMJIT_ABI_NAMESPACE` is defined by the user it would override the AsmJit //! default, which makes it possible to use use multiple AsmJit libraries within a single project, totally controlled //! by the users. This is useful especially in cases in which some of such library comes from a third party. #ifndef ASMJIT_ABI_NAMESPACE #define ASMJIT_ABI_NAMESPACE _abi_1_10 #endif //! \} // Global Dependencies // =================== #include #include #include // We really want std types as globals, not under 'std' namespace. #include #include #include #include #include #include #include #include #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) #include #endif // Build Options // ============= // NOTE: Doxygen cannot document macros that are not defined, that's why we have to define them and then undefine // them immediately, 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 //! Disables X86/X64 backends. #define ASMJIT_NO_X86 //! Disables AArch32 backends (both ARM and Thumb). #define ASMJIT_NO_AARCH32 //! Disables AArch64 backend. #define ASMJIT_NO_AARCH64 //! Disables non-host backends entirely (useful for JIT compilers to minimize the library size). #define ASMJIT_NO_FOREIGN //! Disables deprecated API at compile time (deprecated API won't be available). #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 asmjit::JitRuntime. #define ASMJIT_NO_JIT //! Disables \ref asmjit::Logger and \ref asmjit::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_BUILD_EMBNED #undef ASMJIT_BUILD_STATIC #undef ASMJIT_BUILD_DEBUG #undef ASMJIT_BUILD_RELEASE #undef ASMJIT_NO_X86 #undef ASMJIT_NO_FOREIGN // (keep ASMJIT_NO_DEPRECATED defined, we don't document deprecated APIs). #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_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 message("'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 // 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 // Target Architecture Detection // ============================= #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 #if defined(ASMJIT_NO_FOREIGN) #if !ASMJIT_ARCH_X86 && !defined(ASMJIT_NO_X86) #define ASMJIT_NO_X86 #endif #if !ASMJIT_ARCH_ARM && !defined(ASMJIT_NO_AARCH64) #define ASMJIT_NO_AARCH64 #endif #endif // 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 // API Decorators & C++ Extensions // =============================== //! \def ASMJIT_API //! //! A decorator that is used to decorate API that AsmJit exports when built as a shared library. // 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 //! \def ASMJIT_VIRTAPI //! //! 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_FORCE_INLINE inline __attribute__((__always_inline__)) #elif !defined(ASMJIT_BUILD_DEBUG) && defined(_MSC_VER) #define ASMJIT_FORCE_INLINE __forceinline #else #define ASMJIT_FORCE_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_MAYBE_UNUSED //! //! Expands to `[[maybe_unused]]` if supported or a compiler attribute instead. #if __cplusplus >= 201703L #define ASMJIT_MAYBE_UNUSED [[maybe_unused]] #elif defined(__GNUC__) #define ASMJIT_MAYBE_UNUSED __attribute__((unused)) #else #define ASMJIT_MAYBE_UNUSED #endif #if defined(__clang_major__) && __clang_major__ >= 4 && !defined(_DOXYGEN) // NOTE: Clang allows to apply this attribute to function arguments, which is what we want. Once GCC decides to // support this use, we will enable it for GCC as well. However, until that, it will be clang only, which is // what we need for static analysis. #define ASMJIT_NONNULL(FUNCTION_ARGUMENT) FUNCTION_ARGUMENT __attribute__((__nonnull__)) #else #define ASMJIT_NONNULL(FUNCTION_ARGUMENT) FUNCTION_ARGUMENT #endif //! \def ASMJIT_NOEXCEPT_TYPE //! //! Defined to `noexcept` in C++17 mode or nothing otherwise. Used by function typedefs. #if __cplusplus >= 201703L #define ASMJIT_NOEXCEPT_TYPE noexcept #else #define ASMJIT_NOEXCEPT_TYPE #endif //! \def ASMJIT_ASSUME(...) //! //! Macro that tells the C/C++ compiler that the expression `...` evaluates to true. //! //! This macro has two purposes: //! //! 1. Enable optimizations that would not be possible without the assumption. //! 2. Hint static analysis tools that a certain condition is true to prevent false positives. #if defined(__clang__) #define ASMJIT_ASSUME(...) __builtin_assume(__VA_ARGS__) #elif defined(__GNUC__) #define ASMJIT_ASSUME(...) do { if (!(__VA_ARGS__)) __builtin_unreachable(); } while (0) #elif defined(_MSC_VER) #define ASMJIT_ASSUME(...) __assume(__VA_ARGS__) #else #define ASMJIT_ASSUME(...) (void)0 #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 // Begin-Namespace & End-Namespace Macros // ====================================== #if defined _DOXYGEN #define ASMJIT_BEGIN_NAMESPACE namespace asmjit { #define ASMJIT_END_NAMESPACE } #elif defined(__clang__) #define ASMJIT_BEGIN_NAMESPACE \ namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ _Pragma("clang diagnostic push") \ _Pragma("clang diagnostic ignored \"-Wconstant-logical-operand\"") \ _Pragma("clang diagnostic ignored \"-Wunnamed-type-template-args\"") #define ASMJIT_END_NAMESPACE \ _Pragma("clang diagnostic pop") \ }} #elif defined(__GNUC__) && __GNUC__ == 4 #define ASMJIT_BEGIN_NAMESPACE \ namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") #define ASMJIT_END_NAMESPACE \ _Pragma("GCC diagnostic pop") \ }} #elif defined(__GNUC__) && __GNUC__ >= 8 #define ASMJIT_BEGIN_NAMESPACE \ namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"") #define ASMJIT_END_NAMESPACE \ _Pragma("GCC diagnostic pop") \ }} #elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) #define ASMJIT_BEGIN_NAMESPACE \ namespace asmjit { inline namespace ASMJIT_ABI_NAMESPACE { \ __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 { inline namespace ASMJIT_ABI_NAMESPACE { #define ASMJIT_END_NAMESPACE }} #endif #define ASMJIT_BEGIN_SUB_NAMESPACE(NAMESPACE) \ ASMJIT_BEGIN_NAMESPACE \ namespace NAMESPACE { #define ASMJIT_END_SUB_NAMESPACE \ } \ ASMJIT_END_NAMESPACE // C++ Utilities // ============= #define ASMJIT_NONCOPYABLE(Type) \ Type(const Type& other) = delete; \ Type& operator=(const Type& other) = delete; #define ASMJIT_NONCONSTRUCTIBLE(Type) \ Type() = delete; \ Type(const Type& other) = delete; \ Type& operator=(const Type& other) = delete; //! \def ASMJIT_DEFINE_ENUM_FLAGS(T) //! //! Defines bit operations for enumeration flags. #ifdef _DOXYGEN #define ASMJIT_DEFINE_ENUM_FLAGS(T) #else #define ASMJIT_DEFINE_ENUM_FLAGS(T) \ static ASMJIT_FORCE_INLINE constexpr T operator~(T a) noexcept { \ return T(~(std::underlying_type::type)(a)); \ } \ \ static ASMJIT_FORCE_INLINE constexpr T operator|(T a, T b) noexcept { \ return T((std::underlying_type::type)(a) | \ (std::underlying_type::type)(b)); \ } \ static ASMJIT_FORCE_INLINE constexpr T operator&(T a, T b) noexcept { \ return T((std::underlying_type::type)(a) & \ (std::underlying_type::type)(b)); \ } \ static ASMJIT_FORCE_INLINE constexpr T operator^(T a, T b) noexcept { \ return T((std::underlying_type::type)(a) ^ \ (std::underlying_type::type)(b)); \ } \ \ static ASMJIT_FORCE_INLINE T& operator|=(T& a, T b) noexcept { \ a = T((std::underlying_type::type)(a) | \ (std::underlying_type::type)(b)); \ return a; \ } \ static ASMJIT_FORCE_INLINE T& operator&=(T& a, T b) noexcept { \ a = T((std::underlying_type::type)(a) & \ (std::underlying_type::type)(b)); \ return a; \ } \ static ASMJIT_FORCE_INLINE T& operator^=(T& a, T b) noexcept { \ a = T((std::underlying_type::type)(a) ^ \ (std::underlying_type::type)(b)); \ return a; \ } #endif //! \def ASMJIT_DEFINE_ENUM_COMPARE(T) //! //! Defines comparison operations for enumeration flags. #if defined(_DOXYGEN) || (defined(_MSC_VER) && _MSC_VER <= 1900) #define ASMJIT_DEFINE_ENUM_COMPARE(T) #else #define ASMJIT_DEFINE_ENUM_COMPARE(T) \ static ASMJIT_FORCE_INLINE bool operator<(T a, T b) noexcept { \ return (std::underlying_type::type)(a) < (std::underlying_type::type)(b); \ } \ static ASMJIT_FORCE_INLINE bool operator<=(T a, T b) noexcept { \ return (std::underlying_type::type)(a) <= (std::underlying_type::type)(b); \ } \ static ASMJIT_FORCE_INLINE bool operator>(T a, T b) noexcept { \ return (std::underlying_type::type)(a) > (std::underlying_type::type)(b); \ } \ static ASMJIT_FORCE_INLINE bool operator>=(T a, T b) noexcept { \ return (std::underlying_type::type)(a) >= (std::underlying_type::type)(b); \ } #endif // Cleanup Api-Config Specific Macros // ================================== #undef ASMJIT_CXX_GNU #undef ASMJIT_CXX_MAKE_VER #endif // ASMJIT_CORE_API_CONFIG_H_INCLUDED