asmjit::FuncFrame Class Reference

Function frame.

Function frame is used directly by prolog and epilog insertion (PEI) utils. It provides information necessary to insert a proper and ABI conforming prolog and epilog. Function frame calculation is based on CallConv and other function attributes.

SSE vs AVX vs AVX-512

Function frame provides a way to tell prolog/epilog inserter to use AVX instructions instead of SSE. Use setAvxEnabled() and setAvx512Enabled() to enable AVX and/or AVX-512, respectively. Enabling AVX-512 is mostly for Compiler as it would use 32 SIMD registers instead of 16 when enabled.

Note
If your code uses AVX instructions and AVX is not enabled there would be a performance hit in case that some registers had to be saved/restored in function's prolog/epilog, respectively. Thus, it's recommended to always let the function frame know about the use of AVX.

Function Frame Structure

Various properties can contribute to the size and structure of the function frame. The function frame in most cases won't use all of the properties illustrated (for example Spill Zone and Red Zone are never used together).

+-----------------------------+
| Arguments Passed by Stack |
+-----------------------------+
| Spill Zone |
+-----------------------------+ <- Stack offset (args) starts from here.
| Return Address, if Pushed |
+-----------------------------+ <- Stack pointer (SP) upon entry.
| Save/Restore Stack. |
+-----------------------------+-----------------------------+
| Local Stack | |
+-----------------------------+ Final Stack |
| Call Stack | |
+-----------------------------+-----------------------------+ <- SP after prolog.
| Red Zone |
+-----------------------------+

Public Members

Members

Public Types

Constants

Member Functions

Construction & Destruction
Initialization & Reset
Overloaded Operators
Accessors
Finalization

Member Enumeration Documentation

anonymous enum : uint32_t◆ 

ConstantDescription
kTagInvalidOffset 

Tag used to inform that some offset is invalid.

Constructor & Destructor Documentation

FuncFrame::FuncFrame()defaultnoexcept[1/2]◆ 

Creates a default constructed function frame, which has initialized all members to their default values.

FuncFrame::FuncFrame(const FuncFrame& other)defaultnoexcept[2/2]◆ 

Creates a copy of other function frame.

Member Function Documentation

Error FuncFrame::init(const FuncDetail& func)noexcept◆ 

Initializes the function frame based on func detail.

void FuncFrame::reset()noexcept◆ 

Resets the function frame into its default constructed state.

FuncFrame& FuncFrame::operator=(const FuncFrame& other)defaultnoexcept◆ 

Copy assignment - function frame is copy assignable.

Arch FuncFrame::arch() constnoexcept◆ 

Returns the target architecture of the function frame.

FuncAttributes FuncFrame::attributes() constnoexcept◆ 

Returns function frame attributes, see Attributes.

bool FuncFrame::hasAttribute(FuncAttributes attr) constnoexcept◆ 

Checks whether the FuncFame contains an attribute attr.

void FuncFrame::addAttributes(FuncAttributes attrs)noexcept◆ 

Adds attributes attrs to the FuncFrame.

void FuncFrame::clearAttributes(FuncAttributes attrs)noexcept◆ 

Clears attributes attrs from the FrameFrame.

bool FuncFrame::hasVarArgs() constnoexcept◆ 

Tests whether the function has variable number of arguments.

void FuncFrame::setVarArgs()noexcept◆ 

Sets the variable arguments flag.

void FuncFrame::resetVarArgs()noexcept◆ 

Resets variable arguments flag.

bool FuncFrame::hasPreservedFP() constnoexcept◆ 

Tests whether the function preserves frame pointer (EBP|ESP on X86).

void FuncFrame::setPreservedFP()noexcept◆ 

Enables preserved frame pointer.

void FuncFrame::resetPreservedFP()noexcept◆ 

Disables preserved frame pointer.

bool FuncFrame::hasFuncCalls() constnoexcept◆ 

Tests whether the function calls other functions.

void FuncFrame::setFuncCalls()noexcept◆ 

Sets FuncAttributes::kHasFuncCalls to true.

void FuncFrame::resetFuncCalls()noexcept◆ 

Sets FuncAttributes::kHasFuncCalls to false.

bool FuncFrame::hasIndirectBranchProtection() constnoexcept◆ 

