Globals, code storage, and emitter interface.
Overview
AsmJit library uses CodeHolder to hold code during code generation and emitters inheriting from BaseEmitter to emit code. CodeHolder uses containers to manage its data:
- Section - stores information about a code or data section.
- CodeBuffer - stores actual code or data, part of Section.
- LabelEntry - stores information about a Label - its name, offset, section where it belongs to, and other bits.
- Fixup - stores information about positions in code that needs to be fixed up later, for example when referencing a Label, which was not bound to a position in code yet.
- RelocEntry - stores information about a relocation.
- AddressTableEntry - stores information about an absolute address, which was used in a jump or call. Code referencing an absolute address may need relocation or a record in address table.
To generate code you would need to instantiate at least the following classes:
There are also other core classes that are important:
- Environment - describes where the code will run. Environment brings the concept of target triples or tuples into AsmJit, which means that users can specify target architecture, platform, and ABI.
- TypeId - encapsulates lightweight type functionality that can be used to describe primitive and vector types. Types are used by higher level utilities, for example by Function and Compiler.
- CpuInfo - encapsulates CPU information - stores both CPU information and CPU features described by CpuFeatures.
AsmJit also provides global constants:
- Globals - namespace that provides global constants.
Note
CodeHolder examples use x86::Assembler as abstract interfaces cannot be used to generate code.
CodeHolder & Emitters [¶]
The example below shows how the mentioned classes interact to generate X86 code:
#include <asmjit/x86.h>
#include <stdio.h>
using Func = int (*)(void);
int main() {
a.mov(x86::eax, 1);
a.ret();
Func fn;
return 1;
}
int result = fn();
printf("%d\n", result);
return 0;
}
The example above used x86::Assembler as an emitter. AsmJit provides the following emitters that offer various levels of abstraction:
Targets and JitRuntime [¶]
AsmJit's Target is an interface that provides basic target abstraction. At the moment AsmJit provides only one implementation called JitRuntime, which as the name suggests provides JIT code target and execution runtime. JitRuntime provides all the necessary stuff to implement a simple JIT compiler with basic memory management. It only provides JitRuntime::add() and JitRuntime::release() functions that are used to either add code to the runtime or release it. JitRuntime doesn't do any decisions on when the code should be released, the decision is up to the developer.
See more at Virtual Memory group.
More About Environment
In the previous example the Environment is retrieved from JitRuntime. It's logical as JitRuntime always returns an Environment that is compatible with the host. For example if your application runs on X86_64 CPU the Environment returned will use Arch::kX64 architecture in contrast to Arch::kX86, which will be used in 32-bit mode on an X86 target.
AsmJit allows to setup the Environment manually and to select a different architecture and ABI when necessary. So let's do something else this time, let's always generate a 32-bit code and print its binary representation. To do that, we can create our own Environment and initialize it to Arch::kX86.
#include <asmjit/x86.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
a.mov(eax, dword_ptr(esp, 4));
a.mov(ecx, dword_ptr(esp, 8));
a.mov(edx, dword_ptr(esp, 12));
a.movups(xmm0,
ptr(ecx));
a.movups(xmm1,
ptr(edx));
a.addps(xmm0, xmm1);
a.movups(
ptr(eax), xmm0);
a.ret();
for (size_t i = 0; i < buffer.length; i++)
printf(
"%02X", buffer.
data[i]);
return 0;
}
Explicit Code Relocation [¶]
In addition to Environment, CodeHolder can be configured to specify a base-address (or a virtual base address in a linker terminology), which could be static (useful when you know the location where the target's machine code will be) or dynamic. AsmJit assumes dynamic base-address by default and relocates the code held by CodeHolder to a user provided address on-demand. To be able to relocate to a user provided address it needs to store some information about relocations, which is represented by RelocEntry. Relocation entries are only required if you call external functions from the generated code that cannot be encoded by using a 32-bit displacement (64-bit displacements are not provided by aby supported architecture).
There is also a concept called Fixup - it's a lightweight data structure that doesn't have any identifier and is stored in LabelEntry and CodeHolder as a single-linked list. Fixup represents either a reference to an unbound label and cross-sections references (only relevant to code that uses multiple sections). Since crossing sections is something that cannot be resolved immediately these fixups persist until offsets of these sections are assigned and until CodeHolder::resolve_cross_section_fixups() is called. It's an error if you end up with code that still has fixups after flattening. You can verify it by calling CodeHolder::has_unresolved_fixups(), which inspects the value returned by CodeHolder::unresolved_fixup_count().
AsmJit can flatten code that uses multiple sections by assigning each section an incrementing offset that respects its alignment. Use CodeHolder::flatten() to do that. After the sections are flattened their offsets and virtual sizes are adjusted to respect each section's buffer size and alignment. The CodeHolder::resolve_cross_section_fixups() function must be called before relocating the code held by CodeHolder. You can also flatten your code manually by iterating over all sections and calculating their offsets (relative to base) by your own algorithm. In that case CodeHolder::flatten() should not be called, however, CodeHolder::resolve_cross_section_fixups() should be.
The example below shows how to use a built-in virtual memory allocator JitAllocator instead of using JitRuntime (just in case you want to use your own memory management) and how to relocate the generated code into your own memory block - you can use your own virtual memory allocator if you prefer that, but that's OS specific and not covered by the documentation.
The following code is similar to the previous one, but implements a function working in both 32-bit and 64-bit environments:
#include <asmjit/x86.h>
#include <stdio.h>
using SumIntsFunc = void (*)(int* dst, const int* a, const int* b);
int main() {
code.
init(env, cpu_features);
dst = x86::eax;
src_a = x86::ecx;
src_b = x86::edx;
a.mov(dst , x86::dword_ptr(x86::esp, 4));
a.mov(src_a, x86::dword_ptr(x86::esp, 8));
a.mov(src_b, x86::dword_ptr(x86::esp, 12));
}
else {
dst = x86::rcx;
src_a = x86::rdx;
src_b = x86::r8;
}
else {
dst = x86::rdi;
src_a = x86::rsi;
src_b = x86::rdx;
}
}
a.paddd(x86::xmm0, x86::xmm1);
a.ret();
Error err = allocator.
alloc(span, estimated_size);
return 0;
}
});
int in_a[4] = { 4, 3, 2, 1 };
int in_b[4] = { 1, 5, 2, 8 };
int out[4];
fn(out, in_a, in_b);
printf("{%d %d %d %d}\n", out[0], out[1], out[2], out[3]);
return 0;
}
If you know the base-address in advance (before the code generation) it can be passed as a second argument to CodeHolder::init(). In that case the Assembler will know the absolute position of each instruction and would be able to use it during instruction encoding to prevent relocations where possible. The following example shows how to configure the base address:
#include <asmjit/x86.h>
#include <stdio.h>
void initialize_code_holder_example(
CodeHolder& code) {
uint64_t base_address = uint64_t(0x1234);
code.
init(env, cpu_features, base_address);
}
Label Offsets and Links [¶]
When a label that is not yet bound is used by the Assembler, it creates a Fixup, which is then referenced by LabelEntry. Fixups are also created if a label is referenced in a different section than in which it was bound. Let's examine some functions that can be used to check whether there are any unresolved fixups.
#include <asmjit/core.h>
#include <stdio.h>
printf(
"Label %u is %s\n", label.
id(), is_bound ?
"bound" :
"not bound");
printf("Number of unresolved fixups: %zu\n", n_unresolved);
}
There is no function that would return the number of unbound labels as this is completely unimportant from CodeHolder's perspective. If a label is not used then it doesn't matter whether it's bound or not, only actually used labels matter. After a Label is bound it's possible to query its offset relative to the start of the section where it was bound:
#include <asmjit/core.h>
#include <stdio.h>
printf("Label offset relative to section: %llu\n", (unsigned long long)section_offset);
printf("Label offset relative to base: %llu\n", (unsigned long long)base_offset);
}
Code & Data Sections [¶]
AsmJit allows to create multiple sections within the same CodeHolder. A test-case asmjit_test_x86_sections.cpp can be used as a reference point although the following example should also provide a useful insight:
#include <asmjit/x86.h>
#include <stdio.h>
".data",
SIZE_MAX,
8,
0);
Label L_Data = a.new_label();
a.mov(x86::eax, x86::ebx);
a.section(data);
a.bind(L_Data);
a.db(0x01);
a.section(text);
a.add(x86::ebx, x86::eax);
}
The last line in the example above shows that a Fixup would be created even for bound labels that cross sections. In this case a referenced label was bound in another section, which means that the reference couldn't be resolved at that moment. If your code uses sections, but you wish AsmJit to flatten these sections (you don't plan to flatten them manually) then there is a ready API for that.
#include <asmjit/x86.h>
#include <stdio.h>
void sections_example_continued(
CodeHolder& code) {
exit(1);
}
printf("Data section offset %zu", size_t(data->offset()));
exit(1);
}
exit(1);
}
}
#define ASMJIT_LIBRARY_MAKE_VERSION(
major,
minor,
patch
)[¶]
Value:((major << 16) | (minor << 8) | (patch))
Makes a 32-bit integer that represents AsmJit version in (major << 16) | (minor << 8) | patch
form.
#define ASMJIT_ABI_NAMESPACE v1_18[¶]
AsmJit ABI namespace is an inline namespace within asmjit namespace.
It's used to make sure that when user links to an incompatible version of AsmJit, it won't link. It has also some additional properties as well. When ASMJIT_ABI_NAMESPACE
is defined by the user it would override the AsmJit default, which makes it possible to use multiple AsmJit libraries within a single project, totally controlled by users. This is useful especially in cases in which some of such library comes from third party.
#define ASMJIT_ARCH_X86 __detected_at_runtime__[¶]
Defined to either 0, 32, or 64 depending on whether the target CPU is X86 (32) or X86_64 (64).
#define ASMJIT_ARCH_ARM __detected_at_runtime__[¶]
Defined to either 0, 32, or 64 depending on whether the target CPU is ARM (32) or AArch64 (64).
#define ASMJIT_ARCH_MIPS __detected_at_runtime__[¶]
Defined to either 0, 32, or 64 depending on whether the target CPU is MIPS (32) or MISP64 (64).
#define ASMJIT_ARCH_RISCV __detected_at_runtime__[¶]
Defined to either 0, 32, or 64 depending on whether the target CPU is RV32 (32) or RV64 (64).
#define ASMJIT_ARCH_LA __detected_at_runtime__[¶]
Defined to either 0, 32, or 64 depending on whether the target CPU is 32-bit or 64-bit LoongArch.
#define ASMJIT_ARCH_BITS __detected_at_runtime__(32 | 64)[¶]
Defined to either 32 or 64 depending on the target.
#define ASMJIT_HAS_HOST_BACKEND __detected_at_runtime__[¶]
Defined when AsmJit is built with the target architecture backend.
For example if AsmJit is building for x86 or x86_64 architectures and ASMJIT_NO_X86
is not defined, it would define ASMJIT_HAS_HOST_BACKEND
when <asmjit/code.h>
or `<asmjit/host.h>
is included.
#define ASMJIT_API[¶]
A decorator that is used to decorate API that AsmJit exports when built as a shared library.
#define ASMJIT_VIRTAPI[¶]
This is basically a workaround. When using MSVC and marking class as DLL export everything gets exported, which is unwanted in most projects. MSVC automatically exports typeinfo and vtable if at least one symbol of the class is exported. However, GCC has some strange behavior that even if one or more symbol is exported it doesn't export typeinfo unless the class itself is decorated with "visibility(default)" (i.e. ASMJIT_API).
#define ASMJIT_INLINE inline[¶]
Decorator to force inlining of functions, uses either __attribute__((__always_inline__))
or __forceinline, depending on C++ compiler.
#define ASMJIT_INLINE_NODEBUG inline[¶]
Like ASMJIT_INLINE, but uses additionally __nodebug__
or __artificial__
attribute to make the debugging of some AsmJit functions easier, especially getters and one-line abstractions where usually you don't want to step in.
#define ASMJIT_INLINE_CONSTEXPR inline constexpr[¶]
#define ASMJIT_NOINLINE[¶]
Decorator to avoid inlining of functions, uses either __attribute__((__noinline__))
or __declspec(noinline)
depending on C++ compiler.
#define ASMJIT_CDECL[¶]
CDECL function attribute - either __attribute__((__cdecl__))
or __cdecl
.
#define ASMJIT_STDCALL[¶]
STDCALL function attribute - either __attribute__((__stdcall__))
or __stdcall
.
Note
This expands to nothing on non-x86 targets as STDCALL is X86 specific.
#define ASMJIT_FASTCALL[¶]
FASTCALL function attribute - either __attribute__((__fastcall__))
or __fastcall
.
Note
Expands to nothing on non-x86 targets as FASTCALL is X86 specific.
#define ASMJIT_REGPARM(
N
)[¶]
Expands to __attribute__((__regparm__(N)))
when compiled by GCC or clang, nothing otherwise.
#define ASMJIT_VECTORCALL[¶]
VECTORCALL function attribute - either __attribute__((__vectorcall__))
or __vectorcall
.
Note
Expands to nothing on non-x86 targets as VECTORCALL is X86 specific.
#define ASMJIT_MAY_ALIAS[¶]
Expands to __attribute__((__may_alias__))
if supported.
#define ASMJIT_ASSUME(
...
)[¶]
Macro that tells the C/C++ compiler that the expression ...
evaluates to true.
This macro has two purposes:
- Enable optimizations that would not be possible without the assumption.
- Hint static analysis tools that a certain condition is true to prevent false positives.
#define ASMJIT_LIKELY(
...
)[¶]
Condition is likely to be taken (mostly error handling and edge cases).
#define ASMJIT_UNLIKELY(
...
)[¶]
Condition is unlikely to be taken (mostly error handling and edge cases).
Arch : uint8_tenum class[¶]
Instruction set architecture (ISA).
Constant | Description |
---|
kUnknown | Unknown or uninitialized ISA.
|
kX86 | 32-bit X86 ISA.
|
kX64 | 64-bit X86 ISA also known as X64, X86_64, and AMD64.
|
kRISCV32 | 32-bit RISC-V ISA.
|
kRISCV64 | 64-bit RISC-V ISA.
|
kARM | 32-bit ARM ISA (little endian).
|
kAArch64 | 64-bit ARM ISA in (little endian).
|
kThumb | 32-bit ARM ISA in Thumb mode (little endian).
|
kLA64 | 64-bit LoongArch.
|
kMIPS32_LE | 32-bit MIPS ISA in (little endian).
|
kMIPS64_LE | 64-bit MIPS ISA in (little endian).
|
kARM_BE | 32-bit ARM ISA (big endian).
|
kAArch64_BE | 64-bit ARM ISA in (big endian).
|
kThumb_BE | 32-bit ARM ISA in Thumb mode (big endian).
|
kMIPS32_BE | 32-bit MIPS ISA in (big endian).
|
kMIPS64_BE | 64-bit MIPS ISA in (big endian).
|
kMaxValue | Maximum value of Arch .
|
k32BitMask | Mask used by 32-bit ISAs (odd are 32-bit, even are 64-bit).
|
kBigEndian | First big-endian architecture.
|
kHost | ISA detected at compile-time (ISA of the host).
|
Sub-architecture.
Constant | Description |
---|
kUnknown | Unknown or uninitialized architecture sub-type.
|
kMaxValue | Maximum value of SubArch .
|
kHost | Sub-architecture detected at compile-time (sub-architecture of the host).
|
Identifier used to represent names of different data types across architectures.
Constant | Description |
---|
kDB | Describes 'db' (X86|X86_64 convention, always 8-bit quantity).
|
kDW | Describes 'dw' (X86|X86_64 convention, always 16-bit word).
|
kDD | Describes 'dd' (X86|X86_64 convention, always 32-bit word).
|
kDQ | Describes 'dq' (X86|X86_64 convention, always 64-bit word).
|
kByte | Describes 'byte' (always 8-bit quantity).
|
kHalf | Describes 'half' (most likely 16-bit word).
|
kWord | Describes 'word' (either 16-bit or 32-bit word).
|
kHWord | Describes 'hword' (most likely 16-bit word).
|
kDWord | Describes 'dword' (either 32-bit or 64-bit word).
|
kQWord | Describes 'qword' (64-bit word).
|
kXWord | Describes 'xword' (64-bit word).
|
kShort | Describes 'short' (always 16-bit word).
|
kLong | Describes 'long' (most likely 32-bit word).
|
kQuad | Describes 'quad' (64-bit word).
|
kMaxValue | Maximum value of ArchTypeNameId .
|
Instruction feature hints for each register group provided by ArchTraits.
Instruction feature hints describe miscellaneous instructions provided by the architecture that can be used by register allocator to make certain things simpler - like register swaps or emitting register push/pop sequences.
Constant | Description |
---|
kNoHints | No feature hints.
|
kRegSwap | Architecture supports a register swap by using a single instruction.
|
kPushPop | Architecture provides push/pop instructions.
|
Flags used by CodeBuffer.
Constant | Description |
---|
kNone | No flags.
|
kIsExternal | Buffer is external (not allocated by asmjit).
|
kIsFixed | Buffer is fixed (cannot be reallocated).
|
Operator type that can be used within an Expression.
Constant | Description |
---|
kAdd | Addition.
|
kSub | Subtraction.
|
kMul | Multiplication.
|
kSll | Logical left shift.
|
kSrl | Logical right shift.
|
kSra | Arithmetic right shift.
|
Value type that can be used within an Expression.
Constant | Description |
---|
kNone | No value or invalid.
|
kConstant | Value is 64-bit unsigned integer (constant).
|
kLabel | Value is LabelEntry, which references a Label.
|
kExpression | Value is Expression.
|
Relocation type.
Constant | Description |
---|
kNone | None/deleted (no relocation).
|
kExpression | Expression evaluation, _payload is pointer to Expression .
|
kSectionRelative | Relative relocation from one section to another.
|
kAbsToAbs | Relocate absolute to absolute.
|
kRelToAbs | Relocate relative to absolute.
|
kAbsToRel | Relocate absolute to relative.
|
kX64AddressEntry | Relocate absolute to relative or use trampoline.
|
Type of the Label.
Constant | Description |
---|
kAnonymous | Anonymous label that can optionally have a name, which is only used for debugging purposes.
|
kLocal | Local label (always has parent_id).
|
kGlobal | Global label (never has parent_id).
|
kExternal | External label (references an external symbol).
|
kMaxValue | Maximum value of LabelType .
|
Label flags describe some details about labels used by LabelEntry, mostly for AsmJit's own use.
Constant | Description |
---|
kNone | No flags.
|
kHasOwnExtraData | Label has associated extra data with it that it owns.
|
kHasName | Label has a name.
|
kHasParent | Label has a parent (only a local label can have a parent).
|
Section flags, used by Section.
Constant | Description |
---|
kNone | No flags.
|
kExecutable | Executable (.text sections).
|
kReadOnly | Read-only (.text and .data sections).
|
kZeroInitialized | Zero initialized by the loader (BSS).
|
kComment | Info / comment flag.
|
kBuiltIn | Section is built in and created by default (.text section).
|
kImplicit | Section created implicitly, can be deleted by Target.
|
Flags that can be used with CodeHolder::copy_section_data() and CodeHolder::copy_flattened_data().
Constant | Description |
---|
kNone | No flags.
|
kPadSectionBuffer | If virtual size of a section is greater than the size of its CodeBuffer then all bytes between the buffer size and virtual size will be zeroed. If this option is not set then those bytes would be left as is, which means that if the user didn't initialize them they would have a previous content, which may be unwanted.
|
kPadTargetBuffer | Clears the target buffer if the flattened data is less than the destination size. This option works only with CodeHolder::copy_flattened_data() as it processes multiple sections. It is ignored by CodeHolder::copy_section_data().
|
Align mode, used by BaseEmitter::align().
Constant | Description |
---|
kCode | Align executable code.
|
kData | Align non-executable code.
|
kZero | Align by a sequence of zeros.
|
kMaxValue | Maximum value of AlignMode .
|
Emitter type used by BaseEmitter.
Constant | Description |
---|
kNone | Unknown or uninitialized.
|
kAssembler | Emitter inherits from BaseAssembler.
|
kBuilder | Emitter inherits from BaseBuilder.
|
kCompiler | Emitter inherits from BaseCompiler.
|
kMaxValue | Maximum value of EmitterType .
|
Emitter flags, used by BaseEmitter.
Constant | Description |
---|
kNone | No flags.
|
kAttached | Emitter is attached to CodeHolder.
|
kLogComments | The emitter must emit comments.
|
kOwnLogger | The emitter has its own Logger (not propagated from CodeHolder).
|
kOwnErrorHandler | The emitter has its own ErrorHandler (not propagated from CodeHolder).
|
kFinalized | The emitter was finalized.
|
kDestroyed | The emitter was destroyed.
This flag is used for a very short time when an emitter is being destroyed by CodeHolder.
|
Encoding options.
Constant | Description |
---|
kNone | No encoding options.
|
kOptimizeForSize | Emit instructions that are optimized for size, if possible.
Default: false.
X86 Specific
When this option is set it the assembler will try to fix instructions if possible into operation equivalent instructions that take less bytes by taking advantage of implicit zero extension. For example instruction like mov r64, imm and and r64, imm can be translated to mov r32, imm and and r32, imm when the immediate constant is lesser than 2^31 .
|
kOptimizedAlign | Emit optimized code-alignment sequences.
Default: false.
X86 Specific
Default align sequence used by X86 architecture is one-byte (0x90) opcode that is often shown by disassemblers as NOP. However there are more optimized align sequences for 2-11 bytes that may execute faster on certain CPUs. If this feature is enabled AsmJit will generate specialized sequences for alignment between 2 to 11 bytes.
|
kPredictedJumps | Emit jump-prediction hints.
Default: false.
X86 Specific
Jump prediction is usually based on the direction of the jump. If the jump is backward it is usually predicted as taken; and if the jump is forward it is usually predicted as not-taken. The reason is that loops generally use backward jumps and conditions usually use forward jumps. However this behavior can be overridden by using instruction prefixes. If this option is enabled these hints will be emitted.
This feature is disabled by default, because the only processor that used to take into consideration prediction hints was P4. Newer processors implement heuristics for branch prediction and ignore static hints. This means that this feature can be only used for annotation purposes.
|
Diagnostic options are used to tell emitters and their passes to perform diagnostics when emitting or processing user code. These options control validation and extra diagnostics that can be performed by higher level emitters.
Instruction Validation
BaseAssembler implementation perform by default only basic checks that are necessary to identify all variations of an instruction so the correct encoding can be selected. This is fine for production-ready code as the assembler doesn't have to perform checks that would slow it down. However, sometimes these checks are beneficial especially when the project that uses AsmJit is in a development phase, in which mistakes happen often. To make the experience of using AsmJit seamless it offers validation features that can be controlled by DiagnosticOptions.
Compiler Diagnostics
Diagnostic options work with BaseCompiler passes (precisely with its register allocation pass). These options can be used to enable logging of all operations that the Compiler does.
Constant | Description |
---|
kNone | No validation options.
|
kValidateAssembler | Perform strict validation in BaseAssembler::emit() implementations.
This flag ensures that each instruction is checked before it's encoded into a binary representation. This flag is only relevant for BaseAssembler implementations, but can be set in any other emitter type, in that case if that emitter needs to create an assembler on its own, for the purpose of BaseEmitter::finalize() it would propagate this flag to such assembler so all instructions passed to it are explicitly validated.
Default: false.
|
kValidateIntermediate | Perform strict validation in BaseBuilder::emit() and BaseCompiler::emit() implementations.
This flag ensures that each instruction is checked before an InstNode representing the instruction is created by BaseBuilder or BaseCompiler. This option could be more useful than kValidateAssembler in cases in which there is an invalid instruction passed to an assembler, which was invalid much earlier, most likely when such instruction was passed to Builder/Compiler.
This is a separate option that was introduced, because it's possible to manipulate the instruction stream emitted by BaseBuilder and BaseCompiler - this means that it's allowed to emit invalid instructions (for example with missing operands) that will be fixed later before finalizing it.
Default: false.
|
kRAAnnotate | Annotate all nodes processed by register allocator (Compiler/RA).
NoteAnnotations don't need debug options, however, some debug options like kRADebugLiveness may influence their output (for example the mentioned option would add liveness information to per-instruction annotation).
|
kRADebugCFG | Debug CFG generation and other related algorithms / operations (Compiler/RA).
|
kRADebugLiveness | Debug liveness analysis (Compiler/RA).
|
kRADebugAssignment | Debug register allocation assignment (Compiler/RA).
|
kRADebugUnreachable | Debug the removal of code part of unreachable blocks.
|
kRADebugAll | Enable all debug options (Compiler/RA).
|
Vendor : uint8_tenum class[¶]
Vendor.
Note
AsmJit doesn't use vendor information at the moment. It's provided for future use, if required.
Constant | Description |
---|
kUnknown | Unknown or uninitialized platform vendor.
|
kMaxValue | Maximum value of Vendor .
|
kHost | Platform vendor detected at compile-time.
|
Platform - runtime environment or operating system.
Constant | Description |
---|
kUnknown | Unknown or uninitialized platform.
|
kWindows | Windows OS.
|
kOther | Other platform that is not Windows, most likely POSIX based.
|
kLinux | Linux OS.
|
kHurd | GNU/Hurd OS.
|
kFreeBSD | FreeBSD OS.
|
kOpenBSD | OpenBSD OS.
|
kNetBSD | NetBSD OS.
|
kDragonFlyBSD | DragonFly BSD OS.
|
kHaiku | Haiku OS.
|
kOSX | Apple OSX.
|
kIOS | Apple iOS.
|
kTVOS | Apple TVOS.
|
kWatchOS | Apple WatchOS.
|
kEmscripten | Emscripten platform.
|
kMaxValue | Maximum value of Platform .
|
kHost | Platform detected at compile-time (platform of the host).
|
Platform ABI (application binary interface).
Constant | Description |
---|
kUnknown | Unknown or uninitialized environment.
|
kMSVC | Microsoft ABI.
|
kGNU | GNU ABI.
|
kAndroid | Android Environment / ABI.
|
kCygwin | Cygwin ABI.
|
kDarwin | Darwin ABI.
|
kMaxValue | Maximum value of PlatformABI .
|
kHost | Host ABI detected at compile-time.
|
Floating point ABI (ARM).
Object format.
Note
AsmJit doesn't really use anything except ObjectFormat::kUnknown and ObjectFormat::kJIT at the moment. Object file formats are provided for future extensibility and a possibility to generate object files at some point.
Constant | Description |
---|
kUnknown | Unknown or uninitialized object format.
|
kJIT | JIT code generation object, most likely JitRuntime or a custom Target implementation.
|
kELF | Executable and linkable format (ELF).
|
kCOFF | Common object file format.
|
kXCOFF | Extended COFF object format.
|
kMachO | Mach object file format.
|
kMaxValue | Maximum value of ObjectFormat .
|
Offset format type, used by OffsetFormat.
Constant | Description |
---|
kSignedOffset | A value having _imm_bit_count bits and shifted by _imm_bit_shift .
This offset type is sufficient for many targets that store offset as a continuous set bits within an instruction word / sequence of bytes.
|
kUnsignedOffset | An unsigned value having _imm_bit_count bits and shifted by _imm_bit_shift .
|
kAArch64_ADR | AArch64 ADR format of [.|immlo:2|.....|immhi:19|.....] .
|
kAArch64_ADRP | AArch64 ADRP format of [.|immlo:2|.....|immhi:19|.....] (4kB pages).
|
kThumb32_ADR | AArch32 THUMBv2 immediate encoding of 'ADR' instruction (12-bit payload and sign bit): `|.....|imm:1|..N.N|......|imm:3|....|imm:8|`
Where N is one if the offset is negative. The immediate is encoded as absolute value of the offset if negative.
|
kThumb32_BLX | AArch32 THUMBv2 immediate encoding of 'BLX' instruction (23-bit immediate payload, multiplied by 4): `|.....|imm[22]|imm[19:10]|..|ja|1|jb|imm[9:0]|0`
Where:
ja is calculated as imm[22] ^ imm[21] ^ 1.
jb is calculated as imm[22] ^ imm[20] ^ 1.
|
kThumb32_B | AArch32 THUMBv2 immediate encoding of 'B' instruction without <cond> (24-bit immediate payload, multiplied by 2): `|.....|imm[23]|imm[20:11]|..|ja|1|jb|imm[10:0]`
Where:
ja is calculated as imm[23] ^ imm[22] ^ 1.
jb is calculated as imm[23] ^ imm[21] ^ 1.
|
kThumb32_BCond | AArch32 THUMBv2 immediate encoding of 'B' instruction with <cond> (20-bit immediate payload, multiplied by 2). `|.....|imm[19]|....|imm[16:11]|..|ja|1|jb|imm[10:0]`
Where:
ja is calculated as imm[19] ^ imm[18] ^ 1.
jb is calculated as imm[19] ^ imm[17] ^ 1.
|
kAArch32_ADR | AArch32 ADR instruction, which uses a standard 12-bit immediate encoding that is used by other ARM instructions.
|
kAArch32_U23_SignedOffset | AArch32 signed offset that is similar to kSignedOffset , however it uses absolute value of the offset and its sign is encoded in 23rd bit of the opcode.
|........|U.......|........|........|
|
kAArch32_U23_0To3At0_4To7At8 | AArch32 offset format that encodes 8-bit offset as: `|........|U.......|....|imm[7:4]|....|imm[3:0]|`
in a 32-bit word, where U is a sign of the displacement and the displacement itself is encoded as its absolute value.
|
kAArch32_1To24At0_0At24 | AArch32 offset format that encodes a signed 25-bit offset as: `|.......|imm[0]|imm[24:1]|`
in a 32-bit word.
|
kMaxValue | Maximum value of OffsetFormatType .
|
A policy that can be used with some reset()
member functions.
Constant | Description |
---|
kSoft | Soft reset, doesn't deallocate memory (default).
|
kHard | Hard reset, releases all memory used, if any.
|
TypeId : uint8_tenum class[¶]
Type identifier provides a minimalist type system used across AsmJit library.
This is an additional information that can be used to describe a value-type of physical or virtual register. It's used mostly by BaseCompiler to describe register representation (the group of data stored in the register and the width used) and it's also used by APIs that allow to describe and work with function signatures.
Constant | Description |
---|
kVoid | Void type.
|
kIntPtr | Abstract signed integer type that has a native size.
|
kUIntPtr | Abstract unsigned integer type that has a native size.
|
kInt8 | 8-bit signed integer type.
|
kUInt8 | 8-bit unsigned integer type.
|
kInt16 | 16-bit signed integer type.
|
kUInt16 | 16-bit unsigned integer type.
|
kInt32 | 32-bit signed integer type.
|
kUInt32 | 32-bit unsigned integer type.
|
kInt64 | 64-bit signed integer type.
|
kUInt64 | 64-bit unsigned integer type.
|
kFloat32 | 32-bit floating point type.
|
kFloat64 | 64-bit floating point type.
|
kFloat80 | 80-bit floating point type.
|
kMask8 | 8-bit opmask register (K).
|
kMask16 | 16-bit opmask register (K).
|
kMask32 | 32-bit opmask register (K).
|
kMask64 | 64-bit opmask register (K).
|
kMmx32 | 64-bit MMX register only used for 32 bits.
|
kMmx64 | 64-bit MMX register.
|
template<typename Func>
Func ptr_as_func(void* p
)staticnoexcept[1/2][¶]
Casts a void*
pointer func
to a function pointer Func
.
template<typename Func>
Func ptr_as_func(void* p,
size_t offset
)staticnoexcept[2/2][¶]
Casts a void*
pointer func
to a function pointer Func
.
template<typename Func>
void* func_as_ptr(Func func
)staticnoexcept[¶]
Casts a function pointer func
to a void pointer void*
.