Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/InterpStack.cpp
213799 views
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 "FixedPoint.h"
12
#include "Floating.h"
13
#include "Integral.h"
14
#include "MemberPointer.h"
15
#include "Pointer.h"
16
#include <cassert>
17
#include <cstdlib>
18
19
using namespace clang;
20
using namespace clang::interp;
21
22
InterpStack::~InterpStack() {
23
if (Chunk && Chunk->Next)
24
std::free(Chunk->Next);
25
if (Chunk)
26
std::free(Chunk);
27
Chunk = nullptr;
28
StackSize = 0;
29
#ifndef NDEBUG
30
ItemTypes.clear();
31
#endif
32
}
33
34
// We keep the last chunk around to reuse.
35
void InterpStack::clear() {
36
if (!Chunk)
37
return;
38
39
if (Chunk->Next)
40
std::free(Chunk->Next);
41
42
assert(Chunk);
43
StackSize = 0;
44
#ifndef NDEBUG
45
ItemTypes.clear();
46
#endif
47
}
48
49
void InterpStack::clearTo(size_t NewSize) {
50
assert(NewSize <= size());
51
size_t ToShrink = size() - NewSize;
52
if (ToShrink == 0)
53
return;
54
55
shrink(ToShrink);
56
assert(size() == NewSize);
57
}
58
59
void *InterpStack::grow(size_t Size) {
60
assert(Size < ChunkSize - sizeof(StackChunk) && "Object too large");
61
62
if (!Chunk || sizeof(StackChunk) + Chunk->size() + Size > ChunkSize) {
63
if (Chunk && Chunk->Next) {
64
Chunk = Chunk->Next;
65
} else {
66
StackChunk *Next = new (std::malloc(ChunkSize)) StackChunk(Chunk);
67
if (Chunk)
68
Chunk->Next = Next;
69
Chunk = Next;
70
}
71
}
72
73
auto *Object = reinterpret_cast<void *>(Chunk->End);
74
Chunk->End += Size;
75
StackSize += Size;
76
return Object;
77
}
78
79
void *InterpStack::peekData(size_t Size) const {
80
assert(Chunk && "Stack is empty!");
81
82
StackChunk *Ptr = Chunk;
83
while (Size > Ptr->size()) {
84
Size -= Ptr->size();
85
Ptr = Ptr->Prev;
86
assert(Ptr && "Offset too large");
87
}
88
89
return reinterpret_cast<void *>(Ptr->End - Size);
90
}
91
92
void InterpStack::shrink(size_t Size) {
93
assert(Chunk && "Chunk is empty!");
94
95
while (Size > Chunk->size()) {
96
Size -= Chunk->size();
97
if (Chunk->Next) {
98
std::free(Chunk->Next);
99
Chunk->Next = nullptr;
100
}
101
Chunk->End = Chunk->start();
102
Chunk = Chunk->Prev;
103
assert(Chunk && "Offset too large");
104
}
105
106
Chunk->End -= Size;
107
StackSize -= Size;
108
109
#ifndef NDEBUG
110
size_t TypesSize = 0;
111
for (PrimType T : ItemTypes)
112
TYPE_SWITCH(T, { TypesSize += aligned_size<T>(); });
113
114
size_t StackSize = size();
115
while (TypesSize > StackSize) {
116
TYPE_SWITCH(ItemTypes.back(), {
117
TypesSize -= aligned_size<T>();
118
ItemTypes.pop_back();
119
});
120
}
121
assert(TypesSize == StackSize);
122
#endif
123
}
124
125
void InterpStack::dump() const {
126
#ifndef NDEBUG
127
llvm::errs() << "Items: " << ItemTypes.size() << ". Size: " << size() << '\n';
128
if (ItemTypes.empty())
129
return;
130
131
size_t Index = 0;
132
size_t Offset = 0;
133
134
// The type of the item on the top of the stack is inserted to the back
135
// of the vector, so the iteration has to happen backwards.
136
for (auto TyIt = ItemTypes.rbegin(); TyIt != ItemTypes.rend(); ++TyIt) {
137
Offset += align(primSize(*TyIt));
138
139
llvm::errs() << Index << '/' << Offset << ": ";
140
TYPE_SWITCH(*TyIt, {
141
const T &V = peek<T>(Offset);
142
llvm::errs() << V;
143
});
144
llvm::errs() << '\n';
145
146
++Index;
147
}
148
#endif
149
}
150
151