asmjit::BaseEmitter Class Reference
Inheritance diagram for asmjit::BaseEmitter:
asmjit::BaseAssembler asmjit::BaseBuilder asmjit::a64::Emitter asmjit::x86::Emitter asmjit::a64::Assembler asmjit::x86::Assembler asmjit::BaseCompiler asmjit::a64::Builder asmjit::x86::Builder asmjit::a64::Compiler asmjit::x86::Compiler

Provides a base foundation to emitting code - specialized by BaseAssembler and BaseBuilder.

Public Members

Members

Classes

Member Functions

Construction & Destruction
Cast
Emitter Type & Flags
Target Information
Initialization & Finalization
Logging
Error Handling
Encoding Options
Diagnostic Options
Instruction Options
Emitter State
Sections
Labels
Emit
Emit Utilities
Align
Embed
Comment
Events

Member Function Documentation

EmitterType BaseEmitter::emitterType() constnoexcept◆ 

Returns the type of this emitter, see EmitterType.

EmitterFlags BaseEmitter::emitterFlags() constnoexcept◆ 

Returns emitter flags , see Flags.

bool BaseEmitter::isAssembler() constnoexcept◆ 

Tests whether the emitter inherits from BaseAssembler.

bool BaseEmitter::isBuilder() constnoexcept◆ 

Tests whether the emitter inherits from BaseBuilder.

Note
Both Builder and Compiler emitters would return true.

bool BaseEmitter::isCompiler() constnoexcept◆ 

Tests whether the emitter inherits from BaseCompiler.

bool BaseEmitter::hasEmitterFlag(EmitterFlags flag) constnoexcept◆ 

Tests whether the emitter has the given flag enabled.

bool BaseEmitter::isFinalized() constnoexcept◆ 

Tests whether the emitter is finalized.

bool BaseEmitter::isDestroyed() constnoexcept◆ 

Tests whether the emitter is destroyed (only used during destruction).

CodeHolder* BaseEmitter::code() constnoexcept◆ 

Returns the CodeHolder this emitter is attached to.

const Environment& BaseEmitter::environment() constnoexcept◆ 

Returns the target environment.

The returned Environment reference matches CodeHolder::environment().

bool BaseEmitter::is32Bit() constnoexcept◆ 

Tests whether the target architecture is 32-bit.

bool BaseEmitter::is64Bit() constnoexcept◆ 

Tests whether the target architecture is 64-bit.

Arch BaseEmitter::arch() constnoexcept◆ 

Returns the target architecture type.

SubArch BaseEmitter::subArch() constnoexcept◆ 

Returns the target architecture sub-type.

uint32_t BaseEmitter::registerSize() constnoexcept◆ 

Returns the target architecture's GP register size (4 or 8 bytes).

uint32_t BaseEmitter::instructionAlignment() constnoexcept◆ 

Returns instruction alignment.

The following values are returned based on the target architecture:

  • X86 and X86_64 - instruction alignment is 1
  • AArch32 - instruction alignment is 4 in A32 mode and 2 in THUMB mode.
  • AArch64 - instruction alignment is 4

bool BaseEmitter::isInitialized() constnoexcept◆ 

Tests whether the emitter is initialized (i.e. attached to CodeHolder).

Error BaseEmitter::finalize()virtual◆ 

Finalizes this emitter.

Materializes the content of the emitter by serializing it to the attached CodeHolder through an architecture specific BaseAssembler. This function won't do anything if the emitter inherits from BaseAssembler as assemblers emit directly to a CodeBuffer held by CodeHolder. However, if this is an emitter that inherits from BaseBuilder or BaseCompiler then these emitters need the materialization phase as they store their content in a representation not visible to CodeHolder.

Reimplemented in asmjit::a64::Builder, asmjit::a64::Compiler, asmjit::x86::Builder, and asmjit::x86::Compiler.

bool BaseEmitter::hasLogger() constnoexcept◆ 

Tests whether the emitter has a logger.

bool BaseEmitter::hasOwnLogger() constnoexcept◆ 

Tests whether the emitter has its own logger.

Own logger means that it overrides the possible logger that may be used by CodeHolder this emitter is attached to.