Tests whether the function uses indirect branch protection, see FuncAttributes::kIndirectBranchProtection.

void FuncFrame::setIndirectBranchProtection()noexcept◆ 

Enabled indirect branch protection (sets FuncAttributes::kIndirectBranchProtection attribute to true).

void FuncFrame::resetIndirectBranchProtection()noexcept◆ 

Disables indirect branch protection (sets FuncAttributes::kIndirectBranchProtection attribute to false).

bool FuncFrame::isAvxEnabled() constnoexcept◆ 

Tests whether the function has AVX enabled.

void FuncFrame::setAvxEnabled()noexcept◆ 

Enables AVX use.

void FuncFrame::resetAvxEnabled()noexcept◆ 

Disables AVX use.

bool FuncFrame::isAvx512Enabled() constnoexcept◆ 

Tests whether the function has AVX-512 enabled.

void FuncFrame::setAvx512Enabled()noexcept◆ 

Enables AVX-512 use.

void FuncFrame::resetAvx512Enabled()noexcept◆ 

Disables AVX-512 use.

bool FuncFrame::hasMmxCleanup() constnoexcept◆ 

Tests whether the function has MMX cleanup - 'emms' instruction in epilog.

void FuncFrame::setMmxCleanup()noexcept◆ 

Enables MMX cleanup.

void FuncFrame::resetMmxCleanup()noexcept◆ 

Disables MMX cleanup.

bool FuncFrame::hasAvxCleanup() constnoexcept◆ 

Tests whether the function has AVX cleanup - 'vzeroupper' instruction in epilog.

void FuncFrame::setAvxCleanup()noexcept◆ 

Enables AVX cleanup.

void FuncFrame::resetAvxCleanup()noexcept◆ 

Disables AVX cleanup.

bool FuncFrame::hasCallStack() constnoexcept◆ 

Tests whether the function uses call stack.

bool FuncFrame::hasLocalStack() constnoexcept◆ 

Tests whether the function uses local stack.

bool FuncFrame::hasAlignedVecSR() constnoexcept◆ 

Tests whether vector registers can be saved and restored by using aligned reads and writes.

bool FuncFrame::hasDynamicAlignment() constnoexcept◆ 

Tests whether the function has to align stack dynamically.

bool FuncFrame::hasRedZone() constnoexcept◆ 

Tests whether the calling convention specifies 'RedZone'.

bool FuncFrame::hasSpillZone() constnoexcept◆ 

Tests whether the calling convention specifies 'SpillZone'.

uint32_t FuncFrame::redZoneSize() constnoexcept◆ 

Returns the size of 'RedZone'.

uint32_t FuncFrame::spillZoneSize() constnoexcept◆ 

Returns the size of 'SpillZone'.

void FuncFrame::resetRedZone()noexcept◆ 

Resets the size of red zone, which would disable it entirely.

Note
Red zone is currently only used by an AMD64 SystemV calling convention, which expects 128 bytes of stack to be accessible below stack pointer. These bytes are then accessible within the function and Compiler can use this space as a spill area. However, sometimes it's better to disallow the use of red zone in case that a user wants to use this stack for a custom purpose.

uint32_t FuncFrame::naturalStackAlignment() constnoexcept◆ 

Returns natural stack alignment (guaranteed stack alignment upon entry).

uint32_t FuncFrame::minDynamicAlignment() constnoexcept◆ 

Returns natural stack alignment (guaranteed stack alignment upon entry).

bool FuncFrame::hasCalleeStackCleanup() constnoexcept◆ 

Tests whether the callee must adjust SP before returning (X86-STDCALL only)

uint32_t FuncFrame::calleeStackCleanup() constnoexcept◆ 

Returns home many bytes of the stack the callee must adjust before returning (X86-STDCALL only)

uint32_t FuncFrame::callStackAlignment() constnoexcept◆ 

Returns call stack alignment.

uint32_t FuncFrame::localStackAlignment() constnoexcept◆ 

Returns local stack alignment.

uint32_t FuncFrame::finalStackAlignment() constnoexcept◆ 

Returns final stack alignment (the maximum value of call, local, and natural stack alignments).

void FuncFrame::setCallStackAlignment(uint32_t alignment)noexcept◆ 

