33 template <
typename T,
typename... Tys>
void push(Tys &&...Args) {
34 new (grow<aligned_size<T>()>()) T(std::forward<Tys>(Args)...);
35 ItemTypes.push_back(toPrimType<T>());
39 template <
typename T> T
pop() {
40 assert(!ItemTypes.empty());
41 assert(ItemTypes.back() == toPrimType<T>());
43 T *Ptr = &peekInternal<T>();
44 T
Value = std::move(*Ptr);
45 shrink(aligned_size<T>());
51 assert(!ItemTypes.empty());
52 assert(ItemTypes.back() == toPrimType<T>());
54 T *Ptr = &peekInternal<T>();
55 if constexpr (!std::is_trivially_destructible_v<T>) {
58 shrink(aligned_size<T>());
63 template <
typename T> T &
peek()
const {
64 assert(!ItemTypes.empty());
65 assert(ItemTypes.back() == toPrimType<T>());
66 return peekInternal<T>();
69 template <
typename T> T &
peek(
size_t Offset)
const {
71 return *
reinterpret_cast<T *
>(peekData(Offset));
75 void *
top()
const {
return Chunk ? peekData(0) :
nullptr; }
78 size_t size()
const {
return StackSize; }
85 bool empty()
const {
return StackSize == 0; }
93 template <
typename T>
static constexpr size_t aligned_size() {
94 constexpr size_t PtrAlign =
alignof(
void *);
95 return ((
sizeof(T) + PtrAlign - 1) / PtrAlign) * PtrAlign;
99 template <
typename T> T &peekInternal()
const {
100 return *
reinterpret_cast<T *
>(peekData(aligned_size<T>()));
104 template <
size_t Size>
void *grow() {
105 assert(Size < ChunkSize -
sizeof(StackChunk) &&
"Object too large");
109 if (LLVM_UNLIKELY(!Chunk)) {
110 Chunk =
new (std::malloc(ChunkSize)) StackChunk(Chunk);
111 }
else if (LLVM_UNLIKELY(Chunk->size() >
112 ChunkSize -
sizeof(StackChunk) - Size)) {
116 StackChunk *
Next =
new (std::malloc(ChunkSize)) StackChunk(Chunk);
122 auto *
Object =
reinterpret_cast<void *
>(Chunk->start() + Chunk->Size);
129 void *peekData(
size_t Size)
const;
131 void shrink(
size_t Size);
134 static constexpr size_t ChunkSize = 1024 * 1024;
147 StackChunk(StackChunk *Prev =
nullptr)
148 : Next(
nullptr), Prev(Prev), Size(0) {}
151 size_t size()
const {
return Size; }
154 char *start() {
return reinterpret_cast<char *
>(
this + 1); }
155 const char *start()
const {
156 return reinterpret_cast<const char *
>(
this + 1);
159 static_assert(
sizeof(StackChunk) < ChunkSize,
"Invalid chunk size");
162 StackChunk *Chunk =
nullptr;
164 size_t StackSize = 0;
170 llvm::SmallVector<PrimType> ItemTypes;
172 template <
typename T>
static constexpr PrimType toPrimType() {
173 if constexpr (std::is_same_v<T, Pointer>)
175 else if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, Boolean>)
177 else if constexpr (std::is_same_v<T, int8_t> ||
178 std::is_same_v<T, Char<true>>)
180 else if constexpr (std::is_same_v<T, uint8_t> ||
181 std::is_same_v<T, Char<false>>)
183 else if constexpr (std::is_same_v<T, Integral<16, true>>)
185 else if constexpr (std::is_same_v<T, Integral<16, false>>)
187 else if constexpr (std::is_same_v<T, Integral<32, true>>)
189 else if constexpr (std::is_same_v<T, Integral<32, false>>)
191 else if constexpr (std::is_same_v<T, Integral<64, true>>)
193 else if constexpr (std::is_same_v<T, Integral<64, false>>)
196 else if constexpr (std::is_same_v<T, Floating>)
198 else if constexpr (std::is_same_v<T, IntegralAP<true>>)
200 else if constexpr (std::is_same_v<T, IntegralAP<false>>)
202 else if constexpr (std::is_same_v<T, MemberPointer>)
204 else if constexpr (std::is_same_v<T, FixedPoint>)
207 llvm_unreachable(
"unknown type push()'ed into InterpStack");