Logger* BaseEmitter::logger() constnoexcept◆ 

Returns the logger this emitter uses.

The returned logger is either the emitter's own logger or it's logger used by CodeHolder this emitter is attached to.

void BaseEmitter::setLogger(Logger* logger)noexcept◆ 

Sets or resets the logger of the emitter.

If the logger argument is non-null then the logger will be considered emitter's own logger, see hasOwnLogger() for more details. If the given logger is null then the emitter will automatically use logger that is attached to the CodeHolder this emitter is attached to.

void BaseEmitter::resetLogger()noexcept◆ 

Resets the logger of this emitter.

The emitter will bail to using a logger attached to CodeHolder this emitter is attached to, or no logger at all if CodeHolder doesn't have one.

bool BaseEmitter::hasErrorHandler() constnoexcept◆ 

Tests whether the emitter has an error handler attached.

bool BaseEmitter::hasOwnErrorHandler() constnoexcept◆ 

Tests whether the emitter has its own error handler.

Own error handler means that it overrides the possible error handler that may be used by CodeHolder this emitter is attached to.

ErrorHandler* BaseEmitter::errorHandler() constnoexcept◆ 

Returns the error handler this emitter uses.

The returned error handler is either the emitter's own error handler or it's error handler used by CodeHolder this emitter is attached to.

void BaseEmitter::setErrorHandler(ErrorHandler* errorHandler)noexcept◆ 

Sets or resets the error handler of the emitter.

void BaseEmitter::resetErrorHandler()noexcept◆ 

Resets the error handler.

Error BaseEmitter::reportError(Error err, const char* message = nullptr)◆ 

Handles the given error in the following way:

  1. If the emitter has ErrorHandler attached, it calls its ErrorHandler::handleError() member function first, and then returns the error. The handleError() function may throw.
  2. if the emitter doesn't have ErrorHandler, the error is simply returned.

EncodingOptions BaseEmitter::encodingOptions() constnoexcept◆ 

Returns encoding options.

bool BaseEmitter::hasEncodingOption(EncodingOptions option) constnoexcept◆ 

Tests whether the encoding option is set.

void BaseEmitter::addEncodingOptions(EncodingOptions options)noexcept◆ 

Enables the given encoding options.

void BaseEmitter::clearEncodingOptions(EncodingOptions options)noexcept◆ 

Disables the given encoding options.

DiagnosticOptions BaseEmitter::diagnosticOptions() constnoexcept◆ 

Returns the emitter's diagnostic options.

bool BaseEmitter::hasDiagnosticOption(DiagnosticOptions option) constnoexcept◆ 

Tests whether the given option is present in the emitter's diagnostic options.

void BaseEmitter::addDiagnosticOptions(DiagnosticOptions options)noexcept◆ 

Activates the given diagnostic options.

This function is used to activate explicit validation options that will be then used by all emitter implementations. There are in general two possibilities:

  • Architecture specific assembler is used. In this case a DiagnosticOptions::kValidateAssembler can be used to turn on explicit validation that will be used before an instruction is emitted. This means that internally an extra step will be performed to make sure that the instruction is correct. This is needed, because by default assemblers prefer speed over strictness.

    This option should be used in debug builds as it's pretty expensive.

  • Architecture specific builder or compiler is used. In this case the user can turn on DiagnosticOptions::kValidateIntermediate option that adds explicit validation step before the Builder or Compiler creates an InstNode to represent an emitted instruction. Error will be returned if the instruction is ill-formed. In addition, also DiagnosticOptions::kValidateAssembler can be used, which would not be consumed by Builder / Compiler directly, but it would be propagated to an architecture specific BaseAssembler implementation it creates during BaseEmitter::finalize().

void BaseEmitter::clearDiagnosticOptions(DiagnosticOptions options)noexcept◆ 

Deactivates the given validation options.

See addDiagnosticOptions() and DiagnosticOptions for more details.

InstOptions BaseEmitter::forcedInstOptions() constnoexcept◆ 

Returns forced instruction options.

Forced instruction options are merged with next instruction options before the instruction is encoded. These options have some bits reserved that are used by error handling, logging, and instruction validation purposes. Other options are globals that affect each instruction.

