asmjit::Operand_ Struct Reference

Constructor-less Operand.

Contains no initialization code and can be used safely to define an array of operands that won't be initialized. This is an Operand compatible data structure designed to be statically initialized, static const, or to be used by the user to define an array of operands without having them default initialized.

The key difference between Operand and Operand_:

Operand_ xArray[10]; // Not initialized, contains garbage.
Operand yArray[10]; // All operands initialized to none.

Public Members

Public Types

Member Functions

Construction & Destruction
Operator Overloads
Cast
Accessors

Static Functions

Member Enumeration Documentation

Operand_::DataIndex : uint32_tenum

Indexes to _data array.

Operand_::OpType : uint32_tenum

Operand types that can be encoded in Operand.

ConstantDescription
kOpNone 

Not an operand or not initialized.

kOpReg 

Operand is a register.

kOpMem 

Operand is a memory.

kOpImm 

Operand is an immediate value.

kOpLabel 

Operand is a label.

Operand_::LabelTagenum

Label tag.

ConstantDescription
kLabelTag 

Label tag is used as a sub-type, forming a unique signature across all operand types as 0x1 is never associated with any register type.

This means that a memory operand's BASE register can be constructed from virtually any operand (register vs. label) by just assigning its type (register type or label-tag) and operand id.

Operand_::VirtIdConstants : uint32_tenum

Constants useful for VirtId <-> Index translation.

ConstantDescription
kVirtIdMin 

Minimum valid packed-id.

kVirtIdMax 

Maximum valid packed-id, excludes Globals::kInvalidId.

kVirtIdCount 

Count of valid packed-ids.

Member Function Documentation

bool Operand_::isVirtId(uint32_t id)staticnoexcept

Tests whether the given id is a valid virtual register id.

Since AsmJit supports both physical and virtual registers it must be able to distinguish between these two. The idea is that physical registers are always limited in size, so virtual identifiers start from kVirtIdMin and end at kVirtIdMax.

uint32_t Operand_::indexToVirtId(uint32_t id)staticnoexcept

Converts a real-id into a packed-id that can be stored in Operand.

uint32_t Operand_::virtIdToIndex(uint32_t id)staticnoexcept

Converts a packed-id back to real-id.

void Operand_::copyFrom(const Operand_& other)noexcept

Initializes the operand from other operand (used by operator overloads).

void Operand_::reset()noexcept

Resets the Operand to none.

None operand is defined the following way:

  • Its signature is zero (kOpNone, and the rest zero as well).
  • Its id is 0.
  • The reserved8_4 field is set to 0.
  • The reserved12_4 field is set to zero.

In other words, reset operands have all members set to zero. Reset operand must match the Operand state right after its construction. Alternatively, if you have an array of operands, you can simply use memset().

using namespace asmjit;
assert(a == b);
b = x86::eax;
assert(a != b);
b.reset();
assert(a == b);
memset(&b, 0, sizeof(Operand));
assert(a == b);

bool Operand_::operator==(const Operand_& other) constconstexprconstexprnoexcept

Tests whether this operand is the same as other.

bool Operand_::operator!=(const Operand_& other) constconstexprconstexprnoexcept

Tests whether this operand is not the same as other.

template<typename T>
T& Operand_::as()noexcept[1/2]

Casts this operand to T type.

template<typename T>
const T& Operand_::as() constnoexcept[2/2]

Casts this operand to T type (const).

bool Operand_::hasSignature(uint32_t signature) constconstexprconstexprnoexcept[1/2]

Tests whether the operand matches the given signature sign.

bool Operand_::hasSignature(const Operand_& other) constconstexprconstexprnoexcept[2/2]

Tests whether the operand matches the signature of the other operand.

uint32_t Operand_::signature() constconstexprconstexprnoexcept

Returns operand signature as unsigned 32-bit integer.

Signature is first 4 bytes of the operand data. It's used mostly for operand checking as it's much faster to check 4 bytes at once than having to check these bytes individually.

void Operand_::setSignature(uint32_t signature)noexcept

Sets the operand signature, see signature().

Note
Improper use of setSignature() can lead to hard-to-debug errors.

uint32_t Operand_::opType() constconstexprconstexprnoexcept

Returns the type of the operand, see OpType.

bool Operand_::isNone() constconstexprconstexprnoexcept

Tests whether the operand is none (kOpNone).

bool Operand_::isReg() constconstexprconstexprnoexcept[1/3]

Tests whether the operand is a register (kOpReg).

bool Operand_::isMem() constconstexprconstexprnoexcept

Tests whether the operand is a memory location (kOpMem).

bool Operand_::isImm() constconstexprconstexprnoexcept

Tests whether the operand is an immediate (kOpImm).

bool Operand_::isLabel() constconstexprconstexprnoexcept

Tests whether the operand is a label (kOpLabel).

bool Operand_::isPhysReg() constconstexprconstexprnoexcept

Tests whether the operand is a physical register.

bool Operand_::isVirtReg() constconstexprconstexprnoexcept

Tests whether the operand is a virtual register.

bool Operand_::hasSize() constconstexprconstexprnoexcept[1/2]

Tests whether the operand specifies a size (i.e. the size is not zero).

bool Operand_::hasSize(uint32_t s) constconstexprconstexprnoexcept[2/2]

Tests whether the size of the operand matches size.

uint32_t Operand_::size() constconstexprconstexprnoexcept

Returns the size of the operand in bytes.

The value returned depends on the operand type:

  • None - Should always return zero size.
  • Reg - Should always return the size of the register. If the register size depends on architecture (like x86::CReg and x86::DReg) the size returned should be the greatest possible (so it should return 64-bit size in such case).
  • Mem - Size is optional and will be in most cases zero.
  • Imm - Should always return zero size.
  • Label - Should always return zero size.

uint32_t Operand_::id() constconstexprconstexprnoexcept

Returns the operand id.

The value returned should be interpreted accordingly to the operand type:

  • None - Should be 0.
  • Reg - Physical or virtual register id.
  • Mem - Multiple meanings - BASE address (register or label id), or high value of a 64-bit absolute address.
  • Imm - Should be 0.
  • Label - Label id if it was created by using newLabel() or Globals::kInvalidId if the label is invalid or not initialized.

bool Operand_::equals(const Operand_& other) constconstexprconstexprnoexcept

Tests whether the operand is 100% equal to other operand.

Note
This basically performs a binary comparison, if aby bit is different the operands are not equal.

bool Operand_::isReg(uint32_t rType) constconstexprconstexprnoexcept[2/3]

ASMJIT_NO_DEPRECATED.

Tests whether the operand is a register matching rType.

bool Operand_::isReg(uint32_t rType, uint32_t rId) constconstexprconstexprnoexcept[3/3]

Tests whether the operand is register and of rType and rId.

bool Operand_::isRegOrMem() constconstexprconstexprnoexcept

Tests whether the operand is a register or memory.

Member Data Documentation

uint32_t Operand_::_signature

Operand's signature that provides operand type and additional information.

uint32_t Operand_::_baseId

Either base id as used by memory operand or any id as used by others.

uint32_t Operand_::_data[2]

Data specific to the operand type.

The reason we don't use union is that we have constexpr constructors that construct operands and other constexpr functions that return wither another Operand or something else. These cannot generally work with unions so we also cannot use union if we want to be standard compliant.