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