Skip to content

Commit a4f512a

Browse files
committed
Always do ItemTypes
1 parent 7f0e407 commit a4f512a

File tree

14 files changed

+80
-99
lines changed

14 files changed

+80
-99
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2966,20 +2966,25 @@ bool Compiler<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
29662966
if (T && !E->isLValue())
29672967
return this->delegate(Init);
29682968

2969-
if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) {
2970-
if (!this->emitGetPtrGlobal(*GlobalIndex, E))
2971-
return false;
2969+
std::optional<unsigned> GlobalIndex = P.createGlobal(E);
2970+
if (!GlobalIndex)
2971+
return false;
29722972

2973-
if (T) {
2974-
if (!this->visit(Init))
2975-
return false;
2976-
return this->emitInitGlobal(*T, *GlobalIndex, E);
2977-
}
2973+
if (!this->emitGetPtrGlobal(*GlobalIndex, E))
2974+
return false;
2975+
2976+
// Since this is a global variable, we might've already seen,
2977+
// don't do it again.
2978+
if (P.isGlobalInitialized(*GlobalIndex))
2979+
return true;
29782980

2979-
return this->visitInitializer(Init) && this->emitFinishInit(E);
2981+
if (T) {
2982+
if (!this->visit(Init))
2983+
return false;
2984+
return this->emitInitGlobal(*T, *GlobalIndex, E);
29802985
}
29812986

2982-
return false;
2987+
return this->visitInitializer(Init) && this->emitFinishInit(E);
29832988
}
29842989

29852990
// Otherwise, use a local variable.

clang/lib/AST/ByteCode/Context.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -398,17 +398,11 @@ const llvm::fltSemantics &Context::getFloatSemantics(QualType T) const {
398398
}
399399