InstOptions BaseEmitter::instOptions() constnoexcept◆ 

Returns options of the next instruction.

void BaseEmitter::setInstOptions(InstOptions options)noexcept◆ 

Returns options of the next instruction.

void BaseEmitter::addInstOptions(InstOptions options)noexcept◆ 

Adds options of the next instruction.

void BaseEmitter::resetInstOptions()noexcept◆ 

Resets options of the next instruction.

bool BaseEmitter::hasExtraReg() constnoexcept◆ 

Tests whether the extra register operand is valid.

const RegOnly& BaseEmitter::extraReg() constnoexcept◆ 

Returns an extra operand that will be used by the next instruction (architecture specific).

void BaseEmitter::setExtraReg(const BaseReg& reg)noexcept[1/2]◆ 

Sets an extra operand that will be used by the next instruction (architecture specific).

void BaseEmitter::setExtraReg(const RegOnly& reg)noexcept[2/2]◆ 

Sets an extra operand that will be used by the next instruction (architecture specific).

void BaseEmitter::resetExtraReg()noexcept◆ 

Resets an extra operand that will be used by the next instruction (architecture specific).

const char* BaseEmitter::inlineComment() constnoexcept◆ 

Returns comment/annotation of the next instruction.

void BaseEmitter::setInlineComment(const char* s)noexcept◆ 

Sets comment/annotation of the next instruction.

Note
This string is set back to null by _emit(), but until that it has to remain valid as the Emitter is not required to make a copy of it (and it would be slow to do that for each instruction).

void BaseEmitter::resetInlineComment()noexcept◆ 

Resets the comment/annotation to nullptr.

void BaseEmitter::resetState()noexcept◆ 

Resets the emitter state, which contains instruction options, extra register, and inline comment.

Emitter can have a state that describes instruction options and extra register used by the instruction. Most instructions don't need nor use the state, however, if an instruction uses a prefix such as REX or REP prefix, which is set explicitly, then the state would contain it. This allows to mimic the syntax of assemblers such as X86. For example rep().movs(...) would map to a REP MOVS instuction on X86. The same applies to various hints and the use of a mask register in AVX-512 mode.

Error BaseEmitter::section(Section* section)virtual◆ 

Switches the given section.

Once switched, everything is added to the given section.

Reimplemented in asmjit::BaseAssembler, and asmjit::BaseBuilder.

Label BaseEmitter::newLabel()virtual◆ 

Creates a new label.

Reimplemented in asmjit::BaseAssembler, and asmjit::BaseBuilder.

Label BaseEmitter::newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId)virtual◆ 

Creates a new named label.

Reimplemented in asmjit::BaseAssembler, and asmjit::BaseBuilder.

Label BaseEmitter::newAnonymousLabel(const char* name, size_t nameSize = SIZE_MAX)◆ 

Creates a new anonymous label with a name, which can only be used for debugging purposes.

Label BaseEmitter::newExternalLabel(const char* name, size_t nameSize = SIZE_MAX)◆ 

Creates a new external label.

Label BaseEmitter::labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId)noexcept◆ 

Returns Label by name.

Returns invalid Label in case that the name is invalid or label was not found.

Note
This function doesn't trigger ErrorHandler in case the name is invalid or no such label exist. You must always check the validity of the Label returned.

Error BaseEmitter::bind(const Label& label)virtual◆ 

Binds the label to the current position of the current section.

Note
Attempt to bind the same label multiple times will return an error.

Reimplemented in asmjit::BaseAssembler, and asmjit::BaseBuilder.

bool BaseEmitter::isLabelValid(uint32_t labelId) constnoexcept[1/2]◆ 

Tests whether the label id is valid (i.e. registered).

bool BaseEmitter::isLabelValid(const Label& label) constnoexcept[2/2]◆ 

Tests whether the label is valid (i.e. registered).

Error BaseEmitter::_emitI(InstId instId)[1/7]◆ 

Emits an instruction (internal).

