34 template <
typename T,
typename... Tys>
void push(Tys &&...Args) {
35 new (grow<aligned_size<T>()>())
T(std::forward<Tys>(Args)...);
36 ItemTypes.push_back(toPrimType<T>());
40 template <
typename T>
T pop() {
41 assert(!ItemTypes.empty());
42 assert(ItemTypes.back() == toPrimType<T>());
44 T *Ptr = &peekInternal<T>();
46 shrink(aligned_size<T>());
52 assert(!ItemTypes.empty());
53 assert(ItemTypes.back() == toPrimType<T>());
55 T *Ptr = &peekInternal<T>();
56 if constexpr (!std::is_trivially_destructible_v<T>) {
59 shrink(aligned_size<T>());
64 template <
typename T>
T &
peek()
const {
65 assert(!ItemTypes.empty());
66 assert(ItemTypes.back() == toPrimType<T>());
67 return peekInternal<T>();
70 template <
typename T>
T &
peek(
size_t Offset)
const {
72 return *
reinterpret_cast<T *
>(peekData(Offset));
76 void *
top()
const {
return Chunk ? peekData(0) :
nullptr; }
79 size_t size()
const {
return StackSize; }
86 bool empty()
const {
return StackSize == 0; }
94 template <
typename T>
static constexpr size_t aligned_size() {
95 constexpr size_t PtrAlign =
alignof(
void *);
96 return ((
sizeof(
T) + PtrAlign - 1) / PtrAlign) * PtrAlign;
100 template <
typename T>
T &peekInternal()
const {
101 return *
reinterpret_cast<T *
>(peekData(aligned_size<T>()));
105 template <
size_t Size>
void *grow() {
106 assert(Size < ChunkSize -
sizeof(StackChunk) &&
"Object too large");
110 if (LLVM_UNLIKELY(!Chunk)) {
111 Chunk =
new (std::malloc(ChunkSize)) StackChunk(Chunk);
112 }
else if (LLVM_UNLIKELY(Chunk->size() >
113 ChunkSize -
sizeof(StackChunk) - Size)) {
117 StackChunk *
Next =
new (std::malloc(ChunkSize)) StackChunk(Chunk);
123 auto *
Object =
reinterpret_cast<void *
>(Chunk->start() + Chunk->Size);
129 void *peekDataSlow(
size_t Size)
const;
131 void *peekData(
size_t Size)
const {
132 assert(Chunk &&
"Stack is empty!");
133 if (LLVM_LIKELY(Size <= Chunk->
size()))
134 return reinterpret_cast<void *
>(Chunk->start() + Chunk->Size - Size);
136 return peekDataSlow(Size);
139 void shrinkSlow(
size_t Size);
141 void shrink(
size_t Size) {
142 assert(Chunk &&
"Chunk is empty!");
145 if (LLVM_LIKELY(Size <= Chunk->
size())) {
155 static constexpr size_t ChunkSize = 1024 * 1024;
168 StackChunk(StackChunk *Prev =
nullptr)
169 : Next(
nullptr), Prev(Prev), Size(0) {}
172 size_t size()
const {
return Size; }
175 char *start() {
return reinterpret_cast<char *
>(
this + 1); }
176 const char *start()
const {
177 return reinterpret_cast<const char *
>(
this + 1);
180 static_assert(
sizeof(StackChunk) < ChunkSize,
"Invalid chunk size");
183 StackChunk *Chunk =
nullptr;
185 size_t StackSize = 0;
191 llvm::SmallVector<PrimType> ItemTypes;
193 template <
typename T>
static constexpr PrimType toPrimType() {
194 if constexpr (std::is_same_v<T, Pointer>)
196 else if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, Boolean>)
198 else if constexpr (std::is_same_v<T, int8_t> ||
199 std::is_same_v<T, Char<true>>)
201 else if constexpr (std::is_same_v<T, uint8_t> ||
202 std::is_same_v<T, Char<false>>)
204 else if constexpr (std::is_same_v<T, Integral<16, true>>)
206 else if constexpr (std::is_same_v<T, Integral<16, false>>)
208 else if constexpr (std::is_same_v<T, Integral<32, true>>)
210 else if constexpr (std::is_same_v<T, Integral<32, false>>)
212 else if constexpr (std::is_same_v<T, Integral<64, true>>)
214 else if constexpr (std::is_same_v<T, Integral<64, false>>)
217 else if constexpr (std::is_same_v<T, Floating>)
219 else if constexpr (std::is_same_v<T, IntegralAP<true>>)
221 else if constexpr (std::is_same_v<T, IntegralAP<false>>)
223 else if constexpr (std::is_same_v<T, MemberPointer>)
225 else if constexpr (std::is_same_v<T, FixedPoint>)
227 else if constexpr (std::is_same_v<T, Reflect>)
230 llvm_unreachable(
"unknown type push()'ed into InterpStack");