Low-Latency Machine Code Generation
Documentation of breaking changes.
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.
Useful tips before you start:
ASMJIT_NO_DEPRECATEDmacro defined to make sure that you are not using deprecated functionality at all. Deprecated functions are decorated with
ASMJIT_DEPRECATED()macro, but sometimes it's not possible to decorate everything like classes, which are used by deprecated functions as well, because some compilers would warn about that. If your project compiles fine with
ASMJIT_NO_DEPRECATEDit's not using anything, which was deprecated.
JitAllocator::Spannow represents a memory that the user can access. It abstracts both regular and dual mappings.
Spanis 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.
Spanis 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.
JitAllocator::alloc()to allocate a
Span, then pass the populated Span to
JitAllocatorwrite 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.
Spanfrom rx pointer, use
JitAllocator::query(<span-out>, rx)to get it.
Compiler::setArg()was deprecated, use FuncNode::setArg() instead.
DiagnosticOptions::k(Compiler diagnostics flags).
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.
Imm operand has now only
Imm::valueAs() functions that return its value content, and
Imm::setValue() function that sets the content. Functions like
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() 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
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
ArchInfo::kIdXXX was renamed to
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
Environment, and the second argument is base address, which defaults to
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
This change means that other APIs like
FuncDetail::init() now require both, calling convention and target
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.
Data256structs 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::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
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...
BaseEmitter::DiagnosticOptions, which can be enabled/disabled through
BaseEmitter::clearDiagnosticOptions(), respectively. Validation options now separate between encoding and Builder/Compiler so it's possible to choose the granularity required.
FuncCallNodehas been renamed to
InvokeNode. Additionally, function calls should now use
call(). The reason behind this is to remove the confusion between a
callinstruction and AsmJit's
call()intrinsic, which is now
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