Error BaseEmitter::_emitI(InstId instId, const Operand_& o0)[2/7]◆ 

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1)[3/7]◆ 

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2)[4/7]◆ 

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3)[5/7]◆ 

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4)[6/7]◆ 

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Error BaseEmitter::_emitI(InstId instId, const Operand_& o0, const Operand_& o1, const Operand_& o2, const Operand_& o3, const Operand_& o4, const Operand_& o5)[7/7]◆ 

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<typename... Args>
Error BaseEmitter::emit(InstId instId, Args&&... operands)◆ 

Emits an instruction instId with the given operands.

This is the most universal way of emitting code, which accepts an instruction identifier and instruction operands. This is called an "unchecked" API as emit doesn't provide any type checks at compile-time. This allows to emit instruction with just Operand instances, which could be handy in some cases - for example emitting generic code where you don't know whether some operand is register, memory, or immediate.

Error BaseEmitter::emitOpArray(InstId instId, const Operand_* operands, size_t opCount)◆ 

Similar to emit(), but uses array of operands instead.

Error BaseEmitter::emitInst(const BaseInst& inst, const Operand_* operands, size_t opCount)◆ 

Similar to emit(), but emits instruction with both instruction options and extra register, followed by an array of operands.

Error BaseEmitter::emitProlog(const FuncFrame& frame)◆ 

Emits a function prolog described by the given function frame.

Error BaseEmitter::emitEpilog(const FuncFrame& frame)◆ 

Emits a function epilog described by the given function frame.

Error BaseEmitter::emitArgsAssignment(const FuncFrame& frame, const FuncArgsAssignment& args)◆ 

Emits code that reassigns function frame arguments to the given args.

Error BaseEmitter::align(AlignMode alignMode, uint32_t alignment)virtual◆ 

Aligns the current CodeBuffer position to the alignment specified.

The sequence that is used to fill the gap between the aligned location and the current location depends on the align mode, see AlignMode. The alignment argument specifies alignment in bytes, so for example when it's 32 it means that the code buffer will be aligned to 32 bytes.

Reimplemented in asmjit::a64::Assembler, asmjit::BaseBuilder, and asmjit::x86::Assembler.

Error BaseEmitter::embed(const void* data, size_t dataSize)virtual◆ 

Embeds raw data into the CodeBuffer.

Reimplemented in asmjit::BaseAssembler, and asmjit::BaseBuilder.

Error BaseEmitter::embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1)virtual◆ 

Embeds a typed data array.

This is the most flexible function for embedding data as it allows to:

  • Assign a typeId to the data, so the emitter knows the type of items stored in data. Binary data should use TypeId::kUInt8.
  • Repeat the given data repeatCount times, so the data can be used as a fill pattern for example, or as a pattern used by SIMD instructions.

Reimplemented in asmjit::BaseBuilder, and asmjit::BaseAssembler.

Error BaseEmitter::embedInt8(int8_t value, size_t repeatCount = 1)◆ 

Embeds int8_t value repeated by repeatCount.

Error BaseEmitter::embedUInt8(uint8_t value, size_t repeatCount = 1)◆ 

Embeds uint8_t value repeated by repeatCount.

Error BaseEmitter::embedInt16(int16_t value, size_t repeatCount = 1)◆ 

Embeds int16_t value repeated by repeatCount.

Error BaseEmitter::embedUInt16(uint16_t value, size_t repeatCount = 1)◆ 

Embeds uint16_t value repeated by repeatCount.

Error BaseEmitter::embedInt32(int32_t value, size_t repeatCount = 1)◆ 

Embeds int32_t value repeated by repeatCount.

Error BaseEmitter::embedUInt32(uint32_t value, size_t repeatCount = 1)◆ 

Embeds uint32_t value repeated by repeatCount.

Error BaseEmitter::embedInt64(int64_t value, size_t repeatCount = 1)◆ 

Embeds int64_t value repeated by repeatCount.

Error BaseEmitter::embedUInt64(uint64_t value, size_t repeatCount = 1)◆ 

Embeds uint64_t value repeated by repeatCount.

Error BaseEmitter::embedFloat(float value, size_t repeatCount = 1)◆ 

Embeds a floating point value repeated by repeatCount.

Error BaseEmitter::embedDouble(double value, size_t repeatCount = 1)◆ 

Embeds a floating point value repeated by repeatCount.

Error BaseEmitter::embedConstPool(const Label& label, const ConstPool& pool)virtual◆ 

