- Major documentation reorganization of AsmJit (still far from perfection)

- Documentation - removed verbose @brief and switched to markdown syntax which Doxygen supports.
- Added inline documentation to AVX/AVX2 instructions.
- Added more documentation notes to utility classes.
- Modified documentation groups to be compatible with the new code layout (base/x86).

- Renamed VirtualMemoryManager to VMemMgr.
- Removed MemoryManager interface (not needed).
- Changed JitRuntime to always create a new isolated VMemMgr instance.
- Fixed WinRemoteRuntime to work with the new changes.

- Added missing insertps instruction to database, assembler and compiler.
- Moved global functions in x86cpuinfo to CpuUtil class.

- Should notify Issue #10
This commit is contained in:
kobalicekp
2014-05-04 23:11:12 +02:00
parent bceaebdbe3
commit f1ce2383ba
64 changed files with 10013 additions and 8908 deletions
-2
View File
@@ -234,8 +234,6 @@ AsmJit_AddSource(ASMJIT_SRC asmjit/base
lock.h
logger.cpp
logger.h
memorymanager.cpp
memorymanager.h
podlist.h
podvector.cpp
podvector.h
+27 -1
View File
@@ -269,6 +269,8 @@ static void opcode(asmjit::host::Assembler& a) {
a.xor_(intptr_gp0, 0);
// Fpu.
a.nop();
a.f2xm1();
a.fabs();
a.fadd(fp0, fpx);
@@ -399,6 +401,8 @@ static void opcode(asmjit::host::Assembler& a) {
a.fyl2xp1();
// MMX/MMX-EXT.
a.nop();
a.movd(ptr_gp0, mm7);
a.movd(eax, mm7);
a.movd(mm0, ptr_gp0);
@@ -501,6 +505,8 @@ static void opcode(asmjit::host::Assembler& a) {
a.emms();
// 3DNOW!
a.nop();
a.pf2id(mm0, mm7);
a.pf2id(mm0, ptr_gp0);
a.pf2iw(mm0, mm7);
@@ -550,6 +556,8 @@ static void opcode(asmjit::host::Assembler& a) {
a.femms();
// SSE.
a.nop();
a.addps(xmm0, xmm7);
a.addps(xmm0, ptr_gp0);
a.addss(xmm0, xmm7);
@@ -675,6 +683,8 @@ static void opcode(asmjit::host::Assembler& a) {
a.xorps(xmm0, ptr_gp0);
// SSE2.
a.nop();
a.addpd(xmm0, xmm7);
a.addpd(xmm0, ptr_gp0);
a.addsd(xmm0, xmm7);
@@ -922,7 +932,9 @@ static void opcode(asmjit::host::Assembler& a) {
a.xorpd(xmm0, xmm7);
a.xorpd(xmm0, ptr_gp0);
// SSE3/SSSE3/SSE4.1/SSE4.2.
// SSE3.
a.nop();
a.addsubpd(xmm0, xmm7);
a.addsubpd(xmm0, ptr_gp0);
a.addsubps(xmm0, xmm7);
@@ -945,6 +957,10 @@ static void opcode(asmjit::host::Assembler& a) {
a.movsldup(xmm0, xmm7);
a.movsldup(xmm0, ptr_gp0);
a.mwait();
// SSSE3.
a.nop();
a.psignb(mm0, mm7);
a.psignb(mm0, ptr_gp0);
a.psignb(xmm0, xmm7);
@@ -1009,6 +1025,10 @@ static void opcode(asmjit::host::Assembler& a) {
a.palignr(mm0, ptr_gp0, 0);
a.palignr(xmm0, xmm0, 0);
a.palignr(xmm0, ptr_gp0, 0);
// SSE4.1.
a.nop();
a.blendpd(xmm0, xmm0, 0);
a.blendpd(xmm0, ptr_gp0, 0);
a.blendps(xmm0, xmm0, 0);
@@ -1023,6 +1043,8 @@ static void opcode(asmjit::host::Assembler& a) {
a.dpps(xmm0, ptr_gp0, 0);
a.extractps(gp0, xmm0, 0);
a.extractps(ptr_gp0, xmm0, 0);
a.insertps(xmm0, xmm1, 0);
a.insertps(xmm0, ptr_gp0, 0);
a.movntdqa(xmm0, ptr_gp0);
a.mpsadbw(xmm0, xmm0, 0);
a.mpsadbw(xmm0, ptr_gp0, 0);
@@ -1104,6 +1126,10 @@ static void opcode(asmjit::host::Assembler& a) {
a.roundpd(xmm0, ptr_gp0, 0);
a.roundsd(xmm0, xmm0, 0);
a.roundsd(xmm0, ptr_gp0, 0);
// SSE4.2.
a.nop();
a.pcmpestri(xmm0, xmm0, 0);
a.pcmpestri(xmm0, ptr_gp0, 0);
a.pcmpestrm(xmm0, xmm0, 0);
+16 -13
View File
@@ -27,8 +27,8 @@ static void gen(void* a, void* b, int i) {
static void verify(void* a, void* b) {
int ai = *(int*)a;
int bi = *(int*)b;
if (ai != bi || memcmp(a, b, ai) != 0)
{
if (ai != bi || ::memcmp(a, b, ai) != 0) {
printf("Failed to verify %p\n", a);
problems++;
}
@@ -39,9 +39,11 @@ static void die() {
exit(1);
}
static void stats(MemoryManager* memmgr) {
printf("-- Used: %d\n", (int)memmgr->getUsedBytes());
printf("-- Allocated: %d\n", (int)memmgr->getAllocatedBytes());
static void stats(VMemMgr& memmgr) {
printf("-- Used: %d\n",
static_cast<int>(memmgr.getUsedBytes()));
printf("-- Allocated: %d\n",
static_cast<int>(memmgr.getAllocatedBytes()));
}
static void shuffle(void **a, void **b, size_t count) {
@@ -60,12 +62,13 @@ static void shuffle(void **a, void **b, size_t count) {
}
int main(int argc, char* argv[]) {
MemoryManager* memmgr = MemoryManager::getGlobal();
VMemMgr memmgr;
size_t i;
size_t count = 200000;
printf("Memory alloc/free test - %d allocations.\n\n", (int)count);
printf("Memory alloc/free test - %d allocations.\n\n",
static_cast<int>(count));
void** a = (void**)::malloc(sizeof(void*) * count);
void** b = (void**)::malloc(sizeof(void*) * count);
@@ -77,7 +80,7 @@ int main(int argc, char* argv[]) {
for (i = 0; i < count; i++) {
int r = (rand() % 1000) + 4;
a[i] = memmgr->alloc(r);
a[i] = memmgr.alloc(r);
if (a[i] == NULL) die();
::memset(a[i], 0, r);
@@ -90,7 +93,7 @@ int main(int argc, char* argv[]) {
printf("Freeing virtual memory...");
for (i = 0; i < count; i++) {
if (memmgr->release(a[i]) != kErrorOk) {
if (memmgr.release(a[i]) != kErrorOk) {
printf("Failed to free %p.\n", b[i]);
problems++;
}
@@ -106,7 +109,7 @@ int main(int argc, char* argv[]) {
for (i = 0; i < count; i++) {
int r = (rand() % 1000) + 4;
a[i] = memmgr->alloc(r);
a[i] = memmgr.alloc(r);
b[i] = ::malloc(r);
if (a[i] == NULL || b[i] == NULL) die();
@@ -124,7 +127,7 @@ int main(int argc, char* argv[]) {
printf("Verify and free...");
for (i = 0; i < count / 2; i++) {
verify(a[i], b[i]);
if (memmgr->release(a[i]) != kErrorOk) {
if (memmgr.release(a[i]) != kErrorOk) {
printf("Failed to free %p.\n", a[i]);
problems++;
}
@@ -138,7 +141,7 @@ int main(int argc, char* argv[]) {
for (i = 0; i < count / 2; i++) {
int r = (rand() % 1000) + 4;
a[i] = memmgr->alloc(r);
a[i] = memmgr.alloc(r);
b[i] = ::malloc(r);
if (a[i] == NULL || b[i] == NULL) die();
@@ -151,7 +154,7 @@ int main(int argc, char* argv[]) {
printf("Verify and free...");
for (i = 0; i < count; i++) {
verify(a[i], b[i]);
if (memmgr->release(a[i]) != kErrorOk) {
if (memmgr.release(a[i]) != kErrorOk) {
printf("Failed to free %p.\n", a[i]);
problems++;
}
+1 -1
View File
@@ -44,7 +44,7 @@ int main(int argc, char* argv[]) {
printf(" asmjit::CodeGen : %u\n", static_cast<uint32_t>(sizeof(CodeGen)));
printf(" asmjit::BaseAssembler : %u\n", static_cast<uint32_t>(sizeof(BaseAssembler)));
printf(" asmjit::BaseCompiler : %u\n", static_cast<uint32_t>(sizeof(BaseCompiler)));
printf(" asmjit::BaseRuntime : %u\n", static_cast<uint32_t>(sizeof(BaseRuntime)));
printf(" asmjit::Runtime : %u\n", static_cast<uint32_t>(sizeof(Runtime)));
printf("\n");
printf(" asmjit::Operand : %u\n", static_cast<uint32_t>(sizeof(Operand)));
printf(" asmjit::BaseReg : %u\n", static_cast<uint32_t>(sizeof(BaseReg)));
+1 -1
View File
@@ -22,7 +22,7 @@ using namespace asmjit::host;
// [X86Test]
// ============================================================================
//! @brief Interface used to test Compiler.
//! Interface used to test Compiler.
struct X86Test {
X86Test(const char* name = NULL) { _name.setString(name); }
virtual ~X86Test() {}
+6 -253
View File
@@ -8,9 +8,13 @@
#ifndef _ASMJIT_ASMJIT_H
#define _ASMJIT_ASMJIT_H
// ============================================================================
// [asmjit_mainpage]
// ============================================================================
//! @mainpage
//!
//! @brief AsmJit - Complete x86/x64 JIT and Remote Assembler for C++.
//! AsmJit - Complete x86/x64 JIT and Remote Assembler for C++.
//!
//! AsmJit is a complete JIT and remote assembler for C++ language. It can
//! generate native code for x86 and x64 architectures having support for
@@ -65,259 +69,8 @@
//! @section AsmJit_Main_HomePage AsmJit Homepage
//!
//! - http://code.google.com/p/asmjit/
//!
//! @section AsmJit_Main_ResourcesX86 External X86/X64 Assembler Resources
//! - http://www.agner.org/optimize/
//! - http://www.mark.masmcode.com/ (Assembler Tips)
//! - http://avisynth.org/mediawiki/Filter_SDK/Assembler_optimizing (Optimizing)
//! - http://www.ragestorm.net/distorm/ (Disassembling)
//!
//! @section AsmJit_Main_Terminology Terminology
//!
//! - <b>Non-volatile (preserved) register</b> - Register that can't be changed
//! by callee (callee must save and restore it if it want to use it inside).
//!
//! - <b>Volatile (non-preserved) register</b> - The opossite. Register that can
//! be freely used by callee. The caller must free all registers before calling
//! other function.
//! @defgroup asmjit_base Base - base (backend neutral) classes.
//!
//! Contains all AsmJit classes and helper functions that are neutral or
//! abstract. All abstract classes are reimplemented for every supported
//! architecture.
//!
//! - See @c asmjit::Assembler class for low level code generation
//! documentation.
//! - See @c asmjit::Operand for AsmJit operand's overview.
//!
//! @section AsmJit_Core_Registers Registers
//!
//! There are static objects that represents X86 and X64 registers. They can
//! be used directly (like @c eax, @c mm, @c xmm, ...) or created through
//! these functions:
//!
//! - @c asmjit::gpb_lo() - Get Gpb-lo register.
//! - @c asmjit::gpb_hi() - Get Gpb-hi register.
//! - @c asmjit::gpw() - Get Gpw register.
//! - @c asmjit::gpd() - Get Gpd register.
//! - @c asmjit::gpq() - Get Gpq Gp register.
//! - @c asmjit::gpz() - Get Gpd/Gpq register.
//! - @c asmjit::fp() - Get Fp register.
//! - @c asmjit::mm() - Get Mm register.
//! - @c asmjit::xmm() - Get Xmm register.
//! - @c asmjit::ymm() - Get Ymm register.
//!
//! @section AsmJit_Core_Addressing Addressing
//!
//! X86 and x64 architectures contains several addressing modes and most ones
//! are possible with AsmJit library. Memory represents are represented by
//! @c asmjit::BaseMem class. These functions are used to make operands that
//! represents memory addresses:
//!
//! - @c asmjit::ptr()
//! - @c asmjit::byte_ptr()
//! - @c asmjit::word_ptr()
//! - @c asmjit::dword_ptr()
//! - @c asmjit::qword_ptr()
//! - @c asmjit::tword_ptr()
//! - @c asmjit::oword_ptr()
//! - @c asmjit::yword_ptr()
//! - @c asmjit::intptr_ptr()
//!
//! Most useful function to make pointer should be @c asmjit::ptr(). It creates
//! pointer to the target with unspecified size. Unspecified size works in all
//! intrinsics where are used registers (this means that size is specified by
//! register operand or by instruction itself). For example @c asmjit::ptr()
//! can't be used with @c asmjit::Assembler::inc() instruction. In this case
//! size must be specified and it's also reason to make difference between
//! pointer sizes.
//!
//! Supported are simple address forms (register + displacement) and complex
//! address forms (register + (register << shift) + displacement).
//!
//! @section AsmJit_Core_Immediates Immediates
//!
//! Immediate values are constants thats passed directly after instruction
//! opcode. To create such value use @c asmjit::imm() or @c asmjit::imm_u()
//! methods to create signed or unsigned immediate value.
//!
//! @sa @c asmjit::BaseCompiler.
//! @defgroup asmjit_compiler Compiler (high-level code generation).
//!
//! Contains classes related to @c asmjit::Compiler that can be used
//! to generate code using high-level constructs.
//!
//! - See @c Compiler class for high level code generation
//! documentation - calling conventions, function declaration
//! and variables management.
//! @defgroup asmjit_config Configuration.
//!
//! Contains macros that can be redefined to fit into any project.
//! @defgroup asmjit_cpuinfo Cpu information.
//!
//! X86 or x64 cpuid instruction allows to get information about processor
//! vendor and it's features. It's always used to detect features like MMX,
//! SSE and other newer ones.
//!
//! AsmJit library supports low level cpuid call implemented internally as
//! C++ function using inline assembler or intrinsics and also higher level
//! CPU features detection. The low level function (also used by higher level
//! one) is @c asmjit::cpuid().
//!
//! AsmJit library also contains higher level function @c asmjit::getCpu()
//! that returns features detected by the library. The detection process is
//! done only once and the returned object is always the same. @c BaseCpuInfo
//! structure does not contain only information through @c asmjit::cpuid(), but
//! there is also small multiplatform code to detect number of processors
//! (or cores) through operating system API.
//!
//! It's recommended to use @c asmjit::cpuInfo to detect and check for
//! host processor features.
//!
//! Example how to use asmjit::cpuid():
//!
//! @code
//! // All functions and structures are in asmjit namesapce.
//! using namespace asmjit;
//!
//! // Here will be retrieved result of cpuid call.
//! CpuId out;
//!
//! // Use cpuid function to do the job.
//! cpuid(0 /* eax */, &out /* eax, ebx, ecx, edx */);
//!
//! // If eax argument to cpuid is 0, ebx, ecx and edx registers
//! // are filled with cpu vendor.
//! char vendor[13];
//! memcpy(i->vendor, &out.ebx, 4);
//! memcpy(i->vendor + 4, &out.edx, 4);
//! memcpy(i->vendor + 8, &out.ecx, 4);
//! vendor[12] = '\0';
//!
//! // Print vendor
//! puts(vendor);
//! @endcode
//!
//! If the high-level interface of asmjit::BaseCpuInfo is not enough, you can
//! use low-level asmjit::cpuid() when running on x86/x64 host, but please read
//! processor manuals provided by Intel, AMD or other manufacturer for cpuid
//! details.
//!
//! Example of using @c BaseCpuInfo::getHost():
//!
//! @code
//! // All functions and structures are in asmjit namesapce.
//! using namespace asmjit;
//!
//! // Call to cpuInfo return BaseCpuInfo structure that shouldn't be modified.
//! // Make it const by default.
//! const BaseCpuInfo* cpuInfo = BaseCpuInfo::getHost();
//!
//! // Now you are able to get specific features.
//!
//! // Processor has SSE2
//! if (cpuInfo->hasFeature(kCpuFeatureSse2)) {
//! // your code...
//! }
//! // Processor has MMX
//! else if (cpuInfo->hasFeature(kCpuFeature_MMX)) {
//! // your code...
//! }
//! // Processor is old, no SSE2 or MMX support.
//! else {
//! // your code...
//! }
//! @endcode
//!
//! Better example is in app/test/testcpu.cpp file.
//! @defgroup asmjit_logging Logging and error handling.
//!
//! Contains classes related to loging. Currently logging is implemented in
//! @ref asmjit::BaseLogger class. The function @ref asmjit::BaseLogger::log()
//! can be overridden to redirect logging into any user-defined stream.
//!
//! To log your assembler output to FILE stream use this code:
//!
//! @code
//! // Create assembler
//! Assembler a;
//!
//! // Create and set file based logger
//! FileLogger logger(stderr);
//! a.setLogger(&logger);
//! @endcode
//!
//! You can see that logging goes through @c Assembler. If you are using
//! @c Compiler and you want to log messages in correct assembler order,
//! you should look at @ref Compiler::comment() method. It allows you to
//! insert text message into items stream so the @c Compiler is able to
//! send messages to @ref Assembler in correct order.
//!
//! @sa @c asmjit::BaseLogger, @c asmjit::FileLogger.
//! @defgroup AsmJit_MemoryManagement Virtual memory management.
//!
//! Using @c asmjit::Assembler or @c asmjit::Compiler to generate machine
//! code is not final step. Each generated code needs to run in memory
//! that is not protected against code execution. To alloc this code it's
//! needed to use operating system functions provided to enable execution
//! code in specified memory block or to allocate memory that is not
//! protected. The solution is always to use @c See asmjit::Assembler::make()
//! and @c asmjit::Compiler::make() functions that can allocate memory and
//! relocate code for you. But AsmJit also contains classes for manual memory
//! management thats internally used by AsmJit but can be used by programmers
//! too.
//!
//! Memory management contains low level and high level classes related to
//! allocating and freeing virtual memory. Low level class is
//! @c asmjit::VMem that can allocate and free full pages of virtual memory
//! provided by operating system. Higher level class is @c asmjit::MemoryManager
//! that is able to manage complete allocation and free mechanism. It
//! internally uses larger chunks of memory to make allocation fast and
//! effective.
//!
//! Using @c asmjit::VMem::alloc() is cross-platform way how to allocate this
//! kind of memory without worrying about operating system and it's API. Each
//! memory block that is no longer needed should be released by @ref
//! asmjit::VMem::release() method. Higher-level interface for virtual memory
//! allocation can be found at asmjit::MemoryManager class.
//!
//! @sa @c asmjit::VMem, @ asmjit::MemoryManager.
//! @addtogroup asmjit_config
//! @{
//! @def ASMJIT_OS_WINDOWS
//! @brief Macro that is declared if AsmJit is compiled for Windows.
//! @def ASMJIT_OS_POSIX
//! @brief Macro that is declared if AsmJit is compiled for unix like
//! operating system.
//! @def ASMJIT_API
//! @brief Attribute that's added to classes that can be exported if AsmJit
//! is compiled as a dll library.
//! @def ASMJIT_ASSERT
//! @brief Assertion macro. Default implementation calls
//! @c asmjit::assertionFailed() function.
//! @}
//! @namespace asmjit
//! @brief Main AsmJit library namespace.
//!
//! There are not other namespaces used in AsmJit library.
// [Dependencies - Core]
// [Dependencies - Base]
#include "base.h"
// [Dependencies - X86/X64]
+186 -1
View File
@@ -8,7 +8,193 @@
#ifndef _ASMJIT_BASE_H
#define _ASMJIT_BASE_H
// ============================================================================
// [asmjit_base]
// ============================================================================
//! @defgroup asmjit_base Base
//!
//! @brief AsmJit Base API.
//!
//! Contains all `asmjit` classes and helper functions that are architecture
//! independent or abstract. Abstract classes are implemented by the backend,
//! for example `BaseAssembler` is implemented by `x86x64::X86X64Assembler`.
//!
//! - See `BaseAssembler` for low level code generation documentation.
//! - See `BaseCompiler` for high level code generation documentation.
//! - See `Operand` for operand's overview.
//!
//! @section AsmJit_Core_Registers Registers
//!
//! There are static objects that represents X86 and X64 registers. They can
//! be used directly (like `eax`, `mm`, `xmm`, ...) or created through
//! these functions:
//!
//! - `asmjit::gpb_lo()` - Get Gpb-lo register.
//! - `asmjit::gpb_hi()` - Get Gpb-hi register.
//! - `asmjit::gpw()` - Get Gpw register.
//! - `asmjit::gpd()` - Get Gpd register.
//! - `asmjit::gpq()` - Get Gpq Gp register.
//! - `asmjit::gpz()` - Get Gpd/Gpq register.
//! - `asmjit::fp()` - Get Fp register.
//! - `asmjit::mm()` - Get Mm register.
//! - `asmjit::xmm()` - Get Xmm register.
//! - `asmjit::ymm()` - Get Ymm register.
//!
//! @section AsmJit_Core_Addressing Addressing
//!
//! X86 and x64 architectures contains several addressing modes and most ones
//! are possible with AsmJit library. Memory represents are represented by
//! `BaseMem` class. These functions are used to make operands that represents
//! memory addresses:
//!
//! - `asmjit::ptr()`
//! - `asmjit::byte_ptr()`
//! - `asmjit::word_ptr()`
//! - `asmjit::dword_ptr()`
//! - `asmjit::qword_ptr()`
//! - `asmjit::tword_ptr()`
//! - `asmjit::oword_ptr()`
//! - `asmjit::yword_ptr()`
//! - `asmjit::intptr_ptr()`
//!
//! Most useful function to make pointer should be `asmjit::ptr()`. It creates
//! pointer to the target with unspecified size. Unspecified size works in all
//! intrinsics where are used registers (this means that size is specified by
//! register operand or by instruction itself). For example `asmjit::ptr()`
//! can't be used with @c asmjit::Assembler::inc() instruction. In this case
//! size must be specified and it's also reason to make difference between
//! pointer sizes.
//!
//! Supported are simple address forms (register + displacement) and complex
//! address forms (register + (register << shift) + displacement).
//!
//! @section AsmJit_Core_Immediates Immediates
//!
//! Immediate values are constants thats passed directly after instruction
//! opcode. To create such value use @c asmjit::imm() or @c asmjit::imm_u()
//! methods to create signed or unsigned immediate value.
//!
//! @sa @c asmjit::BaseCompiler.
// ============================================================================
// [asmjit_base_globals]
// ============================================================================
//! @defgroup asmjit_base_globals Globals
//! @ingroup asmjit_base
//!
//! @brief Global definitions, macros and functions.
// ============================================================================
// [asmjit_base_codegen]
// ============================================================================
//! @defgroup asmjit_base_codegen Code Generation (Base)
//! @ingroup asmjit_base
//!
//! @brief Low-level and high-level code generation.
// ============================================================================
// [asmjit_base_cpu_info]
// ============================================================================
//! @defgroup asmjit_base_cpu_info CPU Information (Base)
//! @ingroup asmjit_base
//!
//! @brief CPU Information Interface, platform neutral.
// ============================================================================
// [asmjit_base_logging_and_errors]
// ============================================================================
//! @defgroup asmjit_base_logging_and_errors Logging and Error Handling
//! @ingroup asmjit_base
//!
//! @brief Logging and error handling.
//!
//! AsmJit contains robust interface that can be used to log the generated code
//! and to handle possible errors. Base logging interface is defined in `Logger`
//! class that is abstract and can be overridden. AsmJit contains two loggers
//! that can be used out-of-the box - `FileLogger` that logs into a `FILE*`
//! and `StringLogger` that just concatenates all log messages without sending
//! them to a stream.
//!
//! The following snippet shows how to setup a logger that logs to `stderr`:
//!
//! ~~~
//! // `FileLogger` instance.
//! FileLogger logger(stderr);
//!
//! // `Compiler` or any other `CodeGen` interface.
//! host::Compiler c;
//!
//! // use `setLogger` to replace the `CodeGen` logger.
//! c.setLogger(&logger);
//! ~~~
//!
//! @sa @ref `Logger`, @ref `FileLogger`, @ref `StringLogger`.
// ============================================================================
// [asmjit_base_util]
// ============================================================================
//! @defgroup asmjit_base_util Utilities
//! @ingroup asmjit_base
//!
//! @brief Utilities inside AsmJit made public.
//!
//! AsmJit contains numerous utility classes that are needed by the library
//! itself. The most useful ones have been made public and are now exported.
//!
//! POD-Containers
//! --------------
//!
//! TODO: Documentation
//!
//! String Builder
//! --------------
//!
//! TODO: Documentation
//!
//! Integer Utilities
//! -----------------
//!
//! TODO: Documentation
//!
//! Zone Memory Allocator
//! ---------------------
//!
//! TODO: Documentation
//!
//! CPU Ticks
//! ---------
//!
//! TODO: Documentation
// ============================================================================
// [asmjit_base_vectypes]
// ============================================================================
//! @defgroup asmjit_base_vectypes Vector Types
//! @ingroup asmjit_base
//!
//! @brief Vector types can be used to create a data which is stored in the
//! machine code.
// ============================================================================
// [asmjit::]
// ============================================================================
//! @namespace asmjit
//! Main AsmJit library namespace.
//!
//! There are not other namespaces used in AsmJit library.
// ============================================================================
// [Dependencies - AsmJit]
// ============================================================================
#include "build.h"
#include "base/assembler.h"
@@ -24,7 +210,6 @@
#include "base/intutil.h"
#include "base/lock.h"
#include "base/logger.h"
#include "base/memorymanager.h"
#include "base/podlist.h"
#include "base/podvector.h"
#include "base/string.h"
+2 -2
View File
@@ -10,7 +10,7 @@
// [Dependencies - AsmJit]
#include "../base/assembler.h"
#include "../base/intutil.h"
#include "../base/memorymanager.h"
#include "../base/vmem.h"
// [Dependenceis - C]
#include <stdarg.h>
@@ -24,7 +24,7 @@ namespace asmjit {
// [asmjit::BaseAssembler - Construction / Destruction]
// ============================================================================
BaseAssembler::BaseAssembler(BaseRuntime* runtime) :
BaseAssembler::BaseAssembler(Runtime* runtime) :
CodeGen(runtime),
_buffer(NULL),
_end(NULL),
+96 -89
View File
@@ -23,22 +23,24 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_codegen
//! @{
// ============================================================================
// [asmjit::LabelLink]
// ============================================================================
//! @brief Data structure used to link linked-labels.
//! @internal
//!
//! Data structure used to link linked-labels.
struct LabelLink {
//! @brief Previous link.
//! Previous link.
LabelLink* prev;
//! @brief Offset.
//! Offset.
intptr_t offset;
//! @brief Inlined displacement.
//! Inlined displacement.
intptr_t displacement;
//! @brief RelocId if link must be absolute when relocated.
//! RelocId if link must be absolute when relocated.
intptr_t relocId;
};
@@ -46,11 +48,13 @@ struct LabelLink {
// [asmjit::LabelData]
// ============================================================================
//! @brief Label data.
//! @internal
//!
//! Label data.
struct LabelData {
//! @brief Label offset.
//! Label offset.
intptr_t offset;
//! @brief Label links chain.
//! Label links chain.
LabelLink* links;
};
@@ -58,7 +62,9 @@ struct LabelData {
// [asmjit::RelocData]
// ============================================================================
//! @brief Code relocation data (relative vs absolute addresses).
//! @internal
//!
//! Code relocation data (relative vs absolute addresses).
//!
//! X86/X64:
//!
@@ -68,16 +74,16 @@ struct LabelData {
//! and embedded data. In 32-bit mode we must patch all references to absolute
//! address before we can call generated function.
struct RelocData {
//! @brief Type of relocation.
//! Type of relocation.
uint32_t type;
//! @brief Size of relocation (4 or 8 bytes).
//! Size of relocation (4 or 8 bytes).
uint32_t size;
//! @brief Offset from code begin address.
//! Offset from code begin address.
Ptr from;
//! @brief Relative displacement from code begin address (not to @c offset)
//! or absolute address.
//! Relative displacement from code begin address (not to `offset`) or
//! absolute address.
Ptr data;
};
@@ -85,10 +91,10 @@ struct RelocData {
// [asmjit::BaseAssembler]
// ============================================================================
//! @brief Base assembler.
//! Base assembler.
//!
//! This class implements core setialization API only. The platform specific
//! methods and intrinsics is implemented by derived classes.
//! This class implements the base interface to an assembler. The architecture
//! specific API is implemented by backends.
//!
//! @sa BaseCompiler.
struct BaseAssembler : public CodeGen {
@@ -98,66 +104,66 @@ struct BaseAssembler : public CodeGen {
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @ref BaseAssembler instance.
ASMJIT_API BaseAssembler(BaseRuntime* runtime);
//! @brief Destroy the @ref BaseAssembler instance.
//! Create a new `BaseAssembler` instance.
ASMJIT_API BaseAssembler(Runtime* runtime);
//! Destroy the `BaseAssembler` instance.
ASMJIT_API virtual ~BaseAssembler();
// --------------------------------------------------------------------------
// [Clear / Reset]
// --------------------------------------------------------------------------
//! @brief Clear everything, but not deallocate buffers.
//! Clear everything, but not deallocate buffers.
ASMJIT_API void clear();
//! @brief Reset everything (means also to free all buffers).
//! Reset everything (means also to free all buffers).
ASMJIT_API void reset();
//! @brief Called by clear() and reset() to clear all data related to derived
//! class implementation.
//! Called by clear() and reset() to clear all data related to derived class
//! implementation.
ASMJIT_API virtual void _purge();
// --------------------------------------------------------------------------
// [Buffer]
// --------------------------------------------------------------------------
//! @brief Get capacity of the code buffer.
//! Get capacity of the code buffer.
ASMJIT_INLINE size_t getCapacity() const {
return (size_t)(_end - _buffer);
}
//! @brief Get the number of remaining bytes (space between cursor and the
//! end of the buffer).
//! Get the number of remaining bytes (space between cursor and the end of
//! the buffer).
ASMJIT_INLINE size_t getRemainingSpace() const {
return (size_t)(_end - _cursor);
}
//! @brief Get buffer.
//! Get buffer.
ASMJIT_INLINE uint8_t* getBuffer() const {
return _buffer;
}
//! @brief Get the end of the buffer (points to the first byte that is outside).
//! Get the end of the buffer (points to the first byte that is outside).
ASMJIT_INLINE uint8_t* getEnd() const {
return _end;
}
//! @brief Get the current position in the buffer.
//! Get the current position in the buffer.
ASMJIT_INLINE uint8_t* getCursor() const {
return _cursor;
}
//! @brief Set the current position in the buffer.
//! Set the current position in the buffer.
ASMJIT_INLINE void setCursor(uint8_t* cursor) {
ASMJIT_ASSERT(cursor >= _buffer && cursor <= _end);
_cursor = cursor;
}
//! @brief Get the current offset in the buffer (<code>_cursor - _buffer</code>).
//! Get the current offset in the buffer.
ASMJIT_INLINE size_t getOffset() const {
return (size_t)(_cursor - _buffer);
}
//! @brief Set the current offset in the buffer to @a offset and get the
//! previous offset value.
//! Set the current offset in the buffer to `offset` and get the previous
//! offset value.
ASMJIT_INLINE size_t setOffset(size_t offset) {
ASMJIT_ASSERT(offset < getCapacity());
@@ -166,84 +172,83 @@ struct BaseAssembler : public CodeGen {
return oldOffset;
}
//! @brief Grow the internal buffer.
//! Grow the internal buffer.
//!
//! The internal buffer will grow at least by @a n bytes so @a n bytes
//! can be added to it. If @a n is zero or <code>getOffset() + n</code>
//! is not greater than the current capacity of the buffer this function
//! won't do anything.
//! The internal buffer will grow at least by `n` bytes so `n` bytes can be
//! added to it. If `n` is zero or `getOffset() + n` is not greater than the
//! current capacity of the buffer this function does nothing.
ASMJIT_API Error _grow(size_t n);
//! @brief Reserve the internal buffer to at least @a n bytes.
//! Reserve the internal buffer to at least `n` bytes.
ASMJIT_API Error _reserve(size_t n);
//! @brief Set byte at position @a pos.
//! Set byte at position `pos`.
ASMJIT_INLINE uint8_t getByteAt(size_t pos) const {
ASMJIT_ASSERT(pos + 1 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const uint8_t*>(_buffer + pos);
}
//! @brief Set word at position @a pos.
//! Set word at position `pos`.
ASMJIT_INLINE uint16_t getWordAt(size_t pos) const {
ASMJIT_ASSERT(pos + 2 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const uint16_t*>(_buffer + pos);
}
//! @brief Set dword at position @a pos.
//! Set dword at position `pos`.
ASMJIT_INLINE uint32_t getDWordAt(size_t pos) const {
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const uint32_t*>(_buffer + pos);
}
//! @brief Set qword at position @a pos.
//! Set qword at position `pos`.
ASMJIT_INLINE uint64_t getQWordAt(size_t pos) const {
ASMJIT_ASSERT(pos + 8 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const uint64_t*>(_buffer + pos);
}
//! @brief Set int32_t at position @a pos.
//! Set int32_t at position `pos`.
ASMJIT_INLINE int32_t getInt32At(size_t pos) const {
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const int32_t*>(_buffer + pos);
}
//! @brief Set uint32_t at position @a pos.
//! Set uint32_t at position `pos`.
ASMJIT_INLINE uint32_t getUInt32At(size_t pos) const {
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
return *reinterpret_cast<const uint32_t*>(_buffer + pos);
}
//! @brief Set byte at position @a pos.
//! Set byte at position `pos`.
ASMJIT_INLINE void setByteAt(size_t pos, uint8_t x) {
ASMJIT_ASSERT(pos + 1 <= (size_t)(_end - _buffer));
*reinterpret_cast<uint8_t*>(_buffer + pos) = x;
}
//! @brief Set word at position @a pos.
//! Set word at position `pos`.
ASMJIT_INLINE void setWordAt(size_t pos, uint16_t x) {
ASMJIT_ASSERT(pos + 2 <= (size_t)(_end - _buffer));
*reinterpret_cast<uint16_t*>(_buffer + pos) = x;
}
//! @brief Set dword at position @a pos.
//! Set dword at position `pos`.
ASMJIT_INLINE void setDWordAt(size_t pos, uint32_t x) {
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
*reinterpret_cast<uint32_t*>(_buffer + pos) = x;
}
//! @brief Set qword at position @a pos.
//! Set qword at position `pos`.
ASMJIT_INLINE void setQWordAt(size_t pos, uint64_t x) {
ASMJIT_ASSERT(pos + 8 <= (size_t)(_end - _buffer));
*reinterpret_cast<uint64_t*>(_buffer + pos) = x;
}
//! @brief Set int32_t at position @a pos.
//! Set int32_t at position `pos`.
ASMJIT_INLINE void setInt32At(size_t pos, int32_t x) {
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
*reinterpret_cast<int32_t*>(_buffer + pos) = x;
}
//! @brief Set uint32_t at position @a pos.
//! Set uint32_t at position `pos`.
ASMJIT_INLINE void setUInt32At(size_t pos, uint32_t x) {
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
*reinterpret_cast<uint32_t*>(_buffer + pos) = x;
@@ -253,7 +258,7 @@ struct BaseAssembler : public CodeGen {
// [GetCodeSize]
// --------------------------------------------------------------------------
//! @brief Get current offset in buffer (same as <code>getOffset() + getTramplineSize()</code>).
//! Get current offset in buffer, same as `getOffset() + getTramplineSize()`.
ASMJIT_INLINE size_t getCodeSize() const {
return getOffset() + getTrampolineSize();
}
@@ -262,10 +267,12 @@ struct BaseAssembler : public CodeGen {
// [GetTrampolineSize]
// --------------------------------------------------------------------------
//! @brief Get size of all possible trampolines needed to successfuly generate
//! relative jumps to absolute addresses. This value is only non-zero if jmp
//! of call instructions were used with immediate operand (this means jumping
//! or calling an absolute address directly).
//! Get size of all possible trampolines.
//!
//! Trampolines are needed to successfuly generate relative jumps to absolute
//! addresses. This value is only non-zero if jmp of call instructions were
//! used with immediate operand (this means jumping or calling an absolute
//! address directly).
ASMJIT_INLINE size_t getTrampolineSize() const {
return _trampolineSize;
}
@@ -274,26 +281,26 @@ struct BaseAssembler : public CodeGen {
// [Label]
// --------------------------------------------------------------------------
//! @brief Get count of labels created.
//! Get count of labels created.
ASMJIT_INLINE size_t getLabelsCount() const {
return _labels.getLength();
}
//! @brief Get whether @a label is created.
//! Get whether `label` is created.
ASMJIT_INLINE bool isLabelCreated(const Label& label) const {
return static_cast<size_t>(label.getId()) < _labels.getLength();
}
//! @internal
//!
//! @brief Get @ref LabelData by @a label.
//! Get `LabelData` by `label`.
ASMJIT_INLINE LabelData* getLabelData(const Label& label) const {
return getLabelDataById(label.getId());
}
//! @internal
//!
//! @brief Get @ref LabelData by @a id.
//! Get `LabelData` by `id`.
ASMJIT_INLINE LabelData* getLabelDataById(uint32_t id) const {
ASMJIT_ASSERT(id != kInvalidValue);
ASMJIT_ASSERT(id < _labels.getLength());
@@ -303,30 +310,30 @@ struct BaseAssembler : public CodeGen {
//! @internal
//!
//! @brief Register labels for other code generator (@ref Compiler).
//! Register labels for other code generator, i.e. `Compiler`.
ASMJIT_API Error _registerIndexedLabels(size_t index);
//! @internal
//!
//! @brief Create and initialize a new label.
//! Create and initialize a new `Label`.
ASMJIT_API Error _newLabel(Label* dst);
//! @internal
//!
//! @brief New LabelLink instance.
//! New LabelLink instance.
ASMJIT_API LabelLink* _newLabelLink();
//! @brief Create and return new label.
//! Create and return a new `Label`.
ASMJIT_INLINE Label newLabel() {
Label result(NoInit);
_newLabel(&result);
return result;
}
//! @brief Bind label to the current offset (virtual).
//! Bind label to the current offset.
virtual void _bind(const Label& label) = 0;
//! @brief Bind label to the current offset (virtual).
//! Bind label to the current offset.
//!
//! @note Label can be bound only once!
ASMJIT_INLINE void bind(const Label& label) {
@@ -337,43 +344,43 @@ struct BaseAssembler : public CodeGen {
// [Embed]
// --------------------------------------------------------------------------
//! @brief Embed data into the code buffer.
//! Embed data into the code buffer.
ASMJIT_API Error embed(const void* data, uint32_t size);
// --------------------------------------------------------------------------
// [Align]
// --------------------------------------------------------------------------
//! @brief Align target buffer to @a m bytes.
//! Align target buffer to `m` bytes.
//!
//! Typical usage of this is to align labels at start of the inner loops.
//!
//! Inserts @c nop() instructions or CPU optimized NOPs.
//! Inserts `nop()` instructions or CPU optimized NOPs.
ASMJIT_INLINE Error align(uint32_t m) {
return _align(m);
}
//! @brief Align target buffer to @a m bytes (virtual).
//! Align target buffer to `m` bytes (virtual).
virtual Error _align(uint32_t m) = 0;
// --------------------------------------------------------------------------
// [Reloc]
// --------------------------------------------------------------------------
//! @brief Simplifed version of @c relocCode() method designed for JIT.
//! Simplifed version of `relocCode()` method designed for JIT.
//!
//! @overload
ASMJIT_INLINE size_t relocCode(void* dst) const {
return _relocCode(dst, static_cast<Ptr>((uintptr_t)dst));
}
//! @brief Relocate code to a given address @a dst.
//! Relocate code to a given address `dst`.
//!
//! @param dst Where the relocated code should me stored. The pointer can be
//! address returned by virtual memory allocator or your own address if you
//! want only to store the code for later reuse (or load, etc...).
//! @param addressBase Base address used for relocation. When using JIT code
//! generation, this will be the same as @a dst, only casted to system
//! generation, this will be the same as `dst`, only casted to system
//! integer type. But when generating code for remote process then the value
//! can be different.
//!
@@ -383,12 +390,12 @@ struct BaseAssembler : public CodeGen {
//! for the function.
//!
//! A given buffer will be overwritten, to get number of bytes required use
//! @c getCodeSize().
//! `getCodeSize()`.
ASMJIT_INLINE size_t relocCode(void* dst, Ptr base) const {
return _relocCode(dst, base);
}
//! @brief Reloc code (virtual).
//! Reloc code (virtual).
virtual size_t _relocCode(void* dst, Ptr base) const = 0;
// --------------------------------------------------------------------------
@@ -401,7 +408,7 @@ struct BaseAssembler : public CodeGen {
// [Emit]
// --------------------------------------------------------------------------
//! @brief Emit an instruction.
//! Emit an instruction.
ASMJIT_API Error emit(uint32_t code);
//! @overload
ASMJIT_API Error emit(uint32_t code, const Operand& o0);
@@ -414,7 +421,7 @@ struct BaseAssembler : public CodeGen {
return _emit(code, o0, o1, o2, o3);
}
//! @brief Emit an instruction with integer immediate operand.
//! Emit an instruction with integer immediate operand.
ASMJIT_API Error emit(uint32_t code, int o0);
//! @overload
ASMJIT_API Error emit(uint32_t code, const Operand& o0, int o1);
@@ -423,37 +430,37 @@ struct BaseAssembler : public CodeGen {
//! @overload
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, int o3);
//! @brief Emit an instruction (virtual).
//! Emit an instruction (virtual).
virtual Error _emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3) = 0;
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @brief Buffer where the code is emitted (either live or temporary).
//! Buffer where the code is emitted (either live or temporary).
//!
//! This is actually the base pointer of the buffer, to get the current
//! position (cursor) look at the @c _cursor member.
//! position (cursor) look at the `_cursor` member.
uint8_t* _buffer;
//! @brief The end of the buffer (points to the first invalid byte).
//! The end of the buffer (points to the first invalid byte).
//!
//! The end of the buffer is calculated as <code>_buffer + size</code>.
uint8_t* _end;
//! @brief The current position in code @c _buffer.
//! The current position in code `_buffer`.
uint8_t* _cursor;
//! @brief Size of possible trampolines.
//! Size of possible trampolines.
uint32_t _trampolineSize;
//! @brief Inline comment that will be logged by the next instruction and
//! Inline comment that will be logged by the next instruction and
//! set to NULL.
const char* _comment;
//! @brief Linked list of unused links (@c LabelLink* structures)
//! Unused `LabelLink` structures pool.
LabelLink* _unusedLinks;
//! @brief Labels data.
//! Labels data.
PodVector<LabelData> _labels;
//! @brief Relocations data.
//! Relocations data.
PodVector<RelocData> _relocData;
};
+3 -3
View File
@@ -20,7 +20,7 @@ namespace asmjit {
// [asmjit::CodeGen - Construction / Destruction]
// ============================================================================
CodeGen::CodeGen(BaseRuntime* runtime) :
CodeGen::CodeGen(Runtime* runtime) :
_runtime(runtime),
_logger(NULL),
_errorHandler(NULL),
@@ -40,7 +40,7 @@ CodeGen::~CodeGen() {
// [asmjit::CodeGen - Logging]
// ============================================================================
Error CodeGen::setLogger(BaseLogger* logger) {
Error CodeGen::setLogger(Logger* logger) {
_logger = logger;
return kErrorOk;
}
@@ -64,7 +64,7 @@ Error CodeGen::setError(Error error, const char* message) {
if (handler != NULL && handler->handleError(error, message))
return error;
BaseLogger* logger = _logger;
Logger* logger = _logger;
if (logger != NULL) {
logger->logFormat(kLoggerStyleComment,
"*** ERROR: %s (%u).\n", message, static_cast<unsigned int>(error));
+53 -51
View File
@@ -20,33 +20,35 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_codegen
//! @{
// ============================================================================
// [asmjit::kCodeGen]
// ============================================================================
//! @brief @ref CodeGen features.
//! Features of `CodeGen`.
ASMJIT_ENUM(kCodeGen) {
//! @brief Emit optimized code-alignment sequences.
//! Emit optimized code-alignment sequences.
//!
//! X86/X64:
//! X86/X64
//! -------
//!
//! Default align sequence used by X86/X64 architecture is one-byte 0x90
//! opcode that is mostly shown by disassemblers as nop. However there are
//! more optimized align sequences for 2-11 bytes that may execute faster.
//! If this feature is enabled asmjit will generate specialized sequences
//! for alignment between 1 to 11 bytes. Also when @ref x86x64::Compiler
//! is used, it may add rex prefixes into the code to make some instructions
//! larger so no alignment sequences are needed.
//! for alignment between 1 to 11 bytes. Also when `x86x64::Compiler` is
//! used, it may add rex prefixes into the code to make some instructions
//! greater so no alignment sequences are needed.
//!
//! @default true.
//! Default true.
kCodeGenOptimizedAlign = 0,
//! @brief Emit jump-prediction hints.
//! Emit jump-prediction hints.
//!
//! X86/X64:
//! X86/X64
//! -------
//!
//! 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
@@ -55,7 +57,7 @@ ASMJIT_ENUM(kCodeGen) {
//! However this behavior can be overridden by using instruction prefixes.
//! If this option is enabled these hints will be emitted.
//!
//! @default true.
//! Default true.
kCodeGenPredictedJumps = 1
};
@@ -63,7 +65,7 @@ ASMJIT_ENUM(kCodeGen) {
// [asmjit::CodeGen]
// ============================================================================
//! @brief Abstract class inherited by @ref Assembler and @ref Compiler.
//! Abstract class inherited by `Assembler` and `Compiler`.
struct CodeGen {
ASMJIT_NO_COPY(CodeGen)
@@ -71,76 +73,76 @@ struct CodeGen {
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @ref CodeGen instance.
ASMJIT_API CodeGen(BaseRuntime* runtime);
//! @brief Destroy the @ref CodeGen instance.
//! Create a new `CodeGen` instance.
ASMJIT_API CodeGen(Runtime* runtime);
//! Destroy the `CodeGen` instance.
ASMJIT_API virtual ~CodeGen();
// --------------------------------------------------------------------------
// [Runtime]
// --------------------------------------------------------------------------
//! @brief Get runtime.
ASMJIT_INLINE BaseRuntime* getRuntime() const { return _runtime; }
//! Get runtime.
ASMJIT_INLINE Runtime* getRuntime() const { return _runtime; }
// --------------------------------------------------------------------------
// [Logger]
// --------------------------------------------------------------------------
//! @brief Get whether the code generator has a logger.
//! Get whether the code generator has a logger.
ASMJIT_INLINE bool hasLogger() const { return _logger != NULL; }
//! @brief Get logger.
ASMJIT_INLINE BaseLogger* getLogger() const { return _logger; }
//! @brief Set logger to @a logger.
ASMJIT_API Error setLogger(BaseLogger* logger);
//! Get logger.
ASMJIT_INLINE Logger* getLogger() const { return _logger; }
//! Set logger to `logger`.
ASMJIT_API Error setLogger(Logger* logger);
// --------------------------------------------------------------------------
// [Arch]
// --------------------------------------------------------------------------
//! @brief Get target architecture.
//! Get target architecture.
ASMJIT_INLINE uint32_t getArch() const { return _arch; }
//! @brief Get default register size (4 or 8 bytes).
//! Get default register size (4 or 8 bytes).
ASMJIT_INLINE uint32_t getRegSize() const { return _regSize; }
// --------------------------------------------------------------------------
// [Error]
// --------------------------------------------------------------------------
//! @brief Get last error code.
//! Get last error code.
ASMJIT_INLINE Error getError() const { return _error; }
//! @brief Set last error code and propagate it through the error handler.
//! Set last error code and propagate it through the error handler.
ASMJIT_API Error setError(Error error, const char* message = NULL);
//! @brief Clear the last error code.
//! Clear the last error code.
ASMJIT_INLINE void clearError() { _error = kErrorOk; }
//! @brief Get error handler.
//! Get error handler.
ASMJIT_INLINE ErrorHandler* getErrorHandler() const { return _errorHandler; }
//! @brief Set error handler.
//! Set error handler.
ASMJIT_API Error setErrorHandler(ErrorHandler* handler);
//! @brief Clear error handler.
//! Clear error handler.
ASMJIT_INLINE Error clearErrorHandler() { return setErrorHandler(NULL); }
// --------------------------------------------------------------------------
// [Features]
// --------------------------------------------------------------------------
//! @brief Get code-generator @a feature.
//! Get code-generator `feature`.
ASMJIT_API bool hasFeature(uint32_t feature) const;
//! @brief Set code-generator @a feature to @a value.
//! Set code-generator `feature` to `value`.
ASMJIT_API Error setFeature(uint32_t feature, bool value);
// --------------------------------------------------------------------------
// [Options]
// --------------------------------------------------------------------------
//! @brief Get options.
//! Get options.
ASMJIT_INLINE uint32_t getOptions() const { return _options; }
//! @brief Set options.
//! Set options.
ASMJIT_INLINE void setOptions(uint32_t options) { _options = options; }
//! @brief Get options and clear them.
//! Get options and clear them.
ASMJIT_INLINE uint32_t getOptionsAndClear() {
uint32_t options = _options;
_options = 0;
@@ -151,7 +153,7 @@ struct CodeGen {
// [Purge]
// --------------------------------------------------------------------------
//! @brief Called by clear() and reset() to clear all data used by the code
//! Called by `clear()` and `reset()` to clear all data used by the code
//! generator.
virtual void _purge() = 0;
@@ -159,37 +161,37 @@ struct CodeGen {
// [Make]
// --------------------------------------------------------------------------
//! @brief Make is a convenience method to make and relocate the current code
//! into the associated runtime.
//! Make is a convenience method to make and relocate the current code and
//! add it to the associated `Runtime`.
//!
//! What is needed is only to cast the returned pointer to your function type
//! and then use it. If there was an error during make() @c NULL is returned
//! and the last error code can be obtained by calling @ref getError().
//! and then use it. If there was an error during `make()` `NULL` is returned
//! and the last error code can be obtained by calling `getError()`.
virtual void* make() = 0;
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @brief Runtime.
BaseRuntime* _runtime;
//! @brief Logger.
BaseLogger* _logger;
//! @brief Error handler, called by @ref setError().
//! Runtime.
Runtime* _runtime;
//! Logger.
Logger* _logger;
//! Error handler, called by `setError()`.
ErrorHandler* _errorHandler;
//! @brief Target architecture.
//! Target architecture.
uint8_t _arch;
//! @brief Get the default register size of the architecture (4 or 8 bytes).
//! Get the default register size of the architecture (4 or 8 bytes).
uint8_t _regSize;
//! @brief Last error code.
//! Last error code.
uint8_t _error;
//! @brief Target features.
//! Target features.
uint8_t _features;
//! @brief Options for the next generated instruction (only 8-bits used).
//! Options for the next generated instruction (only 8-bits used).
uint32_t _options;
//! @brief Base zone.
//! Base zone.
Zone _baseZone;
};
+1 -1
View File
@@ -34,7 +34,7 @@ enum { kBaseCompilerDefaultLookAhead = 64 };
// [asmjit::BaseCompiler - Construction / Destruction]
// ============================================================================
BaseCompiler::BaseCompiler(BaseRuntime* runtime) :
BaseCompiler::BaseCompiler(Runtime* runtime) :
CodeGen(runtime),
_nodeFlowId(0),
_nodeFlags(0),
+452 -448
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -31,7 +31,7 @@ const ConstPoolNode ConstPoolTree::_sentinel = { {
//! @internal
//!
//! @brief Remove left horizontal links.
//! Remove left horizontal links.
static ASMJIT_INLINE ConstPoolNode* ConstPoolTree_skewNode(ConstPoolNode* node) {
if (node->_link[0]->_level == node->_level && node->_level != 0 ) {
ConstPoolNode *save = node->_link[0];
@@ -45,7 +45,7 @@ static ASMJIT_INLINE ConstPoolNode* ConstPoolTree_skewNode(ConstPoolNode* node)
//! @internal
//!
//! @brief Remove consecutive horizontal links.
//! Remove consecutive horizontal links.
static ASMJIT_INLINE ConstPoolNode* ConstPoolTree_splitNode(ConstPoolNode* node) {
if (node->_link[1]->_link[1]->_level == node->_level && node->_level != 0) {
ConstPoolNode *save = node->_link[1];
@@ -159,7 +159,7 @@ void ConstPool::reset() {
// [asmjit::ConstPool - Ops]
// ============================================================================
ASMJIT_INLINE size_t ConstPool_getGapIndex(size_t size) {
static ASMJIT_INLINE size_t ConstPool_getGapIndex(size_t size) {
if (size <= 1)
return ConstPool::kIndex1;
else if (size <= 3)
@@ -172,7 +172,7 @@ ASMJIT_INLINE size_t ConstPool_getGapIndex(size_t size) {
return ConstPool::kIndex16;
}
ASMJIT_INLINE ConstPoolGap* ConstPool_allocGap(ConstPool* self) {
static ASMJIT_INLINE ConstPoolGap* ConstPool_allocGap(ConstPool* self) {
ConstPoolGap* gap = self->_gapPool;
if (gap == NULL)
return self->_zone->allocT<ConstPoolGap>();
@@ -181,7 +181,7 @@ ASMJIT_INLINE ConstPoolGap* ConstPool_allocGap(ConstPool* self) {
return gap;
}
ASMJIT_INLINE void ConstPool_freeGap(ConstPool* self, ConstPoolGap* gap) {
static ASMJIT_INLINE void ConstPool_freeGap(ConstPool* self, ConstPoolGap* gap) {
gap->_next = self->_gapPool;
self->_gapPool = gap;
}
+31 -24
View File
@@ -17,13 +17,16 @@
namespace asmjit {
//! @addtogroup asmjit_base_util
//! @{
// ============================================================================
// [asmjit::ConstPoolNode]
// ============================================================================
//! @internal
//!
//! @brief Zone-allocated constant-pool node.
//! Zone-allocated constant-pool node.
struct ConstPoolNode {
// --------------------------------------------------------------------------
// [Accessors]
@@ -37,13 +40,13 @@ struct ConstPoolNode {
// [Members]
// --------------------------------------------------------------------------
//! @brief Left/Right nodes.
//! Left/Right nodes.
ConstPoolNode* _link[2];
//! @brief Horizontal level for balance.
//! Horizontal level for balance.
uint32_t _level : 31;
//! @brief Whether this constant is shared with another.
//! Whether this constant is shared with another.
uint32_t _shared : 1;
//! @brief Data offset from the beginning of the pool.
//! Data offset from the beginning of the pool.
uint32_t _offset;
};
@@ -53,10 +56,10 @@ struct ConstPoolNode {
//! @internal
//!
//! @brief Zone-allocated constant-pool tree.
//! Zone-allocated constant-pool tree.
struct ConstPoolTree {
enum {
//! @brief Maximum tree height == log2(1 << 64).
//! Maximum tree height == log2(1 << 64).
kHeightLimit = 64
};
@@ -169,11 +172,11 @@ struct ConstPoolTree {
// [Members]
// --------------------------------------------------------------------------
//! @brief Root of the tree
//! Root of the tree
ConstPoolNode* _root;
//! @brief Length of the tree (count of nodes).
//! Length of the tree (count of nodes).
size_t _length;
//! @brief Size of the data.
//! Size of the data.
size_t _dataSize;
};
@@ -183,13 +186,13 @@ struct ConstPoolTree {
//! @internal
//!
//! @brief Zone-allocated constant-pool gap.
//! Zone-allocated constant-pool gap.
struct ConstPoolGap {
//! @brief Link to the next gap
//! Link to the next gap
ConstPoolGap* _next;
//! @brief Offset of the gap.
//! Offset of the gap.
size_t _offset;
//! @brief Remaining bytes of the gap (basically a gap size).
//! Remaining bytes of the gap (basically a gap size).
size_t _length;
};
@@ -197,6 +200,7 @@ struct ConstPoolGap {
// [asmjit::ConstPool]
// ============================================================================
//! Constant pool.
struct ConstPool {
ASMJIT_NO_COPY(ConstPool)
@@ -227,21 +231,22 @@ struct ConstPool {
// [Ops]
// --------------------------------------------------------------------------
//! @brief Get whether the constant-pool is empty.
//! Get whether the constant-pool is empty.
ASMJIT_INLINE bool isEmpty() const {
return _size == 0;
}
//! @brief Get the size of the constant-pool in bytes.
//! Get the size of the constant-pool in bytes.
ASMJIT_INLINE size_t getSize() const {
return _size;
}
//! Get minimum alignment.
ASMJIT_INLINE size_t getAlignment() const {
return _alignment;
}
//! @brief Add a constant to the constant pool.
//! Add 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
@@ -264,28 +269,30 @@ struct ConstPool {
// [Fill]
// --------------------------------------------------------------------------
//! @brief Fill the destination with the constants from the pool.
//! Fill the destination with the constants from the pool.
ASMJIT_API void fill(void* dst);
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @brief Zone allocator.
//! Zone allocator.
Zone* _zone;
//! @brief Tree per size.
//! Tree per size.
ConstPoolTree _tree[kIndexCount];
//! @brief Gaps per size.
//! Gaps per size.
ConstPoolGap* _gaps[kIndexCount];
//! @brief Gaps pool
//! Gaps pool
ConstPoolGap* _gapPool;
//! @brief Size of the pool (in bytes).
//! Size of the pool (in bytes).
size_t _size;
//! @brief Alignemnt.
//! Alignemnt.
size_t _alignment;
};
//! @}
} // asmjit namespace
// [Api-End]
+1 -1
View File
@@ -298,7 +298,7 @@ Error BaseContext::removeUnreachableCode() {
//! @internal
//!
//! @brief Translate the given function @a func.
//! Translate the given function `func`.
void BaseContext::cleanup() {
VarData** array = _contextVd.getData();
size_t length = _contextVd.getLength();
+57 -47
View File
@@ -17,10 +17,17 @@
namespace asmjit {
//! @addtogroup asmjit_base_codegen
//! @{
// ============================================================================
// [asmjit::BaseContext]
// ============================================================================
//! @internal
//!
//! Code generation context is the logic behind `BaseCompiler`. The context is
//! used to compile the code stored in `BaseCompiler`.
struct BaseContext {
ASMJIT_NO_COPY(BaseContext)
@@ -35,41 +42,41 @@ struct BaseContext {
// [Reset]
// --------------------------------------------------------------------------
//! @brief Reset the whole context.
//! Reset the whole context.
virtual void reset();
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get compiler.
//! Get compiler.
ASMJIT_INLINE BaseCompiler* getCompiler() const { return _compiler; }
//! @brief Get function.
//! Get function.
ASMJIT_INLINE FuncNode* getFunc() const { return _func; }
//! @brief Get stop node.
//! Get stop node.
ASMJIT_INLINE BaseNode* getStop() const { return _stop; }
//! @brief Get start of the current scope.
//! Get start of the current scope.
ASMJIT_INLINE BaseNode* getStart() const { return _start; }
//! @brief Get end of the current scope.
//! Get end of the current scope.
ASMJIT_INLINE BaseNode* getEnd() const { return _end; }
//! @brief Get extra block.
//! Get extra block.
ASMJIT_INLINE BaseNode* getExtraBlock() const { return _extraBlock; }
//! @brief Set extra block.
//! Set extra block.
ASMJIT_INLINE void setExtraBlock(BaseNode* node) { _extraBlock = node; }
// --------------------------------------------------------------------------
// [Error]
// --------------------------------------------------------------------------
//! @brief Get the last error code.
//! Get the last error code.
ASMJIT_INLINE Error getError() const {
return getCompiler()->getError();
}
//! @brief Set the last error code and propagate it through the error handler.
//! Set the last error code and propagate it through the error handler.
ASMJIT_INLINE Error setError(Error error, const char* message = NULL) {
return getCompiler()->setError(error, message);
}
@@ -78,19 +85,20 @@ struct BaseContext {
// [State]
// --------------------------------------------------------------------------
//! @brief Get current state.
ASMJIT_INLINE BaseVarState* getState() const { return _state; }
//! Get current state.
ASMJIT_INLINE BaseVarState* getState() const {
return _state;
}
//! @brief Load current state from @a target state.
//! Load current state from `target` state.
virtual void loadState(BaseVarState* src) = 0;
//! @brief Save current state, returning new @ref BaseVarState instance.
//! Save current state, returning new `BaseVarState` instance.
virtual BaseVarState* saveState() = 0;
//! @brief Change the current state to @a target state.
//! Change the current state to `target` state.
virtual void switchState(BaseVarState* src) = 0;
//! @brief Change the current state to the intersection of two states @a a
//! and @a b.
//! Change the current state to the intersection of two states `a` and `b`.
virtual void intersectStates(BaseVarState* a, BaseVarState* b) = 0;
// --------------------------------------------------------------------------
@@ -140,7 +148,7 @@ struct BaseContext {
// [Fetch]
// --------------------------------------------------------------------------
//! @brief Fetch.
//! Fetch.
//!
//! Fetch iterates over all nodes and gathers information about all variables
//! used. The process generates information required by register allocator,
@@ -151,14 +159,14 @@ struct BaseContext {
// [RemoveUnreachableCode]
// --------------------------------------------------------------------------
//! @brief Remove unreachable code.
//! Remove unreachable code.
virtual Error removeUnreachableCode();
// --------------------------------------------------------------------------
// [Analyze]
// --------------------------------------------------------------------------
//! @brief Preform variable liveness analysis.
//! Preform variable liveness analysis.
//!
//! Analysis phase iterates over nodes in reverse order and generates a bit
//! array describing variables that are alive at every node in the function.
@@ -180,7 +188,7 @@ struct BaseContext {
// [Translate]
// --------------------------------------------------------------------------
//! @brief Translate code by allocating registers and handling state changes.
//! Translate code by allocating registers and handling state changes.
virtual Error translate() = 0;
// --------------------------------------------------------------------------
@@ -205,70 +213,72 @@ struct BaseContext {
// [Members]
// --------------------------------------------------------------------------
//! @brief Compiler.
//! Compiler.
BaseCompiler* _compiler;
//! @brief Function.
//! Function.
FuncNode* _func;
//! @brief Zone allocator.
//! Zone allocator.
Zone _baseZone;
//! @brief Start of the current active scope.
//! Start of the current active scope.
BaseNode* _start;
//! @brief End of the current active scope.
//! End of the current active scope.
BaseNode* _end;
//! @brief Node that is used to insert extra code after the function body.
//! Node that is used to insert extra code after the function body.
BaseNode* _extraBlock;
//! @brief Stop node.
//! Stop node.
BaseNode* _stop;
//! @brief Unreachable nodes.
//! Unreachable nodes.
PodList<BaseNode*> _unreachableList;
//! @brief Jump nodes.
//! Jump nodes.
PodList<BaseNode*> _jccList;
//! @brief All variables used by the current function.
//! All variables used by the current function.
PodVector<VarData*> _contextVd;
//! @brief Memory used to spill variables.
//! Memory used to spill variables.
MemCell* _memVarCells;
//! @brief Memory used to alloc memory on the stack.
//! Memory used to alloc memory on the stack.
MemCell* _memStackCells;
//! @brief Count of 1-byte cells.
//! Count of 1-byte cells.
uint32_t _mem1ByteVarsUsed;
//! @brief Count of 2-byte cells.
//! Count of 2-byte cells.
uint32_t _mem2ByteVarsUsed;
//! @brief Count of 4-byte cells.
//! Count of 4-byte cells.
uint32_t _mem4ByteVarsUsed;
//! @brief Count of 8-byte cells.
//! Count of 8-byte cells.
uint32_t _mem8ByteVarsUsed;
//! @brief Count of 16-byte cells.
//! Count of 16-byte cells.
uint32_t _mem16ByteVarsUsed;
//! @brief Count of 32-byte cells.
//! Count of 32-byte cells.
uint32_t _mem32ByteVarsUsed;
//! @brief Count of 64-byte cells.
//! Count of 64-byte cells.
uint32_t _mem64ByteVarsUsed;
//! @brief Count of stack memory cells.
//! Count of stack memory cells.
uint32_t _memStackCellsUsed;
//! @brief Maximum memory alignment used by the function.
//! Maximum memory alignment used by the function.
uint32_t _memMaxAlign;
//! @brief Count of bytes used by variables.
//! Count of bytes used by variables.
uint32_t _memVarTotal;
//! @brief Count of bytes used by stack.
//! Count of bytes used by stack.
uint32_t _memStackTotal;
//! @brief Count of bytes used by variables and stack after alignment.
//! Count of bytes used by variables and stack after alignment.
uint32_t _memAllTotal;
//! @brief Default lenght of annotated instruction.
//! Default lenght of annotated instruction.
uint32_t _annotationLength;
//! @brief Current state (used by register allocator).
//! Current state (used by register allocator).
BaseVarState* _state;
};
//! @}
} // asmjit namespace
// [Api-End]
+1 -1
View File
@@ -62,7 +62,7 @@ uint32_t BaseCpuInfo::detectNumberOfCores() {
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
struct HostCpuInfo : public x86x64::CpuInfo {
ASMJIT_INLINE HostCpuInfo() : CpuInfo() {
x86x64::hostCpuDetect(this);
x86x64::CpuUtil::detect(this);
}
};
#else
+33 -30
View File
@@ -16,30 +16,30 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_cpu_info
//! @{
// ============================================================================
// [asmjit::kCpuVendor]
// ============================================================================
//! @brief Cpu vendor IDs.
//! Cpu vendor IDs.
//!
//! Cpu vendor IDs are specific for AsmJit library. Vendor ID is not directly
//! read from cpuid result, instead it's based on CPU vendor string.
ASMJIT_ENUM(kCpuVendor) {
//! @brief Unknown CPU vendor.
//! Unknown CPU vendor.
kCpuVendorUnknown = 0,
//! @brief Intel CPU vendor.
//! Intel CPU vendor.
kCpuVendorIntel = 1,
//! @brief AMD CPU vendor.
//! AMD CPU vendor.
kCpuVendorAmd = 2,
//! @brief National Semiconductor CPU vendor (applies also to Cyrix processors).
//! National Semiconductor CPU vendor (applies also to Cyrix processors).
kCpuVendorNSM = 3,
//! @brief Transmeta CPU vendor.
//! Transmeta CPU vendor.
kCpuVendorTransmeta = 4,
//! @brief VIA CPU vendor.
//! VIA CPU vendor.
kCpuVendorVia = 5
};
@@ -47,11 +47,14 @@ ASMJIT_ENUM(kCpuVendor) {
// [asmjit::BaseCpuInfo]
// ============================================================================
//! @brief Base cpu information.
//! Base cpu information.
struct BaseCpuInfo {
ASMJIT_NO_COPY(BaseCpuInfo)
enum { kFeaturesPerUInt32 = static_cast<int>(sizeof(uint32_t)) * 8 };
//! @internal
enum {
kFeaturesPerUInt32 = static_cast<int>(sizeof(uint32_t)) * 8
};
// --------------------------------------------------------------------------
// [Construction / Destruction]
@@ -63,23 +66,23 @@ struct BaseCpuInfo {
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get CPU vendor string.
//! Get CPU vendor string.
ASMJIT_INLINE const char* getVendorString() const { return _vendorString; }
//! @brief Get CPU brand string.
//! Get CPU brand string.
ASMJIT_INLINE const char* getBrandString() const { return _brandString; }
//! @brief Get CPU vendor ID.
//! Get CPU vendor ID.
ASMJIT_INLINE uint32_t getVendorId() const { return _vendorId; }
//! @brief Get CPU family ID.
//! Get CPU family ID.
ASMJIT_INLINE uint32_t getFamily() const { return _family; }
//! @brief Get CPU model ID.
//! Get CPU model ID.
ASMJIT_INLINE uint32_t getModel() const { return _model; }
//! @brief Get CPU stepping.
//! Get CPU stepping.
ASMJIT_INLINE uint32_t getStepping() const { return _stepping; }
//! @brief Get CPU cores count (or sum of all cores of all procesors).
//! Get CPU cores count (or sum of all cores of all procesors).
ASMJIT_INLINE uint32_t getCoresCount() const { return _coresCount; }
//! @brief Get whether CPU has a @a feature.
//! Get whether CPU has a `feature`.
ASMJIT_INLINE bool hasFeature(uint32_t feature) const {
ASMJIT_ASSERT(feature < sizeof(_features) * 8);
@@ -87,7 +90,7 @@ struct BaseCpuInfo {
(_features[feature / kFeaturesPerUInt32] >> (feature % kFeaturesPerUInt32)) & 0x1);
}
//! @brief Add CPU @a feature.
//! Add a CPU `feature`.
ASMJIT_INLINE BaseCpuInfo& addFeature(uint32_t feature) {
ASMJIT_ASSERT(feature < sizeof(_features) * 8);
@@ -99,36 +102,36 @@ struct BaseCpuInfo {
// [Statics]
// --------------------------------------------------------------------------
//! @brief Detect number of cores (or sum of all cores of all processors).
//! Detect number of cores (or sum of all cores of all processors).
static ASMJIT_API uint32_t detectNumberOfCores();
//! @brief Get host cpu.
//! Get host cpu.
static ASMJIT_API const BaseCpuInfo* getHost();
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @brief Size of the structure in bytes.
//! Size of the structure in bytes.
uint32_t _size;
//! @brief Cpu short vendor string.
//! Cpu short vendor string.
char _vendorString[16];
//! @brief Cpu long vendor string (brand).
//! Cpu long vendor string (brand).
char _brandString[64];
//! @brief Cpu vendor id (see @c asmjit::kCpuVendor enum).
//! Cpu vendor id, see `asmjit::kCpuVendor`.
uint32_t _vendorId;
//! @brief Cpu family ID.
//! Cpu family ID.
uint32_t _family;
//! @brief Cpu model ID.
//! Cpu model ID.
uint32_t _model;
//! @brief Cpu stepping.
//! Cpu stepping.
uint32_t _stepping;
//! @brief Cpu cores count (or sum of all CPU cores of all processors).
//! Cpu cores count (or sum of all CPU cores of all processors).
uint32_t _coresCount;
//! @brief Cpu features bitfield.
//! Cpu features bitfield.
uint32_t _features[4];
};
+3 -1
View File
@@ -16,14 +16,16 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_util
//! @{
// ============================================================================
// [asmjit::CpuTicks]
// ============================================================================
//! CPU ticks utilities.
struct CpuTicks {
//! Get the current CPU ticks for benchmarking (1ms resolution).
static ASMJIT_API uint32_t now();
};
+249 -241
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -27,7 +27,10 @@ ErrorHandler::~ErrorHandler() {}
// [asmjit::ErrorHandler - Interface]
// ============================================================================
ErrorHandler* ErrorHandler::addRef() const { return const_cast<ErrorHandler*>(this); }
ErrorHandler* ErrorHandler::addRef() const {
return const_cast<ErrorHandler*>(this);
}
void ErrorHandler::release() {}
// ============================================================================
+61 -49
View File
@@ -13,80 +13,82 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_logging_and_errors
//! @{
// ============================================================================
// [asmjit::kError]
// ============================================================================
//! @brief AsmJit error codes.
//! AsmJit error codes.
ASMJIT_ENUM(kError) {
//! @brief No error (success).
//! No error (success).
//!
//! This is default state and state you want.
kErrorOk = 0,
//! @brief Heap memory allocation failed.
//! Heap memory allocation failed.
kErrorNoHeapMemory = 1,
//! @brief Virtual memory allocation failed.
//! Virtual memory allocation failed.
kErrorNoVirtualMemory = 2,
//! @brief Invalid argument.
//! Invalid argument.
kErrorInvalidArgument = 3,
//! @brief Invalid state.
//! Invalid state.
kErrorInvalidState = 4,
//! @brief Unknown instruction. This happens only if instruction code is
//! Unknown instruction. This happens only if instruction code is
//! out of bounds. Shouldn't happen.
kErrorAssemblerUnknownInst = 5,
//! @brief Illegal instruction, usually generated by asmjit::Assembler
//! Illegal instruction, usually generated by asmjit::Assembler
//! class when emitting instruction opcode. If this error is generated the
//! target buffer is not affected by this invalid instruction.
//!
//! You can also get this status code if you are under x64 (64-bit x86) and
//! you tried to decode instruction using AH, BH, CH or DH register with REX
//! prefix. These registers can't be accessed if REX prefix is used and AsmJit
//! didn't check for this situation in intrinsics (@c Compiler takes care of
//! didn't check for this situation in intrinsics (`BaseCompiler` takes care of
//! this and rearrange registers if needed).
//!
//! Examples that will raise @c kErrorAssemblerIllegalInst error (a is
//! @c Assembler instance):
//! Example of raising `kErrorAssemblerIllegalInst` error.
//!
//! @code
//! a.mov(dword_ptr(eax), al); // Invalid address size.
//! a.mov(byte_ptr(r10), ah); // Undecodable instruction (AH used with r10
//! // that can be encoded by using REX prefix only)
//! @endcode
//! ~~~
//! // Invalid address size.
//! a.mov(dword_ptr(eax), al);
//!
//! // Undecodable instruction - AH used with r10 that can be encoded by using
//! // REX prefix only.
//! a.mov(byte_ptr(r10), ah);
//! ~~~
//!
//! @note In debug mode you get assertion failure instead of setting error
//! code.
kErrorAssemblerIllegalInst = 6,
//! @brief Illegal addressing used (unencodable).
//! Illegal addressing used (unencodable).
kErrorAssemblerIllegalAddr = 7,
//! @brief Short jump instruction used, but displacement is out of bounds.
//! Short jump instruction used, but displacement is out of bounds.
kErrorAssemblerIllegalShortJump = 8,
//! @brief No function defined.
//! No function defined.
kErrorCompilerNoFunc = 9,
//! @brief Function generation is not finished by using @c Compiler::endFunc()
//! Function generation is not finished by using `BaseCompiler::endFunc()`
//! or something bad happened during generation related to function. This can
//! be missing compiler node, etc...
kErrorCompilerIncompleteFunc = 10,
//! @brief Tried to generate a function with overlapped arguments.
//! Tried to generate a function with overlapped arguments.
kErrorCompilerOverlappedArgs = 11,
//! @brief Compiler can't allocate registers.
//! Compiler can't allocate registers.
kErrorCompilerNoRegs = 12,
//! @brief Compiler can't allocate registers, because they overlap.
//! Compiler can't allocate registers, because they overlap.
kErrorCompilerOverlappedRegs = 13,
//! @brief Tried to call function with an incompatible argument.
//! Tried to call function with an incompatible argument.
kErrorCompilerIncompatibleArg = 14,
//! @brief Incompatible return value.
//! Incompatible return value.
kErrorCompilerIncompatibleRet = 15,
//! @brief Count of AsmJit status codes. Can grow in future.
//! Count of AsmJit status codes. Can grow in future.
kErrorCount = 16
};
@@ -100,42 +102,48 @@ typedef uint32_t Error;
// [asmjit::ErrorHandler]
// ============================================================================
//! Error handler.
//!
//! Error handler can be used to override the default behavior of `CodeGen`
//! error handling and propagation. See `handleError` on how to override it.
//!
//! Please note that `addRef` and `release` functions are used, but there is
//! no reference counting implemented by default, reimplement to change the
//! default behavior.
struct ErrorHandler {
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @ref ErrorHandler.
//! Create a new `ErrorHandler`.
ASMJIT_API ErrorHandler();
//! @brief Destroy the @ref ErrorHandler.
//! Destroy the `ErrorHandler`.
ASMJIT_API virtual ~ErrorHandler();
// --------------------------------------------------------------------------
// [Interface]
// --------------------------------------------------------------------------
//! @brief Reference this error handler.
//! Reference this error handler.
//!
//! @note This member function is provided for convenience. The default
//! implementation does nothing. If you are working in environment where
//! multiple @ref ErrorHandler instances are used in different @ref Assembler
//! and @ref Compiler instances (or in multithreaded environment) you might
//! want to provide your own functionality for reference counting. In that
//! case override @ref addRef() and @ref release() functions to inc/dec your
//! reference count value.
//! multiple `ErrorHandler` instances are used by a different code generators
//! you may provide your own functionality for reference counting. In that
//! case `addRef()` and `release()` functions should be overridden.
ASMJIT_API virtual ErrorHandler* addRef() const;
//! @brief Release this error handler.
//! Release this error handler.
//!
//! @note This member function is provided for convenience. See @ref addRef()
//! @note This member function is provided for convenience. See `addRef()`
//! for more detailed information related to reference counting.
ASMJIT_API virtual void release();
//! @brief Error handler (pure).
//! Error handler (pure).
//!
//! Error handler is called when an error happened. An error can happen in
//! many places, but error handler is mostly used by @ref Assembler and
//! @ref Compiler classes to report anything that may prevent correct code
//! many places, but error handler is mostly used by `BaseAssembler` and
//! `BaseCompiler` classes to report anything that may prevent correct code
//! generation. There are multiple ways how the error handler can be used
//! and each has it's pros/cons.
//!
@@ -144,22 +152,22 @@ struct ErrorHandler {
//! exceptions it is exception-safe and handleError() can report an incoming
//! error by throwing an exception of any type. It's guaranteed that the
//! exception won't be catched by AsmJit and will be propagated to the code
//! calling AsmJit @ref Assembler or @ref Compiler. Alternative to throwing
//! calling AsmJit `BaseAssembler` or `BaseCompiler`. Alternative to throwing
//! exception is using setjmp() / longjmp() pair from the standard C library.
//!
//! If the exception or setjmp() / longjmp() mechanism is used, the state of
//! the @ref Assember or @ref Compiler is unchanged and if it's possible the
//! the `BaseAssember` or `BaseCompiler` is unchanged and if it's possible the
//! execution (instruction serialization) can continue. However if the error
//! happened during any phase that translates or modifies the stored code
//! (for example relocation done by @ref Assembler or analysis/translation
//! done by @ref Compiler) the execution can't continue and the error will
//! be also stored in @ref Assembler or @ref Compiler.
//! (for example relocation done by `BaseAssembler` or analysis/translation
//! done by `BaseCompiler`) the execution can't continue and the error will
//! be also stored in `BaseAssembler` or `BaseCompiler`.
//!
//! Finally, if exceptions nor setjmp() / longjmp() mechanisms were used,
//! you can still implement a compatible design by returning from your error
//! handler. Returning @c true means that error was reported and AsmJit
//! should continue execution. When @c false is returned, AsmJit sets the
//! error immediately to the @ref Assembler or @ref Compiler and execution
//! handler. Returning `true` means that error was reported and AsmJit
//! should continue execution. When `false` is returned, AsmJit sets the
//! error immediately to the `BaseAssembler` or `BaseCompiler` and execution
//! shouldn't continue (this is the default behavior in case no error handler
//! is used).
virtual bool handleError(Error code, const char* message) = 0;
@@ -169,8 +177,9 @@ struct ErrorHandler {
// [asmjit::ErrorUtil]
// ============================================================================
//! Error utilities.
struct ErrorUtil {
//! @brief Get printable version of AsmJit @ref kError code.
//! Get printable version of AsmJit `kError` code.
static ASMJIT_API const char* asString(Error code);
};
@@ -178,6 +187,9 @@ struct ErrorUtil {
// [ASMJIT_PROPAGATE_ERROR]
// ============================================================================
//! @internal
//!
//! Used by AsmJit to return the `_Exp_` result if it's an error.
#define ASMJIT_PROPAGATE_ERROR(_Exp_) \
do { \
::asmjit::Error errval_ = (_Exp_); \
+131 -108
View File
@@ -17,6 +17,9 @@
namespace asmjit {
//! @addtogroup asmjit_base_codegen
//! @{
// ============================================================================
// [Forward Declarations]
// ============================================================================
@@ -28,8 +31,12 @@ struct FnTypeId;
// [asmjit::kFuncConv]
// ============================================================================
//! Function calling convention.
//!
//! For a platform specific calling conventions, see:
//! - `x86x64::kFuncConv` - X86/X64 calling conventions.
ASMJIT_ENUM(kFuncConv) {
//! @brief Calling convention is invalid (can't be used).
//! Calling convention is invalid (can't be used).
kFuncConvNone = 0
};
@@ -37,43 +44,54 @@ ASMJIT_ENUM(kFuncConv) {
// [asmjit::kFuncHint]
// ============================================================================
//! @brief Function hints.
//! Function hints.
//!
//! For a platform specific calling conventions, see:
//! - `x86x64::kFuncHint` - X86/X64 function hints.
ASMJIT_ENUM(kFuncHint) {
//! @brief Make a naked function (default true).
//! Make a naked function (default true).
//!
//! Naked function is function without using standard prolog/epilog sequence).
//!
//! @section X86/X64
//! X86/X64 Specific
//! ----------------
//!
//! Standard prolog sequence is:
//!
//! "push zbp"
//! "mov zsp, zbp"
//! "sub zsp, StackAdjustment"
//! ~~~
//! push zbp
//! mov zsp, zbp
//! sub zsp, StackAdjustment
//! ~~~
//!
//! which is equal to:
//! which is an equivalent to:
//!
//! "enter StackAdjustment, 0"
//! ~~~
//! enter StackAdjustment, 0
//! ~~~
//!
//! Standard epilog sequence is:
//!
//! "mov zsp, zbp"
//! "pop zbp"
//! "ret"
//! ~~~
//! mov zsp, zbp
//! pop zbp
//! ~~~
//!
//! which is equal to:
//! which is an equavalent to:
//!
//! "leave"
//! "ret"
//! ~~~
//! leave
//! ~~~
//!
//! Naked functions can omit the prolog/epilog sequence. The advantage of
//! doing such modification is that EBP/RBP register can be used by the
//! register allocator which can result in less spills/allocs.
kFuncHintNaked = 0,
//! @brief Generate compact function prolog/epilog if possible.
//! Generate compact function prolog/epilog if possible.
//!
//! @section X86/X64
//! X86/X64 Specific
//! ----------------
//!
//! Use shorter, but possible slower prolog/epilog sequence to save/restore
//! registers.
@@ -84,22 +102,26 @@ ASMJIT_ENUM(kFuncHint) {
// [asmjit::kFuncFlags]
// ============================================================================
//! @brief Function flags.
//! Function flags.
//!
//! For a platform specific calling conventions, see:
//! - `x86x64::kFuncFlags` - X86/X64 function flags.
ASMJIT_ENUM(kFuncFlags) {
//! @brief Whether the function is using naked (minimal) prolog / epilog.
//! Whether the function is using naked (minimal) prolog / epilog.
kFuncFlagIsNaked = 0x00000001,
//! @brief Whether an another function is called from this function.
//! Whether an another function is called from this function.
kFuncFlagIsCaller = 0x00000002,
//! @brief Whether the stack is not aligned to the required stack alignment,
//! Whether the stack is not aligned to the required stack alignment,
//! thus it has to be aligned manually.
kFuncFlagIsStackMisaligned = 0x00000004,
//! @brief Whether the stack pointer is adjusted by the stack size needed
//! Whether the stack pointer is adjusted by the stack size needed
//! to save registers and function variables.
//!
//! @section X86/X64
//! X86/X64 Specific
//! ----------------
//!
//! Stack pointer (ESP/RSP) is adjusted by 'sub' instruction in prolog and by
//! 'add' instruction in epilog (only if function is not naked). If function
@@ -107,7 +129,7 @@ ASMJIT_ENUM(kFuncFlags) {
//! adjust the stack (like "and zsp, -Alignment").
kFuncFlagIsStackAdjusted = 0x00000008,
//! @brief Whether the function is finished using @c Compiler::endFunc().
//! Whether the function is finished using `BaseCompiler::endFunc()`.
kFuncFlagIsFinished = 0x80000000
};
@@ -115,14 +137,14 @@ ASMJIT_ENUM(kFuncFlags) {
// [asmjit::kFuncDir]
// ============================================================================
//! @brief Function arguments direction.
//! Function arguments direction.
ASMJIT_ENUM(kFuncDir) {
//! @brief Arguments are passed left to right.
//! Arguments are passed left to right.
//!
//! This arguments direction is unusual to C programming, it's used by pascal
//! compilers and in some calling conventions by Borland compiler).
kFuncDirLtr = 0,
//! @brief Arguments are passed right ro left
//! Arguments are passed right ro left
//!
//! This is default argument direction in C programming.
kFuncDirRtl = 1
@@ -133,7 +155,7 @@ ASMJIT_ENUM(kFuncDir) {
// ============================================================================
enum {
//! @brief Invalid stack offset in function or function parameter.
//! Invalid stack offset in function or function parameter.
kFuncStackInvalid = -1
};
@@ -141,19 +163,19 @@ enum {
// [asmjit::kFuncArg]
// ============================================================================
//! @brief Function argument (lo/hi) specification.
//! Function argument (lo/hi) specification.
ASMJIT_ENUM(kFuncArg) {
//! @brief Maxumum number of function arguments supported by AsmJit.
//! Maxumum number of function arguments supported by AsmJit.
kFuncArgCount = 16,
//! @brief Extended maximum number of arguments (used internally).
//! Extended maximum number of arguments (used internally).
kFuncArgCountLoHi = kFuncArgCount * 2,
//! @brief Index to the LO part of function argument (default).
//! 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,
//! @brief Index to the HI part of function argument.
//! 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
@@ -165,11 +187,11 @@ ASMJIT_ENUM(kFuncArg) {
// [asmjit::kFuncRet]
// ============================================================================
//! @brief Function return value (lo/hi) specification.
//! Function return value (lo/hi) specification.
ASMJIT_ENUM(kFuncRet) {
//! @brief Index to the LO part of function return value.
//! Index to the LO part of function return value.
kFuncRetLo = 0,
//! @brief Index to the HI part of function return value.
//! Index to the HI part of function return value.
kFuncRetHi = 1
};
@@ -187,44 +209,45 @@ ASMJIT_ENUM(kFuncRet) {
//! @internal
//!
//! @brief Declare C/C++ type-id mapped to @c asmjit::kVarType.
//! Declare C/C++ type-id mapped to `kVarType`.
#define ASMJIT_DECLARE_TYPE_ID(_T_, _Id_) \
template<> \
struct TypeId<_T_> { enum { kId = _Id_ }; }
//! @brief Function builder 'void' type.
//! Function builder 'void' type.
struct FnVoid {};
//! @brief Function builder 'int8_t' type.
//! Function builder 'int8_t' type.
struct FnInt8 {};
//! @brief Function builder 'uint8_t' type.
//! Function builder 'uint8_t' type.
struct FnUInt8 {};
//! @brief Function builder 'int16_t' type.
//! Function builder 'int16_t' type.
struct FnInt16 {};
//! @brief Function builder 'uint16_t' type.
//! Function builder 'uint16_t' type.
struct FnUInt16 {};
//! @brief Function builder 'int32_t' type.
//! Function builder 'int32_t' type.
struct FnInt32 {};
//! @brief Function builder 'uint32_t' type.
//! Function builder 'uint32_t' type.
struct FnUInt32 {};
//! @brief Function builder 'int64_t' type.
//! Function builder 'int64_t' type.
struct FnInt64 {};
//! @brief Function builder 'uint64_t' type.
//! Function builder 'uint64_t' type.
struct FnUInt64 {};
//! @brief Function builder 'intptr_t' type.
//! Function builder 'intptr_t' type.
struct FnIntPtr {};
//! @brief Function builder 'uintptr_t' type.
//! Function builder 'uintptr_t' type.
struct FnUIntPtr {};
//! @brief Function builder 'float' type.
//! Function builder 'float' type.
struct FnFloat {};
//! @brief Function builder 'double' type.
//! Function builder 'double' type.
struct FnDouble {};
#if !defined(ASMJIT_DOCGEN)
ASMJIT_DECLARE_TYPE_CORE(kVarTypeIntPtr);
ASMJIT_DECLARE_TYPE_ID(void, kVarTypeInvalid);
@@ -259,15 +282,13 @@ ASMJIT_DECLARE_TYPE_ID(FnFloat, kVarTypeFp32);
ASMJIT_DECLARE_TYPE_ID(double, kVarTypeFp64);
ASMJIT_DECLARE_TYPE_ID(FnDouble, kVarTypeFp64);
#endif // !ASMJIT_DOCGEN
// ============================================================================
// [asmjit::FuncInOut]
// ============================================================================
//! @brief Function in/out (argument or a return value).
//!
//! This class contains function argument or return value translated from the
//! @ref FuncPrototype.
//! Function in/out - argument or return value translated from `FuncPrototype`.
struct FuncInOut {
// --------------------------------------------------------------------------
// [Accessors]
@@ -281,7 +302,7 @@ struct FuncInOut {
ASMJIT_INLINE bool hasStackOffset() const { return _stackOffset != kFuncStackInvalid; }
ASMJIT_INLINE int32_t getStackOffset() const { return static_cast<int32_t>(_stackOffset); }
//! @brief Get whether the argument / return value is assigned.
//! Get whether the argument / return value is assigned.
ASMJIT_INLINE bool isSet() const {
return (_regIndex != kInvalidReg) | (_stackOffset != kFuncStackInvalid);
}
@@ -290,7 +311,7 @@ struct FuncInOut {
// [Reset]
// --------------------------------------------------------------------------
//! @brief Reset the function argument to "unassigned state".
//! Reset the function argument to "unassigned state".
ASMJIT_INLINE void reset() { _packed = 0xFFFFFFFF; }
// --------------------------------------------------------------------------
@@ -299,15 +320,15 @@ struct FuncInOut {
union {
struct {
//! @brief Variable type, see @c kVarType.
//! Variable type, see `kVarType`.
uint8_t _varType;
//! @brief Register index if argument / return value is a register.
//! Register index if argument / return value is a register.
uint8_t _regIndex;
//! @brief Stack offset if argument / return value is on the stack.
//! Stack offset if argument / return value is on the stack.
int16_t _stackOffset;
};
//! @brief All members packed into single 32-bit integer.
//! All members packed into single 32-bit integer.
uint32_t _packed;
};
};
@@ -316,32 +337,32 @@ struct FuncInOut {
// [asmjit::FuncPrototype]
// ============================================================================
//! @brief Function prototype.
//! Function prototype.
//!
//! Function prototype contains information about function return type, count
//! of arguments and their types. Function prototype is a low level structure
//! which doesn't contain platform specific or calling convention specific
//! information. Function prototype is used to create a @ref FuncDecl.
//! information. Function prototype is used to create a `FuncDecl`.
struct FuncPrototype {
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get function return value.
//! Get function return value.
ASMJIT_INLINE uint32_t getRet() const { return _ret; }
//! @brief Get function arguments' IDs.
//! Get function arguments' IDs.
ASMJIT_INLINE const uint32_t* getArgList() const { return _argList; }
//! @brief Get count of function arguments.
//! Get count of function arguments.
ASMJIT_INLINE uint32_t getArgCount() const { return _argCount; }
//! @brief Get argument at index @a id.
//! Get argument at index `id`.
ASMJIT_INLINE uint32_t getArg(uint32_t id) const {
ASMJIT_ASSERT(id < _argCount);
return _argList[id];
}
//! @brief Set function definition - return type and arguments.
//! Set function definition - return type and arguments.
ASMJIT_INLINE void _setPrototype(uint32_t ret, const uint32_t* argList, uint32_t argCount) {
_ret = ret;
_argList = argList;
@@ -361,62 +382,62 @@ struct FuncPrototype {
// [asmjit::FuncDecl]
// ============================================================================
//! @brief Function declaration.
//! Function declaration.
struct FuncDecl {
// --------------------------------------------------------------------------
// [Accessors - Calling Convention]
// --------------------------------------------------------------------------
//! @brief Get function calling convention, see @c kFuncConv.
//! Get function calling convention, see `kFuncConv`.
ASMJIT_INLINE uint32_t getConvention() const { return _convention; }
//! @brief Get whether the callee pops the stack.
//! Get whether the callee pops the stack.
ASMJIT_INLINE uint32_t getCalleePopsStack() const { return _calleePopsStack; }
//! @brief Get direction of arguments passed on the stack.
//! Get direction of arguments passed on the stack.
//!
//! Direction should be always @c kFuncDirRtl.
//! Direction should be always `kFuncDirRtl`.
//!
//! @note This is related to used calling convention, it's not affected by
//! number of function arguments or their types.
ASMJIT_INLINE uint32_t getDirection() const { return _direction; }
//! @brief Get stack size needed for function arguments passed on the stack.
//! Get stack size needed for function arguments passed on the stack.
ASMJIT_INLINE uint32_t getArgStackSize() const { return _argStackSize; }
//! @brief Get size of "Red Zone".
//! Get size of "Red Zone".
ASMJIT_INLINE uint32_t getRedZoneSize() const { return _redZoneSize; }
//! @brief Get size of "Spill Zone".
//! Get size of "Spill Zone".
ASMJIT_INLINE uint32_t getSpillZoneSize() const { return _spillZoneSize; }
// --------------------------------------------------------------------------
// [Accessors - Arguments and Return]
// --------------------------------------------------------------------------
//! @brief Get whether the function has a return value.
//! Get whether the function has a return value.
ASMJIT_INLINE bool hasRet() const { return _retCount != 0; }
//! @brief Get count of function return values.
//! Get count of function return values.
ASMJIT_INLINE uint32_t getRetCount() const { return _retCount; }
//! @brief Get function return value.
//! Get function return value.
ASMJIT_INLINE FuncInOut& getRet(uint32_t index = kFuncRetLo) { return _retList[index]; }
//! @brief Get function return value.
//! Get function return value.
ASMJIT_INLINE const FuncInOut& getRet(uint32_t index = kFuncRetLo) const { return _retList[index]; }
//! @brief Get count of function arguments.
//! Get count of function arguments.
ASMJIT_INLINE uint32_t getArgCount() const { return _argCount; }
//! @brief Get function arguments array.
//! Get function arguments array.
ASMJIT_INLINE FuncInOut* getArgList() { return _argList; }
//! @brief Get function arguments array (const).
//! Get function arguments array (const).
ASMJIT_INLINE const FuncInOut* getArgList() const { return _argList; }
//! @brief Get function argument at index @a index.
//! Get function argument at index `index`.
ASMJIT_INLINE FuncInOut& getArg(size_t index) {
ASMJIT_ASSERT(index < kFuncArgCountLoHi);
return _argList[index];
}
//! @brief Get function argument at index @a index.
//! Get function argument at index `index`.
ASMJIT_INLINE const FuncInOut& getArg(size_t index) const {
ASMJIT_ASSERT(index < kFuncArgCountLoHi);
return _argList[index];
@@ -431,38 +452,38 @@ struct FuncDecl {
// [Members]
// --------------------------------------------------------------------------
//! @brief Calling convention.
//! Calling convention.
uint8_t _convention;
//! @brief Whether a callee pops stack.
//! Whether a callee pops stack.
uint8_t _calleePopsStack : 1;
//! @brief Direction for arguments passed on the stack, see @c kFuncDir.
//! Direction for arguments passed on the stack, see `kFuncDir`.
uint8_t _direction : 1;
//! @brief Reserved #0 (alignment).
//! Reserved #0 (alignment).
uint8_t _reserved0 : 6;
//! @brief Count of arguments (in @c _argList).
//! Count of arguments in `_argList`.
uint8_t _argCount;
//! @brief Count of return value(s).
//! Count of return value(s).
uint8_t _retCount;
//! @brief Count of bytes consumed by arguments on the stack (aligned).
//! Count of bytes consumed by arguments on the stack (aligned).
uint32_t _argStackSize;
//! @brief Size of "Red Zone".
//! Size of "Red Zone".
//!
//! @note Used by AMD64-ABI (128 bytes).
uint16_t _redZoneSize;
//! @brief Size of "Spill Zone".
//! Size of "Spill Zone".
//!
//! @note Used by WIN64-ABI (32 bytes).
uint16_t _spillZoneSize;
//! @brief Function arguments (including HI arguments) mapped to physical
//! Function arguments (including HI arguments) mapped to physical
//! registers and stack offset.
FuncInOut _argList[kFuncArgCountLoHi];
//! @brief Function return value(s).
//! Function return value(s).
FuncInOut _retList[2];
};
@@ -470,7 +491,7 @@ struct FuncDecl {
// [asmjit::FuncBuilderX]
// ============================================================================
//! @brief Custom function builder for up to 32 function arguments.
//! Custom function builder for up to 32 function arguments.
struct FuncBuilderX : public FuncPrototype {
// --------------------------------------------------------------------------
// [Construction / Destruction]
@@ -484,7 +505,7 @@ struct FuncBuilderX : public FuncPrototype {
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Set return type to @a retType.
//! Set return type to `retType`.
ASMJIT_INLINE void setRet(uint32_t retType) {
_ret = retType;
}
@@ -523,7 +544,7 @@ struct FuncBuilderX : public FuncPrototype {
#define _TID(_T_) TypeId<_T_>::kId
//! @brief Function builder (no args).
//! Function builder (no args).
template<typename RET>
struct FuncBuilder0 : public FuncPrototype {
ASMJIT_INLINE FuncBuilder0() {
@@ -531,7 +552,7 @@ struct FuncBuilder0 : public FuncPrototype {
}
};
//! @brief Function builder (1 argument).
//! Function builder (1 argument).
template<typename RET, typename P0>
struct FuncBuilder1 : public FuncPrototype {
ASMJIT_INLINE FuncBuilder1() {
@@ -540,7 +561,7 @@ struct FuncBuilder1 : public FuncPrototype {
}
};
//! @brief Function builder (2 arguments).
//! Function builder (2 arguments).
template<typename RET, typename P0, typename P1>
struct FuncBuilder2 : public FuncPrototype {
ASMJIT_INLINE FuncBuilder2() {
@@ -549,7 +570,7 @@ struct FuncBuilder2 : public FuncPrototype {
}
};
//! @brief Function builder (3 arguments).
//! Function builder (3 arguments).
template<typename RET, typename P0, typename P1, typename P2>
struct FuncBuilder3 : public FuncPrototype {
ASMJIT_INLINE FuncBuilder3() {
@@ -558,7 +579,7 @@ struct FuncBuilder3 : public FuncPrototype {
}
};
//! @brief Function builder (4 arguments).
//! Function builder (4 arguments).
template<typename RET, typename P0, typename P1, typename P2, typename P3>
struct FuncBuilder4 : public FuncPrototype {
ASMJIT_INLINE FuncBuilder4() {
@@ -567,7 +588,7 @@ struct FuncBuilder4 : public FuncPrototype {
}
};
//! @brief Function builder (5 arguments).
//! Function builder (5 arguments).
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4>
struct FuncBuilder5 : public FuncPrototype {
ASMJIT_INLINE FuncBuilder5() {
@@ -576,7 +597,7 @@ struct FuncBuilder5 : public FuncPrototype {
}
};
//! @brief Function builder (6 arguments).
//! Function builder (6 arguments).
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>
struct FuncBuilder6 : public FuncPrototype {
ASMJIT_INLINE FuncBuilder6() {
@@ -585,7 +606,7 @@ struct FuncBuilder6 : public FuncPrototype {
}
};
//! @brief Function builder (7 arguments).
//! Function builder (7 arguments).
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
struct FuncBuilder7 : public FuncPrototype {
ASMJIT_INLINE FuncBuilder7() {
@@ -594,7 +615,7 @@ struct FuncBuilder7 : public FuncPrototype {
}
};
//! @brief Function builder (8 arguments).
//! Function builder (8 arguments).
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
struct FuncBuilder8 : public FuncPrototype {
ASMJIT_INLINE FuncBuilder8() {
@@ -603,7 +624,7 @@ struct FuncBuilder8 : public FuncPrototype {
}
};
//! @brief Function builder (9 arguments).
//! Function builder (9 arguments).
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
struct FuncBuilder9 : public FuncPrototype {
ASMJIT_INLINE FuncBuilder9() {
@@ -612,7 +633,7 @@ struct FuncBuilder9 : public FuncPrototype {
}
};
//! @brief Function builder (10 arguments).
//! Function builder (10 arguments).
template<typename RET, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
struct FuncBuilder10 : public FuncPrototype {
ASMJIT_INLINE FuncBuilder10() {
@@ -623,6 +644,8 @@ struct FuncBuilder10 : public FuncPrototype {
#undef _TID
//! @}
} // asmjit namespace
// [Api-End]
+30 -18
View File
@@ -16,7 +16,7 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_globals
//! @{
// ============================================================================
@@ -26,25 +26,25 @@ namespace asmjit {
static const size_t kInvalidIndex = ~static_cast<size_t>(0);
ASMJIT_ENUM(kGlobals) {
//! @brief Invalid value or operand id.
//! Invalid value or operand id.
kInvalidValue = 0xFFFFFFFF,
//! @brief Invalid register index.
//! Invalid register index.
kInvalidReg = 0xFF,
//! @brief Minimum reserved bytes in @ref Buffer.
//! Minimum reserved bytes in `Buffer`.
kBufferGrow = 32U,
//! @brief Minimum size of assembler/compiler code buffer.
//! Minimum size of assembler/compiler code buffer.
kMemAllocMinimum = 4096,
//! @brief Memory grow threshold.
//! Memory grow threshold.
//!
//! After the grow threshold is reached the capacity won't be doubled
//! anymore.
kMemAllocGrowMax = 8192 * 1024,
//! @brief Host memory allocator overhead.
//! Host memory allocator overhead.
//!
//! We decrement the overhead from our pools so the host operating system
//! doesn't need allocate an extra virtual page to put the data it needs
@@ -58,17 +58,17 @@ ASMJIT_ENUM(kGlobals) {
// [asmjit::kArch]
// ============================================================================
//! @brief Architecture.
//! Architecture.
ASMJIT_ENUM(kArch) {
//! @brief No/Unknown architecture.
//! No/Unknown architecture.
kArchNone = 0,
//! @brief X86 architecture.
//! X86 architecture.
kArchX86 = 1,
//! @brief X64 architecture, also called AMD64.
//! X64 architecture, also called AMD64.
kArchX64 = 2,
//! @brief Arm architecture.
//! Arm architecture.
kArchArm = 4,
#if defined(ASMJIT_HOST_X86)
@@ -83,25 +83,32 @@ ASMJIT_ENUM(kArch) {
kArchHost = kArchArm,
#endif // ASMJIT_HOST_ARM
//! @brief Whether the host is 64-bit.
//! Whether the host is 64-bit.
kArchHost64Bit = sizeof(intptr_t) >= 8
};
//! @}
// ============================================================================
// [asmjit::Init / NoInit]
// ============================================================================
#if !defined(ASMJIT_DOCGEN)
struct _Init {};
static const _Init Init = {};
struct _NoInit {};
static const _NoInit NoInit = {};
#endif // !ASMJIT_DOCGEN
// ============================================================================
// [asmjit::Assert]
// ============================================================================
//! @brief Called in debug build on assertion failure.
//! @addtogroup asmjit_base_logging_and_errors
//! @{
//! Called in debug build on assertion failure.
//!
//! @param exp Expression that failed.
//! @param file Source file name where it happened.
@@ -128,16 +135,21 @@ ASMJIT_API void assertionFailed(const char* exp, const char* file, int line);
// [asmjit_cast<>]
// ============================================================================
//! @brief Cast used to cast pointer to function. It's like reinterpret_cast<>,
//! @addtogroup asmjit_base_util
//! @{
//! Cast used to cast pointer to function. It's like reinterpret_cast<>,
//! but uses internally C style cast to work with MinGW.
//!
//! If you are using single compiler and @c reinterpret_cast<> works for you,
//! there is no reason to use @c asmjit_cast<>. If you are writing
//! If you are using single compiler and `reinterpret_cast<>` works for you,
//! there is no reason to use `asmjit_cast<>`. If you are writing
//! cross-platform software with various compiler support, consider using
//! @c asmjit_cast<> instead of @c reinterpret_cast<>.
//! `asmjit_cast<>` instead of `reinterpret_cast<>`.
template<typename T, typename Z>
static ASMJIT_INLINE T asmjit_cast(Z* p) { return (T)p; }
//! @}
// [Api-End]
#include "../apiend.h"
+43 -16
View File
@@ -20,13 +20,14 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_util
//! @{
// ============================================================================
// [asmjit::IntTraits]
// ============================================================================
//! @internal
template<typename T>
struct IntTraits {
enum {
@@ -46,31 +47,40 @@ struct IntTraits {
// [asmjit::IntUtil]
// ============================================================================
//! Integer utilities.
struct IntUtil {
// --------------------------------------------------------------------------
// [Float <-> Int]
// --------------------------------------------------------------------------
//! @internal
union Float {
int32_t i;
float f;
};
//! @internal
union Double {
int64_t i;
double d;
};
//! Bit-cast `float` to 32-bit integer.
static ASMJIT_INLINE int32_t floatAsInt(float f) { Float m; m.f = f; return m.i; }
//! Bit-cast 32-bit integer to `float`.
static ASMJIT_INLINE float intAsFloat(int32_t i) { Float m; m.i = i; return m.f; }
//! Bit-cast `double` to 64-bit integer.
static ASMJIT_INLINE int64_t doubleAsInt(double d) { Double m; m.d = d; return m.i; }
//! Bit-cast 64-bit integer to `double`.
static ASMJIT_INLINE double intAsDouble(int64_t i) { Double m; m.i = i; return m.d; }
// --------------------------------------------------------------------------
// [AsmJit - Pack / Unpack]
// --------------------------------------------------------------------------
//! Pack two 8-bit integer and one 16-bit integer into a 32-bit integer as it
//! is an array of `{u0,u1,w2}`.
static ASMJIT_INLINE uint32_t pack32_2x8_1x16(uint32_t u0, uint32_t u1, uint32_t w2) {
#if defined(ASMJIT_HOST_LE)
return u0 + (u1 << 8) + (w2 << 16);
@@ -79,6 +89,7 @@ struct IntUtil {
#endif // ASMJIT_HOST
}
//! Pack four 8-bit integer into a 32-bit integer as it is an array of `{u0,u1,u2,u3}`.
static ASMJIT_INLINE uint32_t pack32_4x8(uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) {
#if defined(ASMJIT_HOST_LE)
return u0 + (u1 << 8) + (u2 << 16) + (u3 << 24);
@@ -87,6 +98,7 @@ struct IntUtil {
#endif // ASMJIT_HOST
}
//! Pack two 32-bit integer into a 64-bit integer as it is an array of `{u0,u1}`.
static ASMJIT_INLINE uint64_t pack64_2x32(uint32_t u0, uint32_t u1) {
#if defined(ASMJIT_HOST_LE)
return (static_cast<uint64_t>(u1) << 32) + u0;
@@ -102,9 +114,11 @@ struct IntUtil {
// NOTE: Because some environments declare min() and max() as macros, it has
// been decided to use different name so we never collide with them.
//! Get minimum value of `a` and `b`.
template<typename T>
static ASMJIT_INLINE T iMin(const T& a, const T& b) { return a < b ? a : b; }
//! Get maximum value of `a` and `b`.
template<typename T>
static ASMJIT_INLINE T iMax(const T& a, const T& b) { return a > b ? a : b; }
@@ -112,6 +126,7 @@ struct IntUtil {
// [AsmJit - MaxUInt]
// --------------------------------------------------------------------------
//! Get maximum unsigned value of `T`.
template<typename T>
static ASMJIT_INLINE T maxUInt() { return ~T(0); }
@@ -119,6 +134,7 @@ struct IntUtil {
// [AsmJit - InInterval]
// --------------------------------------------------------------------------
//! Get whether `x` is greater or equal than `start` and less or equal than `end`.
template<typename T>
static ASMJIT_INLINE bool inInterval(const T& x, const T& start, const T& end) {
return x >= start && x <= end;
@@ -128,8 +144,7 @@ struct IntUtil {
// [AsmJit - IsInt/IsUInt]
// --------------------------------------------------------------------------
//! @brief Get whether the given integer @a x can be casted to a signed 8-bit
//! integer.
//! Get whether the given integer `x` can be casted to a signed 8-bit integer.
template<typename T>
static ASMJIT_INLINE bool isInt8(T x) {
if (IntTraits<T>::kIsSigned)
@@ -138,8 +153,7 @@ struct IntUtil {
return x <= T(127);
}
//! @brief Get whether the given integer @a x can be casted to an unsigned 8-bit
//! integer.
//! Get whether the given integer `x` can be casted to an unsigned 8-bit integer.
template<typename T>
static ASMJIT_INLINE bool isUInt8(T x) {
if (IntTraits<T>::kIsSigned)
@@ -148,8 +162,7 @@ struct IntUtil {
return sizeof(T) <= sizeof(uint8_t) ? true : x <= T(255);
}
//! @brief Get whether the given integer @a x can be casted to a signed 16-bit
//! integer.
//! Get whether the given integer `x` can be casted to a signed 16-bit integer.
template<typename T>
static ASMJIT_INLINE bool isInt16(T x) {
if (IntTraits<T>::kIsSigned)
@@ -158,8 +171,7 @@ struct IntUtil {
return x >= T(0) && (sizeof(T) <= sizeof(int16_t) ? true : x <= T(32767));
}
//! @brief Get whether the given integer @a x can be casted to an unsigned 16-bit
//! integer.
//! Get whether the given integer `x` can be casted to an unsigned 16-bit integer.
template<typename T>
static ASMJIT_INLINE bool isUInt16(T x) {
if (IntTraits<T>::kIsSigned)
@@ -168,8 +180,7 @@ struct IntUtil {
return sizeof(T) <= sizeof(uint16_t) ? true : x <= T(65535);
}
//! @brief Get whether the given integer @a x can be casted to a signed 32-bit
//! integer.
//! Get whether the given integer `x` can be casted to a signed 32-bit integer.
template<typename T>
static ASMJIT_INLINE bool isInt32(T x) {
if (IntTraits<T>::kIsSigned)
@@ -178,8 +189,7 @@ struct IntUtil {
return x >= T(0) && (sizeof(T) <= sizeof(int32_t) ? true : x <= T(2147483647));
}
//! @brief Get whether the given integer @a x can be casted to an unsigned 32-bit
//! integer.
//! Get whether the given integer `x` can be casted to an unsigned 32-bit integer.
template<typename T>
static ASMJIT_INLINE bool isUInt32(T x) {
if (IntTraits<T>::kIsSigned)
@@ -192,6 +202,7 @@ struct IntUtil {
// [AsmJit - IsPowerOf2]
// --------------------------------------------------------------------------
//! Get whether the `n` value is a power of two (only one bit is set).
template<typename T>
static ASMJIT_INLINE bool isPowerOf2(T n) {
return n != 0 && (n & (n - 1)) == 0;
@@ -201,49 +212,59 @@ struct IntUtil {
// [AsmJit - Mask]
// --------------------------------------------------------------------------
//! Generate a bit-mask that has `x` bit set.
static ASMJIT_INLINE uint32_t mask(uint32_t x) {
ASMJIT_ASSERT(x < 32);
return (1U << x);
}
//! Generate a bit-mask that has `x0` and `x1` bits set.
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1) {
return mask(x0) | mask(x1);
}
//! Generate a bit-mask that has `x0`, `x1` and `x2` bits set.
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2) {
return mask(x0) | mask(x1) | mask(x2);
}
//! Generate a bit-mask that has `x0`, `x1`, `x2` and `x3` bits set.
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) {
return mask(x0) | mask(x1) | mask(x2) | mask(x3);
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3` and `x4` bits set.
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4) {
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
mask(x4) ;
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4` and `x5` bits set.
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5) {
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
mask(x4) | mask(x5) ;
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5` and `x6` bits set.
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6) {
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
mask(x4) | mask(x5) | mask(x6) ;
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6` and `x7` bits set.
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) {
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
mask(x4) | mask(x5) | mask(x6) | mask(x7) ;
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6`, `x7` and `x8` bits set.
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7, uint32_t x8) {
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
mask(x4) | mask(x5) | mask(x6) | mask(x7) |
mask(x8) ;
}
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6`, `x7`, `x8` and `x9` bits set.
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7, uint32_t x8, uint32_t x9) {
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
mask(x4) | mask(x5) | mask(x6) | mask(x7) |
@@ -254,6 +275,7 @@ struct IntUtil {
// [AsmJit - Bits]
// --------------------------------------------------------------------------
//! Generate a bit-mask that has `x` most significant bits set.
static ASMJIT_INLINE uint32_t bits(uint32_t x) {
// Shifting more bits that the type has has undefined behavior. Everything
// we need is that application shouldn't crash because of that, but the
@@ -271,6 +293,7 @@ struct IntUtil {
// [AsmJit - HasBit]
// --------------------------------------------------------------------------
//! Get whether `x` has bit `n` set.
static ASMJIT_INLINE bool hasBit(uint32_t x, uint32_t n) {
return static_cast<bool>((x >> n) & 0x1);
}
@@ -279,7 +302,9 @@ struct IntUtil {
// [AsmJit - BitCount]
// --------------------------------------------------------------------------
// From http://graphics.stanford.edu/~seander/bithacks.html .
//! Get count of bits in `x`.
//!
//! Taken from http://graphics.stanford.edu/~seander/bithacks.html .
static ASMJIT_INLINE uint32_t bitCount(uint32_t x) {
x = x - ((x >> 1) & 0x55555555U);
x = (x & 0x33333333U) + ((x >> 2) & 0x33333333U);
@@ -290,6 +315,7 @@ struct IntUtil {
// [AsmJit - FindFirstBit]
// --------------------------------------------------------------------------
//! @internal
static ASMJIT_INLINE uint32_t findFirstBitSlow(uint32_t mask) {
// This is a reference (slow) implementation of findFirstBit(), used when
// we don't have compiler support for this task. The implementation speed
@@ -308,6 +334,7 @@ struct IntUtil {
return 0xFFFFFFFFU;
}
//! Find a first bit in `mask`.
static ASMJIT_INLINE uint32_t findFirstBit(uint32_t mask) {
#if defined(_MSC_VER)
DWORD i;
@@ -369,13 +396,13 @@ struct IntUtil {
return (base % alignment) == 0;
}
//! @brief Align @a base to @a alignment.
//! Align `base` to `alignment`.
template<typename T>
static ASMJIT_INLINE T alignTo(T base, T alignment) {
return (base + (alignment - 1)) & ~(alignment - 1);
}
//! @brief Get delta required to align @a base to @a alignment.
//! Get delta required to align `base` to `alignment`.
template<typename T>
static ASMJIT_INLINE T deltaTo(T base, T alignment) {
return alignTo(base, alignment) - base;
+16 -16
View File
@@ -26,14 +26,14 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_util
//! @{
// ============================================================================
// [asmjit::Lock]
// ============================================================================
//! @brief Lock - used in thread-safe code for locking.
//! Lock - used in thread-safe code for locking.
struct Lock {
ASMJIT_NO_COPY(Lock)
@@ -44,14 +44,14 @@ struct Lock {
#if defined(ASMJIT_OS_WINDOWS)
typedef CRITICAL_SECTION Handle;
//! @brief Create a new @ref Lock instance.
//! Create a new `Lock` instance.
ASMJIT_INLINE Lock() { InitializeCriticalSection(&_handle); }
//! @brief Destroy the @ref Lock instance.
//! Destroy the `Lock` instance.
ASMJIT_INLINE ~Lock() { DeleteCriticalSection(&_handle); }
//! @brief Lock.
//! Lock.
ASMJIT_INLINE void lock() { EnterCriticalSection(&_handle); }
//! @brief Unlock.
//! Unlock.
ASMJIT_INLINE void unlock() { LeaveCriticalSection(&_handle); }
#endif // ASMJIT_OS_WINDOWS
@@ -63,14 +63,14 @@ struct Lock {
#if defined(ASMJIT_OS_POSIX)
typedef pthread_mutex_t Handle;
//! @brief Create a new @ref Lock instance.
//! Create a new `Lock` instance.
ASMJIT_INLINE Lock() { pthread_mutex_init(&_handle, NULL); }
//! @brief Destroy the @ref Lock instance.
//! Destroy the `Lock` instance.
ASMJIT_INLINE ~Lock() { pthread_mutex_destroy(&_handle); }
//! @brief Lock.
//! Lock.
ASMJIT_INLINE void lock() { pthread_mutex_lock(&_handle); }
//! @brief Unlock.
//! Unlock.
ASMJIT_INLINE void unlock() { pthread_mutex_unlock(&_handle); }
#endif // ASMJIT_OS_POSIX
@@ -78,7 +78,7 @@ struct Lock {
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get handle.
//! Get handle.
ASMJIT_INLINE Handle& getHandle() { return _handle; }
//! @overload
ASMJIT_INLINE const Handle& getHandle() const { return _handle; }
@@ -87,7 +87,7 @@ struct Lock {
// [Members]
// --------------------------------------------------------------------------
//! @brief Handle.
//! Handle.
Handle _handle;
};
@@ -95,7 +95,7 @@ struct Lock {
// [asmjit::AutoLock]
// ============================================================================
//! @brief Scope auto locker.
//! Scope auto locker.
struct AutoLock {
ASMJIT_NO_COPY(AutoLock)
@@ -103,12 +103,12 @@ struct AutoLock {
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Locks @a target.
//! Autolock `target`, scoped.
ASMJIT_INLINE AutoLock(Lock& target) : _target(target) {
_target.lock();
}
//! @brief Unlocks target.
//! Autounlock `target`.
ASMJIT_INLINE ~AutoLock() {
_target.unlock();
}
@@ -117,7 +117,7 @@ struct AutoLock {
// [Members]
// --------------------------------------------------------------------------
//! @brief Pointer to target (lock).
//! Pointer to target (lock).
Lock& _target;
};
+11 -11
View File
@@ -21,21 +21,21 @@
namespace asmjit {
// ============================================================================
// [asmjit::BaseLogger - Construction / Destruction]
// [asmjit::Logger - Construction / Destruction]
// ============================================================================
BaseLogger::BaseLogger() {
Logger::Logger() {
_options = 0;
::memset(_indentation, 0, ASMJIT_ARRAY_SIZE(_indentation));
}
BaseLogger::~BaseLogger() {}
Logger::~Logger() {}
// ============================================================================
// [asmjit::BaseLogger - Logging]
// [asmjit::Logger - Logging]
// ============================================================================
void BaseLogger::logFormat(uint32_t style, const char* fmt, ...) {
void Logger::logFormat(uint32_t style, const char* fmt, ...) {
char buf[1024];
size_t len;
@@ -47,7 +47,7 @@ void BaseLogger::logFormat(uint32_t style, const char* fmt, ...) {
logString(style, buf, len);
}
void BaseLogger::logBinary(uint32_t style, const void* data, size_t size) {
void Logger::logBinary(uint32_t style, const void* data, size_t size) {
static const char prefix[] = ".data ";
static const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
@@ -78,10 +78,10 @@ void BaseLogger::logBinary(uint32_t style, const void* data, size_t size) {
}
// ============================================================================
// [asmjit::BaseLogger - LogBinary]
// [asmjit::Logger - LogBinary]
// ============================================================================
void BaseLogger::setOption(uint32_t id, bool value) {
void Logger::setOption(uint32_t id, bool value) {
if (id >= kLoggerOptionCount)
return;
@@ -94,10 +94,10 @@ void BaseLogger::setOption(uint32_t id, bool value) {
}
// ============================================================================
// [asmjit::BaseLogger - Indentation]
// [asmjit::Logger - Indentation]
// ============================================================================
void BaseLogger::setIndentation(const char* indentation) {
void Logger::setIndentation(const char* indentation) {
::memset(_indentation, 0, ASMJIT_ARRAY_SIZE(_indentation));
if (!indentation)
return;
@@ -120,7 +120,7 @@ FileLogger::~FileLogger() {}
// [asmjit::FileLogger - Accessors]
// ============================================================================
//! @brief Set file stream.
//! Set file stream.
void FileLogger::setStream(FILE* stream) {
_stream = stream;
}
+49 -52
View File
@@ -20,24 +20,24 @@
namespace asmjit {
//! @addtogroup asmjit_logging
//! @addtogroup asmjit_base_logging_and_errors
//! @{
// ============================================================================
// [asmjit::kLoggerOption]
// ============================================================================
//! @brief Logger options.
//! Logger options.
ASMJIT_ENUM(kLoggerOption) {
//! @brief Whether to output instructions also in binary form.
//! Whether to output instructions also in binary form.
kLoggerOptionBinaryForm = 0,
//! @brief Whether to output immediates as hexadecimal numbers.
//! Whether to output immediates as hexadecimal numbers.
kLoggerOptionHexImmediate = 1,
//! @brief Whether to output displacements as hexadecimal numbers.
//! Whether to output displacements as hexadecimal numbers.
kLoggerOptionHexDisplacement = 2,
//! @brief Count of logger options.
//! Count of logger options.
kLoggerOptionCount = 3
};
@@ -45,6 +45,7 @@ ASMJIT_ENUM(kLoggerOption) {
// [asmjit::kLoggerStyle]
// ============================================================================
//! Logger style.
ASMJIT_ENUM(kLoggerStyle) {
kLoggerStyleDefault = 0,
kLoggerStyleDirective = 1,
@@ -59,77 +60,75 @@ ASMJIT_ENUM(kLoggerStyle) {
// [asmjit::Logger]
// ============================================================================
//! @brief Abstract logging class.
//! Abstract logging class.
//!
//! This class can be inherited and reimplemented to fit into your logging
//! subsystem. When reimplementing use @c asmjit::Logger::log() method to
//! log into your stream.
//! subsystem. When reimplementing use `Logger::log()` method to log into
//! a custom stream.
//!
//! This class also contain @c _enabled member that can be used to enable
//! This class also contain `_enabled` member that can be used to enable
//! or disable logging.
struct BaseLogger {
ASMJIT_NO_COPY(BaseLogger)
struct Logger {
ASMJIT_NO_COPY(Logger)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a @ref BaseLogger instance.
ASMJIT_API BaseLogger();
//! @brief Destroy the @ref BaseLogger instance.
ASMJIT_API virtual ~BaseLogger();
//! Create a `Logger` instance.
ASMJIT_API Logger();
//! Destroy the `Logger` instance.
ASMJIT_API virtual ~Logger();
// --------------------------------------------------------------------------
// [Logging]
// --------------------------------------------------------------------------
//! @brief Abstract method to log output.
//!
//! Default implementation that is in @c asmjit::Logger is to do nothing.
//! It's virtual to fit to your logging system.
//! Log output.
virtual void logString(uint32_t style, const char* buf, size_t len = kInvalidIndex) = 0;
//! @brief Log formatter message (like sprintf) sending output to @c logString() method.
//! Log formatter message (like sprintf) sending output to `logString()` method.
ASMJIT_API void logFormat(uint32_t style, const char* fmt, ...);
//! @brief Log binary data.
//! Log binary data.
ASMJIT_API void logBinary(uint32_t style, const void* data, size_t size);
// --------------------------------------------------------------------------
// [Options]
// --------------------------------------------------------------------------
//! @brief Get all logger options as a single integer.
ASMJIT_INLINE uint32_t getOptions() const
{ return _options; }
//! Get all logger options as a single integer.
ASMJIT_INLINE uint32_t getOptions() const {
return _options;
}
//! @brief Get the given logger option.
//! Get the given logger option.
ASMJIT_INLINE bool getOption(uint32_t id) const {
ASMJIT_ASSERT(id < kLoggerOptionCount);
return static_cast<bool>((_options >> id) & 0x1);
}
//! @brief Set the given logger option.
//! Set the given logger option.
ASMJIT_API void setOption(uint32_t id, bool value);
// --------------------------------------------------------------------------
// [Indentation]
// --------------------------------------------------------------------------
//! @brief Get indentation.
//! Get indentation.
ASMJIT_INLINE const char* getIndentation() const { return _indentation; }
//! @brief Set indentation.
//! Set indentation.
ASMJIT_API void setIndentation(const char* indentation);
//! @brief Reset indentation.
//! Reset indentation.
ASMJIT_INLINE void resetIndentation() { setIndentation(NULL); }
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @brief Options, see @ref kLoggerOption.
//! Options, see `kLoggerOption`.
uint32_t _options;
//! @brief Indentation.
//! Indentation.
char _indentation[12];
};
@@ -137,35 +136,33 @@ struct BaseLogger {
// [asmjit::FileLogger]
// ============================================================================
//! @brief Logger that can log to standard C @c FILE* stream.
struct FileLogger : public BaseLogger {
//! Logger that can log to standard C `FILE*` stream.
struct FileLogger : public Logger {
ASMJIT_NO_COPY(FileLogger)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @c FileLogger.
//! @param stream FILE stream where logging will be sent (can be @c NULL
//! to disable logging).
//! Create a new `FileLogger` that logs to a `FILE` stream.
ASMJIT_API FileLogger(FILE* stream = NULL);
//! @brief Destroy the @ref FileLogger.
//! Destroy the `FileLogger`.
ASMJIT_API virtual ~FileLogger();
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get @c FILE* stream.
//! Get `FILE*` stream.
//!
//! @note Return value can be @c NULL.
//! @note Return value can be `NULL`.
ASMJIT_INLINE FILE* getStream() const { return _stream; }
//! @brief Set @c FILE* stream.
//! Set `FILE*` stream.
//!
//! @param stream @c FILE stream where to log output (can be @c NULL to
//! disable logging).
//! @param stream `FILE` stream where to log output, can be set to `NULL` to
//! disable logging.
ASMJIT_API void setStream(FILE* stream);
// --------------------------------------------------------------------------
@@ -178,7 +175,7 @@ struct FileLogger : public BaseLogger {
// [Members]
// --------------------------------------------------------------------------
//! @brief C file stream.
//! C file stream.
FILE* _stream;
};
@@ -186,31 +183,31 @@ struct FileLogger : public BaseLogger {
// [asmjit::StringLogger]
// ============================================================================
//! @brief String logger.
struct StringLogger : public BaseLogger {
//! String logger.
struct StringLogger : public Logger {
ASMJIT_NO_COPY(StringLogger)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create new @ref StringLogger.
//! Create new `StringLogger`.
ASMJIT_API StringLogger();
//! @brief Destroy the @ref StringLogger.
//! Destroy the `StringLogger`.
ASMJIT_API virtual ~StringLogger();
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get <code>char*</code> pointer which represents the resulting
//! Get <code>char*</code> pointer which represents the resulting
//! string.
//!
//! The pointer is owned by @ref StringLogger, it can't be modified or freed.
//! The pointer is owned by `StringLogger`, it can't be modified or freed.
ASMJIT_INLINE const char* getString() const { return _stringBuilder.getData(); }
//! @brief Clear the resulting string.
//! Clear the resulting string.
ASMJIT_INLINE void clearString() { _stringBuilder.clear(); }
// --------------------------------------------------------------------------
@@ -223,7 +220,7 @@ struct StringLogger : public BaseLogger {
// [Members]
// --------------------------------------------------------------------------
//! @brief Output.
//! Output.
StringBuilder _stringBuilder;
};
File diff suppressed because it is too large Load Diff
-169
View File
@@ -1,169 +0,0 @@
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_MEMORYMANAGER_H
#define _ASMJIT_BASE_MEMORYMANAGER_H
// [Dependencies - AsmJit]
#include "../base/defs.h"
#include "../base/error.h"
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
//! @addtogroup AsmJit_MemoryManagement
//! @{
// ============================================================================
// [asmjit::kVirtualAlloc]
// ============================================================================
//! @brief Type of virtual memory allocation, see @ref MemoryManager::alloc().
ASMJIT_ENUM(kVirtualAlloc) {
//! @brief Normal memory allocation, has to be freed by @ref MemoryManager::release().
kVirtualAllocFreeable = 0,
//! @brief Allocate permanent memory, can't be freed.
kVirtualAllocPermanent = 1
};
// ============================================================================
// [asmjit::MemoryManager]
// ============================================================================
//! @brief Virtual memory manager interface.
//!
//! This class is pure virtual. You can get default virtual memory manager using
//! @c getGlobal() method. If you want to create more memory managers with same
//! functionality as global memory manager use @c VirtualMemoryManager class.
struct MemoryManager {
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create memory manager instance.
ASMJIT_API MemoryManager();
//! @brief Destroy memory manager instance, this means also to free all memory
//! blocks.
ASMJIT_API virtual ~MemoryManager();
// --------------------------------------------------------------------------
// [Interface]
// --------------------------------------------------------------------------
//! @brief Free all allocated memory.
virtual void reset() = 0;
//! @brief Allocate a @a size bytes of virtual memory.
//!
//! Note that if you are implementing your own virtual memory manager then you
//! can quitly ignore type of allocation. This is mainly for AsmJit to memory
//! manager that allocated memory will be never freed.
virtual void* alloc(size_t size, uint32_t type = kVirtualAllocFreeable) = 0;
//! @brief Free previously allocated memory at a given @a address.
virtual Error release(void* address) = 0;
//! @brief Free some tail memory.
virtual Error shrink(void* address, size_t used) = 0;
//! @brief Get how many bytes are currently used.
virtual size_t getUsedBytes() = 0;
//! @brief Get how many bytes are currently allocated.
virtual size_t getAllocatedBytes() = 0;
// --------------------------------------------------------------------------
// [Statics]
// --------------------------------------------------------------------------
//! @brief Get global memory manager instance.
//!
//! Global instance is instance of @c VirtualMemoryManager class. Global memory
//! manager is used by default by @ref Assembler::make() and @ref Compiler::make()
//! methods.
static ASMJIT_API MemoryManager* getGlobal();
};
// ============================================================================
// [asmjit::VirtualMemoryManager]
// ============================================================================
//! @brief Reference implementation of memory manager that uses @ref asmjit::VMem
//! class to allocate chunks of virtual memory and bit arrays to manage it.
struct VirtualMemoryManager : public MemoryManager {
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a @c VirtualMemoryManager instance.
ASMJIT_API VirtualMemoryManager();
#if defined(ASMJIT_OS_WINDOWS)
//! @brief Create a @c VirtualMemoryManager instance for process @a hProcess.
//!
//! This is specialized version of constructor available only for windows and
//! usable to alloc/free memory of different process.
explicit ASMJIT_API VirtualMemoryManager(HANDLE hProcess);
#endif // ASMJIT_OS_WINDOWS
//! @brief Destroy the @c VirtualMemoryManager instance, this means also to
//! free all blocks.
ASMJIT_API virtual ~VirtualMemoryManager();
// --------------------------------------------------------------------------
// [Interface]
// --------------------------------------------------------------------------
ASMJIT_API virtual void reset();
ASMJIT_API virtual void* alloc(size_t size, uint32_t type = kVirtualAllocFreeable);
ASMJIT_API virtual Error release(void* address);
ASMJIT_API virtual Error shrink(void* address, size_t used);
ASMJIT_API virtual size_t getUsedBytes();
ASMJIT_API virtual size_t getAllocatedBytes();
// --------------------------------------------------------------------------
// [Virtual Memory Manager Specific]
// --------------------------------------------------------------------------
//! @brief Get whether to keep allocated memory after memory manager is
//! destroyed.
//!
//! @sa @c setKeepVirtualMemory().
ASMJIT_API bool getKeepVirtualMemory() const;
//! @brief Set whether to keep allocated memory after memory manager is
//! destroyed.
//!
//! This method is usable when patching code of remote process. You need to
//! allocate process memory, store generated assembler into it and patch the
//! method you want to redirect (into your code). This method affects only
//! VirtualMemoryManager destructor. After destruction all internal
//! structures are freed, only the process virtual memory remains.
//!
//! @note Memory allocated with kVirtualAllocPermanent is always kept.
//!
//! @sa @c getKeepVirtualMemory().
ASMJIT_API void setKeepVirtualMemory(bool keepVirtualMemory);
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @brief Pointer to private data hidden out of the public API.
void* _d;
};
//! @}
} // asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_MEMORYMANAGER_H
+5 -4
View File
@@ -17,13 +17,14 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_util
//! @{
// ============================================================================
// [asmjit::PodList<T>]
// ============================================================================
//! @internal
template <typename T>
struct PodList {
ASMJIT_NO_COPY(PodList<T>)
@@ -37,12 +38,12 @@ struct PodList {
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get next node.
//! Get next node.
ASMJIT_INLINE Link* getNext() const { return _next; }
//! @brief Get value.
//! Get value.
ASMJIT_INLINE T getValue() const { return _value; }
//! @brief Set value to @a value.
//! Set value to `value`.
ASMJIT_INLINE void setValue(const T& value) { _value = value; }
// --------------------------------------------------------------------------
+55 -36
View File
@@ -18,20 +18,23 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_util
//! @{
// ============================================================================
// [asmjit::PodVectorData]
// ============================================================================
//! @internal
struct PodVectorData {
//! @brief Get data.
ASMJIT_INLINE void* getData() const { return (void*)(this + 1); }
//! Get data.
ASMJIT_INLINE void* getData() const {
return (void*)(this + 1);
}
//! @brief Capacity of the vector.
//! Capacity of the vector.
size_t capacity;
//! @brief Length of the vector.
//! Length of the vector.
size_t length;
};
@@ -39,6 +42,7 @@ struct PodVectorData {
// [asmjit::PodVectorBase]
// ============================================================================
//! @internal
struct PodVectorBase {
static ASMJIT_API const PodVectorData _nullData;
@@ -46,11 +50,11 @@ struct PodVectorBase {
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new instance of @ref PodVectorBase.
//! Create a new instance of `PodVectorBase`.
ASMJIT_INLINE PodVectorBase() :
_d(const_cast<PodVectorData*>(&_nullData)) {}
//! @brief Destroy the @ref PodVectorBase and data.
//! Destroy the `PodVectorBase` and data.
ASMJIT_INLINE ~PodVectorBase() {
if (_d != &_nullData)
::free(_d);
@@ -76,7 +80,7 @@ public:
// [asmjit::PodVector<T>]
// ============================================================================
//! @brief Template used to store and manage array of POD data.
//! Template used to store and manage array of POD data.
//!
//! This template has these adventages over other vector<> templates:
//! - Non-copyable (designed to be non-copyable, we want it)
@@ -91,38 +95,51 @@ struct PodVector : PodVectorBase {
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create new instance of @ref PodVector<>.
//! Create a new instance of `PodVector<T>`.
ASMJIT_INLINE PodVector() {}
//! @brief Destroy the @ref PodVector<> and data.
//! Destroy the `PodVector<>` and data.
ASMJIT_INLINE ~PodVector() {}
// --------------------------------------------------------------------------
// [Data]
// --------------------------------------------------------------------------
//! @brief Get whether the vector is empty.
ASMJIT_INLINE bool isEmpty() const { return _d->length == 0; }
//! @brief Get length.
ASMJIT_INLINE size_t getLength() const { return _d->length; }
//! @brief Get capacity.
ASMJIT_INLINE size_t getCapacity() const { return _d->capacity; }
//! Get whether the vector is empty.
ASMJIT_INLINE bool isEmpty() const {
return _d->length == 0;
}
//! Get length.
ASMJIT_INLINE size_t getLength() const {
return _d->length;
}
//! Get capacity.
ASMJIT_INLINE size_t getCapacity() const {
return _d->capacity;
}
//! Get data.
ASMJIT_INLINE T* getData() {
return static_cast<T*>(_d->getData());
}
//! @brief Get data.
ASMJIT_INLINE T* getData() { return static_cast<T*>(_d->getData()); }
//! @overload
ASMJIT_INLINE const T* getData() const { return static_cast<const T*>(_d->getData()); }
ASMJIT_INLINE const T* getData() const {
return static_cast<const T*>(_d->getData());
}
// --------------------------------------------------------------------------
// [Clear / Reset]
// --------------------------------------------------------------------------
//! @brief Clear vector data, but don't free an internal buffer.
//! Clear vector data, but don't free an internal buffer.
ASMJIT_INLINE void clear() {
if (_d != &_nullData)
_d->length = 0;
}
//! @brief Clear vector data and free internal buffer.
//! Clear vector data and free internal buffer.
ASMJIT_INLINE void reset() {
if (_d != &_nullData) {
::free(_d);
@@ -134,19 +151,21 @@ struct PodVector : PodVectorBase {
// [Grow / Reserve]
// --------------------------------------------------------------------------
//! @brief Called to grow the buffer to fit at least @a n elements more.
ASMJIT_INLINE Error _grow(size_t n)
{ return PodVectorBase::_grow(n, sizeof(T)); }
//! Called to grow the buffer to fit at least `n` elements more.
ASMJIT_INLINE Error _grow(size_t n) {
return PodVectorBase::_grow(n, sizeof(T));
}
//! @brief Realloc internal array to fit at least @a to items.
ASMJIT_INLINE Error _reserve(size_t n)
{ return PodVectorBase::_reserve(n, sizeof(T)); }
//! Realloc internal array to fit at least `n` items.
ASMJIT_INLINE Error _reserve(size_t n) {
return PodVectorBase::_reserve(n, sizeof(T));
}
// --------------------------------------------------------------------------
// [Ops]
// --------------------------------------------------------------------------
//! @brief Prepend @a item to vector.
//! Prepend `item` to vector.
Error prepend(const T& item) {
PodVectorData* d = _d;
@@ -162,7 +181,7 @@ struct PodVector : PodVectorBase {
return kErrorOk;
}
//! @brief Insert an @a item at the @a index.
//! Insert an `item` at the `index`.
Error insert(size_t index, const T& item) {
PodVectorData* d = _d;
ASMJIT_ASSERT(index <= d->length);
@@ -180,7 +199,7 @@ struct PodVector : PodVectorBase {
return kErrorOk;
}
//! @brief Append @a item to vector.
//! Append `item` to vector.
Error append(const T& item) {
PodVectorData* d = _d;
@@ -195,7 +214,7 @@ struct PodVector : PodVectorBase {
return kErrorOk;
}
//! @brief Get index of @a val or kInvalidIndex if not found.
//! Get index of `val` or `kInvalidIndex` if not found.
size_t indexOf(const T& val) const {
PodVectorData* d = _d;
@@ -209,7 +228,7 @@ struct PodVector : PodVectorBase {
return kInvalidIndex;
}
//! @brief Remove item at index @a i.
//! Remove item at index `i`.
void removeAt(size_t i) {
PodVectorData* d = _d;
ASMJIT_ASSERT(i < d->length);
@@ -219,26 +238,26 @@ struct PodVector : PodVectorBase {
::memmove(data, data + 1, d->length - i);
}
//! @brief Swap this pod-vector with @a other.
//! Swap this pod-vector with `other`.
void swap(PodVector<T>& other) {
T* otherData = other._d;
other._d = _d;
_d = otherData;
}
//! @brief Get item at index @a i.
//! Get item at index `i`.
ASMJIT_INLINE T& operator[](size_t i) {
ASMJIT_ASSERT(i < getLength());
return getData()[i];
}
//! @brief Get item at index @a i.
//! Get item at index `i`.
ASMJIT_INLINE const T& operator[](size_t i) const {
ASMJIT_ASSERT(i < getLength());
return getData()[i];
}
//! @brief Allocate and append a new item and return its address.
//! Allocate and append a new item and return its address.
T* newElement() {
PodVectorData* d = _d;
+9 -13
View File
@@ -12,7 +12,6 @@
#include "../base/cpuinfo.h"
#include "../base/defs.h"
#include "../base/error.h"
#include "../base/memorymanager.h"
#include "../base/runtime.h"
// [Api-Begin]
@@ -21,19 +20,18 @@
namespace asmjit {
// ============================================================================
// [asmjit::BaseRuntime - Construction / Destruction]
// [asmjit::Runtime - Construction / Destruction]
// ============================================================================
BaseRuntime::BaseRuntime() {}
BaseRuntime::~BaseRuntime() {}
Runtime::Runtime() {}
Runtime::~Runtime() {}
// ============================================================================
// [asmjit::JitRuntime - Construction / Destruction]
// ============================================================================
JitRuntime::JitRuntime(MemoryManager* memmgr) :
_memoryManager(memmgr ? memmgr : MemoryManager::getGlobal()),
_allocType(kVirtualAllocFreeable) {}
JitRuntime::JitRuntime() :
_allocType(kVMemAllocFreeable) {}
JitRuntime::~JitRuntime() {}
@@ -82,8 +80,7 @@ Error JitRuntime::add(void** dst, BaseAssembler* assembler) {
return kErrorCompilerNoFunc;
}
MemoryManager* memmgr = getMemoryManager();
void* p = memmgr->alloc(codeSize, getAllocType());
void* p = _memMgr.alloc(codeSize, getAllocType());
if (p == NULL) {
*dst = NULL;
@@ -93,9 +90,9 @@ Error JitRuntime::add(void** dst, BaseAssembler* assembler) {
// Relocate the code.
size_t relocSize = assembler->relocCode(p);
// Return unused memory to MemoryManager.
// Return unused memory to `VMemMgr`.
if (relocSize < codeSize)
memmgr->shrink(p, relocSize);
_memMgr.shrink(p, relocSize);
// Return the code.
*dst = p;
@@ -103,8 +100,7 @@ Error JitRuntime::add(void** dst, BaseAssembler* assembler) {
}
Error JitRuntime::release(void* p) {
MemoryManager* memmgr = getMemoryManager();
return memmgr->release(p);
return _memMgr.release(p);
}
} // asmjit namespace
+42 -39
View File
@@ -10,63 +10,57 @@
// [Dependencies - AsmJit]
#include "../base/error.h"
#include "../base/vmem.h"
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
//! @addtogroup asmjit_base_codegen
//! @{
// ============================================================================
// [Forward Declarations]
// ============================================================================
struct BaseAssembler;
struct BaseCpuInfo;
struct MemoryManager;
// ============================================================================
// [asmjit::BaseRuntime]
// [asmjit::Runtime]
// ============================================================================
//! @brief Base runtime.
struct BaseRuntime {
ASMJIT_NO_COPY(BaseRuntime)
//! Base runtime.
struct Runtime {
ASMJIT_NO_COPY(Runtime)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a @ref BaseRuntime instance.
ASMJIT_API BaseRuntime();
//! @brief Destroy the @ref BaseRuntime instance.
ASMJIT_API virtual ~BaseRuntime();
//! Create a `Runtime` instance.
ASMJIT_API Runtime();
//! Destroy the `Runtime` instance.
ASMJIT_API virtual ~Runtime();
// --------------------------------------------------------------------------
// [Interface]
// --------------------------------------------------------------------------
//! @brief Get stack alignment of target runtime.
//! Get stack alignment of target runtime.
virtual uint32_t getStackAlignment() = 0;
//! @brief Get CPU information.
//! Get CPU information.
virtual const BaseCpuInfo* getCpuInfo() = 0;
//! @brief Allocate memory for code generated in @a assembler and reloc it
//! to the target location.
//! Allocate a memory needed for a code generated by `BaseAssembler` and
//! relocate it to the target location.
//!
//! This method is universal allowing any preprocessing / postprocessing
//! with code generated by @ref BaseAssembler or @ref BaseCompiler. Because
//! @ref BaseCompiler always uses @ref BaseAssembler it's allowed to access
//! only the @ref BaseAssembler instance.
//!
//! This method is always last step when using code generation. You can use
//! it to allocate memory for JIT code, saving code to remote process or a
//! file.
//!
//! @retrurn Status code, see @ref kError.
//! Returns Status code as `kError`.
virtual Error add(void** dst, BaseAssembler* assembler) = 0;
//! @brief Release memory allocated by add.
//! Release memory allocated by `add`.
virtual Error release(void* p) = 0;
};
@@ -74,21 +68,21 @@ struct BaseRuntime {
// [asmjit::JitRuntime]
// ============================================================================
//! @brief JIT runtime.
struct JitRuntime : public BaseRuntime {
//! JIT runtime.
struct JitRuntime : public Runtime {
ASMJIT_NO_COPY(JitRuntime)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a @c JitRuntime instance.
ASMJIT_API JitRuntime(MemoryManager* memmgr = NULL);
//! @brief Destroy the @c JitRuntime instance.
//! Create a `JitRuntime` instance.
ASMJIT_API JitRuntime();
//! Destroy the `JitRuntime` instance.
ASMJIT_API virtual ~JitRuntime();
// --------------------------------------------------------------------------
// [Memory Manager and Alloc Type]
// [Accessors]
// --------------------------------------------------------------------------
// Note: These members can be ignored by all derived classes. They are here
@@ -96,13 +90,20 @@ struct JitRuntime : public BaseRuntime {
// code patching or making dynamic loadable libraries/executables) ignore
// members accessed by these accessors.
//! @brief Get the @c MemoryManager instance.
ASMJIT_INLINE MemoryManager* getMemoryManager() const { return _memoryManager; }
//! Get the `VMemMgr` instance.
ASMJIT_INLINE VMemMgr* getMemMgr() const {
return const_cast<VMemMgr*>(&_memMgr);
}
//! @brief Get the type of allocation.
ASMJIT_INLINE uint32_t getAllocType() const { return _allocType; }
//! @brief Set the type of allocation.
ASMJIT_INLINE void setAllocType(uint32_t allocType) { _allocType = allocType; }
//! Get the type of allocation.
ASMJIT_INLINE uint32_t getAllocType() const {
return _allocType;
}
//! Set the type of allocation.
ASMJIT_INLINE void setAllocType(uint32_t allocType) {
_allocType = allocType;
}
// --------------------------------------------------------------------------
// [Interface]
@@ -118,12 +119,14 @@ struct JitRuntime : public BaseRuntime {
// [Members]
// --------------------------------------------------------------------------
//! @brief Memory manager.
MemoryManager* _memoryManager;
//! @brief Type of allocation.
//! Virtual memory manager.
VMemMgr _memMgr;
//! Type of allocation.
uint32_t _allocType;
};
//! @}
} // asmjit namespace
// [Api-End]
+96 -70
View File
@@ -20,18 +20,20 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_util
//! @{
// ============================================================================
// [asmjit::kStringOp]
// ============================================================================
//! @brief String operation.
//! @internal
//!
//! String operation.
ASMJIT_ENUM(kStringOp) {
//! @brief Replace the current string by a given content.
//! Replace the current string by a given content.
kStringOpSet = 0,
//! @brief Append a given content to the current string.
//! Append a given content to the current string.
kStringOpAppend = 1
};
@@ -39,7 +41,9 @@ ASMJIT_ENUM(kStringOp) {
// [asmjit::kStringFormat]
// ============================================================================
//! @brief String format flags.
//! @internal
//!
//! String format flags.
ASMJIT_ENUM(kStringFormat) {
kStringFormatShowSign = 0x00000001,
kStringFormatShowSpace = 0x00000002,
@@ -51,7 +55,9 @@ ASMJIT_ENUM(kStringFormat) {
// [asmjit::StringUtil]
// ============================================================================
//! @brief String utilities.
//! @internal
//!
//! String utilities.
struct StringUtil {
static ASMJIT_INLINE size_t nlen(const char* s, size_t maxlen) {
size_t i;
@@ -66,7 +72,9 @@ struct StringUtil {
// [asmjit::StringBuilder]
// ============================================================================
//! @brief String builder.
//! @internal
//!
//! String builder.
//!
//! String builder was designed to be able to build a string using append like
//! operation to append numbers, other strings, or signle characters. It can
@@ -90,31 +98,31 @@ struct StringBuilder {
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get string builder capacity.
//! Get string builder capacity.
ASMJIT_INLINE size_t getCapacity() const { return _capacity; }
//! @brief Get length.
//! Get length.
ASMJIT_INLINE size_t getLength() const { return _length; }
//! @brief Get null-terminated string data.
//! Get null-terminated string data.
ASMJIT_INLINE char* getData() { return _data; }
//! @brief Get null-terminated string data (const).
//! Get null-terminated string data (const).
ASMJIT_INLINE const char* getData() const { return _data; }
// --------------------------------------------------------------------------
// [Prepare / Reserve]
// --------------------------------------------------------------------------
//! @brief Prepare to set/append.
//! Prepare to set/append.
ASMJIT_API char* prepare(uint32_t op, size_t len);
//! @brief Reserve @a to bytes in string builder.
//! Reserve `to` bytes in string builder.
ASMJIT_API bool reserve(size_t to);
// --------------------------------------------------------------------------
// [Clear]
// --------------------------------------------------------------------------
//! @brief Clear the content in String builder.
//! Clear the content in String builder.
ASMJIT_API void clear();
// --------------------------------------------------------------------------
@@ -132,77 +140,91 @@ struct StringBuilder {
// [Set]
// --------------------------------------------------------------------------
//! @brief Replace the current content by @a str of @a len.
ASMJIT_INLINE bool setString(const char* str, size_t len = kInvalidIndex)
{ return _opString(kStringOpSet, str, len); }
//! Replace the current content by `str` of `len`.
ASMJIT_INLINE bool setString(const char* str, size_t len = kInvalidIndex) {
return _opString(kStringOpSet, str, len);
}
//! @brief Replace the current content by formatted string @a fmt.
ASMJIT_INLINE bool setVFormat(const char* fmt, va_list ap)
{ return _opVFormat(kStringOpSet, fmt, ap); }
//! Replace the current content by formatted string `fmt`.
ASMJIT_INLINE bool setVFormat(const char* fmt, va_list ap) {
return _opVFormat(kStringOpSet, fmt, ap);
}
//! @brief Replace the current content by formatted string @a fmt.
//! Replace the current content by formatted string `fmt`.
ASMJIT_API bool setFormat(const char* fmt, ...);
//! @brief Replace the current content by @a c character.
ASMJIT_INLINE bool setChar(char c)
{ return _opChar(kStringOpSet, c); }
//! Replace the current content by `c` character.
ASMJIT_INLINE bool setChar(char c) {
return _opChar(kStringOpSet, c);
}
//! @brief Replace the current content by @a c of @a len.
ASMJIT_INLINE bool setChars(char c, size_t len)
{ return _opChars(kStringOpSet, c, len); }
//! Replace the current content by `c` of `len`.
ASMJIT_INLINE bool setChars(char c, size_t len) {
return _opChars(kStringOpSet, c, len);
}
//! @brief Replace the current content by @a i..
ASMJIT_INLINE bool setInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0)
{ return _opNumber(kStringOpSet, i, base, width, flags | kStringFormatSigned); }
//! Replace the current content by formatted integer `i`.
ASMJIT_INLINE bool setInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
return _opNumber(kStringOpSet, i, base, width, flags | kStringFormatSigned);
}
//! @brief Replace the current content by @a i..
ASMJIT_INLINE bool setUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0)
{ return _opNumber(kStringOpSet, i, base, width, flags); }
//! Replace the current content by formatted integer `i`.
ASMJIT_INLINE bool setUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
return _opNumber(kStringOpSet, i, base, width, flags);
}
//! @brief Replace the current content by the given @a data converted to a HEX string.
ASMJIT_INLINE bool setHex(const void* data, size_t len)
{ return _opHex(kStringOpSet, data, len); }
//! Replace the current content by the given `data` converted to a HEX string.
ASMJIT_INLINE bool setHex(const void* data, size_t len) {
return _opHex(kStringOpSet, data, len);
}
// --------------------------------------------------------------------------
// [Append]
// --------------------------------------------------------------------------
//! @brief Append @a str of @a len.
ASMJIT_INLINE bool appendString(const char* str, size_t len = kInvalidIndex)
{ return _opString(kStringOpAppend, str, len); }
//! Append `str` of `len`.
ASMJIT_INLINE bool appendString(const char* str, size_t len = kInvalidIndex) {
return _opString(kStringOpAppend, str, len);
}
//! @brief Append a formatted string @a fmt to the current content.
ASMJIT_INLINE bool appendVFormat(const char* fmt, va_list ap)
{ return _opVFormat(kStringOpAppend, fmt, ap); }
//! Append a formatted string `fmt` to the current content.
ASMJIT_INLINE bool appendVFormat(const char* fmt, va_list ap) {
return _opVFormat(kStringOpAppend, fmt, ap);
}
//! @brief Append a formatted string @a fmt to the current content.
//! Append a formatted string `fmt` to the current content.
ASMJIT_API bool appendFormat(const char* fmt, ...);
//! @brief Append @a c character.
ASMJIT_INLINE bool appendChar(char c)
{ return _opChar(kStringOpAppend, c); }
//! Append `c` character.
ASMJIT_INLINE bool appendChar(char c) {
return _opChar(kStringOpAppend, c);
}
//! @brief Append @a c of @a len.
ASMJIT_INLINE bool appendChars(char c, size_t len)
{ return _opChars(kStringOpAppend, c, len); }
//! Append `c` of `len`.
ASMJIT_INLINE bool appendChars(char c, size_t len) {
return _opChars(kStringOpAppend, c, len);
}
//! @brief Append @a i.
ASMJIT_INLINE bool appendInt(int64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0)
{ return _opNumber(kStringOpAppend, static_cast<uint64_t>(i), base, width, flags | kStringFormatSigned); }
//! Append `i`.
ASMJIT_INLINE bool appendInt(int64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
return _opNumber(kStringOpAppend, static_cast<uint64_t>(i), base, width, flags | kStringFormatSigned);
}
//! @brief Append @a i.
ASMJIT_INLINE bool appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0)
{ return _opNumber(kStringOpAppend, i, base, width, flags); }
//! Append `i`.
ASMJIT_INLINE bool appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
return _opNumber(kStringOpAppend, i, base, width, flags);
}
//! @brief Append the given @a data converted to a HEX string.
ASMJIT_INLINE bool appendHex(const void* data, size_t len)
{ return _opHex(kStringOpAppend, data, len); }
//! Append the given `data` converted to a HEX string.
ASMJIT_INLINE bool appendHex(const void* data, size_t len) {
return _opHex(kStringOpAppend, data, len);
}
// --------------------------------------------------------------------------
// [_Append]
// --------------------------------------------------------------------------
//! @brief Append @a str of @a len (inlined, without buffer overflow check).
//! Append `str` of `len`, inlined, without buffer overflow check.
ASMJIT_INLINE void _appendString(const char* str, size_t len = kInvalidIndex) {
// len should be a constant if we are inlining.
if (len == kInvalidIndex) {
@@ -230,7 +252,7 @@ struct StringBuilder {
}
}
//! @brief Append @a c character (inlined, without buffer overflow check).
//! Append `c` character, inlined, without buffer overflow check.
ASMJIT_INLINE void _appendChar(char c) {
ASMJIT_ASSERT(_capacity - _length >= 1);
@@ -239,7 +261,7 @@ struct StringBuilder {
_data[_length] = '\0';
}
//! @brief Append @a c of @a len (inlined, without buffer overflow check).
//! Append `c` of `len`, inlined, without buffer overflow check.
ASMJIT_INLINE void _appendChars(char c, size_t len) {
ASMJIT_ASSERT(_capacity - _length >= len);
@@ -282,10 +304,12 @@ struct StringBuilder {
// [Eq]
// --------------------------------------------------------------------------
//! @brief Check for equality with other @a str.
//! Check for equality with other `str` of `len`.
ASMJIT_API bool eq(const char* str, size_t len = kInvalidIndex) const;
//! @brief Check for equality with StringBuilder @a other.
ASMJIT_INLINE bool eq(const StringBuilder& other) const { return eq(other._data); }
//! Check for equality with `other`.
ASMJIT_INLINE bool eq(const StringBuilder& other) const {
return eq(other._data);
}
// --------------------------------------------------------------------------
// [Operator Overload]
@@ -301,13 +325,13 @@ struct StringBuilder {
// [Members]
// --------------------------------------------------------------------------
//! @brief String data.
//! String data.
char* _data;
//! @brief Length.
//! Length.
size_t _length;
//! @brief Capacity.
//! Capacity.
size_t _capacity;
//! @brief Whether the string can be freed.
//! Whether the string can be freed.
size_t _canFree;
};
@@ -315,6 +339,7 @@ struct StringBuilder {
// [asmjit::StringBuilderT]
// ============================================================================
//! @internal
template<size_t N>
struct StringBuilderT : public StringBuilder {
ASMJIT_NO_COPY(StringBuilderT<N>)
@@ -336,8 +361,9 @@ struct StringBuilderT : public StringBuilder {
// [Members]
// --------------------------------------------------------------------------
//! @brief Embedded data.
char _embeddedData[static_cast<size_t>(N + 1 + sizeof(intptr_t)) & ~static_cast<size_t>(sizeof(intptr_t) - 1)];
//! Embedded data.
char _embeddedData[static_cast<size_t>(
N + 1 + sizeof(intptr_t)) & ~static_cast<size_t>(sizeof(intptr_t) - 1)];
};
//! @}
+150 -147
View File
File diff suppressed because it is too large Load Diff
+1106 -46
View File
File diff suppressed because it is too large Load Diff
+133 -24
View File
@@ -8,61 +8,170 @@
#ifndef _ASMJIT_BASE_VMEM_H
#define _ASMJIT_BASE_VMEM_H
// [Dependencies]
#include "../base/defs.h"
#include "../base/error.h"
// [Dependencies - Windows]
#if defined(ASMJIT_OS_WINDOWS)
# include <windows.h>
#endif // ASMJIT_OS_WINDOWS
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_util
//! @{
// ============================================================================
// [asmjit::VMem]
// [asmjit::kVMemAlloc]
// ============================================================================
//! @brief Class that helps with allocating memory for executing code
//! generated by JIT compiler.
//! Type of virtual memory allocation, see `VMemMgr::alloc()`.
ASMJIT_ENUM(kVMemAlloc) {
//! Normal memory allocation, has to be freed by `VMemMgr::release()`.
kVMemAllocFreeable = 0,
//! Allocate permanent memory, can't be freed.
kVMemAllocPermanent = 1
};
// ============================================================================
// [asmjit::VMemUtil]
// ============================================================================
//! Virtual memory utilities.
//!
//! There are defined functions that provides facility to allocate and free
//! memory where can be executed code. If processor and operating system
//! supports execution protection then you can't run code from normally
//! malloc()'ed memory.
//! Defines functions that provide facility to allocate and free memory that is
//! executable in a platform independent manner. If both the processor and host
//! operating system support data-execution-prevention then the only way how to
//! run machine code is to allocate it to a memory that has marked as executable.
//! VMemUtil is just unified interface to platform dependent APIs.
//!
//! Functions are internally implemented by operating system dependent way.
//! VirtualAlloc() function is used for Windows operating system and mmap()
//! for posix ones. If you want to study or create your own functions, look
//! at VirtualAlloc() or mmap() documentation (depends on you target OS).
//!
//! Under posix operating systems is also useable mprotect() function, that
//! can enable execution protection to malloc()'ed memory block.
struct VMem {
//! @brief Allocate virtual memory.
//! `VirtualAlloc()` function is used on Windows operating system and `mmap()`
//! on POSIX. `VirtualAlloc()` and `mmap()` documentation provide a detailed
//! overview on how to use a platform specific APIs.
struct VMemUtil {
//! Get the alignment guaranteed by alloc().
static ASMJIT_API size_t getAlignment();
//! Get size of the single page.
static ASMJIT_API size_t getPageSize();
//! Allocate virtual memory.
//!
//! Pages are readable/writeable, but they are not guaranteed to be
//! executable unless 'canExecute' is true. Returns the address of
//! allocated memory, or NULL on failure.
static ASMJIT_API void* alloc(size_t length, size_t* allocated, bool canExecute);
//! @brief Free memory allocated by @c alloc()
//! Free memory allocated by `alloc()`.
static ASMJIT_API void release(void* addr, size_t length);
#if defined(ASMJIT_OS_WINDOWS)
//! @brief Allocate virtual memory of @a hProcess.
//! Allocate virtual memory of `hProcess`.
//!
//! @note This function is Windows specific.
static ASMJIT_API void* allocProcessMemory(HANDLE hProcess, size_t length, size_t* allocated, bool canExecute);
//! @brief Free virtual memory of @a hProcess.
//! Free virtual memory of `hProcess`.
//!
//! @note This function is Windows specific.
static ASMJIT_API void releaseProcessMemory(HANDLE hProcess, void* addr, size_t length);
#endif // ASMJIT_OS_WINDOWS
};
//! @brief Get the alignment guaranteed by alloc().
static ASMJIT_API size_t getAlignment();
// ============================================================================
// [asmjit::VMemMgr]
// ============================================================================
//! @brief Get size of the single page.
static ASMJIT_API size_t getPageSize();
//! Reference implementation of memory manager that uses `VMemUtil` to allocate
//! chunks of virtual memory and bit arrays to manage it.
struct VMemMgr {
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a `VMemMgr` instance.
ASMJIT_API VMemMgr();
#if defined(ASMJIT_OS_WINDOWS)
//! Create a `VMemMgr` instance for `hProcess`.
//!
//! This is a specialized version of constructor available only for windows
//! and usable to alloc/free memory of a different process.
explicit ASMJIT_API VMemMgr(HANDLE hProcess);
#endif // ASMJIT_OS_WINDOWS
//! Destroy the `VMemMgr` instance and free all blocks.
ASMJIT_API ~VMemMgr();
// --------------------------------------------------------------------------
// [Reset]
// --------------------------------------------------------------------------
//! Free all allocated memory.
ASMJIT_API void reset();
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
#if defined(ASMJIT_OS_WINDOWS)
//! Get the handle of the process memory manager is bound to.
ASMJIT_API HANDLE getProcessHandle() const;
#endif // ASMJIT_OS_WINDOWS
//! Get how many bytes are currently used.
ASMJIT_API size_t getUsedBytes() const;
//! Get how many bytes are currently allocated.
ASMJIT_API size_t getAllocatedBytes() const;
//! Get whether to keep allocated memory after the `VMemMgr` is destroyed.
//!
//! @sa `setKeepVirtualMemory()`.
ASMJIT_API bool getKeepVirtualMemory() const;
//! Set whether to keep allocated memory after memory manager is
//! destroyed.
//!
//! This method is usable when patching code of remote process. You need to
//! allocate process memory, store generated assembler into it and patch the
//! method you want to redirect (into your code). This method affects only
//! VMemMgr destructor. After destruction all internal
//! structures are freed, only the process virtual memory remains.
//!
//! @note Memory allocated with kVMemAllocPermanent is always kept.
//!
//! @sa `getKeepVirtualMemory()`.
ASMJIT_API void setKeepVirtualMemory(bool keepVirtualMemory);
// --------------------------------------------------------------------------
// [Alloc / Release]
// --------------------------------------------------------------------------
//! Allocate a `size` bytes of virtual memory.
//!
//! Note that if you are implementing your own virtual memory manager then you
//! can quitly ignore type of allocation. This is mainly for AsmJit to memory
//! manager that allocated memory will be never freed.
ASMJIT_API void* alloc(size_t size, uint32_t type = kVMemAllocFreeable);
//! Free previously allocated memory at a given `address`.
ASMJIT_API Error release(void* address);
//! Free some tail memory.
ASMJIT_API Error shrink(void* address, size_t used);
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @internal
//!
//! Pointer to private data hidden out of the public API.
void* _d;
};
//! @}
+1 -1
View File
@@ -20,7 +20,7 @@
namespace asmjit {
//! @brief Zero width chunk used when Zone doesn't have any memory allocated.
//! Zero width chunk used when Zone doesn't have any memory allocated.
static const Zone::Chunk Zone_zeroChunk = {
NULL, 0, 0, { 0 }
};
+29 -31
View File
@@ -16,17 +16,17 @@
namespace asmjit {
//! @addtogroup asmjit_base
//! @addtogroup asmjit_base_util
//! @{
// ============================================================================
// [asmjit::Zone]
// ============================================================================
//! @brief Fast incremental memory allocator.
//! Fast incremental memory allocator.
//!
//! Memory allocator designed to allocate small objects that will be invalidated
//! (free) all at once.
//! (freed) all at once.
struct Zone {
// --------------------------------------------------------------------------
// [Chunk]
@@ -34,19 +34,19 @@ struct Zone {
//! @internal
//!
//! @brief One allocated chunk of memory.
//! One allocated chunk of memory.
struct Chunk {
//! @brief Get count of remaining (unused) bytes in chunk.
//! Get count of remaining (unused) bytes in chunk.
ASMJIT_INLINE size_t getRemainingSize() const { return size - pos; }
//! @brief Link to previous chunk.
//! Link to previous chunk.
Chunk* prev;
//! @brief Position in this chunk.
//! Position in this chunk.
size_t pos;
//! @brief Size of this chunk (in bytes).
//! Size of this chunk (in bytes).
size_t size;
//! @brief Data.
//! Data.
uint8_t data[sizeof(void*)];
};
@@ -54,25 +54,25 @@ struct Zone {
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new instance of @c Zone allocator.
//! Create a new instance of `Zone` allocator.
//!
//! @param chunkSize Default size of the first chunk.
ASMJIT_API Zone(size_t chunkSize);
//! @brief Destroy @ref Zone instance.
//! Destroy `Zone` instance.
ASMJIT_API ~Zone();
// --------------------------------------------------------------------------
// [Clear / Reset]
// --------------------------------------------------------------------------
//! @brief Free all allocated memory except first block that remains for reuse.
//! Free all allocated memory except first block that remains for reuse.
//!
//! Note that this method will invalidate all instances using this memory
//! allocated by this zone instance.
ASMJIT_API void clear();
//! @brief Free all allocated memory at once.
//! Free all allocated memory at once.
//!
//! Note that this method will invalidate all instances using this memory
//! allocated by this zone instance.
@@ -82,32 +82,30 @@ struct Zone {
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get (default) chunk size.
//! Get (default) chunk size.
ASMJIT_INLINE size_t getChunkSize() const { return _chunkSize; }
// --------------------------------------------------------------------------
// [Alloc]
// --------------------------------------------------------------------------
//! @brief Allocate @c size bytes of memory.
//! Allocate `size` bytes of memory.
//!
//! Pointer allocated by this way will be valid until @c Zone object is
//! destroyed. To create class by this way use placement @c new and @c delete
//! Pointer allocated by this way will be valid until `Zone` object is
//! destroyed. To create class by this way use placement `new` and `delete`
//! operators:
//!
//! @code
//! ~~~
//! // Example of simple class allocation.
//! using namespace asmjit
//!
//! // Your class.
//! class Object
//! {
//! class Object {
//! // members...
//! };
//!
//! // Your function
//! void f()
//! {
//! void f() {
//! // Create zone object with chunk size of 65536 bytes.
//! Zone zone(65536);
//!
@@ -120,9 +118,9 @@ struct Zone {
//! obj->~Object();
//!
//! // Zone destructor will free all memory allocated through it, you can
//! // call @c zone.reset() if you wan't to reuse current @ref Zone.
//! // call `zone.reset()` if you wan't to reuse current `Zone`.
//! }
//! @endcode
//! ~~~
ASMJIT_INLINE void* alloc(size_t size) {
Chunk* cur = _chunks;
@@ -136,7 +134,7 @@ struct Zone {
return (void*)p;
}
//! @brief Like @ref alloc(), but returns <code>T*</code>.
//! Like `alloc()`, but the return is casted to `T*`.
template<typename T>
ASMJIT_INLINE T* allocT(size_t size = sizeof(T)) {
return static_cast<T*>(alloc(size));
@@ -145,7 +143,7 @@ struct Zone {
//! @internal
ASMJIT_API void* _alloc(size_t size);
//! @brief Allocate @c size bytes of zeroed memory.
//! Allocate `size` bytes of zeroed memory.
ASMJIT_INLINE void* calloc(size_t size) {
Chunk* cur = _chunks;
@@ -163,22 +161,22 @@ struct Zone {
//! @internal
ASMJIT_API void* _calloc(size_t size);
//! @brief Helper to duplicate data.
//! Helper to duplicate data.
ASMJIT_API void* dup(const void* data, size_t size);
//! @brief Helper to duplicate string.
//! Helper to duplicate string.
ASMJIT_API char* sdup(const char* str);
//! @brief Helper to duplicate formatted string, maximum length is 256 bytes.
//! Helper to duplicate formatted string, maximum length is 256 bytes.
ASMJIT_API char* sformat(const char* str, ...);
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! @brief Last allocated chunk of memory.
//! Last allocated chunk of memory.
Chunk* _chunks;
//! @brief Default chunk size.
//! Default chunk size.
size_t _chunkSize;
};
+10
View File
@@ -31,6 +31,16 @@
// [Dependencies - C++]
#include <new>
// ============================================================================
// [asmjit::build - Documentation]
// ============================================================================
#if defined(ASMJIT_DOCGEN)
# define ASMJIT_BUILD_X86
# define ASMJIT_BUILD_X64
# define ASMJIT_API
#endif // ASMJIT_DOCGEN
// ============================================================================
// [asmjit::build - OS]
// ============================================================================
+4 -5
View File
@@ -22,11 +22,10 @@ namespace contrib {
// ============================================================================
WinRemoteRuntime::WinRemoteRuntime(HANDLE hProcess) :
_hProcess(hProcess),
_memoryManager(hProcess) {
_memMgr(hProcess) {
// We are patching another process so enable keep-virtual-memory option.
_memoryManager.setKeepVirtualMemory(true);
_memMgr.setKeepVirtualMemory(true);
}
WinRemoteRuntime::~WinRemoteRuntime() {}
@@ -53,7 +52,7 @@ uint32_t WinRemoteRuntime::add(void** dest, BaseAssembler* assembler) {
}
// Allocate a pernament remote process memory.
void* processMemPtr = _memoryManager.alloc(codeSize, kVirtualAllocPermanent);
void* processMemPtr = _memMgr.alloc(codeSize, kVMemAllocPermanent);
if (processMemPtr == NULL) {
::free(codeData);
@@ -64,7 +63,7 @@ uint32_t WinRemoteRuntime::add(void** dest, BaseAssembler* assembler) {
// Relocate and write the code to the process memory.
assembler->relocCode(codeData, (uintptr_t)processMemPtr);
::WriteProcessMemory(_hProcess, processMemPtr, codeData, codeSize, NULL);
::WriteProcessMemory(getProcessHandle(), processMemPtr, codeData, codeSize, NULL);
::free(codeData);
*dest = processMemPtr;
+15 -13
View File
@@ -21,28 +21,33 @@ namespace contrib {
// [asmjit::contrib::WinRemoteRuntime]
// ============================================================================
//! @brief WinRemoteRuntime can be used to inject code to a remote process.
struct WinRemoteRuntime : public BaseRuntime {
//! WinRemoteRuntime can be used to inject code to a remote process.
struct WinRemoteRuntime : public Runtime {
ASMJIT_NO_COPY(WinRemoteRuntime)
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a @c WinRemoteRuntime instance for a given @a hProcess.
//! Create a `WinRemoteRuntime` instance for a given `hProcess`.
ASMJIT_API WinRemoteRuntime(HANDLE hProcess);
//! @brief Destroy the @c WinRemoteRuntime instance.
//! Destroy the `WinRemoteRuntime` instance.
ASMJIT_API virtual ~WinRemoteRuntime();
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get the remote process handle.
ASMJIT_INLINE HANDLE getProcess() const { return _hProcess; }
//! Get the remote process handle.
ASMJIT_INLINE HANDLE getProcessHandle() const {
return _memMgr.getProcessHandle();
}
//! @brief Get the virtual memory manager.
ASMJIT_INLINE VirtualMemoryManager* getMemoryManager() { return &_memoryManager; }
//! Get the remote memory manager.
ASMJIT_INLINE VMemMgr* getMemMgr() const {
return const_cast<VMemMgr*>(&_memMgr);
}
// --------------------------------------------------------------------------
// [Interface]
@@ -54,11 +59,8 @@ struct WinRemoteRuntime : public BaseRuntime {
// [Members]
// --------------------------------------------------------------------------
//! @brief Process.
HANDLE _hProcess;
//! @brief Virtual memory manager.
VirtualMemoryManager _memoryManager;
//! Remove memory manager.
VMemMgr _memMgr;
};
} // contrib namespace
+107
View File
@@ -8,7 +8,114 @@
#ifndef _ASMJIT_X86_H
#define _ASMJIT_X86_H
// ============================================================================
// [asmjit_x86x64]
// ============================================================================
//! @defgroup asmjit_x86x64 X86/X64
//!
//! @brief X86/X64 API
// ============================================================================
// [asmjit_x86x64_codegen]
// ============================================================================
//! @defgroup asmjit_x86x64_codegen Code Generation (X86/X64)
//! @ingroup asmjit_x86x64
//!
//! @brief Low-level and high-level code generation.
// ============================================================================
// [asmjit_x86x64_cpu_info]
// ============================================================================
//! @defgroup asmjit_x86x64_cpu_info CPU Information (X86/X64)
//! @ingroup asmjit_x86x64
//!
//! @brief CPU information specific to X86/X64 architecture.
//!
//! The CPUID instruction can be used to get an exhaustive information related
//! to the host X86/X64 processor. AsmJit contains utilities that can get the
//! most important information related to the features supported by the CPU
//! and the host operating system, in addition to host processor name and number
//! of cores. Class `CpuInfo` extends `BaseCpuInfo` and provides functionality
//! specific to X86 and X64.
//!
//! By default AsmJit queries the CPU information after the library is loaded
//! and the queried information is reused by all instances of `JitRuntime`.
//! The global instance of `CpuInfo` can't be changed, because it will affect
//! the code generation of all `Runtime`s. If there is a need to have a
//! specific CPU information which contains modified features or processor
//! vendor it's possible by creating a new instance of `CpuInfo` and setting
//! up its members. `CpuUtil::detect` can be used to detect CPU features into
//! an existing `CpuInfo` instance - it may become handly if only one property
//! has to be turned on/off.
//!
//! If the high-level interface `CpuInfo` offers is not enough there is also
//! `CpuUtil::callCpuId` helper that can be used to call CPUID instruction with
//! a given parameters and to consume the output.
//!
//! Cpu detection is important when generating a JIT code that may or may not
//! use certain CPU features. For example there used to be a SSE/SSE2 detection
//! in the past and today there is often AVX/AVX2 detection.
//!
//! The example below shows how to detect SSE2:
//!
//! ~~~
//! using namespace asmjit;
//! using namespace asmjit::host;
//!
//! // Get `CpuInfo` global instance.
//! const CpuInfo* cpuInfo = CpuInfo::getHost();
//!
//! if (cpuInfo->hasFeature(kCpuFeatureSse2)) {
//! // Processor has SSE2.
//! }
//! else if (cpuInfo->hasFeature(kCpuFeatureMmx)) {
//! // Processor doesn't have SSE2, but has MMX.
//! }
//! else {
//! // An archaic processor, it's a wonder AsmJit works here!
//! }
//! ~~~
//!
//! The next example shows how to call CPUID directly:
//!
//! ~~~
//! using namespace asmjit;
//!
//! // The result of CPUID call.
//! CpuId out;
//!
//! // Call CPUID, first two arguments are passed in EAX/ECX.
//! CpuUtil::callCpuId(0, 0, &out);
//!
//! // If EAX argument is 0, EBX, ECX and EDX registers are filled with a cpu vendor.
//! char cpuVendor[13];
//! memcpy(cpuVendor, &out.ebx, 4);
//! memcpy(cpuVendor + 4, &out.edx, 4);
//! memcpy(cpuVendor + 8, &out.ecx, 4);
//! vendor[12] = '\0';
//!
//! // Print a CPU vendor retrieved from CPUID.
//! ::printf("%s", cpuVendor);
//! ~~~
//!
//! @sa @ref asmjit_base_cpu_info
// ============================================================================
// [asmjit_x86x64_constants]
// ============================================================================
//! @defgroup asmjit_x86x64_constants Constants (X86/X64)
//! @ingroup asmjit_x86x64
//!
//! @brief Constants and definitions specific to X86/X64 architecture.
// ============================================================================
// [Dependencies - AsmJit]
// ============================================================================
#include "base.h"
#include "x86/x86assembler.h"
+17 -16
View File
@@ -14,9 +14,9 @@
// [Dependencies - AsmJit]
#include "../base/intutil.h"
#include "../base/logger.h"
#include "../base/memorymanager.h"
#include "../base/runtime.h"
#include "../base/string.h"
#include "../base/vmem.h"
#include "../x86/x86assembler.h"
#include "../x86/x86cpuinfo.h"
#include "../x86/x86defs.h"
@@ -60,7 +60,7 @@ enum kVexVVVV {
//! @internal
//!
//! @brief Instruction 2-byte/3-byte opcode prefix definition.
//! Instruction 2-byte/3-byte opcode prefix definition.
struct OpCodeMM {
uint8_t len;
uint8_t data[3];
@@ -68,7 +68,7 @@ struct OpCodeMM {
//! @internal
//!
//! @brief Mandatory prefixes encoded in 'asmjit' opcode [66, F3, F2] and asmjit
//! Mandatory prefixes encoded in 'asmjit' opcode [66, F3, F2] and asmjit
//! extensions
static const uint8_t x86OpCodePP[8] = {
0x00,
@@ -83,7 +83,7 @@ static const uint8_t x86OpCodePP[8] = {
//! @internal
//!
//! @brief Instruction 2-byte/3-byte opcode prefix data.
//! Instruction 2-byte/3-byte opcode prefix data.
static const OpCodeMM x86OpCodeMM[] = {
{ 0, { 0x00, 0x00, 0 } },
{ 1, { 0x0F, 0x00, 0 } },
@@ -111,7 +111,9 @@ static const uint8_t x86OpCodePopSeg[8] = { 0x00, 0x07, 0x00, 0x17, 0x1F, 0xA1,
// [asmjit::X64TrampolineWriter]
// ============================================================================
//! @brief Trampoline writer.
//! @internal
//!
//! Trampoline writer.
struct X64TrampolineWriter {
// Size of trampoline
enum {
@@ -120,9 +122,8 @@ struct X64TrampolineWriter {
kSizeTotal = kSizeJmp + kSizeAddr
};
// Write trampoline into code at address @a code that will jump to @a target.
static void writeTrampoline(uint8_t* code, uint64_t target)
{
// Write trampoline into code at address `code` that will jump to `target`.
static void writeTrampoline(uint8_t* code, uint64_t target) {
code[0] = 0xFF; // Jmp OpCode.
code[1] = 0x25; // ModM (RIP addressing).
((uint32_t*)(code + 2))[0] = 0; // Offset (zero).
@@ -221,7 +222,7 @@ struct X64TrampolineWriter {
// [asmjit::x86x64::Assembler - Construction / Destruction]
// ============================================================================
X86X64Assembler::X86X64Assembler(BaseRuntime* runtime) : BaseAssembler(runtime) {}
X86X64Assembler::X86X64Assembler(Runtime* runtime) : BaseAssembler(runtime) {}
X86X64Assembler::~X86X64Assembler() {}
// ============================================================================
@@ -887,12 +888,12 @@ static bool X86Assembler_dumpComment(StringBuilder& sb, size_t len, const uint8_
// [asmjit::x86x64::Assembler - Emit]
// ============================================================================
//! @brief Encode MODR/M.
//! Encode MODR/M.
static ASMJIT_INLINE uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) {
return (m << 6) + (o << 3) + rm;
}
//! @brief Encode SIB.
//! Encode SIB.
static ASMJIT_INLINE uint32_t x86EncodeSib(uint32_t s, uint32_t i, uint32_t b) {
return (s << 6) + (i << 3) + b;
}
@@ -928,7 +929,7 @@ static ASMJIT_INLINE Error X86X64Assembler_emit(X86X64Assembler* self, uint32_t
//
// AVX:
// 0x0008 - AVX.W.
// 0xF000 - VVVV, zeros by default, see @ref kVexVVVV.
// 0xF000 - VVVV, zeros by default, see `kVexVVVV`.
//
uint32_t opX;
@@ -3969,8 +3970,8 @@ _EmitXopM:
// [Emit - Jump/Call to an Immediate]
// --------------------------------------------------------------------------
// Emit relative relocation to absolute pointer @a target. It's needed
// to add what instruction is emitting this, because in x64 mode the relative
// Emit relative relocation to absolute pointer `target`. It's needed to add
// what instruction is emitting this, because in x64 mode the relative
// displacement can be impossible to calculate and in this case the trampoline
// is used.
_EmitJmpOrCallImm:
@@ -4087,7 +4088,7 @@ _GrowBuffer:
namespace asmjit {
namespace x86 {
Assembler::Assembler(BaseRuntime* runtime) : X86X64Assembler(runtime) {
Assembler::Assembler(Runtime* runtime) : X86X64Assembler(runtime) {
_arch = kArchX86;
_regSize = 4;
}
@@ -4116,7 +4117,7 @@ Error Assembler::_emit(uint32_t code, const Operand& o0, const Operand& o1, cons
namespace asmjit {
namespace x64 {
Assembler::Assembler(BaseRuntime* runtime) : X86X64Assembler(runtime) {
Assembler::Assembler(Runtime* runtime) : X86X64Assembler(runtime) {
_arch = kArchX64;
_regSize = 8;
}
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -96,14 +96,14 @@ static Error X86X64Compiler_emitConstPool(X86X64Compiler* self,
// [asmjit::x86x64::X86X64Compiler - Construction / Destruction]
// ============================================================================
X86X64Compiler::X86X64Compiler(BaseRuntime* runtime) : BaseCompiler(runtime) {}
X86X64Compiler::X86X64Compiler(Runtime* runtime) : BaseCompiler(runtime) {}
X86X64Compiler::~X86X64Compiler() {}
// ============================================================================
// [asmjit::x86x64::X86X64Compiler - Inst]
// ============================================================================
//! @brief Get compiler instruction item size without operands assigned.
//! Get compiler instruction item size without operands assigned.
static ASMJIT_INLINE size_t X86X64Compiler_getInstSize(uint32_t code) {
return (IntUtil::inInterval<uint32_t>(code, _kInstJbegin, _kInstJend)) ? sizeof(JumpNode) : sizeof(InstNode);
}
@@ -600,7 +600,7 @@ _OnError:
template<typename Assembler>
static ASMJIT_INLINE void* X86X64Compiler_make(X86X64Compiler* self) {
Assembler assembler(self->_runtime);
BaseLogger* logger = self->_logger;
Logger* logger = self->_logger;
if (logger) {
assembler.setLogger(logger);
@@ -699,7 +699,7 @@ _Error:
namespace asmjit {
namespace x86 {
Compiler::Compiler(BaseRuntime* runtime) : X86X64Compiler(runtime) {
Compiler::Compiler(Runtime* runtime) : X86X64Compiler(runtime) {
_arch = kArchX86;
_regSize = 4;
_targetVarMapping = _varMapping;
@@ -721,7 +721,7 @@ Compiler::~Compiler() {}
namespace asmjit {
namespace x64 {
Compiler::Compiler(BaseRuntime* runtime) : X86X64Compiler(runtime) {
Compiler::Compiler(Runtime* runtime) : X86X64Compiler(runtime) {
_arch = kArchX64;
_regSize = 8;
_targetVarMapping = _varMapping;
File diff suppressed because it is too large Load Diff
+35 -35
View File
@@ -1557,7 +1557,7 @@ static void X86X64Context_prepareSingleVarInst(uint32_t code, VarAttr* va) {
//! @internal
//!
//! @brief Add unreachable-flow data to the unreachable flow list.
//! Add unreachable-flow data to the unreachable flow list.
static ASMJIT_INLINE Error X86X64Context_addUnreachableNode(X86X64Context* self, BaseNode* node) {
PodList<BaseNode*>::Link* link = self->_baseZone.allocT<PodList<BaseNode*>::Link>();
if (link == NULL)
@@ -1571,7 +1571,7 @@ static ASMJIT_INLINE Error X86X64Context_addUnreachableNode(X86X64Context* self,
//! @internal
//!
//! @brief Add jump-flow data to the jcc flow list.
//! Add jump-flow data to the jcc flow list.
static ASMJIT_INLINE Error X86X64Context_addJccNode(X86X64Context* self, BaseNode* node) {
PodList<BaseNode*>::Link* link = self->_baseZone.allocT<PodList<BaseNode*>::Link>();
@@ -1586,7 +1586,7 @@ static ASMJIT_INLINE Error X86X64Context_addJccNode(X86X64Context* self, BaseNod
//! @internal
//!
//! @brief Get mask of all registers actually used to pass function arguments.
//! Get mask of all registers actually used to pass function arguments.
static ASMJIT_INLINE RegMask X86X64Context_getUsedArgs(X86X64Context* self, X86X64CallNode* node, X86X64FuncDecl* decl) {
RegMask regs;
regs.reset();
@@ -1815,7 +1815,7 @@ static ASMJIT_INLINE Error X86X64Context_insertSArgNode(
//! @internal
//!
//! @brief Prepare the given function @a func.
//! Prepare the given function `func`.
//!
//! For each node:
//! - Create and assign groupId and flowId.
@@ -2608,12 +2608,12 @@ _NoMemory:
//! @internal
struct LivenessTarget {
//! @brief Previous target.
//! Previous target.
LivenessTarget* prev;
//! @brief Target node.
//! Target node.
TargetNode* node;
//! @brief Jumped from.
//! Jumped from.
JumpNode* from;
};
@@ -2952,33 +2952,33 @@ struct X86X64BaseAlloc {
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get the context.
//! Get the context.
ASMJIT_INLINE X86X64Context* getContext() const { return _context; }
//! @brief Get the current state (always the same instance as X86X64Context::_x86State).
//! Get the current state (always the same instance as X86X64Context::_x86State).
ASMJIT_INLINE VarState* getState() const { return _context->getState(); }
//! @brief Get the node.
//! Get the node.
ASMJIT_INLINE BaseNode* getNode() const { return _node; }
//! @brief Get VarAttr list (all).
//! Get VarAttr list (all).
ASMJIT_INLINE VarAttr* getVaList() const { return _vaList[0]; }
//! @brief Get VarAttr list (per class).
//! Get VarAttr list (per class).
ASMJIT_INLINE VarAttr* getVaListByClass(uint32_t c) const { return _vaList[c]; }
//! @brief Get VarAttr count (all).
//! Get VarAttr count (all).
ASMJIT_INLINE uint32_t getVaCount() const { return _vaCount; }
//! @brief Get VarAttr count (per class).
//! Get VarAttr count (per class).
ASMJIT_INLINE uint32_t getVaCountByClass(uint32_t c) const { return _count.get(c); }
//! @brief Get whether all variables of class @a c are done.
//! Get whether all variables of class `c` are done.
ASMJIT_INLINE bool isVaDone(uint32_t c) const { return _done.get(c) == _count.get(c); }
//! @brief Get how many variables have been allocated.
//! Get how many variables have been allocated.
ASMJIT_INLINE uint32_t getVaDone(uint32_t c) const { return _done.get(c); }
ASMJIT_INLINE void addVaDone(uint32_t c, uint32_t n = 1) { _done.add(c, n); }
//! @brief Get number of allocable registers per class.
//! Get number of allocable registers per class.
ASMJIT_INLINE uint32_t getGaRegs(uint32_t c) const {
return _context->_gaRegs[c];
}
@@ -3007,25 +3007,25 @@ protected:
// [Members]
// --------------------------------------------------------------------------
//! @brief Context.
//! Context.
X86X64Context* _context;
//! @brief Compiler.
//! Compiler.
X86X64Compiler* _compiler;
//! @brief Node.
//! Node.
BaseNode* _node;
//! @brief Variable instructions.
//! Variable instructions.
VarInst* _vi;
//! @brief VarAttr list (per register class).
//! VarAttr list (per register class).
VarAttr* _vaList[4];
//! @brief Count of all VarAttr's.
//! Count of all VarAttr's.
uint32_t _vaCount;
//! @brief VarAttr's total counter.
//! VarAttr's total counter.
RegCount _count;
//! @brief VarAttr's done counter.
//! VarAttr's done counter.
RegCount _done;
};
@@ -3120,7 +3120,7 @@ ASMJIT_INLINE void X86X64BaseAlloc::unuseAfter() {
//! @internal
//!
//! @brief Register allocator context (asm instructions).
//! Register allocator context (asm instructions).
struct X86X64VarAlloc : public X86X64BaseAlloc {
// --------------------------------------------------------------------------
// [Construction / Destruction]
@@ -3162,7 +3162,7 @@ protected:
// [GuessAlloc / GuessSpill]
// --------------------------------------------------------------------------
//! @brief Guess which register is the best candidate for 'vd' from
//! Guess which register is the best candidate for 'vd' from
//! 'allocableRegs'.
//!
//! The guess is based on looking ahead and inspecting register allocator
@@ -3173,7 +3173,7 @@ protected:
template<int C>
ASMJIT_INLINE uint32_t guessAlloc(VarData* vd, uint32_t allocableRegs);
//! @brief Guess whether to move the given 'vd' instead of spill.
//! Guess whether to move the given 'vd' instead of spill.
template<int C>
ASMJIT_INLINE uint32_t guessSpill(VarData* vd, uint32_t allocableRegs);
@@ -3188,9 +3188,9 @@ protected:
// [Members]
// --------------------------------------------------------------------------
//! @brief Will alloc to these registers.
//! Will alloc to these registers.
RegMask _willAlloc;
//! @brief Will spill these registers.
//! Will spill these registers.
RegMask _willSpill;
};
@@ -3745,7 +3745,7 @@ ASMJIT_INLINE void X86X64VarAlloc::modified() {
//! @internal
//!
//! @brief Register allocator context (function call).
//! Register allocator context (function call).
struct X86X64CallAlloc : public X86X64BaseAlloc {
// --------------------------------------------------------------------------
// [Construction / Destruction]
@@ -3758,7 +3758,7 @@ struct X86X64CallAlloc : public X86X64BaseAlloc {
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get the node.
//! Get the node.
ASMJIT_INLINE X86X64CallNode* getNode() const { return static_cast<X86X64CallNode*>(_node); }
// --------------------------------------------------------------------------
@@ -3837,9 +3837,9 @@ protected:
// [Members]
// --------------------------------------------------------------------------
//! @brief Will alloc to these registers.
//! Will alloc to these registers.
RegMask _willAlloc;
//! @brief Will spill these registers.
//! Will spill these registers.
RegMask _willSpill;
};
@@ -5298,7 +5298,7 @@ static ASMJIT_INLINE Error X86X64Context_serialize(X86X64Context* self, X86X64As
BaseNode* node_ = start;
StringBuilder& sb = self->_stringBuilder;
BaseLogger* logger;
Logger* logger;
uint32_t vdCount;
uint32_t annotationLength;
+34 -34
View File
@@ -22,7 +22,7 @@
namespace asmjit {
namespace x86x64 {
//! @addtogroup asmjit_x86x64
//! @addtogroup asmjit_x86x64_codegen
//! @{
// ============================================================================
@@ -31,7 +31,7 @@ namespace x86x64 {
//! @internal
//!
//! @brief Compiler context is used by @ref X86X64Compiler.
//! Compiler context is used by `X86X64Compiler`.
//!
//! Compiler context is used during compilation and normally developer doesn't
//! need access to it. The context is user per function (it's reset after each
@@ -43,9 +43,9 @@ struct X86X64Context : public BaseContext {
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @ref Context instance.
//! Create a new `X86X64Context` instance.
X86X64Context(X86X64Compiler* compiler);
//! @brief Destroy the @ref Context instance.
//! Destroy the `X86X64Context` instance.
virtual ~X86X64Context();
// --------------------------------------------------------------------------
@@ -58,12 +58,12 @@ struct X86X64Context : public BaseContext {
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get compiler as @ref X86X64Compiler.
//! Get compiler as `X86X64Compiler`.
ASMJIT_INLINE X86X64Compiler* getCompiler() const {
return static_cast<X86X64Compiler*>(_compiler);
}
//! @brief Get function as @ref X86X64FuncNode.
//! Get function as `X86X64FuncNode`.
ASMJIT_INLINE X86X64FuncNode* getFunc() const {
return reinterpret_cast<X86X64FuncNode*>(_func);
}
@@ -72,7 +72,7 @@ struct X86X64Context : public BaseContext {
return _baseRegsCount == 16;
}
//! @brief Get clobbered registers (global).
//! Get clobbered registers (global).
ASMJIT_INLINE uint32_t getClobberedRegs(uint32_t c) {
return _clobberedRegs.get(c);
}
@@ -131,7 +131,7 @@ struct X86X64Context : public BaseContext {
// [Attach / Detach]
// --------------------------------------------------------------------------
//! @brief Attach.
//! Attach.
//!
//! Attach a register to the 'VarData', changing 'VarData' members to show
//! that the variable is currently alive and linking variable with the
@@ -157,7 +157,7 @@ struct X86X64Context : public BaseContext {
ASMJIT_CONTEXT_CHECK_STATE
}
//! @brief Detach.
//! Detach.
//!
//! The opposite of 'Attach'. Detach resets the members in 'VarData'
//! (regIndex, state and changed flags) and unlinks the variable with the
@@ -185,7 +185,7 @@ struct X86X64Context : public BaseContext {
// [Rebase]
// --------------------------------------------------------------------------
//! @brief Rebase.
//! Rebase.
//!
//! Change the register of the 'VarData' changing also the current 'VarState'.
//! Rebase is nearly identical to 'Detach' and 'Attach' sequence, but doesn't
@@ -213,7 +213,7 @@ struct X86X64Context : public BaseContext {
// [Load / Save]
// --------------------------------------------------------------------------
//! @brief Load.
//! Load.
//!
//! Load variable from its memory slot to a register, emitting 'Load'
//! instruction and changing the variable state to allocated.
@@ -230,7 +230,7 @@ struct X86X64Context : public BaseContext {
ASMJIT_CONTEXT_CHECK_STATE
}
//! @brief Save.
//! Save.
//!
//! Save the variable into its home location, but keep it as allocated.
template<int C>
@@ -254,7 +254,7 @@ struct X86X64Context : public BaseContext {
// [Move / Swap]
// --------------------------------------------------------------------------
//! @brief Move a register.
//! Move a register.
//!
//! Move register from one index to another, emitting 'Move' if needed. This
//! function does nothing if register is already at the given index.
@@ -273,7 +273,7 @@ struct X86X64Context : public BaseContext {
ASMJIT_CONTEXT_CHECK_STATE
}
//! @brief Swap two registers
//! Swap two registers
//!
//! It's only possible to swap Gp registers.
ASMJIT_INLINE void swapGp(VarData* aVd, VarData* bVd) {
@@ -308,7 +308,7 @@ struct X86X64Context : public BaseContext {
// [Alloc / Spill]
// --------------------------------------------------------------------------
//! @brief Alloc
//! Alloc
template<int C>
ASMJIT_INLINE void alloc(VarData* vd, uint32_t regIndex) {
ASMJIT_ASSERT(vd->getClass() == C);
@@ -346,7 +346,7 @@ struct X86X64Context : public BaseContext {
ASMJIT_CONTEXT_CHECK_STATE
}
//! @brief Spill.
//! Spill.
//!
//! Spill variable/register, saves the content to the memory-home if modified.
template<int C>
@@ -391,7 +391,7 @@ struct X86X64Context : public BaseContext {
// [Unuse]
// --------------------------------------------------------------------------
//! @brief Unuse.
//! Unuse.
//!
//! Unuse variable, it will be detached it if it's allocated then its state
//! will be changed to kVarStateUnused.
@@ -413,7 +413,7 @@ struct X86X64Context : public BaseContext {
// [State]
// --------------------------------------------------------------------------
//! @brief Get state as @ref VarState.
//! Get state as `VarState`.
ASMJIT_INLINE VarState* getState() const {
return const_cast<VarState*>(&_x86State);
}
@@ -465,45 +465,45 @@ struct X86X64Context : public BaseContext {
// [Members]
// --------------------------------------------------------------------------
//! @brief X86/X64 stack-pointer (esp or rsp).
//! X86/X64 stack-pointer (esp or rsp).
GpReg _zsp;
//! @brief X86/X64 frame-pointer (ebp or rbp).
//! X86/X64 frame-pointer (ebp or rbp).
GpReg _zbp;
//! @brief Temporary memory operand.
//! Temporary memory operand.
Mem _memSlot;
//! @brief X86/X64 specific compiler state (linked with @ref _state).
//! X86/X64 specific compiler state, linked to `_state`.
VarState _x86State;
//! @brief Clobbered registers (for the whole function).
//! Clobbered registers (for the whole function).
RegMask _clobberedRegs;
//! @brief Memory cell where is stored address used to restore manually
//! Memory cell where is stored address used to restore manually
//! aligned stack.
MemCell* _stackFrameCell;
//! @brief Global allocable registers mask.
//! Global allocable registers mask.
uint32_t _gaRegs[kRegClassCount];
//! @brief X86/X64 number of Gp/Xmm registers.
//! X86/X64 number of Gp/Xmm registers.
uint8_t _baseRegsCount;
//! @brief Function arguments base pointer (register).
//! Function arguments base pointer (register).
uint8_t _argBaseReg;
//! @brief Function variables base pointer (register).
//! Function variables base pointer (register).
uint8_t _varBaseReg;
//! @brief Whether to emit comments.
//! Whether to emit comments.
uint8_t _emitComments;
//! @brief Function arguments base offset.
//! Function arguments base offset.
int32_t _argBaseOffset;
//! @brief Function variables base offset.
//! Function variables base offset.
int32_t _varBaseOffset;
//! @brief Function arguments displacement.
//! Function arguments displacement.
int32_t _argActualDisp;
//! @brief Function variables displacement.
//! Function variables displacement.
int32_t _varActualDisp;
//! @brief Temporary string builder used for logging.
//! Temporary string builder used for logging.
StringBuilderT<256> _stringBuilder;
};
+75 -83
View File
@@ -28,65 +28,34 @@ namespace asmjit {
namespace x86x64 {
// ============================================================================
// [asmjit::x86x64::hostCpuId]
// [asmjit::x86x64::CpuVendor]
// ============================================================================
// This is messy, I know. Cpuid is implemented as intrinsic in VS2005, but
// we should support other compilers as well. Main problem is that MS compilers
// in 64-bit mode not allows to use inline assembler, so we need intrinsic and
// we need also asm version.
struct CpuVendor {
uint32_t id;
char text[12];
};
// hostCpuId() and detectCpuInfo() for x86 and x64 platforms begins here.
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
void hostCpuId(uint32_t inEax, uint32_t inEcx, CpuId* result) {
static const CpuVendor cpuVendorTable[] = {
{ kCpuVendorAmd , { 'A', 'M', 'D', 'i', 's', 'b', 'e', 't', 't', 'e', 'r', '!' } },
{ kCpuVendorAmd , { 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D' } },
{ kCpuVendorVia , { 'C', 'e', 'n', 't', 'a', 'u', 'r', 'H', 'a', 'u', 'l', 's' } },
{ kCpuVendorNSM , { 'C', 'y', 'r', 'i', 'x', 'I', 'n', 's', 't', 'e', 'a', 'd' } },
{ kCpuVendorIntel , { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l' } },
{ kCpuVendorTransmeta, { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'T', 'M', 'x', '8', '6' } },
{ kCpuVendorNSM , { 'G', 'e', 'o', 'd', 'e', ' ', 'b', 'y', ' ', 'N', 'S', 'C' } },
{ kCpuVendorTransmeta, { 'T', 'r', 'a', 'n', 's', 'm', 'e', 't', 'a', 'C', 'P', 'U' } },
{ kCpuVendorVia , { 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 } }
};
#if defined(_MSC_VER)
// 2009-02-05: Thanks to Mike Tajmajer for supporting VC7.1 compiler.
// ASMJIT_HOST_X64 is here only for readibility, only VS2005 can compile 64-bit code.
# if _MSC_VER >= 1400 || defined(ASMJIT_HOST_X64)
// Done by intrinsics.
__cpuidex(reinterpret_cast<int*>(result->i), inEax, inEcx);
# else // _MSC_VER < 1400
uint32_t cpuid_eax = inEax;
uint32_t cpuid_ecx = inCax;
uint32_t* cpuid_out = result->i;
static ASMJIT_INLINE bool cpuVendorEq(const CpuVendor& info, const char* vendorString) {
const uint32_t* a = reinterpret_cast<const uint32_t*>(info.text);
const uint32_t* b = reinterpret_cast<const uint32_t*>(vendorString);
__asm {
mov eax, cpuid_eax
mov ecx, cpuid_ecx
mov edi, cpuid_out
cpuid
mov dword ptr[edi + 0], eax
mov dword ptr[edi + 4], ebx
mov dword ptr[edi + 8], ecx
mov dword ptr[edi + 12], edx
}
# endif // _MSC_VER < 1400
#elif defined(__GNUC__)
// Note, patched to preserve ebx/rbx register which is used by GCC.
# if defined(ASMJIT_HOST_X86)
# define __myCpuId(inEax, inEcx, outEax, outEbx, outEcx, outEdx) \
asm ("mov %%ebx, %%edi\n" \
"cpuid\n" \
"xchg %%edi, %%ebx\n" \
: "=a" (outEax), "=D" (outEbx), "=c" (outEcx), "=d" (outEdx) : "a" (inEax), "c" (inEcx))
# else
# define __myCpuId(inEax, inEcx, outEax, outEbx, outEcx, outEdx) \
asm ("mov %%rbx, %%rdi\n" \
"cpuid\n" \
"xchg %%rdi, %%rbx\n" \
: "=a" (outEax), "=D" (outEbx), "=c" (outEcx), "=d" (outEdx) : "a" (inEax), "c" (inEcx))
# endif
__myCpuId(inEax, inEcx, result->eax, result->ebx, result->ecx, result->edx);
#endif // Compiler #ifdef.
return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]);
}
// ============================================================================
// [asmjit::x86x64::cpuSimplifyBrandString]
// ============================================================================
static ASMJIT_INLINE void cpuSimplifyBrandString(char* s) {
static ASMJIT_INLINE void simplifyBrandString(char* s) {
// Always clear the current character in the buffer. It ensures that there
// is no garbage after the string NULL terminator.
char* d = s;
@@ -117,38 +86,61 @@ _Skip:
}
// ============================================================================
// [asmjit::x86x64::CpuVendor]
// [asmjit::x86x64::CpuUtil]
// ============================================================================
struct CpuVendor {
uint32_t id;
char text[12];
};
// This is messy, I know. Cpuid is implemented as intrinsic in VS2005, but
// we should support other compilers as well. Main problem is that MS compilers
// in 64-bit mode not allows to use inline assembler, so we need intrinsic and
// we need also asm version.
static const CpuVendor cpuVendorTable[] = {
{ kCpuVendorAmd , { 'A', 'M', 'D', 'i', 's', 'b', 'e', 't', 't', 'e', 'r', '!' } },
{ kCpuVendorAmd , { 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D' } },
{ kCpuVendorVia , { 'C', 'e', 'n', 't', 'a', 'u', 'r', 'H', 'a', 'u', 'l', 's' } },
{ kCpuVendorNSM , { 'C', 'y', 'r', 'i', 'x', 'I', 'n', 's', 't', 'e', 'a', 'd' } },
{ kCpuVendorIntel , { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l' } },
{ kCpuVendorTransmeta, { 'G', 'e', 'n', 'u', 'i', 'n', 'e', 'T', 'M', 'x', '8', '6' } },
{ kCpuVendorNSM , { 'G', 'e', 'o', 'd', 'e', ' ', 'b', 'y', ' ', 'N', 'S', 'C' } },
{ kCpuVendorTransmeta, { 'T', 'r', 'a', 'n', 's', 'm', 'e', 't', 'a', 'C', 'P', 'U' } },
{ kCpuVendorVia , { 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 , 'V', 'I', 'A', 0 } }
};
// callCpuId() and detectCpuInfo() for x86 and x64 platforms begins here.
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
void CpuUtil::callCpuId(uint32_t inEax, uint32_t inEcx, CpuId* outResult) {
static ASMJIT_INLINE bool cpuVendorEq(const CpuVendor& info, const char* vendorString) {
const uint32_t* a = reinterpret_cast<const uint32_t*>(info.text);
const uint32_t* b = reinterpret_cast<const uint32_t*>(vendorString);
#if defined(_MSC_VER)
// 2009-02-05: Thanks to Mike Tajmajer for supporting VC7.1 compiler.
// ASMJIT_HOST_X64 is here only for readibility, only VS2005 can compile 64-bit code.
# if _MSC_VER >= 1400 || defined(ASMJIT_HOST_X64)
// Done by intrinsics.
__cpuidex(reinterpret_cast<int*>(outResult->i), inEax, inEcx);
# else // _MSC_VER < 1400
uint32_t cpuid_eax = inEax;
uint32_t cpuid_ecx = inCax;
uint32_t* cpuid_out = outResult->i;
return (a[0] == b[0]) & (a[1] == b[1]) & (a[2] == b[2]);
__asm {
mov eax, cpuid_eax
mov ecx, cpuid_ecx
mov edi, cpuid_out
cpuid
mov dword ptr[edi + 0], eax
mov dword ptr[edi + 4], ebx
mov dword ptr[edi + 8], ecx
mov dword ptr[edi + 12], edx
}
# endif // _MSC_VER < 1400
#elif defined(__GNUC__)
// Note, patched to preserve ebx/rbx register which is used by GCC.
# if defined(ASMJIT_HOST_X86)
# define __myCpuId(inEax, inEcx, outEax, outEbx, outEcx, outEdx) \
asm ("mov %%ebx, %%edi\n" \
"cpuid\n" \
"xchg %%edi, %%ebx\n" \
: "=a" (outEax), "=D" (outEbx), "=c" (outEcx), "=d" (outEdx) : "a" (inEax), "c" (inEcx))
# else
# define __myCpuId(inEax, inEcx, outEax, outEbx, outEcx, outEdx) \
asm ("mov %%rbx, %%rdi\n" \
"cpuid\n" \
"xchg %%rdi, %%rbx\n" \
: "=a" (outEax), "=D" (outEbx), "=c" (outEcx), "=d" (outEdx) : "a" (inEax), "c" (inEcx))
# endif
__myCpuId(inEax, inEcx, outResult->eax, outResult->ebx, outResult->ecx, outResult->edx);
#endif // COMPILER
}
// ============================================================================
// [asmjit::x86x64::hostCpuDetect]
// ============================================================================
void hostCpuDetect(CpuInfo* cpuInfo) {
void CpuUtil::detect(CpuInfo* cpuInfo) {
CpuId regs;
uint32_t i;
@@ -163,7 +155,7 @@ void hostCpuDetect(CpuInfo* cpuInfo) {
cpuInfo->_coresCount = BaseCpuInfo::detectNumberOfCores();
// Get vendor string/id.
hostCpuId(0, 0, &regs);
callCpuId(0, 0, &regs);
maxId = regs.eax;
::memcpy(cpuInfo->_vendorString, &regs.ebx, 4);
@@ -178,7 +170,7 @@ void hostCpuDetect(CpuInfo* cpuInfo) {
}
// Get feature flags in ecx/edx and family/model in eax.
hostCpuId(1, 0, &regs);
callCpuId(1, 0, &regs);
// Fill family and model fields.
cpuInfo->_family = (regs.eax >> 8) & 0x0F;
@@ -235,7 +227,7 @@ void hostCpuDetect(CpuInfo* cpuInfo) {
// Detect new features if the processor supports CPUID-07.
if (maxId >= 7) {
hostCpuId(7, 0, &regs);
callCpuId(7, 0, &regs);
if (regs.ebx & 0x00000001) cpuInfo->addFeature(kCpuFeatureFsGsBase);
if (regs.ebx & 0x00000008) cpuInfo->addFeature(kCpuFeatureBmi);
@@ -252,13 +244,13 @@ void hostCpuDetect(CpuInfo* cpuInfo) {
// Calling cpuid with 0x80000000 as the in argument gets the number of valid
// extended IDs.
hostCpuId(0x80000000, 0, &regs);
callCpuId(0x80000000, 0, &regs);
uint32_t maxExtId = IntUtil::iMin<uint32_t>(regs.eax, 0x80000004);
uint32_t* brand = reinterpret_cast<uint32_t*>(cpuInfo->_brandString);
for (i = 0x80000001; i <= maxExtId; i++) {
hostCpuId(i, 0, &regs);
callCpuId(i, 0, &regs);
switch (i) {
case 0x80000001:
@@ -292,7 +284,7 @@ void hostCpuDetect(CpuInfo* cpuInfo) {
}
// Simplify the brand string (remove unnecessary spaces to make printing nicer).
cpuSimplifyBrandString(cpuInfo->_brandString);
simplifyBrandString(cpuInfo->_brandString);
}
#endif
+82 -72
View File
@@ -18,103 +18,109 @@
namespace asmjit {
namespace x86x64 {
//! @addtogroup asmjit_x86x64
//! @addtogroup asmjit_x86x64_cpu_info
//! @{
// ============================================================================
// [Forward Declarations]
// ============================================================================
struct CpuInfo;
// ============================================================================
// [asmjit::x86x64::kCpuFeature]
// ============================================================================
//! @brief X86 CPU features.
//! X86 CPU features.
ASMJIT_ENUM(kCpuFeature) {
//! @brief Cpu has multithreading.
//! Cpu has multithreading.
kCpuFeatureMultithreading = 1,
//! @brief Cpu has execute disable bit.
//! Cpu has execute disable bit.
kCpuFeatureExecuteDisableBit,
//! @brief Cpu has RDTSC.
//! Cpu has RDTSC.
kCpuFeatureRdtsc,
//! @brief Cpu has RDTSCP.
//! Cpu has RDTSCP.
kCpuFeatureRdtscp,
//! @brief Cpu has CMOV.
//! Cpu has CMOV.
kCpuFeatureCmov,
//! @brief Cpu has CMPXCHG8B.
//! Cpu has CMPXCHG8B.
kCpuFeatureCmpXchg8B,
//! @brief Cpu has CMPXCHG16B (x64).
//! Cpu has CMPXCHG16B (x64).
kCpuFeatureCmpXchg16B,
//! @brief Cpu has CLFUSH.
//! Cpu has CLFUSH.
kCpuFeatureClflush,
//! @brief Cpu has PREFETCH.
//! Cpu has PREFETCH.
kCpuFeaturePrefetch,
//! @brief Cpu has LAHF/SAHF.
//! Cpu has LAHF/SAHF.
kCpuFeatureLahfSahf,
//! @brief Cpu has FXSAVE/FXRSTOR.
//! Cpu has FXSAVE/FXRSTOR.
kCpuFeatureFxsr,
//! @brief Cpu has FXSAVE/FXRSTOR optimizations.
//! Cpu has FXSAVE/FXRSTOR optimizations.
kCpuFeatureFfxsr,
//! @brief Cpu has MMX.
//! Cpu has MMX.
kCpuFeatureMmx,
//! @brief Cpu has extended MMX.
//! Cpu has extended MMX.
kCpuFeatureMmxExt,
//! @brief Cpu has 3dNow!
//! Cpu has 3dNow!
kCpuFeature3dNow,
//! @brief Cpu has enchanced 3dNow!
//! Cpu has enchanced 3dNow!
kCpuFeature3dNowExt,
//! @brief Cpu has SSE.
//! Cpu has SSE.
kCpuFeatureSse,
//! @brief Cpu has SSE2.
//! Cpu has SSE2.
kCpuFeatureSse2,
//! @brief Cpu has SSE3.
//! Cpu has SSE3.
kCpuFeatureSse3,
//! @brief Cpu has Supplemental SSE3 (SSSE3).
//! Cpu has Supplemental SSE3 (SSSE3).
kCpuFeatureSsse3,
//! @brief Cpu has SSE4.A.
//! Cpu has SSE4.A.
kCpuFeatureSse4A,
//! @brief Cpu has SSE4.1.
//! Cpu has SSE4.1.
kCpuFeatureSse41,
//! @brief Cpu has SSE4.2.
//! Cpu has SSE4.2.
kCpuFeatureSse42,
//! @brief Cpu has Misaligned SSE (MSSE).
//! Cpu has Misaligned SSE (MSSE).
kCpuFeatureMsse,
//! @brief Cpu has MONITOR and MWAIT.
//! Cpu has MONITOR and MWAIT.
kCpuFeatureMonitorMWait,
//! @brief Cpu has MOVBE.
//! Cpu has MOVBE.
kCpuFeatureMovbe,
//! @brief Cpu has POPCNT.
//! Cpu has POPCNT.
kCpuFeaturePopcnt,
//! @brief Cpu has LZCNT.
//! Cpu has LZCNT.
kCpuFeatureLzcnt,
//! @brief Cpu has AESNI.
//! Cpu has AESNI.
kCpuFeatureAesni,
//! @brief Cpu has PCLMULQDQ.
//! Cpu has PCLMULQDQ.
kCpuFeaturePclmulqdq,
//! @brief Cpu has RDRAND.
//! Cpu has RDRAND.
kCpuFeatureRdrand,
//! @brief Cpu has AVX.
//! Cpu has AVX.
kCpuFeatureAvx,
//! @brief Cpu has AVX2.
//! Cpu has AVX2.
kCpuFeatureAvx2,
//! @brief Cpu has F16C.
//! Cpu has F16C.
kCpuFeatureF16C,
//! @brief Cpu has FMA3.
//! Cpu has FMA3.
kCpuFeatureFma3,
//! @brief Cpu has FMA4.
//! Cpu has FMA4.
kCpuFeatureFma4,
//! @brief Cpu has XOP.
//! Cpu has XOP.
kCpuFeatureXop,
//! @brief Cpu has BMI.
//! Cpu has BMI.
kCpuFeatureBmi,
//! @brief Cpu has BMI2.
//! Cpu has BMI2.
kCpuFeatureBmi2,
//! @brief Cpu has HLE.
//! Cpu has HLE.
kCpuFeatureHle,
//! @brief Cpu has RTM.
//! Cpu has RTM.
kCpuFeatureRtm,
//! @brief Cpu has FSGSBASE.
//! Cpu has FSGSBASE.
kCpuFeatureFsGsBase,
//! @brief Cpu has enhanced REP MOVSB/STOSB.
//! Cpu has enhanced REP MOVSB/STOSB.
kCpuFeatureRepMovsbStosbExt,
//! @brief Count of X86/X64 Cpu features.
//! Count of X86/X64 Cpu features.
kCpuFeatureCount
};
@@ -122,23 +128,38 @@ ASMJIT_ENUM(kCpuFeature) {
// [asmjit::x86x64::CpuId]
// ============================================================================
//! @brief X86/X64 cpuid output.
//! X86/X64 CPUID output.
union CpuId {
//! @brief EAX/EBX/ECX/EDX output.
//! EAX/EBX/ECX/EDX output.
uint32_t i[4];
struct {
//! @brief EAX output.
//! EAX output.
uint32_t eax;
//! @brief EBX output.
//! EBX output.
uint32_t ebx;
//! @brief ECX output.
//! ECX output.
uint32_t ecx;
//! @brief EDX output.
//! EDX output.
uint32_t edx;
};
};
// ============================================================================
// [asmjit::x86x64::CpuUtil]
// ============================================================================
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
//! CPU utilities available only if the host processor is X86/X64.
struct CpuUtil {
//! Get the result of calling CPUID instruction to `out`.
ASMJIT_API static void callCpuId(uint32_t inEax, uint32_t inEcx, CpuId* out);
//! Detect the Host CPU.
ASMJIT_API static void detect(CpuInfo* cpuInfo);
};
#endif // ASMJIT_HOST_X86 || ASMJIT_HOST_X64
// ============================================================================
// [asmjit::x86x64::CpuInfo]
// ============================================================================
@@ -157,22 +178,22 @@ struct CpuInfo : public BaseCpuInfo {
// [Accessors]
// --------------------------------------------------------------------------
//! @brief Get processor type.
//! Get processor type.
ASMJIT_INLINE uint32_t getProcessorType() const {
return _processorType;
}
//! @brief Get brand index.
//! Get brand index.
ASMJIT_INLINE uint32_t getBrandIndex() const {
return _brandIndex;
}
//! @brief Get flush cache line size.
//! Get flush cache line size.
ASMJIT_INLINE uint32_t getFlushCacheLineSize() const {
return _flushCacheLineSize;
}
//! @brief Get maximum logical processors count.
//! Get maximum logical processors count.
ASMJIT_INLINE uint32_t getMaxLogicalProcessors() const {
return _maxLogicalProcessors;
}
@@ -181,7 +202,7 @@ struct CpuInfo : public BaseCpuInfo {
// [Statics]
// --------------------------------------------------------------------------
//! @brief Get global instance of @ref X86CpuInfo.
//! Get global instance of `x86x64::CpuInfo`.
static ASMJIT_INLINE const CpuInfo* getHost() {
return static_cast<const CpuInfo*>(BaseCpuInfo::getHost());
}
@@ -190,27 +211,16 @@ struct CpuInfo : public BaseCpuInfo {
// [Members]
// --------------------------------------------------------------------------
//! @brief Processor type.
//! Processor type.
uint32_t _processorType;
//! @brief Brand index.
//! Brand index.
uint32_t _brandIndex;
//! @brief Flush cache line size in bytes.
//! Flush cache line size in bytes.
uint32_t _flushCacheLineSize;
//! @brief Maximum number of addressable IDs for logical processors.
//! Maximum number of addressable IDs for logical processors.
uint32_t _maxLogicalProcessors;
};
// ============================================================================
// [asmjit::x86x64::hostCpuId / hostCpuDetect]
// ============================================================================
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
//! @brief Get the result of calling CPUID instruction.
ASMJIT_API void hostCpuId(uint32_t inEax, uint32_t inEcx, CpuId* result);
//! @brief Detect host CPU.
ASMJIT_API void hostCpuDetect(CpuInfo* cpuInfo);
#endif // ASMJIT_HOST_X86 || ASMJIT_HOST_X64
//! @}
} // x86x64 namespace
+803 -800
View File
File diff suppressed because it is too large Load Diff
+821 -802
View File
File diff suppressed because it is too large Load Diff
+24 -26
View File
@@ -52,8 +52,6 @@ static ASMJIT_INLINE uint32_t x86ArgTypeToXmmType(uint32_t aType) {
#define R(_Index_) kRegIndex##_Index_
static uint32_t X86X64FuncDecl_initConv(X86X64FuncDecl* self, uint32_t arch, uint32_t conv) {
uint32_t i;
// Setup defaults.
self->_argStackSize = 0;
self->_redZoneSize = 0;
@@ -66,13 +64,8 @@ static uint32_t X86X64FuncDecl_initConv(X86X64FuncDecl* self, uint32_t arch, uin
self->_passed.reset();
self->_preserved.reset();
for (i = 0; i < ASMJIT_ARRAY_SIZE(self->_passedOrderGp); i++) {
self->_passedOrderGp[i] = kInvalidReg;
}
for (i = 0; i < ASMJIT_ARRAY_SIZE(self->_passedOrderXmm); i++) {
self->_passedOrderXmm[i] = kInvalidReg;
}
::memset(self->_passedOrderGp, kInvalidReg, ASMJIT_ARRAY_SIZE(self->_passedOrderGp));
::memset(self->_passedOrderXmm, kInvalidReg, ASMJIT_ARRAY_SIZE(self->_passedOrderXmm));
// --------------------------------------------------------------------------
// [X86 Support]
@@ -328,10 +321,14 @@ static Error X86X64FuncDecl_initFunc(X86X64FuncDecl* self, uint32_t arch,
FuncInOut& arg = self->getArg(i);
uint32_t varType = varMapping[arg.getVarType()];
if (x86ArgIsInt(varType) && gpPos < 16 && self->_passedOrderGp[gpPos] != kInvalidReg) {
arg._regIndex = self->_passedOrderGp[gpPos++];
self->_used.add(kRegClassGp, IntUtil::mask(arg.getRegIndex()));
}
if (!x86ArgIsInt(varType) || gpPos >= ASMJIT_ARRAY_SIZE(self->_passedOrderGp))
continue;
if (self->_passedOrderGp[gpPos] == kInvalidReg)
continue;
arg._regIndex = self->_passedOrderGp[gpPos++];
self->_used.add(kRegClassGp, IntUtil::mask(arg.getRegIndex()));
}
// Stack arguments.
@@ -375,11 +372,13 @@ static Error X86X64FuncDecl_initFunc(X86X64FuncDecl* self, uint32_t arch,
FuncInOut& arg = self->getArg(i);
uint32_t varType = varMapping[arg.getVarType()];
if (x86ArgIsInt(varType)) {
if (x86ArgIsInt(varType) && i < ASMJIT_ARRAY_SIZE(self->_passedOrderGp)) {
arg._regIndex = self->_passedOrderGp[i];
self->_used.add(kRegClassGp, IntUtil::mask(arg.getRegIndex()));
continue;
}
else if (x86ArgIsFp(varType)) {
if (x86ArgIsFp(varType) && i < ASMJIT_ARRAY_SIZE(self->_passedOrderXmm)) {
arg._varType = static_cast<uint8_t>(x86ArgTypeToXmmType(varType));
arg._regIndex = self->_passedOrderXmm[i];
self->_used.add(kRegClassXy, IntUtil::mask(arg.getRegIndex()));
@@ -413,10 +412,14 @@ static Error X86X64FuncDecl_initFunc(X86X64FuncDecl* self, uint32_t arch,
FuncInOut& arg = self->getArg(i);
uint32_t varType = varMapping[arg.getVarType()];
if (x86ArgIsInt(varType) && gpPos < 32 && self->_passedOrderGp[gpPos] != kInvalidReg) {
arg._regIndex = self->_passedOrderGp[gpPos++];
self->_used.add(kRegClassGp, IntUtil::mask(arg.getRegIndex()));
}
if (!x86ArgIsInt(varType) || gpPos >= ASMJIT_ARRAY_SIZE(self->_passedOrderGp))
continue;
if (self->_passedOrderGp[gpPos] == kInvalidReg)
continue;
arg._regIndex = self->_passedOrderGp[gpPos++];
self->_used.add(kRegClassGp, IntUtil::mask(arg.getRegIndex()));
}
// Register arguments (Xmm), always left-to-right.
@@ -523,13 +526,8 @@ void X86X64FuncDecl::reset() {
_passed.reset();
_preserved.reset();
for (i = 0; i < ASMJIT_ARRAY_SIZE(_passedOrderGp); i++) {
_passedOrderGp[i] = kInvalidReg;
}
for (i = 0; i < ASMJIT_ARRAY_SIZE(_passedOrderXmm); i++) {
_passedOrderXmm[i] = kInvalidReg;
}
::memset(_passedOrderGp, kInvalidReg, ASMJIT_ARRAY_SIZE(_passedOrderGp));
::memset(_passedOrderXmm, kInvalidReg, ASMJIT_ARRAY_SIZE(_passedOrderXmm));
}
} // x86x64 namespace
+89 -78
View File
@@ -19,14 +19,14 @@
namespace asmjit {
namespace x86x64 {
//! @addtogroup asmjit_x86x64
//! @addtogroup asmjit_x86x64_codegen
//! @{
// ============================================================================
// [asmjit::x86x64::kFuncConv]
// ============================================================================
//! @brief X86 function calling conventions.
//! X86 function calling conventions.
//!
//! Calling convention is scheme how function arguments are passed into
//! function and how functions returns values. In assembler programming
@@ -34,33 +34,32 @@ namespace x86x64 {
//! even small inconsistency can cause undefined behavior or crash.
//!
//! List of calling conventions for 32-bit x86 mode:
//! - @c kFuncConvCDecl - Calling convention for C runtime.
//! - @c kFuncConvStdCall - Calling convention for WinAPI functions.
//! - @c kFuncConvMsThisCall - Calling convention for C++ members under
//! Windows (produced by MSVC and all MSVC compatible compilers).
//! - @c kFuncConvMsFastCall - Fastest calling convention that can be used
//! by MSVC compiler.
//! - @c kFuncConv_BORNANDFASTCALL - Borland fastcall convention.
//! - @c kFuncConvGccFastCall - GCC fastcall convention (2 register arguments).
//! - @c kFuncConvGccRegParm1 - GCC regparm(1) convention.
//! - @c kFuncConvGccRegParm2 - GCC regparm(2) convention.
//! - @c kFuncConvGccRegParm3 - GCC regparm(3) convention.
//! - `kFuncConvCDecl` - Calling convention for C runtime.
//! - `kFuncConvStdCall` - Calling convention for WinAPI functions.
//! - `kFuncConvMsThisCall` - Calling convention for C++ members under
//! Windows (produced by MSVC and all MSVC compatible compilers).
//! - `kFuncConvMsFastCall` - Fastest calling convention that can be used
//! by MSVC compiler.
//! - `kFuncConvBorlandFastCall` - Borland fastcall convention.
//! - `kFuncConvGccFastCall` - GCC fastcall convention (2 register arguments).
//! - `kFuncConvGccRegParm1` - GCC regparm(1) convention.
//! - `kFuncConvGccRegParm2` - GCC regparm(2) convention.
//! - `kFuncConvGccRegParm3` - GCC regparm(3) convention.
//!
//! List of calling conventions for 64-bit x86 mode (x64):
//! - @c kFuncConvX64W - Windows 64-bit calling convention (WIN64 ABI).
//! - @c kFuncConvX64U - Unix 64-bit calling convention (AMD64 ABI).
//! - `kFuncConvX64W` - Windows 64-bit calling convention (WIN64 ABI).
//! - `kFuncConvX64U` - Unix 64-bit calling convention (AMD64 ABI).
//!
//! There is also @c kFuncConvHost that is defined to fit best to your
//! compiler.
//! There is also `kFuncConvHost` that is defined to fit the host calling
//! convention.
//!
//! These types are used together with @c asmjit::Compiler::addFunc()
//! method.
//! These types are used together with `BaseCompiler::addFunc()` method.
ASMJIT_ENUM(kFuncConv) {
// --------------------------------------------------------------------------
// [X64]
// --------------------------------------------------------------------------
//! @brief X64 calling convention for Windows platform (WIN64 ABI).
//! X64 calling convention for Windows platform (WIN64 ABI).
//!
//! For first four arguments are used these registers:
//! - 1. 32/64-bit integer or floating point argument - rcx/xmm0
@@ -93,7 +92,7 @@ ASMJIT_ENUM(kFuncConv) {
//! http://msdn.microsoft.com/en-us/library/9b372w95.aspx .
kFuncConvX64W = 1,
//! @brief X64 calling convention for Unix platforms (AMD64 ABI).
//! X64 calling convention for Unix platforms (AMD64 ABI).
//!
//! First six 32 or 64-bit integer arguments are passed in rdi, rsi, rdx,
//! rcx, r8, r9 registers. First eight floating point or Xmm arguments
@@ -120,7 +119,7 @@ ASMJIT_ENUM(kFuncConv) {
// [X86]
// --------------------------------------------------------------------------
//! @brief Cdecl calling convention (used by C runtime).
//! Cdecl calling convention (used by C runtime).
//!
//! Compatible across MSVC and GCC.
//!
@@ -131,7 +130,7 @@ ASMJIT_ENUM(kFuncConv) {
//! - Caller.
kFuncConvCDecl = 3,
//! @brief Stdcall calling convention (used by WinAPI).
//! Stdcall calling convention (used by WinAPI).
//!
//! Compatible across MSVC and GCC.
//!
@@ -146,7 +145,7 @@ ASMJIT_ENUM(kFuncConv) {
//! - Floating points - fp0 register.
kFuncConvStdCall = 4,
//! @brief MSVC specific calling convention used by MSVC/Intel compilers
//! MSVC specific calling convention used by MSVC/Intel compilers
//! for struct/class methods.
//!
//! This is MSVC (and Intel) only calling convention used in Windows
@@ -170,7 +169,7 @@ ASMJIT_ENUM(kFuncConv) {
//! it's implicit and there is no way how to override it.
kFuncConvMsThisCall = 5,
//! @brief MSVC specific fastcall.
//! MSVC specific fastcall.
//!
//! Two first parameters (evaluated from left-to-right) are in ECX:EDX
//! registers, all others on the stack in right-to-left order.
@@ -189,7 +188,7 @@ ASMJIT_ENUM(kFuncConv) {
//! mechanism.
kFuncConvMsFastCall = 6,
//! @brief Borland specific fastcall with 2 parameters in registers.
//! Borland specific fastcall with 2 parameters in registers.
//!
//! Two first parameters (evaluated from left-to-right) are in ECX:EDX
//! registers, all others on the stack in left-to-right order.
@@ -208,7 +207,7 @@ ASMJIT_ENUM(kFuncConv) {
//! to other fastcall conventions used in different compilers.
kFuncConvBorlandFastCall = 7,
//! @brief GCC specific fastcall convention.
//! GCC specific fastcall convention.
//!
//! Two first parameters (evaluated from left-to-right) are in ECX:EDX
//! registers, all others on the stack in right-to-left order.
@@ -223,11 +222,10 @@ ASMJIT_ENUM(kFuncConv) {
//! - Integer types - EAX:EDX registers.
//! - Floating points - fp0 register.
//!
//! @note This calling convention should be compatible with
//! @c kFuncConvMsFastCall.
//! @note This calling convention should be compatible with `kFuncConvMsFastCall`.
kFuncConvGccFastCall = 8,
//! @brief GCC specific regparm(1) convention.
//! GCC specific regparm(1) convention.
//!
//! The first parameter (evaluated from left-to-right) is in EAX register,
//! all others on the stack in right-to-left order.
@@ -243,7 +241,7 @@ ASMJIT_ENUM(kFuncConv) {
//! - Floating points - fp0 register.
kFuncConvGccRegParm1 = 9,
//! @brief GCC specific regparm(2) convention.
//! GCC specific regparm(2) convention.
//!
//! Two first parameters (evaluated from left-to-right) are in EAX:EDX
//! registers, all others on the stack in right-to-left order.
@@ -259,7 +257,7 @@ ASMJIT_ENUM(kFuncConv) {
//! - Floating points - fp0 register.
kFuncConvGccRegParm2 = 10,
//! @brief GCC specific fastcall with 3 parameters in registers.
//! GCC specific fastcall with 3 parameters in registers.
//!
//! Three first parameters (evaluated from left-to-right) are in
//! EAX:EDX:ECX registers, all others on the stack in right-to-left order.
@@ -277,7 +275,7 @@ ASMJIT_ENUM(kFuncConv) {
//! @internal
//!
//! @brief Count of function calling conventions.
//! Count of function calling conventions.
_kFuncConvCount = 12,
// --------------------------------------------------------------------------
@@ -285,24 +283,24 @@ ASMJIT_ENUM(kFuncConv) {
// --------------------------------------------------------------------------
//! @def kFuncConvHost
//! @brief Default calling convention for current platform / operating system.
//! Default calling convention for current platform / operating system.
//! @def kFuncConvHostCDecl
//! @brief Default C calling convention based on current compiler's settings.
//! Default C calling convention based on current compiler's settings.
//! @def kFuncConvHostStdCall
//! @brief Compatibility for __stdcall calling convention.
//! Compatibility for `__stdcall` calling convention.
//!
//! @note This enumeration is always set to a value which is compatible with
//! current compilers __stdcall calling convention. In 64-bit mode the value
//! is compatible with @ref kFuncConvX64W or @ref kFuncConvX64U.
//! is compatible with `kFuncConvX64W` or `kFuncConvX64U`.
//! @def kFuncConvHostFastCall
//! @brief Compatibility for __fastcall calling convention.
//! Compatibility for `__fastcall` calling convention.
//!
//! @note This enumeration is always set to a value which is compatible with
//! current compilers __fastcall calling convention. In 64-bit mode the value
//! is compatible with @ref kFuncConvX64W or @ref kFuncConvX64U.
//! current compilers `__fastcall` calling convention. In 64-bit mode the value
//! is compatible with `kFuncConvX64W` or `kFuncConvX64U`.
#if defined(ASMJIT_HOST_X86)
@@ -339,16 +337,16 @@ ASMJIT_ENUM(kFuncConv) {
// [asmjit::x86x64::kFuncHint]
// ============================================================================
//! @brief X86 function hints.
//! X86 function hints.
ASMJIT_ENUM(kFuncHint) {
//! @brief Use push/pop sequences instead of mov sequences in function prolog
//! Use push/pop sequences instead of mov sequences in function prolog
//! and epilog.
kFuncHintPushPop = 16,
//! @brief Add emms instruction to the function epilog.
//! Add emms instruction to the function epilog.
kFuncHintEmms = 17,
//! @brief Add sfence instruction to the function epilog.
//! Add sfence instruction to the function epilog.
kFuncHintSFence = 18,
//! @brief Add lfence instruction to the function epilog.
//! Add lfence instruction to the function epilog.
kFuncHintLFence = 19
};
@@ -356,36 +354,34 @@ ASMJIT_ENUM(kFuncHint) {
// [asmjit::x86x64::kFuncFlags]
// ============================================================================
//! @brief X86 function flags.
//! X86 function flags.
ASMJIT_ENUM(kFuncFlags) {
//! @brief Whether to emit register load/save sequence using push/pop pairs.
//! Whether to emit register load/save sequence using push/pop pairs.
kFuncFlagPushPop = 0x00010000,
//! @brief Whether to emit "enter" instead of three instructions in case
//! Whether to emit `enter` instead of three instructions in case
//! that the function is not naked or misaligned.
kFuncFlagEnter = 0x00020000,
//! @brief Whether to emit "leave" instead of two instructions in case
//! Whether to emit `leave` instead of two instructions in case
//! that the function is not naked or misaligned.
kFuncFlagLeave = 0x00040000,
//! @brief Whether it's required to move arguments to a new stack location,
//! Whether it's required to move arguments to a new stack location,
//! because of manual aligning.
kFuncFlagMoveArgs = 0x00080000,
//! @brief Whether to emit EMMS instruction in epilog (auto-detected).
//! Whether to emit `emms` instruction in epilog (auto-detected).
kFuncFlagEmms = 0x01000000,
//! @brief Whether to emit SFence instruction in epilog (auto-detected).
//! Whether to emit `sfence` instruction in epilog (auto-detected).
//!
//! @note @ref kFuncFlagSFence and @ref kFuncFlagLFence
//! combination will result in emitting mfence.
//! `kFuncFlagSFence` with `kFuncFlagLFence` results in emitting `mfence`.
kFuncFlagSFence = 0x02000000,
//! @brief Whether to emit LFence instruction in epilog (auto-detected).
//! Whether to emit `lfence` instruction in epilog (auto-detected).
//!
//! @note @ref kFuncFlagSFence and @ref kFuncFlagLFence
//! combination will result in emitting mfence.
//! `kFuncFlagSFence` with `kFuncFlagLFence` results in emitting `mfence`.
kFuncFlagLFence = 0x04000000
};
@@ -393,6 +389,9 @@ ASMJIT_ENUM(kFuncFlags) {
// [asmjit::x86x64::x86GetArchFromCConv]
// ============================================================================
//! Get architecture by a calling convention.
//!
//! Returns `kArchX86` or `kArchX64` depending on `conv`.
static ASMJIT_INLINE uint32_t x86GetArchFromCConv(uint32_t conv) {
return IntUtil::inInterval<uint32_t>(conv, kFuncConvX64W, kFuncConvX64U) ? kArchX64 : kArchX86;
}
@@ -401,56 +400,68 @@ static ASMJIT_INLINE uint32_t x86GetArchFromCConv(uint32_t conv) {
// [asmjit::x86x64::X86X64FuncDecl]
// ============================================================================
//! @brief X86 function, including calling convention, arguments and their
//! X86 function, including calling convention, arguments and their
//! register indices or stack positions.
struct X86X64FuncDecl : public FuncDecl {
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! @brief Create a new @ref X86X64FuncDecl instance.
ASMJIT_INLINE X86X64FuncDecl() { reset(); }
//! Create a new `X86X64FuncDecl` instance.
ASMJIT_INLINE X86X64FuncDecl() {
reset();
}
// --------------------------------------------------------------------------
// [Accessors - X86]
// --------------------------------------------------------------------------
//! @brief Get used registers (mask).
//! Get used registers (mask).
//!
//! @note The result depends on the function calling convention AND the
//! function prototype. Returned mask contains only registers actually used
//! to pass function arguments.
ASMJIT_INLINE uint32_t getUsed(uint32_t c) const { return _used.get(c); }
ASMJIT_INLINE uint32_t getUsed(uint32_t c) const {
return _used.get(c);
}
//! @brief Get passed registers (mask).
//! Get passed registers (mask).
//!
//! @note The result depends on the function calling convention used; the
//! prototype of the function doesn't affect the mask returned.
ASMJIT_INLINE uint32_t getPassed(uint32_t c) const { return _passed.get(c); }
ASMJIT_INLINE uint32_t getPassed(uint32_t c) const {
return _passed.get(c);
}
//! @brief Get preserved registers (mask).
//! Get preserved registers (mask).
//!
//! @note The result depends on the function calling convention used; the
//! prototype of the function doesn't affect the mask returned.
ASMJIT_INLINE uint32_t getPreserved(uint32_t c) const { return _preserved.get(c); }
ASMJIT_INLINE uint32_t getPreserved(uint32_t c) const {
return _preserved.get(c);
}
//! @brief Get ther order of passed registers (Gp).
//! Get ther order of passed registers (Gp).
//!
//! @note The result depends on the function calling convention used; the
//! prototype of the function doesn't affect the mask returned.
ASMJIT_INLINE const uint8_t* getPassedOrderGp() const { return _passedOrderGp; }
ASMJIT_INLINE const uint8_t* getPassedOrderGp() const {
return _passedOrderGp;
}
//! @brief Get ther order of passed registers (Xmm).
//! Get ther order of passed registers (Xmm).
//!
//! @note The result depends on the function calling convention used; the
//! prototype of the function doesn't affect the mask returned.
ASMJIT_INLINE const uint8_t* getPassedOrderXmm() const { return _passedOrderXmm; }
ASMJIT_INLINE const uint8_t* getPassedOrderXmm() const {
return _passedOrderXmm;
}
// --------------------------------------------------------------------------
// [SetPrototype]
// --------------------------------------------------------------------------
//! @brief Set function prototype.
//! Set function prototype.
//!
//! This will set function calling convention and setup arguments variables.
//!
@@ -467,18 +478,18 @@ struct X86X64FuncDecl : public FuncDecl {
// [Members]
// --------------------------------------------------------------------------
//! @brief Used registers .
//! Used registers.
RegMask _used;
//! @brief Passed registers (defined by the calling convention).
//! Passed registers (defined by the calling convention).
RegMask _passed;
//! @brief Preserved registers (defined by the calling convention).
//! Preserved registers (defined by the calling convention).
RegMask _preserved;
//! @brief Order of registers defined to pass function arguments (Gp).
uint8_t _passedOrderGp[kFuncArgCount];
//! @brief Order of registers defined to pass function arguments (Xmm).
uint8_t _passedOrderXmm[kFuncArgCount];
//! Order of registers defined to pass function arguments (Gp).
uint8_t _passedOrderGp[8];
//! Order of registers defined to pass function arguments (Xmm).
uint8_t _passedOrderXmm[8];
};
//! @}
+408
View File
@@ -0,0 +1,408 @@
# Doxyfile 1.8.7
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "AsmJit"
PROJECT_NUMBER = "1.1"
PROJECT_BRIEF = "Complete Remote and JIT Assembler for x86/x64"
OUTPUT_DIRECTORY = .
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF =
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = YES
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
JAVADOC_AUTOBRIEF = NO
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
# new page for each member. If set to NO, the documentation of a member will be
# part of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 2
MARKDOWN_SUPPORT = YES
AUTOLINK_SUPPORT = NO
IDL_PROPERTY_SUPPORT = NO
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = NO
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = NO
HIDE_UNDOC_CLASSES = YES
HIDE_FRIEND_COMPOUNDS = YES
HIDE_IN_BODY_DOCS = YES
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = NO
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = NO
SHOW_GROUPED_MEMB_INC = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = YES
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = NO
GENERATE_TESTLIST = NO
GENERATE_BUGLIST = NO
GENERATE_DEPRECATEDLIST= NO
MAX_INITIALIZER_LINES = 0
SHOW_USED_FILES = NO
SHOW_FILES = NO
SHOW_NAMESPACES = NO
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ../src/asmjit
INPUT_ENCODING = UTF-8
RECURSIVE = YES
EXCLUDE =
USE_MDFILE_AS_MAINPAGE = ../README.md
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
SOURCE_TOOLTIPS = YES
VERBATIM_HEADERS = NO
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
GENERATE_LATEX = NO
GENERATE_RTF = NO
GENERATE_MAN = NO
HTML_OUTPUT = doc
HTML_FILE_EXTENSION = .html
LAYOUT_FILE = doc-layout.xml
HTML_HEADER = doc-header.html
HTML_FOOTER = doc-footer.html
HTML_STYLESHEET = doc-style.css
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 0
SEARCHENGINE = NO
#---------------------------------------------------------------------------
# Configuration options related to the CHM output
#---------------------------------------------------------------------------
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows.
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler ( hhc.exe). If non-empty
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
# The BINARY_TOC flag controls whether a binary table of contents is generated (
# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
# the same information as the tab index, you could consider setting
# DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 0
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 250
# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = NO
PREDEFINED = ASMJIT_DOCGEN=1
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
CLASS_GRAPH = NO
+21
View File
@@ -0,0 +1,21 @@
<!--BEGIN GENERATE_TREEVIEW-->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
$navpath
<li class="footer">$generatedby
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
</ul>
</div>
<!--END GENERATE_TREEVIEW-->
<!--BEGIN !GENERATE_TREEVIEW-->
<hr class="footer"/><address class="footer"><small>
$generatedby &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
</a> $doxygenversion
</small></address>
<!--END !GENERATE_TREEVIEW-->
</body>
</html>
+37
View File
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<title>$projectname: $title</title>
<script type="text/javascript" src="$relpath^jquery.js"></script>
<script type="text/javascript" src="$relpath^dynsections.js"></script>
$treeview
$search
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
$extrastylesheet
</head>
<body>
<!-- do not remove this div, it is closed by doxygen! -->
<div id="top">
<!--BEGIN TITLEAREA-->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<!--BEGIN PROJECT_LOGO-->
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
<!--END PROJECT_LOGO-->
<td style="padding-left: 0.5em;">
<div id="projectname">$projectname&#160;<span id="projectnumber">$projectnumber</span> API</div>
<div id="projectbrief">$projectbrief</div>
</td>
</tr>
</tbody>
</table>
</div>
<!--END TITLEAREA-->
+112
View File
@@ -0,0 +1,112 @@
<doxygenlayout version="1.0">
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="pages" visible="yes" title=""/>
<tab type="modules" visible="yes" title=""/>
<tab type="namespaces" visible="no" title=""/>
<tab type="classes" visible="no" title=""/>
<tab type="files" visible="no" title=""/>
<tab type="examples" visible="no" title=""/>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription title=""/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<detaileddescription title=""/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
<services title=""/>
<interfaces title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
<publicstaticmethods title=""/>
<publicattributes title=""/>
<publicstaticattributes title=""/>
<protectedtypes title=""/>
<protectedslots title=""/>
<protectedmethods title=""/>
<protectedstaticmethods title=""/>
<protectedattributes title=""/>
<protectedstaticattributes title=""/>
<packagetypes title=""/>
<packagemethods title=""/>
<packagestaticmethods title=""/>
<packageattributes title=""/>
<packagestaticattributes title=""/>
<properties title=""/>
<events title=""/>
<privatetypes title=""/>
<privateslots title=""/>
<privatemethods title=""/>
<privatestaticmethods title=""/>
<privateattributes title=""/>
<privatestaticattributes title=""/>
<friends title=""/>
<related title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<services title=""/>
<interfaces title=""/>
<constructors title=""/>
<functions title=""/>
<related title=""/>
<variables title=""/>
<properties title=""/>
<events title=""/>
</memberdef>
<allmemberslink visible="yes"/>
</class>
<!-- Layout definition for a group page -->
<group>
<groupgraph visible="$GROUP_GRAPHS"/>
<detaileddescription title=""/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
<membergroups visible="yes"/>
</memberdecl>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
</doxygenlayout>
+1399
View File
File diff suppressed because it is too large Load Diff
-1634
View File
File diff suppressed because it is too large Load Diff
-405
View File
@@ -1,405 +0,0 @@
body, table, div, p, dl {
font-family: Lucida Grande, Verdana, Geneva, Arial, sans-serif;
font-size: 12px;
}
/* @group Heading Levels */
h1 {
text-align: center;
font-size: 150%;
}
h2 {
font-size: 120%;
}
h3 {
font-size: 100%;
}
/* @end */
caption {
font-weight: bold;
}
div.qindex, div.navtab{
background-color: #e8eef2;
border: 1px solid #84b0c7;
text-align: center;
margin: 2px;
padding: 2px;
}
div.qindex, div.navpath {
width: 100%;
line-height: 140%;
}
div.navtab {
margin-right: 15px;
}
/* @group Link Styling */
a {
color: #153788;
font-weight: normal;
text-decoration: none;
}
.contents a:visited {
color: #1b77c5;
}
a:hover {
text-decoration: underline;
}
a.qindex {
font-weight: bold;
}
a.qindexHL {
font-weight: bold;
background-color: #6666cc;
color: #ffffff;
border: 1px double #9295C2;
}
.contents a.qindexHL:visited {
color: #ffffff;
}
a.el {
font-weight: bold;
}
a.elRef {
}
a.code {
}
a.codeRef {
}
/* @end */
dl.el {
margin-left: -1cm;
}
.fragment {
font-family: monospace, fixed;
font-size: 105%;
}
pre.fragment {
border: 1px dotted #CCCCFF;
padding: 4px 6px;
margin: 4px 8px 4px 2px;
}
div.ah {
background-color: black;
font-weight: bold;
color: #ffffff;
margin-bottom: 3px;
margin-top: 3px
}
div.groupHeader {
margin-left: 16px;
margin-top: 12px;
margin-bottom: 6px;
font-weight: bold;
}
div.groupText {
margin-left: 16px;
font-style: italic;
}
body {
background: white;
color: black;
margin-right: 20px;
margin-left: 20px;
}
td.indexkey {
background-color: #e8eef2;
font-weight: bold;
border: 1px solid #CCCCCC;
margin: 2px 0px 2px 0;
padding: 2px 10px;
}
td.indexvalue {
background-color: #e8eef2;
border: 1px solid #CCCCCC;
padding: 2px 10px;
margin: 2px 0px;
}
tr.memlist {
background-color: #f0f0f0;
}
p.formulaDsp {
text-align: center;
}
img.formulaDsp {
}
img.formulaInl {
vertical-align: middle;
}
/* @group Code Colorization */
span.keyword {
color: #008000
}
span.keywordtype {
color: #604020
}
span.keywordflow {
color: #e08000
}
span.comment {
color: #800000
}
span.preprocessor {
color: #806020
}
span.stringliteral {
color: #002080
}
span.charliteral {
color: #008080
}
/* @end */
td.tiny {
font-size: 75%;
}
.dirtab {
padding: 4px;
border-collapse: collapse;
border: 1px solid #84b0c7;
}
th.dirtab {
background: #e8eef2;
font-weight: bold;
}
hr {
height: 0;
border: none;
border-top: 1px solid #666;
}
/* @group Member Descriptions */
.mdescLeft, .mdescRight,
.memItemLeft, .memItemRight,
.memTemplItemLeft, .memTemplItemRight, .memTemplParams {
background-color: #FFFFFF;
border: none;
margin: 4px;
padding: 1px 0 0 8px;
}
.mdescLeft, .mdescRight {
padding: 0px 8px 4px 8px;
color: #555;
}
.memItemLeft, .memItemRight {
padding-top: 4px;
padding-bottom: 4px;
border-top: 1px solid #CCCCFF;
}
.mdescLeft, .mdescRight {
}
.memTemplParams {
color: #606060;
}
/* @end */
/* @group Member Details */
/* Styles for detailed member documentation */
.memtemplate {
margin-left: 3px;
font-weight: normal;
font-size: 80%;
color: #606060;
}
.memnav {
background-color: #e8eef2;
border: 1px solid #84b0c7;
text-align: center;
margin: 2px;
margin-right: 15px;
padding: 2px;
}
.memitem {
padding: 0;
}
.memname {
white-space: nowrap;
font-weight: bold;
}
.memproto, .memdoc {
}
.memproto {
padding: 0;
background-color: #EEEEFF;
border: 1px solid #CCCCFF;
}
.memdoc {
padding: 2px 5px;
border-left: 1px solid #CCCCFF;
border-right: 1px solid #CCCCFF;
border-bottom: 1px solid #CCCCFF;
}
.paramkey {
text-align: right;
}
.paramtype {
white-space: nowrap;
}
.paramname {
color: #606060;
font-weight: normal;
white-space: nowrap;
}
.paramname em {
font-style: normal;
}
/* @end */
/* @group Directory (tree) */
/* for the tree view */
.ftvtree {
font-family: sans-serif;
margin: 0.5em;
}
/* these are for tree view when used as main index */
.directory {
font-size: 9pt;
font-weight: bold;
}
.directory h3 {
margin: 0px;
margin-top: 1em;
font-size: 11pt;
}
/*
The following two styles can be used to replace the root node title
with an image of your choice. Simply uncomment the next two styles,
specify the name of your image and be sure to set 'height' to the
proper pixel height of your image.
*/
/*
.directory h3.swap {
height: 61px;
background-repeat: no-repeat;
background-image: url("yourimage.gif");
}
.directory h3.swap span {
display: none;
}
*/
.directory > h3 {
margin-top: 0;
}
.directory p {
margin: 0px;
white-space: nowrap;
}
.directory div {
display: none;
margin: 0px;
}
.directory img {
vertical-align: -30%;
}
/* these are for tree view when not used as main index */
.directory-alt {
font-size: 100%;
font-weight: bold;
}
.directory-alt h3 {
margin: 0px;
margin-top: 1em;
font-size: 11pt;
}
.directory-alt > h3 {
margin-top: 0;
}
.directory-alt p {
margin: 0px;
white-space: nowrap;
}
.directory-alt div {
display: none;
margin: 0px;
}
.directory-alt img {
vertical-align: -30%;
}
/* @end */
address {
font-style: normal;
color: #333;
}