13#ifndef LLVM_CLANG_AST_INTERP_INTERPSTACK_H
14#define LLVM_CLANG_AST_INTERP_INTERPSTACK_H
32 template <
typename T,
typename... Tys>
void push(Tys &&... Args) {
33 new (grow(aligned_size<T>())) T(std::forward<Tys>(Args)...);
35 ItemTypes.push_back(toPrimType<T>());
40 template <
typename T> T
pop() {
42 assert(!ItemTypes.empty());
43 assert(ItemTypes.back() == toPrimType<T>());
46 auto *Ptr = &peek<T>();
47 auto Value = std::move(*Ptr);
49 shrink(aligned_size<T>());
56 assert(ItemTypes.back() == toPrimType<T>());
59 auto *Ptr = &peek<T>();
61 shrink(aligned_size<T>());
65 template <
typename T> T &
peek()
const {
66 return *
reinterpret_cast<T *
>(
peek(aligned_size<T>()));
70 void *
top()
const {
return Chunk ?
peek(0) :
nullptr; }
73 size_t size()
const {
return StackSize; }
79 bool empty()
const {
return StackSize == 0; }
84 template <
typename T>
constexpr size_t aligned_size()
const {
85 constexpr size_t PtrAlign =
alignof(
void *);
86 return ((
sizeof(T) + PtrAlign - 1) / PtrAlign) * PtrAlign;
90 void *grow(
size_t Size);
92 void *
peek(
size_t Size)
const;
94 void shrink(
size_t Size);
97 static constexpr size_t ChunkSize = 1024 * 1024;
110 StackChunk(StackChunk *Prev =
nullptr)
111 : Next(nullptr), Prev(Prev), End(reinterpret_cast<char *>(this + 1)) {}
114 size_t size()
const {
return End - start(); }
117 char *start() {
return reinterpret_cast<char *
>(
this + 1); }
118 const char *start()
const {
119 return reinterpret_cast<const char *
>(
this + 1);
122 static_assert(
sizeof(StackChunk) < ChunkSize,
"Invalid chunk size");
125 StackChunk *Chunk =
nullptr;
127 size_t StackSize = 0;
131 std::vector<PrimType> ItemTypes;
133 template <
typename T>
static constexpr PrimType toPrimType() {
134 if constexpr (std::is_same_v<T, Pointer>)
136 else if constexpr (std::is_same_v<T, bool> ||
137 std::is_same_v<T, Boolean>)
139 else if constexpr (std::is_same_v<T, int8_t> ||
140 std::is_same_v<T, Integral<8, true>>)
142 else if constexpr (std::is_same_v<T, uint8_t> ||
143 std::is_same_v<T, Integral<8, false>>)
145 else if constexpr (std::is_same_v<T, int16_t> ||
146 std::is_same_v<T, Integral<16, true>>)
148 else if constexpr (std::is_same_v<T, uint16_t> ||
149 std::is_same_v<T, Integral<16, false>>)
151 else if constexpr (std::is_same_v<T, int32_t> ||
152 std::is_same_v<T, Integral<32, true>>)
154 else if constexpr (std::is_same_v<T, uint32_t> ||
155 std::is_same_v<T, Integral<32, false>>)
157 else if constexpr (std::is_same_v<T, int64_t> ||
158 std::is_same_v<T, Integral<64, true>>)
160 else if constexpr (std::is_same_v<T, uint64_t> ||
161 std::is_same_v<T, Integral<64, false>>)
163 else if constexpr (std::is_same_v<T, Floating>)
166 llvm_unreachable(
"unknown type push()'ed into InterpStack");
Stack frame storing temporaries and parameters.
T pop()
Returns the value from the top of the stack and removes it.
void push(Tys &&... Args)
Constructs a value in place on the top of the stack.
void * top() const
Returns a pointer to the top object.
void clear()
Clears the stack without calling any destructors.
size_t size() const
Returns the size of the stack in bytes.
void discard()
Discards the top value from the stack.
~InterpStack()
Destroys the stack, freeing up storage.
T & peek() const
Returns a reference to the value on the top of the stack.
PrimType
Enumeration of the primitive types of the VM.