Embeds a constant pool at the current offset by performing the following:

  1. Aligns by using AlignMode::kData to the minimum pool alignment.
  2. Binds the ConstPool label so it's bound to an aligned location.
  3. Emits ConstPool content.

Reimplemented in asmjit::BaseAssembler, and asmjit::BaseBuilder.

Error BaseEmitter::embedLabel(const Label& label, size_t dataSize = 0)virtual◆ 

Embeds an absolute label address as data.

The dataSize is an optional argument that can be used to specify the size of the address data. If it's zero (default) the address size is deduced from the target architecture (either 4 or 8 bytes).

Reimplemented in asmjit::BaseAssembler, and asmjit::BaseBuilder.

Error BaseEmitter::embedLabelDelta(const Label& label, const Label& base, size_t dataSize = 0)virtual◆ 

Embeds a delta (distance) between the label and base calculating it as label - base.

This function was designed to make it easier to embed lookup tables where each index is a relative distance of two labels.

Reimplemented in asmjit::BaseAssembler, and asmjit::BaseBuilder.

Error BaseEmitter::comment(const char* data, size_t size = SIZE_MAX)virtual◆ 

Emits a comment stored in data with an optional size parameter.

Reimplemented in asmjit::BaseAssembler, and asmjit::BaseBuilder.

Error BaseEmitter::commentf(const char* fmt, ...)◆ 

Emits a formatted comment specified by fmt and variable number of arguments.

Error BaseEmitter::commentv(const char* fmt, va_list ap)◆ 

Emits a formatted comment specified by fmt and ap.

Error BaseEmitter::onAttach(CodeHolder* code)virtualnoexcept◆ 

Error BaseEmitter::onDetach(CodeHolder* code)virtualnoexcept◆ 

void BaseEmitter::onSettingsUpdated()virtualnoexcept◆ 

Called when CodeHolder has updated an important setting, which involves the following:

This function ensures that the settings are properly propagated from CodeHolder to the emitter.

Note
This function is virtual and can be overridden, however, if you do so, always call BaseEmitter::onSettingsUpdated() within your own implementation to ensure that the emitter is in a consistent state.

Member Data Documentation

EmitterType BaseEmitter::_emitterType = EmitterType::kNone◆ 

EmitterFlags BaseEmitter::_emitterFlags = EmitterFlags::kNone◆ 

uint8_t BaseEmitter::_instructionAlignment = 0u◆ 

Instruction alignment.

ValidationFlags BaseEmitter::_validationFlags = ValidationFlags::kNone◆ 

Validation flags in case validation is used.

Note
Validation flags are specific to the emitter and they are setup at construction time and then never changed.

DiagnosticOptions BaseEmitter::_diagnosticOptions = DiagnosticOptions::kNone◆ 

Validation options.

uint64_t BaseEmitter::_archMask = 0◆ 

All supported architectures in a bit-mask, where LSB is the bit with a zero index.

EncodingOptions BaseEmitter::_encodingOptions = EncodingOptions::kNone◆ 

Encoding options.

InstOptions BaseEmitter::_forcedInstOptions = InstOptions::kReserved◆ 

Forced instruction options, combined with _instOptions by emit().

uint32_t BaseEmitter::_privateData = 0◆ 

Internal private data used freely by any emitter.

CodeHolder* BaseEmitter::_code = nullptr◆ 

CodeHolder the emitter is attached to.

Logger* BaseEmitter::_logger = nullptr◆ 

Attached Logger.

ErrorHandler* BaseEmitter::_errorHandler = nullptr◆ 

Attached ErrorHandler.

Environment BaseEmitter::_environment {}◆ 

Describes the target environment, matches CodeHolder::environment().

OperandSignature BaseEmitter::_gpSignature {}◆ 

Native GP register signature and signature related information.

InstOptions BaseEmitter::_instOptions = InstOptions::kNone◆ 

Next instruction options (affects the next instruction).

RegOnly BaseEmitter::_extraReg {}◆ 

Extra register (op-mask {k} on AVX-512) (affects the next instruction).

const char* BaseEmitter::_inlineComment = nullptr◆ 

Inline comment of the next instruction (affects the next instruction).