Error Handling

Error handling.

Overview

AsmJit uses error codes to represent and return errors. Every function that can fail returns an Error code. Exceptions are never thrown by AsmJit itself even in extreme conditions like out-of-memory, but it's possible to override ErrorHandler::handleError() to throw, in that case no error will be returned and exception will be thrown instead. All functions where this can happen are not marked noexcept.

Errors should never be ignored, however, checking errors after each AsmJit API call would simply over-complicate the whole code generation experience. ErrorHandler exists to make the use of AsmJit API simpler as it allows to customize how errors can be handled:

  • Record the error and continue (the way how the error is user-implemented).
  • Throw an exception. AsmJit doesn't use exceptions and is completely exception-safe, but it's perfectly legal to throw an exception from the error handler.
  • Use plain old C's setjmp() and longjmp(). Asmjit always puts Assembler, Builder and Compiler to a consistent state before calling ErrorHandler::handleError(), so longjmp() can be used without issues to cancel the code-generation if an error occurred. This method can be used if exception handling in your project is turned off and you still want some comfort. In most cases it should be safe as AsmJit uses Zone memory and the ownership of memory it allocates always ends with the instance that allocated it. If using this approach please never jump outside the life-time of CodeHolder and BaseEmitter.

Using ErrorHandler

An example of attaching ErrorHandler to CodeHolder.

#include <asmjit/x86.h>
#include <stdio.h>
using namespace asmjit;
// A simple error handler implementation, extend according to your needs.
class MyErrorHandler : public ErrorHandler {
public:
void handleError(Error err, const char* message, BaseEmitter* origin) override {
printf("AsmJit error: %s\n", message);
}
};
int main() {
MyErrorHandler myErrorHandler;
CodeHolder code;
code.init(rt.environment(), rt.cpuFeatures());
code.setErrorHandler(&myErrorHandler);
x86::Assembler a(&code);
// ... code generation ...
return 0;
}

Useful classes in error handling group:

  • See DebugUtils that provides utilities useful for debugging.
  • See Error that lists error codes that AsmJit uses.
  • See ErrorHandler for more details about error handling.

Namespaces

Classes

Macros

Typedefs

Enumerations

Macro Definition Documentation

#define ASMJIT_ASSERT(...)◆ 

