clang 24.0.0git
Program.h
Go to the documentation of this file.
1//===--- Program.h - Bytecode for the constexpr 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// Defines a program which organises and links multiple bytecode functions.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_INTERP_PROGRAM_H
14#define LLVM_CLANG_AST_INTERP_PROGRAM_H
15
16#include "DeclOrExpr.h"
17#include "Function.h"
18#include "Pointer.h"
19#include "PrimType.h"
20#include "Record.h"
21#include "Source.h"
22#include "llvm/ADT/DenseMap.h"
23#include "llvm/Support/Allocator.h"
24#include <vector>
25
26namespace clang {
27class RecordDecl;
28class Expr;
29class FunctionDecl;
30class StringLiteral;
31class VarDecl;
32
33namespace interp {
34class Context;
35
36/// The program contains and links the bytecode for all functions.
37class Program final {
38public:
39 Program(Context &Ctx) : Ctx(Ctx) {}
40
42 // Manually destroy all the blocks. They are almost all harmless,
43 // but primitive arrays might have an InitMap* heap allocated and
44 // that needs to be freed.
45 for (Global *G : Globals)
46 if (Block *B = G->block(); B->isInitialized())
47 B->invokeDtor();
48
49 // Records might actually allocate memory themselves, but they
50 // are allocated using a BumpPtrAllocator. Call their desctructors
51 // here manually so they are properly freeing their resources.
52 for (const auto &RecordPair : Records) {
53 if (Record *R = RecordPair.second)
54 R->~Record();
55 }
56
57 for (Function *F : Funcs.values())
58 F->~Function();
59 }
60
61 const Context &getContext() const { return Ctx; }
62
63 /// Returns a pointer to a global.
64 Pointer getPtrGlobal(unsigned Idx) const;
65
66 /// Returns the value of a global.
67 Block *getGlobal(unsigned Idx) {
68 assert(Idx < Globals.size());
69 return Globals[Idx]->block();
70 }
71
72 bool isGlobalInitialized(unsigned Index) const {
73 return getPtrGlobal(Index).isInitialized();
74 }
75
76 /// Finds a global's index.
79
80 /// Returns or creates a global an creates an index to it.
82 const Expr *Init = nullptr);
83
84 /// Returns or creates a dummy value for unknown declarations.
85 unsigned getOrCreateDummy(DeclOrExpr D, bool IsConstexprUnknown = false);
86
87 /// Creates a global and returns its index.
89 bool IsConstexprUnknown = false);
90
91 /// Creates a global from a lifetime-extended temporary.
92 UnsignedOrNone createGlobal(const Expr *E, QualType ExprType);
93
94 /// Creates a new function from a code range.
95 template <typename... Ts>
96 Function *createFunction(const FunctionDecl *Def, Ts &&...Args) {
97 Def = Def->getFirstDecl();
98 auto *Func = new (Allocate(sizeof(Function)))
99 Function(Def, std::forward<Ts>(Args)...);
100 Funcs.insert({Def, Func});
101 return Func;
102 }
103 /// Creates an anonymous function.
104 template <typename... Ts> Function *createFunction(Ts &&...Args) {
105 auto *Func = new Function(std::forward<Ts>(Args)...);
106 AnonFuncs.emplace_back(Func);
107 return Func;
108 }
109
110 /// Returns a function.
112
113 /// Returns a record or creates one if it does not exist.
115
116 /// Creates a descriptor for a primitive type.
118 const Type *SourceTy = nullptr,
119 bool IsConst = false, bool IsTemporary = false,
120 bool IsMutable = false,
121 bool IsVolatile = false) {
122 return allocateDescriptor(D, SourceTy, T, IsConst, IsTemporary, IsMutable,
123 IsVolatile);
124 }
125
126 /// Creates a descriptor for a composite type.
128 bool IsConst = false, bool IsTemporary = false,
129 bool IsMutable = false, bool IsVolatile = false,
130 const Expr *Init = nullptr);
131
132 void *Allocate(size_t Size, unsigned Align = 8) const {
133 return Allocator.Allocate(Size, Align);
134 }
135 template <typename T> T *Allocate(size_t Num = 1) const {
136 return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
137 }
138 void Deallocate(void *Ptr) const {}
139
140 /// Context to manage declaration lifetimes.
141 class DeclScope {
142 public:
143 DeclScope(Program &P) : P(P), PrevDecl(P.CurrentDeclaration) {
144 ++P.LastDeclaration;
145 P.CurrentDeclaration = P.LastDeclaration;
146 }
147 ~DeclScope() { P.CurrentDeclaration = PrevDecl; }
148
149 private:
150 Program &P;
151 unsigned PrevDecl;
152 };
153
154 /// Returns the current declaration ID.
156 if (CurrentDeclaration == NoDeclaration)
157 return std::nullopt;
158 return CurrentDeclaration;
159 }
160
161private:
162 friend class DeclScope;
163
164 UnsignedOrNone createGlobal(DeclOrExpr D, QualType Ty, bool IsStatic,
165 bool IsExtern, bool IsWeak,
166 bool IsConstexprUnknown,
167 const Expr *Init = nullptr);
168
169 /// Reference to the VM context.
170 Context &Ctx;
171 /// Mapping from decls to cached bytecode functions.
172 llvm::DenseMap<const FunctionDecl *, Function *> Funcs;
173 /// List of anonymous functions.
174 std::vector<std::unique_ptr<Function>> AnonFuncs;
175
176 /// Custom allocator for global storage.
177 using PoolAllocTy = llvm::BumpPtrAllocator;
178
179 /// Descriptor + storage for a global object.
180 ///
181 /// Global objects never go out of scope, thus they do not track pointers.
182 class Global {
183 public:
184 /// Create a global descriptor for string literals.
185 template <typename... Tys>
186 Global(Tys... Args) : B(std::forward<Tys>(Args)...) {}
187
188 /// Allocates the global in the pool, reserving storate for data.
189 void *operator new(size_t Meta, PoolAllocTy &Alloc, size_t Data) {
190 return Alloc.Allocate(Meta + Data, alignof(void *));
191 }
192
193 /// Return a pointer to the data.
194 std::byte *data() { return B.data(); }
195 /// Return a pointer to the block.
196 Block *block() { return &B; }
197 const Block *block() const { return &B; }
198
199 private:
200 Block B;
201 };
202
203 /// Allocator for globals.
204 mutable PoolAllocTy Allocator;
205
206 /// Global objects.
207 std::vector<Global *> Globals;
208 /// Cached global indices.
209 llvm::DenseMap<const void *, unsigned> GlobalIndices;
210
211 /// Mapping from decls to record metadata.
212 llvm::DenseMap<const RecordDecl *, Record *> Records;
213
214 /// Dummy parameter to generate pointers from.
215 llvm::DenseMap<const void *, unsigned> DummyVariables;
216
217 /// Creates a new descriptor.
218 template <typename... Ts> Descriptor *allocateDescriptor(Ts &&...Args) {
219 return new (Allocator) Descriptor(std::forward<Ts>(Args)...);
220 }
221
222 /// No declaration ID.
223 static constexpr unsigned NoDeclaration = ~0u;
224 /// Last declaration ID.
225 unsigned LastDeclaration = 0;
226 /// Current declaration ID.
227 unsigned CurrentDeclaration = NoDeclaration;
228
229public:
230 /// Dumps the disassembled bytecode to \c llvm::errs().
231 void dump() const;
232 void dump(llvm::raw_ostream &OS) const;
233};
234
235} // namespace interp
236} // namespace clang
237
238inline void *operator new(size_t Bytes, const clang::interp::Program &C,
239 size_t Alignment = 8) {
240 return C.Allocate(Bytes, Alignment);
241}
242
243inline void operator delete(void *Ptr, const clang::interp::Program &C,
244 size_t) {
245 C.Deallocate(Ptr);
246}
247inline void *operator new[](size_t Bytes, const clang::interp::Program &C,
248 size_t Alignment = 8) {
249 return C.Allocate(Bytes, Alignment);
250}
251
252#endif
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
This represents one expression.
Definition Expr.h:113
Represents a function declaration or definition.
Definition Decl.h:2059
A (possibly-)qualified type.
Definition TypeBase.h:938
Represents a struct/union/class.
Definition Decl.h:4460
decl_type * getFirstDecl()
Return the first declaration of this declaration or itself if this is the only declaration.
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1819
The base class of the type hierarchy.
Definition TypeBase.h:1879
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:713
Represents a variable declaration or definition.
Definition Decl.h:933
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:43
std::byte * data()
Returns a pointer to the stored data.
bool isInitialized() const
Returns whether the data of this block has been initialized via invoking the Ctor func.
Definition InterpBlock.h:98
Holds all information required to evaluate constexpr code in a module.
Definition Context.h:47
Bytecode function.
Definition Function.h:98
A pointer to a memory block, live or dead.
Definition Pointer.h:531
bool isInitialized() const
Checks if an object was initialized.
Definition Pointer.cpp:631
Context to manage declaration lifetimes.
Definition Program.h:141
The program contains and links the bytecode for all functions.
Definition Program.h:37
UnsignedOrNone createGlobal(const ValueDecl *VD, const Expr *Init, bool IsConstexprUnknown=false)
Creates a global and returns its index.
Definition Program.cpp:117
void * Allocate(size_t Size, unsigned Align=8) const
Definition Program.h:132
Function * getFunction(const FunctionDecl *F)
Returns a function.
Definition Program.cpp:234
Block * getGlobal(unsigned Idx)
Returns the value of a global.
Definition Program.h:67
Descriptor * createDescriptor(DeclOrExpr D, PrimType T, const Type *SourceTy=nullptr, bool IsConst=false, bool IsTemporary=false, bool IsMutable=false, bool IsVolatile=false)
Creates a descriptor for a primitive type.
Definition Program.h:117
const Context & getContext() const
Definition Program.h:61
UnsignedOrNone getOrCreateGlobal(const ValueDecl *VD, const Expr *Init=nullptr)
Returns or creates a global an creates an index to it.
Definition Program.cpp:51
unsigned getOrCreateDummy(DeclOrExpr D, bool IsConstexprUnknown=false)
Returns or creates a dummy value for unknown declarations.
Definition Program.cpp:63
Function * createFunction(const FunctionDecl *Def, Ts &&...Args)
Creates a new function from a code range.
Definition Program.h:96
bool isGlobalInitialized(unsigned Index) const
Definition Program.h:72
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
Definition Program.cpp:20
void dump() const
Dumps the disassembled bytecode to llvm::errs().
Definition Disasm.cpp:283
T * Allocate(size_t Num=1) const
Definition Program.h:135
void Deallocate(void *Ptr) const
Definition Program.h:138
Function * createFunction(Ts &&...Args)
Creates an anonymous function.
Definition Program.h:104
UnsignedOrNone getCurrentDecl() const
Returns the current declaration ID.
Definition Program.h:155
Record * getOrCreateRecord(const RecordDecl *RD)
Returns a record or creates one if it does not exist.
Definition Program.cpp:241
Program(Context &Ctx)
Definition Program.h:39
Structure/Class descriptor.
Definition Record.h:25
Code completion in a.
PrimType
Enumeration of the primitive types of the VM.
Definition PrimType.h:34
bool Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Definition Interp.h:3945
bool Init(InterpState &S, CodePtr OpPC)
Definition Interp.h:2413
Top level wrappers for InstallAPI frontend operations.
OptionalUnsigned< unsigned > UnsignedOrNone
const FunctionProtoType * T
Describes a memory block created by an allocation site.
Definition Descriptor.h:122