172 lines
4.4 KiB
C++
172 lines
4.4 KiB
C++
// This file is part of AsmJit project <https://asmjit.com>
|
|
//
|
|
// See asmjit.h or LICENSE.md for license and copyright information
|
|
// SPDX-License-Identifier: Zlib
|
|
|
|
#ifndef ASMJIT_CORE_RASTACK_P_H_INCLUDED
|
|
#define ASMJIT_CORE_RASTACK_P_H_INCLUDED
|
|
|
|
#include "../core/api-config.h"
|
|
#ifndef ASMJIT_NO_COMPILER
|
|
|
|
#include "../core/radefs_p.h"
|
|
|
|
ASMJIT_BEGIN_NAMESPACE
|
|
|
|
//! \cond INTERNAL
|
|
//! \addtogroup asmjit_ra
|
|
//! \{
|
|
|
|
//! Stack slot.
|
|
struct RAStackSlot {
|
|
//! Stack slot flags.
|
|
//!
|
|
//! TODO: kFlagStackArg is not used by the current implementation, do we need to keep it?
|
|
enum Flags : uint16_t {
|
|
//! Stack slot is register home slot.
|
|
kFlagRegHome = 0x0001u,
|
|
//! Stack slot position matches argument passed via stack.
|
|
kFlagStackArg = 0x0002u
|
|
};
|
|
|
|
enum ArgIndex : uint32_t {
|
|
kNoArgIndex = 0xFF
|
|
};
|
|
|
|
//! \name Members
|
|
//! \{
|
|
|
|
//! Base register used to address the stack.
|
|
uint8_t _baseRegId;
|
|
//! Minimum alignment required by the slot.
|
|
uint8_t _alignment;
|
|
//! Reserved for future use.
|
|
uint16_t _flags;
|
|
//! Size of memory required by the slot.
|
|
uint32_t _size;
|
|
|
|
//! Usage counter (one unit equals one memory access).
|
|
uint32_t _useCount;
|
|
//! Weight of the slot, calculated by \ref RAStackAllocator::calculateStackFrame().
|
|
uint32_t _weight;
|
|
//! Stack offset, calculated by \ref RAStackAllocator::calculateStackFrame().
|
|
int32_t _offset;
|
|
|
|
//! \}
|
|
|
|
//! \name Accessors
|
|
//! \{
|
|
|
|
inline uint32_t baseRegId() const noexcept { return _baseRegId; }
|
|
inline void setBaseRegId(uint32_t id) noexcept { _baseRegId = uint8_t(id); }
|
|
|
|
inline uint32_t size() const noexcept { return _size; }
|
|
inline uint32_t alignment() const noexcept { return _alignment; }
|
|
|
|
inline uint32_t flags() const noexcept { return _flags; }
|
|
inline bool hasFlag(uint32_t flag) const noexcept { return (_flags & flag) != 0; }
|
|
inline void addFlags(uint32_t flags) noexcept { _flags = uint16_t(_flags | flags); }
|
|
|
|
inline bool isRegHome() const noexcept { return hasFlag(kFlagRegHome); }
|
|
inline bool isStackArg() const noexcept { return hasFlag(kFlagStackArg); }
|
|
|
|
inline uint32_t useCount() const noexcept { return _useCount; }
|
|
inline void addUseCount(uint32_t n = 1) noexcept { _useCount += n; }
|
|
|
|
inline uint32_t weight() const noexcept { return _weight; }
|
|
inline void setWeight(uint32_t weight) noexcept { _weight = weight; }
|
|
|
|
inline int32_t offset() const noexcept { return _offset; }
|
|
inline void setOffset(int32_t offset) noexcept { _offset = offset; }
|
|
|
|
//! \}
|
|
};
|
|
|
|
typedef ZoneVector<RAStackSlot*> RAStackSlots;
|
|
|
|
//! Stack allocator.
|
|
class RAStackAllocator {
|
|
public:
|
|
ASMJIT_NONCOPYABLE(RAStackAllocator)
|
|
|
|
enum Size : uint32_t {
|
|
kSize1 = 0,
|
|
kSize2 = 1,
|
|
kSize4 = 2,
|
|
kSize8 = 3,
|
|
kSize16 = 4,
|
|
kSize32 = 5,
|
|
kSize64 = 6,
|
|
kSizeCount = 7
|
|
};
|
|
|
|
//! \name Members
|
|
//! \{
|
|
|
|
//! Allocator used to allocate internal data.
|
|
ZoneAllocator* _allocator;
|
|
//! Count of bytes used by all slots.
|
|
uint32_t _bytesUsed;
|
|
//! Calculated stack size (can be a bit greater than `_bytesUsed`).
|
|
uint32_t _stackSize;
|
|
//! Minimum stack alignment.
|
|
uint32_t _alignment;
|
|
//! Stack slots vector.
|
|
RAStackSlots _slots;
|
|
|
|
//! \}
|
|
|
|
//! \name Construction & Destruction
|
|
//! \{
|
|
|
|
inline RAStackAllocator() noexcept
|
|
: _allocator(nullptr),
|
|
_bytesUsed(0),
|
|
_stackSize(0),
|
|
_alignment(1),
|
|
_slots() {}
|
|
|
|
inline void reset(ZoneAllocator* allocator) noexcept {
|
|
_allocator = allocator;
|
|
_bytesUsed = 0;
|
|
_stackSize = 0;
|
|
_alignment = 1;
|
|
_slots.reset();
|
|
}
|
|
|
|
//! \}
|
|
|
|
//! \name Accessors
|
|
//! \{
|
|
|
|
inline ZoneAllocator* allocator() const noexcept { return _allocator; }
|
|
|
|
inline uint32_t bytesUsed() const noexcept { return _bytesUsed; }
|
|
inline uint32_t stackSize() const noexcept { return _stackSize; }
|
|
inline uint32_t alignment() const noexcept { return _alignment; }
|
|
|
|
inline RAStackSlots& slots() noexcept { return _slots; }
|
|
inline const RAStackSlots& slots() const noexcept { return _slots; }
|
|
inline uint32_t slotCount() const noexcept { return _slots.size(); }
|
|
|
|
//! \}
|
|
|
|
//! \name Utilities
|
|
//! \{
|
|
|
|
RAStackSlot* newSlot(uint32_t baseRegId, uint32_t size, uint32_t alignment, uint32_t flags = 0) noexcept;
|
|
|
|
Error calculateStackFrame() noexcept;
|
|
Error adjustSlotOffsets(int32_t offset) noexcept;
|
|
|
|
//! \}
|
|
};
|
|
|
|
//! \}
|
|
//! \endcond
|
|
|
|
ASMJIT_END_NAMESPACE
|
|
|
|
#endif // !ASMJIT_NO_COMPILER
|
|
#endif // ASMJIT_CORE_RASTACK_P_H_INCLUDED
|