Value:
do { \
if (ASMJIT_LIKELY(__VA_ARGS__)) \
break; \
::asmjit::DebugUtils::assertionFailed(__FILE__, __LINE__, #__VA_ARGS__); \
} while (0)

AsmJit's own assert macro used in AsmJit code-base.

#define ASMJIT_PROPAGATE(...)◆ 

Value:
do { \
::asmjit::Error _err = __VA_ARGS__; \
if (ASMJIT_UNLIKELY(_err)) \
return _err; \
} while (0)

Propagates a possible Error produced by ... to the caller by returning the error immediately.

Used by AsmJit internally, but kept public for users that want to use the same technique to propagate errors to the caller.

Typedef Documentation

typedef uint32_t Error◆ 

AsmJit error type (uint32_t).

Enumeration Type Documentation

ErrorCode : uint32_tenum◆ 

AsmJit error codes.

ConstantDescription
kErrorOk 

No error (success).

kErrorOutOfMemory 

Out of memory.

kErrorInvalidArgument 

Invalid argument.

kErrorInvalidState 

Invalid state.

If this error is returned it means that either you are doing something wrong or AsmJit caught itself by doing something wrong. This error should never be ignored.

kErrorInvalidArch 

Invalid or incompatible architecture.

kErrorNotInitialized 

The object is not initialized.

kErrorAlreadyInitialized 

The object is already initialized.

kErrorFeatureNotEnabled 

Either a built-in feature was disabled at compile time and it's not available or the feature is not available on the target platform.

For example trying to allocate large pages on unsupported platform would return this error.

kErrorTooManyHandles 

Too many handles (Windows) or file descriptors (Unix/Posix).

kErrorTooLarge 

Code generated is larger than allowed.

kErrorNoCodeGenerated 

No code generated.

Returned by runtime if the CodeHolder contains no code.

kErrorInvalidDirective 

Invalid directive.

kErrorInvalidLabel 

Attempt to use uninitialized label.

kErrorTooManyLabels 

Label index overflow - a single BaseAssembler instance can hold almost 2^32 (4 billion) labels.

If there is an attempt to create more labels then this error is returned.

kErrorLabelAlreadyBound 

Label is already bound.

kErrorLabelAlreadyDefined 

Label is already defined (named labels).

kErrorLabelNameTooLong 

Label name is too long.

kErrorInvalidLabelName 

Label must always be local if it's anonymous (without a name).

kErrorInvalidParentLabel 

Parent id passed to CodeHolder::newNamedLabelEntry() was either invalid or parent is not supported by the requested LabelType.

kErrorInvalidSection 

Invalid section.

kErrorTooManySections 

Too many sections (section index overflow).

kErrorInvalidSectionName 

Invalid section name (most probably too long).

kErrorTooManyRelocations 

Relocation index overflow (too many relocations).

kErrorInvalidRelocEntry 

Invalid relocation entry.

kErrorRelocOffsetOutOfRange 

Reloc entry contains address that is out of range (unencodable).

kErrorInvalidAssignment 

Invalid assignment to a register, function argument, or function return value.

kErrorInvalidInstruction 

Invalid instruction.

kErrorInvalidRegType 

Invalid register type.

kErrorInvalidRegGroup 

Invalid register group.

kErrorInvalidPhysId 

Invalid physical register id.

kErrorInvalidVirtId 

Invalid virtual register id.

kErrorInvalidElementIndex 

Invalid element index (ARM).

kErrorInvalidPrefixCombination 

Invalid prefix combination (X86|X64).

kErrorInvalidLockPrefix 

Invalid LOCK prefix (X86|X64).

kErrorInvalidXAcquirePrefix 

Invalid XACQUIRE prefix (X86|X64).

kErrorInvalidXReleasePrefix 

Invalid XRELEASE prefix (X86|X64).

kErrorInvalidRepPrefix 

Invalid REP prefix (X86|X64).

kErrorInvalidRexPrefix 

Invalid REX prefix (X86|X64).

kErrorInvalidExtraReg 

Invalid {...} register (X86|X64).

kErrorInvalidKMaskUse 

Invalid {k} use (not supported by the instruction) (X86|X64).

kErrorInvalidKZeroUse 

Invalid {k}{z} use (not supported by the instruction) (X86|X64).

kErrorInvalidBroadcast 

Invalid broadcast - Currently only related to invalid use of AVX-512 {1tox} (X86|X64).

kErrorInvalidEROrSAE 

Invalid 'embedded-rounding' {er} or 'suppress-all-exceptions' {sae} (AVX-512) (X86|X64).

kErrorInvalidAddress 

Invalid address used (not encodable).

kErrorInvalidAddressIndex 

Invalid index register used in memory address (not encodable).

kErrorInvalidAddressScale 

Invalid address scale (not encodable).

kErrorInvalidAddress64Bit 

Invalid use of 64-bit address.

kErrorInvalidAddress64BitZeroExtension 

Invalid use of 64-bit address that require 32-bit zero-extension (X64).

kErrorInvalidDisplacement 

Invalid displacement (not encodable).

kErrorInvalidSegment 

Invalid segment (X86).

kErrorInvalidImmediate 

Invalid immediate (out of bounds on X86 and invalid pattern on ARM).

kErrorInvalidOperandSize 

Invalid operand size.

kErrorAmbiguousOperandSize 

Ambiguous operand size (memory has zero size while it's required to determine the operation type.

kErrorOperandSizeMismatch 

Mismatching operand size (size of multiple operands doesn't match the operation size).

kErrorInvalidOption 

Invalid option.

kErrorOptionAlreadyDefined 

Option already defined.

kErrorInvalidTypeId 

Invalid TypeId.

kErrorInvalidUseOfGpbHi 

Invalid use of a 8-bit GPB-HIGH register.

kErrorInvalidUseOfGpq 

Invalid use of a 64-bit GPQ register in 32-bit mode.

kErrorInvalidUseOfF80 

Invalid use of an 80-bit float (TypeId::kFloat80).

kErrorNotConsecutiveRegs 

Instruction requires the use of consecutive registers, but registers in operands weren't (AVX512, ASIMD load/store, etc...).

kErrorConsecutiveRegsAllocation 

Failed to allocate consecutive registers - allocable registers either too restricted or a bug in RW info.

kErrorIllegalVirtReg 

Illegal virtual register - reported by instruction validation.

kErrorTooManyVirtRegs 

AsmJit cannot create more virtual registers.

kErrorNoMorePhysRegs 

AsmJit requires a physical register, but no one is available.

kErrorOverlappedRegs 

A variable has been assigned more than once to a function argument (BaseCompiler).

kErrorOverlappingStackRegWithRegArg 

Invalid register to hold stack arguments offset.

kErrorExpressionLabelNotBound 

Unbound label cannot be evaluated by expression.

kErrorExpressionOverflow 

Arithmetic overflow during expression evaluation.

kErrorFailedToOpenAnonymousMemory 

Failed to open anonymous memory handle or file descriptor.

kErrorFailedToOpenFile 

Failed to open a file.

Note
This is a generic error that is used by internal filesystem API.
kErrorProtectionFailure 

Protection failure can be returned from a virtual memory allocator or when trying to change memory access permissions.

kErrorCount 

Count of AsmJit error codes.