clang 22.0.0git
InterpBlock.h
Go to the documentation of this file.
1//===-- InterpBlock.h - Allocated blocks for the interpreter -*- 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// Defines the classes describing allocated blocks.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_INTERP_BLOCK_H
14#define LLVM_CLANG_AST_INTERP_BLOCK_H
15
16#include "Descriptor.h"
17#include "llvm/Support/raw_ostream.h"
18
19namespace clang {
20namespace interp {
21class Block;
22class DeadBlock;
23class InterpState;
24class Pointer;
25enum PrimType : uint8_t;
26
27/// A memory block, either on the stack or in the heap.
28///
29/// The storage described by the block is immediately followed by
30/// optional metadata, which is followed by the actual data.
31///
32/// Block* rawData() data()
33/// │ │ │
34/// │ │ │
35/// ▼ ▼ ▼
36/// ┌───────────────┬─────────────────────────┬─────────────────┐
37/// │ Block │ Metadata │ Data │
38/// │ sizeof(Block) │ Desc->getMetadataSize() │ Desc->getSize() │
39/// └───────────────┴─────────────────────────┴─────────────────┘
40///
41/// Desc->getAllocSize() describes the size after the Block, i.e.
42/// the data size and the metadata size.
43///
44class Block final {
45private:
46 static constexpr uint8_t ExternFlag = 1 << 0;
47 static constexpr uint8_t DeadFlag = 1 << 1;
48 static constexpr uint8_t WeakFlag = 1 << 2;
49 static constexpr uint8_t DummyFlag = 1 << 3;
50
51public:
52 /// Creates a new block.
53 Block(unsigned EvalID, UnsignedOrNone DeclID, const Descriptor *Desc,
54 bool IsStatic = false, bool IsExtern = false, bool IsWeak = false,
55 bool IsDummy = false)
56 : Desc(Desc), DeclID(DeclID), EvalID(EvalID), IsStatic(IsStatic) {
57 assert(Desc);
58 AccessFlags |= (ExternFlag * IsExtern);
59 AccessFlags |= (WeakFlag * IsWeak);
60 AccessFlags |= (DummyFlag * IsDummy);
61 }
62
63 Block(unsigned EvalID, const Descriptor *Desc, bool IsStatic = false,
64 bool IsExtern = false, bool IsWeak = false, bool IsDummy = false)
65 : Desc(Desc), EvalID(EvalID), IsStatic(IsStatic) {
66 assert(Desc);
67 AccessFlags |= (ExternFlag * IsExtern);
68 AccessFlags |= (WeakFlag * IsWeak);
69 AccessFlags |= (DummyFlag * IsDummy);
70 }
71
72 /// Returns the block's descriptor.
73 const Descriptor *getDescriptor() const { return Desc; }
74 /// Checks if the block has any live pointers.
75 bool hasPointers() const { return Pointers; }
76 /// Checks if the block is extern.
77 bool isExtern() const { return AccessFlags & ExternFlag; }
78 /// Checks if the block has static storage duration.
79 bool isStatic() const { return IsStatic; }
80 /// Checks if the block is temporary.
81 bool isTemporary() const { return Desc->IsTemporary; }
82 bool isWeak() const { return AccessFlags & WeakFlag; }
83 bool isDynamic() const { return (DynAllocId != std::nullopt); }
84 bool isDummy() const { return AccessFlags & DummyFlag; }
85 bool isDead() const { return AccessFlags & DeadFlag; }
86 /// Returns the size of the block.
87 unsigned getSize() const { return Desc->getAllocSize(); }
88 /// Returns the declaration ID.
89 UnsignedOrNone getDeclID() const { return DeclID; }
90 /// Returns whether the data of this block has been initialized via
91 /// invoking the Ctor func.
92 bool isInitialized() const { return IsInitialized; }
93 /// The Evaluation ID this block was created in.
94 unsigned getEvalID() const { return EvalID; }
95
96 /// Returns a pointer to the stored data.
97 /// You are allowed to read Desc->getSize() bytes from this address.
98 std::byte *data() {
99 // rawData might contain metadata as well.
100 size_t DataOffset = Desc->getMetadataSize();
101 return rawData() + DataOffset;
102 }
103 const std::byte *data() const {
104 // rawData might contain metadata as well.
105 size_t DataOffset = Desc->getMetadataSize();
106 return rawData() + DataOffset;
107 }
108
109 /// Returns a pointer to the raw data, including metadata.
110 /// You are allowed to read Desc->getAllocSize() bytes from this address.
111 std::byte *rawData() {
112 return reinterpret_cast<std::byte *>(this) + sizeof(Block);
113 }
114 const std::byte *rawData() const {
115 return reinterpret_cast<const std::byte *>(this) + sizeof(Block);
116 }
117
118 template <typename T> T deref() const {
119 return *reinterpret_cast<const T *>(data());
120 }
121
122 /// Invokes the constructor.
123 void invokeCtor() {
124 assert(!IsInitialized);
125 std::memset(rawData(), 0, Desc->getAllocSize());
126 if (Desc->CtorFn) {
127 Desc->CtorFn(this, data(), Desc->IsConst, Desc->IsMutable,
128 Desc->IsVolatile,
129 /*isActive=*/true, /*InUnion=*/false, Desc);
130 }
131 IsInitialized = true;
132 }
133
134 /// Invokes the Destructor.
135 void invokeDtor() {
136 assert(IsInitialized);
137 if (Desc->DtorFn)
138 Desc->DtorFn(this, data(), Desc);
139 IsInitialized = false;
140 }
141
142 void dump() const { dump(llvm::errs()); }
143 void dump(llvm::raw_ostream &OS) const;
144
145 bool isAccessible() const { return AccessFlags == 0; }
146
147private:
148 friend class Pointer;
149 friend class DeadBlock;
150 friend class InterpState;
151 friend class DynamicAllocator;
152 friend class Program;
153
154 Block(unsigned EvalID, const Descriptor *Desc, bool IsExtern, bool IsStatic,
155 bool IsWeak, bool IsDummy, bool IsDead)
156 : Desc(Desc), EvalID(EvalID), IsStatic(IsStatic) {
157 assert(Desc);
158 AccessFlags |= (ExternFlag * IsExtern);
159 AccessFlags |= (DeadFlag * IsDead);
160 AccessFlags |= (WeakFlag * IsWeak);
161 AccessFlags |= (DummyFlag * IsDummy);
162 }
163
164 /// To be called by DynamicAllocator.
165 void setDynAllocId(unsigned ID) { DynAllocId = ID; }
166
167 /// Deletes a dead block at the end of its lifetime.
168 void cleanup();
169
170 /// Pointer chain management.
171 void addPointer(Pointer *P);
172 void removePointer(Pointer *P);
173 void replacePointer(Pointer *Old, Pointer *New);
174#ifndef NDEBUG
175 bool hasPointer(const Pointer *P) const;
176#endif
177
178 /// Pointer to the stack slot descriptor.
179 const Descriptor *Desc;
180 /// Start of the chain of pointers.
181 Pointer *Pointers = nullptr;
182 /// Unique identifier of the declaration.
183 UnsignedOrNone DeclID = std::nullopt;
184 const unsigned EvalID = ~0u;
185 /// Flag indicating if the block has static storage duration.
186 bool IsStatic = false;
187 /// Flag indicating if the block contents have been initialized
188 /// via invokeCtor.
189 bool IsInitialized = false;
190 /// Allocation ID for this dynamic allocation, if it is one.
191 UnsignedOrNone DynAllocId = std::nullopt;
192 /// AccessFlags containing IsExtern, IsDead, IsWeak, and IsDummy bits.
193 uint8_t AccessFlags = 0;
194};
195
196/// Descriptor for a dead block.
197///
198/// Dead blocks are chained in a double-linked list to deallocate them
199/// whenever pointers become dead.
200class DeadBlock final {
201public:
202 /// Copies the block.
203 DeadBlock(DeadBlock *&Root, Block *Blk);
204
205 /// Returns a pointer to the stored data.
206 std::byte *data() { return B.data(); }
207 std::byte *rawData() { return B.rawData(); }
208
209private:
210 friend class Block;
211 friend class InterpState;
212
213 void free();
214
215 /// Root pointer of the list.
216 DeadBlock *&Root;
217 /// Previous block in the list.
218 DeadBlock *Prev;
219 /// Next block in the list.
220 DeadBlock *Next;
221
222 /// Actual block storing data and tracking pointers.
223 Block B;
224};
225
226} // namespace interp
227} // namespace clang
228
229#endif
StringRef P
static char ID
Definition: Arena.cpp:183
bool IsStatic
Definition: Format.cpp:3189
const CFGBlock * Block
Definition: HTMLLogger.cpp:152
A memory block, either on the stack or in the heap.
Definition: InterpBlock.h:44
unsigned getSize() const
Returns the size of the block.
Definition: InterpBlock.h:87
void invokeDtor()
Invokes the Destructor.
Definition: InterpBlock.h:135
bool isExtern() const
Checks if the block is extern.
Definition: InterpBlock.h:77
friend class Pointer
Definition: InterpBlock.h:148
std::byte * data()
Returns a pointer to the stored data.
Definition: InterpBlock.h:98
const Descriptor * getDescriptor() const
Returns the block's descriptor.
Definition: InterpBlock.h:73
Block(unsigned EvalID, const Descriptor *Desc, bool IsStatic=false, bool IsExtern=false, bool IsWeak=false, bool IsDummy=false)
Definition: InterpBlock.h:63
const std::byte * rawData() const
Definition: InterpBlock.h:114
bool isDead() const
Definition: InterpBlock.h:85
void invokeCtor()
Invokes the constructor.
Definition: InterpBlock.h:123
bool isStatic() const
Checks if the block has static storage duration.
Definition: InterpBlock.h:79
Block(unsigned EvalID, UnsignedOrNone DeclID, const Descriptor *Desc, bool IsStatic=false, bool IsExtern=false, bool IsWeak=false, bool IsDummy=false)
Creates a new block.
Definition: InterpBlock.h:53
bool isTemporary() const
Checks if the block is temporary.
Definition: InterpBlock.h:81
std::byte * rawData()
Returns a pointer to the raw data, including metadata.
Definition: InterpBlock.h:111
const std::byte * data() const
Definition: InterpBlock.h:103
bool isInitialized() const
Returns whether the data of this block has been initialized via invoking the Ctor func.
Definition: InterpBlock.h:92
bool isDynamic() const
Definition: InterpBlock.h:83
UnsignedOrNone getDeclID() const
Returns the declaration ID.
Definition: InterpBlock.h:89
void dump() const
Definition: InterpBlock.h:142
bool isDummy() const
Definition: InterpBlock.h:84
unsigned getEvalID() const
The Evaluation ID this block was created in.
Definition: InterpBlock.h:94
bool isWeak() const
Definition: InterpBlock.h:82
bool isAccessible() const
Definition: InterpBlock.h:145
bool hasPointers() const
Checks if the block has any live pointers.
Definition: InterpBlock.h:75
Descriptor for a dead block.
Definition: InterpBlock.h:200
std::byte * data()
Returns a pointer to the stored data.
Definition: InterpBlock.h:206
Manages dynamic memory allocations done during bytecode interpretation.
Interpreter context.
Definition: InterpState.h:43
A pointer to a memory block, live or dead.
Definition: Pointer.h:90
The program contains and links the bytecode for all functions.
Definition: Program.h:36
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:34
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
Describes a memory block created by an allocation site.
Definition: Descriptor.h:122
const bool IsConst
Flag indicating if the block is mutable.
Definition: Descriptor.h:161
unsigned getAllocSize() const
Returns the allocated size, including metadata.
Definition: Descriptor.h:242
const BlockDtorFn DtorFn
Definition: Descriptor.h:173
const BlockCtorFn CtorFn
Storage management methods.
Definition: Descriptor.h:172
unsigned getMetadataSize() const
Returns the size of the metadata.
Definition: Descriptor.h:246
const bool IsMutable
Flag indicating if a field is mutable.
Definition: Descriptor.h:163
const bool IsTemporary
Flag indicating if the block is a temporary.
Definition: Descriptor.h:165