Sets call stack alignment.

Note
This also updates the final stack alignment.

void FuncFrame::setLocalStackAlignment(uint32_t value)noexcept◆ 

Sets local stack alignment.

Note
This also updates the final stack alignment.

void FuncFrame::updateCallStackAlignment(uint32_t alignment)noexcept◆ 

Combines call stack alignment with alignment, updating it to the greater value.

Note
This also updates the final stack alignment.

void FuncFrame::updateLocalStackAlignment(uint32_t alignment)noexcept◆ 

Combines local stack alignment with alignment, updating it to the greater value.

Note
This also updates the final stack alignment.

uint32_t FuncFrame::callStackSize() constnoexcept◆ 

Returns call stack size.

uint32_t FuncFrame::localStackSize() constnoexcept◆ 

Returns local stack size.

void FuncFrame::setCallStackSize(uint32_t size)noexcept◆ 

Sets call stack size.

void FuncFrame::setLocalStackSize(uint32_t size)noexcept◆ 

Sets local stack size.

void FuncFrame::updateCallStackSize(uint32_t size)noexcept◆ 

Combines call stack size with size, updating it to the greater value.

void FuncFrame::updateLocalStackSize(uint32_t size)noexcept◆ 

Combines local stack size with size, updating it to the greater value.

uint32_t FuncFrame::finalStackSize() constnoexcept◆ 

Returns final stack size (only valid after the FuncFrame is finalized).

uint32_t FuncFrame::localStackOffset() constnoexcept◆ 

Returns an offset to access the local stack (non-zero only if call stack is used).

bool FuncFrame::hasDAOffset() constnoexcept◆ 

Tests whether the function prolog/epilog requires a memory slot for storing unaligned SP.

uint32_t FuncFrame::daOffset() constnoexcept◆ 

Returns a memory offset used to store DA (dynamic alignment) slot (relative to SP).

RegMask FuncFrame::dirtyRegs(RegGroup group) constnoexcept◆ 

Returns mask of registers of the given register group that are modified by the function.

The engine would then calculate which registers must be saved & restored by the function by using the data provided by the calling convention.

void FuncFrame::setDirtyRegs(RegGroup group, RegMask regs)noexcept◆ 

Sets which registers (as a mask) are modified by the function.

Remarks
Please note that this will completely overwrite the existing register mask, use addDirtyRegs() to modify the existing register mask.

void FuncFrame::addDirtyRegs(RegGroup group, RegMask regs)noexcept[1/3]◆ 

Adds which registers (as a mask) are modified by the function.

void FuncFrame::addDirtyRegs(const BaseReg& reg)noexcept[2/3]◆ 

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>
void FuncFrame::addDirtyRegs(const BaseReg& reg, Args&&... args)noexcept[3/3]◆ 

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

void FuncFrame::setAllDirty()noexcept[1/2]◆ 

A helper function to set all registers from all register groups dirty.

Note
This should not be used in general as it's the most pessimistic case. However, it can be used for testing or in cases in which all registers are considered clobbered.

void FuncFrame::setAllDirty(RegGroup group)noexcept[2/2]◆ 

A helper function to set all registers from the given register group dirty.

RegMask FuncFrame::savedRegs(RegGroup group) constnoexcept◆ 

Returns a calculated mask of registers of the given group that will be saved and restored in the function's prolog and epilog, respectively.

The register mask is calculated from both dirtyRegs (provided by user) and preservedMask (provided by the calling convention).

RegMask FuncFrame::preservedRegs(RegGroup group) constnoexcept◆ 

Returns the mask of preserved registers of the given register group.

Preserved registers are those that must survive the function call unmodified. The function can only modify preserved registers it they are saved and restored in function's prolog and epilog, respectively.

uint32_t FuncFrame::saveRestoreRegSize(RegGroup group) constnoexcept◆ 

Returns the size of a save-restore are for the required register group.

uint32_t FuncFrame::pushPopSaveSize() constnoexcept◆ 

Returns stack size required to save/restore registers via push/pop.

uint32_t FuncFrame::pushPopSaveOffset() constnoexcept◆ 

Returns an offset to the stack where registers are saved via push/pop.

