vkdoom_m/asmjit/asmjit/base/globals.h
2018-08-12 02:11:13 +02:00

341 lines
11 KiB
C++

// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_GLOBALS_H
#define _ASMJIT_BASE_GLOBALS_H
// [Dependencies]
#include "../asmjit_build.h"
// [Api-Begin]
#include "../asmjit_apibegin.h"
namespace asmjit {
//! \addtogroup asmjit_base
//! \{
// ============================================================================
// [asmjit::Globals]
// ============================================================================
enum { kInvalidValue = 0xFFFFFFFFU };
//! AsmJit globals.
namespace Globals {
//! Invalid index
//!
//! Invalid index is the last possible index that is never used in practice. In
//! AsmJit it is used exclusively with strings to indicate the the length of the
//! string is not known and has to be determined.
static const size_t kInvalidIndex = ~static_cast<size_t>(0);
//! Invalid base address.
static const uint64_t kNoBaseAddress = ~static_cast<uint64_t>(0);
//! Global definitions.
ASMJIT_ENUM(Defs) {
//! Invalid register id.
kInvalidRegId = 0xFF,
//! Host memory allocator overhead.
kAllocOverhead = static_cast<int>(sizeof(intptr_t) * 4),
//! Aggressive growing strategy threshold.
kAllocThreshold = 8192 * 1024
};
ASMJIT_ENUM(Limits) {
//! Count of register kinds that are important to Function API and CodeCompiler.
//! The target architecture can define more register kinds for special registers,
//! but these will never map to virtual registers and will never be used to pass
//! and return function arguments and function return values, respectively.
kMaxVRegKinds = 4,
//! Maximum number of physical registers of all kinds of all supported
//! architectures. This is only important for \ref CodeCompiler and its
//! \ref RAPass (register allocator pass).
//!
//! NOTE: The distribution of these registers is architecture specific.
kMaxPhysRegs = 64,
//! Maximum alignment.
kMaxAlignment = 64,
//! Maximum label or symbol length in bytes (take into consideration that a
//! single UTF-8 character can take more than single byte to encode it).
kMaxLabelLength = 2048
};
} // Globals namespace
// ============================================================================
// [asmjit::Error]
// ============================================================================
//! AsmJit error type (uint32_t).
typedef uint32_t Error;
//! AsmJit error codes.
ASMJIT_ENUM(ErrorCode) {
//! No error (success).
//!
//! This is default state and state you want.
kErrorOk = 0,
//! Heap memory allocation failed.
kErrorNoHeapMemory,
//! Virtual memory allocation failed.
kErrorNoVirtualMemory,
//! 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
//! not be underestimated.
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,
//! CodeHolder can't have attached more than one \ref Assembler at a time.
kErrorSlotOccupied,
//! No code generated.
//!
//! Returned by runtime if the \ref CodeHolder contains no code.
kErrorNoCodeGenerated,
//! Code generated is larger than allowed.
kErrorCodeTooLarge,
//! Attempt to use uninitialized label.
kErrorInvalidLabel,
//! Label index overflow - a single `Assembler` instance can hold more than
//! 2 billion labels (2147483391 to be exact). If there is an attempt to
//! create more labels this error is returned.
kErrorLabelIndexOverflow,
//! 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 `CodeHolder::newNamedLabelId()` was invalid.
kErrorInvalidParentLabel,
//! Parent id specified for a non-local (global) label.
kErrorNonLocalLabelCantHaveParent,
//! Relocation index overflow.
kErrorRelocIndexOverflow,
//! Invalid relocation entry.
kErrorInvalidRelocEntry,
//! Invalid instruction.
kErrorInvalidInstruction,
//! Invalid register type.
kErrorInvalidRegType,
//! Invalid register kind.
kErrorInvalidRegKind,
//! Invalid register's physical id.
kErrorInvalidPhysId,
//! Invalid register's virtual id.
kErrorInvalidVirtId,
//! Invalid prefix combination.
kErrorInvalidPrefixCombination,
//! Invalid LOCK prefix.
kErrorInvalidLockPrefix,
//! Invalid XACQUIRE prefix.
kErrorInvalidXAcquirePrefix,
//! Invalid XACQUIRE prefix.
kErrorInvalidXReleasePrefix,
//! Invalid REP prefix.
kErrorInvalidRepPrefix,
//! Invalid REX prefix.
kErrorInvalidRexPrefix,
//! Invalid mask register (not 'k').
kErrorInvalidKMaskReg,
//! 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 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 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 (TypeId::kF80).
kErrorInvalidUseOfF80,
//! Some registers in the instruction muse be consecutive (some ARM and AVX512 neural-net instructions).
kErrorNotConsecutiveRegs,
//! AsmJit requires a physical register, but no one is available.
kErrorNoMorePhysRegs,
//! A variable has been assigned more than once to a function argument (CodeCompiler).
kErrorOverlappedRegs,
//! Invalid register to hold stack arguments offset.
kErrorOverlappingStackRegWithRegArg,
//! Count of AsmJit error codes.
kErrorCount
};
// ============================================================================
// [asmjit::Internal]
// ============================================================================
namespace Internal {
#if defined(ASMJIT_CUSTOM_ALLOC) && \
defined(ASMJIT_CUSTOM_REALLOC) && \
defined(ASMJIT_CUSTOM_FREE)
static ASMJIT_INLINE void* allocMemory(size_t size) noexcept { return ASMJIT_CUSTOM_ALLOC(size); }
static ASMJIT_INLINE void* reallocMemory(void* p, size_t size) noexcept { return ASMJIT_CUSTOM_REALLOC(p, size); }
static ASMJIT_INLINE void releaseMemory(void* p) noexcept { ASMJIT_CUSTOM_FREE(p); }
#elif !defined(ASMJIT_CUSTOM_ALLOC) && \
!defined(ASMJIT_CUSTOM_REALLOC) && \
!defined(ASMJIT_CUSTOM_FREE)
static ASMJIT_INLINE void* allocMemory(size_t size) noexcept { return ::malloc(size); }
static ASMJIT_INLINE void* reallocMemory(void* p, size_t size) noexcept { return ::realloc(p, size); }
static ASMJIT_INLINE void releaseMemory(void* p) noexcept { ::free(p); }
#else
# error "[asmjit] You must provide either none or all of ASMJIT_CUSTOM_[ALLOC|REALLOC|FREE]"
#endif
//! Cast designed to cast between function and void* pointers.
template<typename Dst, typename Src>
static ASMJIT_INLINE Dst ptr_cast(Src p) noexcept { return (Dst)p; }
} // Internal namespace
template<typename Func>
static ASMJIT_INLINE Func ptr_as_func(void* func) noexcept { return Internal::ptr_cast<Func, void*>(func); }
template<typename Func>
static ASMJIT_INLINE void* func_as_ptr(Func func) noexcept { return Internal::ptr_cast<void*, Func>(func); }
// ============================================================================
// [asmjit::DebugUtils]
// ============================================================================
namespace DebugUtils {
//! 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 ASMJIT_INLINE Error errored(Error err) noexcept { return err; }
//! Get 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 assertions put a breakpoint at assertionFailed()
//! function (asmjit/base/globals.cpp) and check the call stack to locate the
//! failing code.
ASMJIT_API void ASMJIT_NORETURN assertionFailed(const char* file, int line, const char* msg) noexcept;
#if defined(ASMJIT_DEBUG)
# define ASMJIT_ASSERT(exp) \
do { \
if (ASMJIT_LIKELY(exp)) \
break; \
::asmjit::DebugUtils::assertionFailed(__FILE__, __LINE__, #exp); \
} while (0)
# define ASMJIT_NOT_REACHED() \
do { \
::asmjit::DebugUtils::assertionFailed(__FILE__, __LINE__, \
"ASMJIT_NOT_REACHED has been reached"); \
ASMJIT_ASSUME(0); \
} while (0)
#else
# define ASMJIT_ASSERT(exp) ASMJIT_NOP
# define ASMJIT_NOT_REACHED() ASMJIT_ASSUME(0)
#endif // DEBUG
//! \internal
//!
//! Used by AsmJit to propagate a possible `Error` produced by `...` to the caller.
#define ASMJIT_PROPAGATE(...) \
do { \
::asmjit::Error _err = __VA_ARGS__; \
if (ASMJIT_UNLIKELY(_err)) \
return _err; \
} while (0)
} // DebugUtils namespace
// ============================================================================
// [asmjit::Init / NoInit]
// ============================================================================
#if !defined(ASMJIT_DOCGEN)
struct _Init {};
static const _Init Init = {};
struct _NoInit {};
static const _NoInit NoInit = {};
#endif // !ASMJIT_DOCGEN
//! \}
} // asmjit namespace
// [Api-End]
#include "../asmjit_apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_GLOBALS_H