Documentation of breaking changes.
Overview
AsmJit is a live project that is being actively developed. Deprecating the existing API in favor of a new one is preferred, but it's not always possible if the changes are significant. AsmJit authors prefer to do accumulated breaking changes at once instead of breaking the API often. This page documents deprecated and removed APIs and should serve as a how-to guide for people that want to port existing code to work with the newest AsmJit.
API Changes [¶]
Changes committed at 2025-09-06
Core changes:
- Refactored AsmJit to use snake_case_function_names() instead of camelCasedFunctionNames().
- Renamed Compiler's
newIntPtr()
and newUIntPtr()
to new_gp_ptr()
, or you should use just new_gpz()
.
- Renamed Zone to Arena (including containers) and merged Arena and ArenaAllocator into a single class.
- Removed
Support::Temporary
in favor of Span<uint8_t>
. CodeHolder
and Arena
now accept Span<uint8_t>
instead of Support::Temporary
.
Changes committed at 2025-06-15
Core changes:
- No more architecture specific RegTraits - removed
BaseRegTraits
and kept just RegTraits:
BaseRegTraits
-> RegTraits
arm::RegTraits
-> RegTraits
x86::RegTraits
-> RegTraits
- Removed register signature and helper functions from ArchTraits. This functionality is now available via asmjit::RegTraits and asmjit::RegUtils and doesn't require a valid architecture traits instance.
- No more architecture specific Gp/Vec/Mask register types in RegType and RegGroup:
RegGroup::kX86_Rip
-> RegGroup::kPC
RegGroup::kX86_KReg
-> RegGroup::kMask
RegType::kX86_GpbLo
-> RegType::kGp8Lo
RegType::kX86_GpbLo
-> RegType::kGp8Lo
RegType::kX86_GpbHi
-> RegType::kGp8Hi
RegType::kX86_Gpw
-> RegType::kGp16
RegType::kX86_Gpd
-> RegType::kGp32
RegType::kX86_Gpq
-> RegType::kGp64
RegType::kX86_Xmm
-> RegType::kVec128
RegType::kX86_Ymm
-> RegType::kVec256
RegType::kX86_Zmm
-> RegType::kVec512
RegType::kX86_KReg
-> RegType::kMask
RegType::kARM_PC
-> RegType::kPC
RegType::kARM_GpW
-> RegType::kGp32
RegType::kARM_GpX
-> RegType::kGp64
RegType::kARM_VecB
-> RegType::kVec8
RegType::kARM_VecH
-> RegType::kVec16
RegType::kARM_VecS
-> RegType::kVec32
RegType::kARM_VecD
-> RegType::kVec64
RegType::kARM_VecQ
-> RegType::kVec128
RegType::kARM_VecV
-> RegType::kVec128
- Renamed
asmjit::BaseReg
to asmjit::Reg, added asmjit::UniGp
and asmjit::UniVec
which are now base classes for platform specific [x86|a64]Gp
and [x86|a64]Vec
- Gp and Vec register API is now more platform independent - use
isGp32()
instead of isGpd()
, similarly, use isGp64
instead of isGpq()
(X86_64) or isGpX()
(AArch64), etc... The same applies to vectors - use isVec128()
instead of isXmm()
(X86) or isVecQ()
(AArch64), isVec256()
instead of isYmm()
, etc...
- Renamed some member functions in Operand and Reg:
isType(regId)
-> isReg(regId)
isGroup(regGroup)
-> isReg(regGroup)
regOp.type()
-> regOp.regType()
regOp.group()
-> regOp.regGroup()
- Removed some static functions from Operand, Reg, etc... in favor of member functions. Most of the operand functionality is now provided by Operand_ class:
Operand::isGp(op)
-> op.isGp();
x86::Reg::isGp(op, id)
-> op.isGp(id);
- Removed sub-registers
x86::Gpb
, x86::GpbLo
, x86::GpbHi
, x86::Gpw
, x86::Gpd
, x86::Gpq
, x86::Xmm
, x86::Ymm
, x86::Zmm
- use just x86::Gp
and x86::Vec
, which represent all removed X86 sub-registers. From now, use x86::Gp
to work with x86 general purpose registers and x86::Vec
to work with XMM, YMM, and ZMM registers.
- Removed sub-registers
a64::GpW
and a64::GpX
, a64::VecB
, a64::VecH
, a64::VecS
, a64::VecD
, a64::VecV
, which represent all removed AArch64 sub-registers. From now, use a64::Gp
to work with general purpose registers and a64::Vec
to work with NEON registers of any size, element type, and element index.
- Since sub-register types are gone it's no longer possible to write
gpb(id)
to get AL register, etc... However, all register operands that can hold multiple register types now offer Reg::make_xxx(id)
API, which can be used as a convenience or just use platform specific API like x86::gpd(id)
or x86::gp32(id)
, similarly for AArch64 use a64::x(id)
or a64::gp64(id)
, etc...
- Renamed some id getters -
Section::id()
-> Section::sectionId()
, etc...
Builder changes:
- Removed BaseBuilder::deletePass() - this function was most likely never used by user code and it was also never used by AsmJit. Passes should be only added and not removed, which simplifies some planned future changes.
Changes committed at 2025-05-24
Core changes:
- AsmJit now requires C++17 to compile.
- Deprecated asmjit/asmjit.h header. Use asmjit/core.h to include everything except backend specific stuff, and asmjit/x86.h or asmjit/a64.h to include tools of a specific architecture. At this time the asmjit.h header is just deprecated, so it will still work as it used to for some time.
Changes committed at 2025-05-10
Core changes:
- Removed AVX512 functionality that was never used on x86 hardware as Xeon Phi was never supported by AsmJit:
- AVX512_ER
- AVX512_PF
- AVX512_4FMAPS
- AVX512_4VNNIW
- Instruction 'vcvtneps2bf16' no longer accepts memory operand without explicit size (to minimize ambiguity)
Changes committed at 2024-01-01
Core changes:
- Renamed equality functions
eq()
to equals()
- Only related to String
, ZoneVector
, and CpuFeatures
. Old function names were deprecated.
- Removed
CallConvId::kNone
in favor of CallConvId::kCDecl
, which is now the default calling convention.
- Deprecated
CallConvId::kHost
in favor of CallConvId::kCDecl
- host calling convention is now not part of CallConvId, it can be calculated from CallConvId and Environment instead.
Changes committed at 2023-12-27
Core changes:
- Renamed
a64::Vec::ElementType
to a64::VecElementType
and made it a typed enum. This enum was used mostly internally, but there is a public API using it, so it's a breaking change.
- Refactored
FuncSignature
, FuncSignatureT
, and FuncSignatureBuilder
. There is only FuncSignature
now, which acts as a function signature holder and builder. Replace FuncSignatureBuilder
with FuncSignature
and use FuncSignature::build<args>
instead of FuncSignatureT<args>
. The old API has been deprecated.
- The maximum number of function arguments was raised from 16 to 32.
Changes committed at 2023-12-26
Core changes:
- Reworked InstNode and InstExNode to be friendlier to static analysis and to not cause undefined behavior. InstNode has no operands visually embedded within the struct so there is no _opArray (which was internal). This means that sizeof(InstNode) changed, but since it's allocated by AsmJit this should be fine. Moreover, there is no longer InstExNode as that was more a hack, instead there is now InstNodeWithOperands, which is a template and specifies the number of operands embedded (InstNode accesses these). All nodes that inherited InstExNode now just inherit InstNodeWithOperands<InstNode::kBaseOpCapacity>, which would provide the same number of nodes as InstNode.
- Moved GP and Vec registers from asmjit::arm namespace to asmjit::a64 namespace. At this time there was no prior deprecation as having arm::Vec would collide with a64::Vec as arm namespace is used within a64 namespace. Just change
arm::Gp
to a64::Gp
and arm::Vec
to a64::Vec
.
Changes committed at 2023-09-10
Core changes:
- Changed allocation API to work with spans (JitAllocator).
- This change is required to support more hardened platforms in the future that make it very difficult to write JIT compilers.
JitAllocator::Span
now represents a memory that the user can access. It abstracts both regular and dual mappings.
- The
Span
is mostly designed to make it possible to write into it, so in general the read+execute pointer is what user is intended to keep. Use span.rx()
to access RX pointer. Span
is not needed after the memory it references has been modified, only remember span.rx()
pointer, which is then used to deallocate or change the memory the span references.
- Use a new
JitAllocator::alloc()
to allocate a Span
, then pass the populated Span to JitAllocator
write API such as JitAllocator::write()
- note that JitAllocator can also establish a scope, so you can use a lambda function that would perform the write, but since it's going through JitAllocator it's able to ensure that the memory is actually writable.
- If you need to repopulate a
Span
from rx pointer, use JitAllocator::query(<span-out>, rx)
to get it.
- Study what JitRuntime is doing to better understand how this new API works in detail.
- Users of JitRuntime do not have to do anything as JitRuntime properly abstracts the allocation.
- Renamed some X86 CPU features to make them compatible with architecture manuals:
- Changed
AVX512_CDI
to AVX512_CD
.
- Changed
AVX512_ERI
to AVX512_ER
.
- Changed
AVX512_PFI
to AVX512_PF
.
- Old names were deprecated.
Changes committed at 2021-12-13
Core changes:
- Removed old deprecated API.
- Many enumerations were changed to enum class, and many public APIs were changed to use such enums instead of uint32_t. This change makes some APIs backward incompatible - there are no deprecations this time.
- Extracted operand signature manipulation to
OperandSignature
.
- Setting function arguments through
Compiler::setArg()
was deprecated, use FuncNode::setArg() instead.
- Moved
{arch}Features::k
to CpuFeatures::{arch}k
.
- Moved
BaseEmitter::kEncodingOption
to EncodingOptions::k
.
- Moved
BaseEmitter::kFlag
to EmitterFlags::k
.
- Moved
BaseEmitter::kType
to EmitterType::k
.
- Moved
BaseEmitter::kValidationOption
to DiagnosticOptions::kValidate
.
- Moved
BaseFeatures
to CpuFeatures
.
- Moved
BaseInst::kControl
to InstControlFlow::k
.
- Moved
BaseInst::kOption
and x86::Inst::kOption
to InstOptions::k
.
- Moved
BaseNode::kNode
to NodeType::k
.
- Moved
BaseReg::kGroup
and x86::Reg::kGroup
to RegGroup::k
.
- Moved
BaseReg::kType
and x86::Reg::kType
to RegType::k
.
- Moved
CallConv::kFlag
to CallConvFlags::k
.
- Moved
CallConv::kId
to CallConvId::k
.
- Moved
CallConv::kStrategy
to CallConvStrategy::k
.
- Moved
CodeBuffer::kFlag
to CodeBufferFlags
.
- Moved
ConstPool::kScope
to ConstPoolScope::k
.
- Moved
Environment::kArch
to Arch::k
.
- Moved
Environment::kSubArch
to SubArch::k
.
- Moved
Environment::kFormat
to OjectFormat::k
.
- Moved
Environment::kPlatform
to Platform::k
.
- Moved
Environment::kAbi
to PlatformABI::k
.
- Moved
Environment::kVendor
to Vendor::k
.
- Moved
FormatOptions::kFlag
to FormatFlags::k
and DiagnosticOptions::k
(Compiler diagnostics flags).
- Moved
FormatOptions::kIndentation
to FormatIndentationGroup::k
.
- Moved
FuncFrame::kAttr
to FuncAttributes::k
.
- Moved
Globals::kReset
to ResetPolicy::k
.
- Moved
InstDB::kAvx512Flag
to InstDB::Avx512Flags::k
.
- Moved
InstDB::kFlag
to InstDB::InstFlags::k
.
- Moved
InstDB::kMemFlag
to InstDB::OpFlags::kMem
.
- Moved
InstDB::kMode
to InstDB::Mode::k
.
- Moved
InstDB::kOpFlag
to InstDB::OpFlags::k{OpType}...
.
- Moved
JitAllocator::kOption
to JitAllocatorOptions::k
.
- Moved
Label::kType
to LabelType::k
.
- Moved
Operand::kOpType
to OperandType::k
.
- Moved
OpRWInfo::kFlag
to OpRWFlags::k
.
- Moved
Type::kId
to TypeId::k
.
- Moved
VirtMem::k
to VirtMem::MemoryFlags::k
.
Changes committed at 2020-05-30
AsmJit has been cleaned up significantly, many todo items have been fixed and many functions and classes have been redesigned, some in an incompatible way.
Core changes:
Imm
operand has now only Imm::value()
and Imm::valueAs()
functions that return its value content, and Imm::setValue()
function that sets the content. Functions like setI8()
, setU8()
were deprecated.
Old functions were deprecated, but code using them should still compile.
ArchInfo
has been replaced with Environment
. Environment provides more details about the architecture, but drops some properties that were used by arch info - gpSize(
) and gpCount()
. gpSize()
can be replaced with registerSize()
getter, which returns a native register size of the architecture the environment uses. However, gpCount()
was removed - at the moment ArchTraits
can be used to access such properties.
Some other functions were renamed, like ArchInfo::isX86Family()
is now Environment::isFamilyX86()
, etc. The reason for changing the order was support for more properties and all the accessors now start with the type of the property, like Environment::isPlatformWindows()
.
This function causes many other classes to provide environment()
getter instead of archInfo()
getter. In addition, AsmJit now uses arch()
to get an architecture instead of archId()
. ArchInfo::kIdXXX
was renamed to Environment::kArchXXX
.
Some functions were deprecated, some removed...
CodeInfo
has been removed in favor of Environment
. If you used CodeInfo
to set architecture and base address, this is now possible with Environment
and setting base address explicitly by CodeHolder::init()
- the first argument is
Environment
, and the second argument is base address, which defaults to Globals::kNoBaseAddress
.
CodeInfo class was deprecated, but the code using it should still compile with warnings.
CallConv
has been updated to offer a more unified way of representing calling conventions - many calling conventions were abstracted to follow standard naming like CallConvId::kCDecl
or CallConvId::kStdCall
.
This change means that other APIs like FuncDetail::init()
now require both, calling convention and target Environment
.
Logging
namespace has been renamed to Formatter
, which now provides general functionality for formatting in AsmJit.
Logging namespace should still work, but its use is deprecated. Unfortunately this will be without deprecation warnings, so make sure you don't use it.
Data64
, Data128
, and Data256
structs were deprecated and should no longer be used. There is no replacement, AsmJit users should simply create their own structures if they need them or use the new repeated embed API in emitters, see BaseEmitter::embedDataArray()
.
Emitter changes:
BaseEmitter::emit()
function signature has been changed to accept 3 operands by reference and the rest 3 operands as a continuous array. This change is purely cosmetic and shouldn't affect users as emit() has many overloads that dispatch to the right function.
x86::Emitter
(Assembler, Builder, Compiler) deprecates embed utilities like dint8()
, duint8()
, duint16()
, dxmm()
, etc... in favor of a new and more powerful BaseEmitter::embedDataArray()
. This function also allows emitting repeated values and/or patterns, which is used by helpers BaseEmitter::embedUInt8()
, and others...
- Validation is now available through
BaseEmitter::DiagnosticOptions
, which can be enabled/disabled through BaseEmitter::addDiagnosticOptions()
and BaseEmitter::clearDiagnosticOptions()
, respectively. Validation options now separate between encoding and Builder/Compiler so it's possible to choose the granularity required.
Builder changes:
- Internal functions for creating nodes were redesigned. They now accept a pointer to the node created as a first parameter. These changes should not affect AsmJit users as these functions were used internally.
Compiler changes:
FuncCallNode
has been renamed to InvokeNode
. Additionally, function calls should now use x86::Compiler::invoke()
instead of call()
. The reason behind this is to remove the confusion between a call
instruction and AsmJit's call()
intrinsic, which is now invoke()
.
Creating new nodes also changed. Now the preferred way of invoking a function is to call x86::Compiler::invoke()
where the first argument is InvokeNode**
. The function now returns an error and would call ErrorHandler
in case of a failure. Error handling was unspecified in the past - the function was marked noexcept, but called error handler, which could throw.
The reason behind this change is to make the API consistent with other changes and to also make it possible to inspect the possible error. In the previous API it returned a new node or nullptr
in case of error, which the user couldn't inspect unless there was an attached ErrorHandler
.
Samples:
#include <asmjit/x86.h>
void basicSetup() {
}
}