1//===--- InterpStack.cpp - Stack implementation for the VM ------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "InterpStack.h"
10#include "Boolean.h"
11#include "Floating.h"
12#include "Integral.h"
13#include "Pointer.h"
14#include <cassert>
15#include <cstdlib>
16
17using namespace clang;
18using namespace clang::interp;
19
20InterpStack::~InterpStack() {
21 clear();
22}
23
24void InterpStack::clear() {
25 if (Chunk && Chunk->Next)
26 std::free(ptr: Chunk->Next);
27 if (Chunk)
28 std::free(ptr: Chunk);
29 Chunk = nullptr;
30 StackSize = 0;
31#ifndef NDEBUG
32 ItemTypes.clear();
33#endif
34}
35
36void *InterpStack::grow(size_t Size) {
37 assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large");
38
39 if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) {
40 if (Chunk && Chunk->Next) {
41 Chunk = Chunk->Next;
42 } else {
43 StackChunk *Next = new (std::malloc(size: ChunkSize)) StackChunk(Chunk);
44 if (Chunk)
45 Chunk->Next = Next;
46 Chunk = Next;
47 }
48 }
49
50 auto *Object = reinterpret_cast<void *>(Chunk->End);
51 Chunk->End += Size;
52 StackSize += Size;
53 return Object;
54}
55
56void *InterpStack::peekData(size_t Size) const {
57 assert(Chunk && "Stack is empty!");
58
59 StackChunk *Ptr = Chunk;
60 while (Size > Ptr->size()) {
61 Size -= Ptr->size();
62 Ptr = Ptr->Prev;
63 assert(Ptr && "Offset too large");
64 }
65
66 return reinterpret_cast<void *>(Ptr->End - Size);
67}
68
69void InterpStack::shrink(size_t Size) {
70 assert(Chunk && "Chunk is empty!");
71
72 while (Size > Chunk->size()) {
73 Size -= Chunk->size();
74 if (Chunk->Next) {
75 std::free(ptr: Chunk->Next);
76 Chunk->Next = nullptr;
77 }
78 Chunk->End = Chunk->start();
79 Chunk = Chunk->Prev;
80 assert(Chunk && "Offset too large");
81 }
82
83 Chunk->End -= Size;
84 StackSize -= Size;
85}
86
87void InterpStack::dump() const {
88#ifndef NDEBUG
89 llvm::errs() << "Items: " << ItemTypes.size() << ". Size: " << size() << '\n';
90 if (ItemTypes.empty())
91 return;
92
93 size_t Index = 0;
94 size_t Offset = 0;
95
96 // The type of the item on the top of the stack is inserted to the back
97 // of the vector, so the iteration has to happen backwards.
98 for (auto TyIt = ItemTypes.rbegin(); TyIt != ItemTypes.rend(); ++TyIt) {
99 Offset += align(Size: primSize(Type: *TyIt));
100
101 llvm::errs() << Index << '/' << Offset << ": ";
102 TYPE_SWITCH(*TyIt, {
103 const T &V = peek<T>(Offset);
104 llvm::errs() << V;
105 });
106 llvm::errs() << '\n';
107
108 ++Index;
109 }
110#endif
111}
112

source code of clang/lib/AST/Interp/InterpStack.cpp