400400
bool Context::Run(State &Parent, const Function *Func) {
401-
402-
{
403-
InterpState State(Parent, *P, Stk, *this, Func);
404-
if (Interpret(State)) {
405-
assert(Stk.empty());
406-
return true;
407-
}
408-
// State gets destroyed here, so the Stk.clear() below doesn't accidentally
409-
// remove values the State's destructor might access.
401+
InterpState State(Parent, *P, Stk, *this, Func);
402+
if (Interpret(State)) {
403+
assert(Stk.empty());
404+
return true;
410405
}
411-
412406
Stk.clear();
413407
return false;
414408
}

clang/lib/AST/ByteCode/Context.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace interp {
3030
class Function;
3131
class Program;
3232
class State;
33-
enum PrimType : unsigned;
33+
enum PrimType : uint8_t;
3434

3535
struct ParamOffset {
3636
unsigned Offset;

clang/lib/AST/ByteCode/Descriptor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class Record;
2424
class SourceInfo;
2525
struct InitMap;
2626
struct Descriptor;
27-
enum PrimType : unsigned;
27+
enum PrimType : uint8_t;
2828

2929
using DeclTy = llvm::PointerUnion<const Decl *, const Expr *>;
3030
using InitMapPtr = std::optional<std::pair<bool, std::shared_ptr<InitMap>>>;

clang/lib/AST/ByteCode/Function.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace interp {
2828
class Program;
2929
class ByteCodeEmitter;
3030
class Pointer;
31-
enum PrimType : uint32_t;
31+
enum PrimType : uint8_t;
3232

3333
/// Describes a scope block.
3434
///

clang/lib/AST/ByteCode/InterpBlock.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ using namespace clang::interp;
1818

1919
void Block::addPointer(Pointer *P) {
2020
assert(P);
21-
if (IsStatic) {
22-
assert(!Pointers);
23-
return;
24-
}
2521

2622
#ifndef NDEBUG
2723
assert(!hasPointer(P));
@@ -39,10 +35,6 @@ void Block::addPointer(Pointer *P) {
3935
void Block::removePointer(Pointer *P) {
4036
assert(P->isBlockPointer());
4137
assert(P);
42-
if (IsStatic) {
43-
assert(!Pointers);
44-
return;
45-
}
4638

4739
#ifndef NDEBUG
4840
assert(hasPointer(P));
@@ -74,10 +66,6 @@ void Block::replacePointer(Pointer *Old, Pointer *New) {
7466
assert(New);
7567
assert(New->isBlockPointer());
7668
assert(Old != New);
77-
if (IsStatic) {
78-
assert(!Pointers);
79-
return;
80-
}
8169
#ifndef NDEBUG
8270
assert(hasPointer(Old));
8371
#endif

clang/lib/AST/ByteCode/InterpBlock.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Block;
2222
class DeadBlock;
2323
class InterpState;
2424
class Pointer;
25-
enum PrimType : unsigned;
25+
enum PrimType : uint8_t;
2626

2727
/// A memory block, either on the stack or in the heap.
2828
///
@@ -130,7 +130,7 @@ class Block final {
130130
void dump() const { dump(llvm::errs()); }
131131
void dump(llvm::raw_ostream &OS) const;
132132

133-
private:
133+
public:
134134
friend class Pointer;
135135
friend class DeadBlock;
136136
friend class InterpState;

clang/lib/AST/ByteCode/InterpStack.cpp

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,33 +26,33 @@ InterpStack::~InterpStack() {
2626
std::free(Chunk);
2727
Chunk = nullptr;
2828
StackSize = 0;
29-
#ifndef NDEBUG
3029
ItemTypes.clear();
31-
#endif
3230
}
3331

3432
// We keep the last chunk around to reuse.
3533
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
34+
for (PrimType Item : llvm::reverse(ItemTypes)) {
35+
TYPE_SWITCH(Item, { this->discard<T>(); });
36+
}
37+
assert(ItemTypes.empty());
38+
assert(empty());
4739
}
4840

4941
void InterpStack::clearTo(size_t NewSize) {
50-
assert(NewSize <= size());
51-
size_t ToShrink = size() - NewSize;
52-
if (ToShrink == 0)
42+
if (NewSize == 0)
43+
return clear();
44+
if (NewSize == size())
5345
return;
5446

55-
shrink(ToShrink);
47+
assert(NewSize <= size());
48+
for (PrimType Item : llvm::reverse(ItemTypes)) {
49+
TYPE_SWITCH(Item, { this->discard<T>(); });
50+
51+
if (size() == NewSize)
52+
break;
53+
}
54+
55+
// Note: discard() above already removed the types from ItemTypes.
5656
assert(size() == NewSize);
5757
}
5858

@@ -105,25 +105,9 @@ void InterpStack::shrink(size_t Size) {
105105

106106
Chunk->End -= Size;
107107
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
123108
}
124109

125110
void InterpStack::dump() const {
126-
#ifndef NDEBUG
127111
llvm::errs() << "Items: " << ItemTypes.size() << ". Size: " << size() << '\n';
128112
if (ItemTypes.empty())
129113
return;
@@ -133,17 +117,16 @@ void InterpStack::dump() const {
133117

134118
// The type of the item on the top of the stack is inserted to the back
135119
// 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));
120+
for (PrimType Item : llvm::reverse(ItemTypes)) {
121+
Offset += align(primSize(Item));
138122

139123
llvm::errs() << Index << '/' << Offset << ": ";
140-
TYPE_SWITCH(*TyIt, {
124+
TYPE_SWITCH(Item, {
141125
const T &V = peek<T>(Offset);
142126
llvm::errs() << V;
143127
});
144128
llvm::errs() << '\n';
145129

146130
++Index;
147131
}
148-
#endif
149132
}

clang/lib/AST/ByteCode/InterpStack.h

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include "IntegralAP.h"
1818
#include "MemberPointer.h"
1919
#include "PrimType.h"
20-
#include <vector>
2120

2221
namespace clang {
2322
namespace interp {
@@ -33,18 +32,14 @@ class InterpStack final {
3332
/// Constructs a value in place on the top of the stack.
3433
template <typename T, typename... Tys> void push(Tys &&...Args) {
3534
new (grow(aligned_size<T>())) T(std::forward<Tys>(Args)...);
36-
#ifndef NDEBUG
3735
ItemTypes.push_back(toPrimType<T>());
38-
#endif
3936
}
4037

4138
/// Returns the value from the top of the stack and removes it.
4239
template <typename T> T pop() {
43-
#ifndef NDEBUG
4440
assert(!ItemTypes.empty());
4541
assert(ItemTypes.back() == toPrimType<T>());
4642
ItemTypes.pop_back();
47-
#endif
4843
T *Ptr = &peekInternal<T>();
4944
T Value = std::move(*Ptr);
5045
shrink(aligned_size<T>());
@@ -53,22 +48,20 @@ class InterpStack final {
5348

5449
/// Discards the top value from the stack.
5550
template <typename T> void discard() {
56-
#ifndef NDEBUG
5751
assert(!ItemTypes.empty());
5852
assert(ItemTypes.back() == toPrimType<T>());
5953
ItemTypes.pop_back();
60-
#endif
6154
T *Ptr = &peekInternal<T>();
62-
Ptr->~T();
55+
if constexpr (!std::is_trivially_destructible_v<T>) {
56+
Ptr->~T();
57+
}
6358
shrink(aligned_size<T>());
6459
}
6560

6661
/// Returns a reference to the value on the top of the stack.
6762
template <typename T> T &peek() const {
68-
#ifndef NDEBUG
6963
assert(!ItemTypes.empty());
7064
assert(ItemTypes.back() == toPrimType<T>());
71-
#endif
7265
return peekInternal<T>();
7366
}
7467

@@ -83,7 +76,7 @@ class InterpStack final {
8376
/// Returns the size of the stack in bytes.
8477
size_t size() const { return StackSize; }
8578

86-
/// Clears the stack without calling any destructors.
79+
/// Clears the stack.
8780
void clear();
8881
void clearTo(size_t NewSize);
8982

@@ -146,9 +139,11 @@ class InterpStack final {
146139
/// Total size of the stack.
147140
size_t StackSize = 0;
148141

149-
#ifndef NDEBUG
150-
/// vector recording the type of data we pushed into the stack.
151-
std::vector<PrimType> ItemTypes;
142+
/// SmallVector recording the type of data we pushed into the stack.
143+
/// We don't usually need this during normal code interpretation but
144+
/// when aborting, we need type information to call the destructors
145+
/// for what's left on the stack.
146+
llvm::SmallVector<PrimType> ItemTypes;
152147

153148
template <typename T> static constexpr PrimType toPrimType() {
154149
if constexpr (std::is_same_v<T, Pointer>)
@@ -192,7 +187,6 @@ class InterpStack final {
192187

193188
llvm_unreachable("unknown type push()'ed into InterpStack");
194189
}
195-
#endif
196190
};
197191

198192
} // namespace interp

clang/lib/AST/ByteCode/InterpState.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ InterpState::~InterpState() {
4545

4646
while (DeadBlocks) {
4747
DeadBlock *Next = DeadBlocks->Next;
48+
49+
// There might be a pointer in a global structure pointing to the dead
50+
// block.
51+
for (Pointer *P = DeadBlocks->B.Pointers; P; P = P->asBlockPointer().Next)
52+
DeadBlocks->B.removePointer(P);
53+
4854
std::free(DeadBlocks);
4955
DeadBlocks = Next;
5056
}
@@ -53,12 +59,6 @@ InterpState::~InterpState() {
5359
void InterpState::cleanup() {
5460
// As a last resort, make sure all pointers still pointing to a dead block
5561
// don't point to it anymore.
56-
for (DeadBlock *DB = DeadBlocks; DB; DB = DB->Next) {
57-
for (Pointer *P = DB->B.Pointers; P; P = P->asBlockPointer().Next) {
58-
P->PointeeStorage.BS.Pointee = nullptr;
59-
}
60-
}
61-
6262
Alloc.cleanup();
6363
}
6464

@@ -77,6 +77,9 @@ bool InterpState::reportOverflow(const Expr *E, const llvm::APSInt &Value) {
7777
void InterpState::deallocate(Block *B) {
7878
assert(B);
7979
assert(!B->isDynamic());
80+
assert(!B->isStatic());
81+
assert(!B->IsDead);
82+
8083
// The block might have a pointer saved in a field in its data
8184
// that points to the block itself. We call the dtor first,
8285
// which will destroy all the data but leave InlineDescriptors

0 commit comments

Comments
 (0)