uint32_t FuncFrame::extraRegSaveSize() constnoexcept◆ 

Returns stack size required to save/restore extra registers that don't use push/pop/.

Note
On X86 this covers all registers except GP registers, on other architectures it can be always zero (for example AArch64 saves all registers via push/pop like instructions, so this would be zero).

uint32_t FuncFrame::extraRegSaveOffset() constnoexcept◆ 

Returns an offset to the stack where extra registers are saved.

bool FuncFrame::hasStackAdjustment() constnoexcept◆ 

Tests whether the functions contains stack adjustment.

uint32_t FuncFrame::stackAdjustment() constnoexcept◆ 

Returns function's stack adjustment used in function's prolog and epilog.

If the returned value is zero it means that the stack is not adjusted. This can mean both that the stack is not used and/or the stack is only adjusted by instructions that pust/pop registers into/from stack.

Member Data Documentation

FuncAttributes FuncFrame::_attributes {}◆ 

Function attributes.

Arch FuncFrame::_arch {}◆ 

Target architecture.

uint8_t FuncFrame::_spRegId = uint8_t(BaseReg::kIdBad)◆ 

SP register ID (to access call stack and local stack).

uint8_t FuncFrame::_saRegId = uint8_t(BaseReg::kIdBad)◆ 

SA register ID (to access stack arguments).

uint8_t FuncFrame::_redZoneSize = 0◆ 

Red zone size (copied from CallConv).

uint8_t FuncFrame::_spillZoneSize = 0◆ 

Spill zone size (copied from CallConv).

uint8_t FuncFrame::_naturalStackAlignment = 0◆ 

Natural stack alignment (copied from CallConv).

uint8_t FuncFrame::_minDynamicAlignment = 0◆ 

Minimum stack alignment to turn on dynamic alignment.

uint8_t FuncFrame::_callStackAlignment = 0◆ 

Call stack alignment.

uint8_t FuncFrame::_localStackAlignment = 0◆ 

Local stack alignment.

uint8_t FuncFrame::_finalStackAlignment = 0◆ 

Final stack alignment.

uint16_t FuncFrame::_calleeStackCleanup = 0◆ 

Adjustment of the stack before returning (X86-STDCALL).

uint32_t FuncFrame::_callStackSize = 0◆ 

Call stack size.

uint32_t FuncFrame::_localStackSize = 0◆ 

Local stack size.

uint32_t FuncFrame::_finalStackSize = 0◆ 

Final stack size (sum of call stack and local stack).

uint32_t FuncFrame::_localStackOffset = 0◆ 

Local stack offset (non-zero only if call stack is used).

uint32_t FuncFrame::_daOffset = 0◆ 

Offset relative to SP that contains previous SP (before alignment).

uint32_t FuncFrame::_saOffsetFromSP = 0◆ 

Offset of the first stack argument relative to SP.

uint32_t FuncFrame::_saOffsetFromSA = 0◆ 

Offset of the first stack argument relative to SA (_saRegId or FP).

uint32_t FuncFrame::_stackAdjustment = 0◆ 

Local stack adjustment in prolog/epilog.

Support::Array<RegMask, Globals::kNumVirtGroups>FuncFrame::_dirtyRegs {}◆ 

Registers that are dirty.

Support::Array<RegMask, Globals::kNumVirtGroups>FuncFrame::_preservedRegs {}◆ 

Registers that must be preserved (copied from CallConv).

Support::Array<uint8_t, Globals::kNumVirtGroups>FuncFrame::_saveRestoreRegSize {}◆ 

Size to save/restore per register group.

Support::Array<uint8_t, Globals::kNumVirtGroups>FuncFrame::_saveRestoreAlignment {}◆ 

Alignment of save/restore area per register group.

uint16_t FuncFrame::_pushPopSaveSize = 0◆ 

Stack size required to save registers with push/pop.

uint16_t FuncFrame::_extraRegSaveSize = 0◆ 

Stack size required to save extra registers that cannot use push/pop.

uint32_t FuncFrame::_pushPopSaveOffset = 0◆ 

Offset where registers saved/restored via push/pop are stored.

uint32_t FuncFrame::_extraRegSaveOffset = 0◆ 

Offset where extra registers that cannot use push/pop are stored.