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
58 const Context &getContext() const { return Ctx; }
59
60 /// Marshals a native pointer to an ID for embedding in bytecode.
61 unsigned getOrCreateNativePointer(const void *Ptr);
62
63 /// Returns the value of a marshalled native pointer.
64 const void *getNativePointer(unsigned Idx) const;
65
66 /// Emits a string literal among global data.
67 unsigned createGlobalString(const StringLiteral *S,
68 const Expr *Base = nullptr);
69
70 /// Returns a pointer to a global.
71 Pointer getPtrGlobal(unsigned Idx) const;
72
73 /// Returns the value of a global.
74 Block *getGlobal(unsigned Idx) {
75 assert(Idx < Globals.size());
76 return Globals[Idx]->block();
77 }
78
79 bool isGlobalInitialized(unsigned Index) const {
80 return getPtrGlobal(Index).isInitialized();
81 }
82
83 /// Finds a global's index.
86
87 /// Returns or creates a global an creates an index to it.
89 const Expr *Init = nullptr);
90
91 /// Returns or creates a dummy value for unknown declarations.
92 unsigned getOrCreateDummy(DeclOrExpr D, bool IsConstexprUnknown = false);
93
94 /// Creates a global and returns its index.
96 bool IsConstexprUnknown = false);
97
98 /// Creates a global from a lifetime-extended temporary.
99 UnsignedOrNone createGlobal(const Expr *E, QualType ExprType);
100
101 /// Creates a new function from a code range.
102 template <typename... Ts>
103 Function *createFunction(const FunctionDecl *Def, Ts &&...Args) {
104 Def = Def->getCanonicalDecl();
105 auto *Func = new Function(*this, Def, std::forward<Ts>(Args)...);
106 Funcs.insert({Def, std::unique_ptr<Function>(Func)});
107 return Func;
108 }
109 /// Creates an anonymous function.
110 template <typename... Ts> Function *createFunction(Ts &&...Args) {
111 auto *Func = new Function(*this, std::forward<Ts>(Args)...);
112 AnonFuncs.emplace_back(Func);
113 return Func;
114 }
115
116 /// Returns a function.
118
119 /// Returns a record or creates one if it does not exist.
121
122 /// Creates a descriptor for a primitive type.
124 const Type *SourceTy = nullptr,
125 Descriptor::MetadataSize MDSize = std::nullopt,
126 bool IsConst = false, bool IsTemporary = false,
127 bool IsMutable = false,
128 bool IsVolatile = false) {
129 return allocateDescriptor(D, SourceTy, T, MDSize, IsConst, IsTemporary,
130 IsMutable, IsVolatile);
131 }
132
133 /// Creates a descriptor for a composite type.
135 Descriptor::MetadataSize MDSize = std::nullopt,
136 bool IsConst = false, bool IsTemporary = false,
137 bool IsMutable = false, bool IsVolatile = false,
138 const Expr *Init = nullptr);
139
140 void *Allocate(size_t Size, unsigned Align = 8) const {
141 return Allocator.Allocate(Size, Align);
142 }
143 template <typename T> T *Allocate(size_t Num = 1) const {
144 return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
145 }
146 void Deallocate(void *Ptr) const {}
147
148 /// Context to manage declaration lifetimes.
149 class DeclScope {
150 public:
151 DeclScope(Program &P) : P(P), PrevDecl(P.CurrentDeclaration) {
152 ++P.LastDeclaration;
153 P.CurrentDeclaration = P.LastDeclaration;
154 }
155 ~DeclScope() { P.CurrentDeclaration = PrevDecl; }
156
157 private:
158 Program &P;
159 unsigned PrevDecl;
160 };
161
162 /// Returns the current declaration ID.
164 if (CurrentDeclaration == NoDeclaration)
165 return std::nullopt;
166 return CurrentDeclaration;
167 }
168
169private:
170 friend class DeclScope;
171
172 UnsignedOrNone createGlobal(DeclOrExpr D, QualType Ty, bool IsStatic,
173 bool IsExtern, bool IsWeak,
174 bool IsConstexprUnknown,
175 const Expr *Init = nullptr);
176
177 /// Reference to the VM context.
178 Context &Ctx;
179 /// Mapping from decls to cached bytecode functions.
180 llvm::DenseMap<const FunctionDecl *, std::unique_ptr<Function>> Funcs;
181 /// List of anonymous functions.
182 std::vector<std::unique_ptr<Function>> AnonFuncs;
183
184 /// Native pointers referenced by bytecode.
185 std::vector<const void *> NativePointers;
186 /// Cached native pointer indices.
187 llvm::DenseMap<const void *, unsigned> NativePointerIndices;
188
189 /// Custom allocator for global storage.
190 using PoolAllocTy = llvm::BumpPtrAllocator;
191
192 /// Descriptor + storage for a global object.
193 ///
194 /// Global objects never go out of scope, thus they do not track pointers.
195 class Global {
196 public:
197 /// Create a global descriptor for string literals.
198 template <typename... Tys>
199 Global(Tys... Args) : B(std::forward<Tys>(Args)...) {}
200
201 /// Allocates the global in the pool, reserving storate for data.
202 void *operator new(size_t Meta, PoolAllocTy &Alloc, size_t Data) {
203 return Alloc.Allocate(Meta + Data, alignof(void *));
204 }
205
206 /// Return a pointer to the data.
207 std::byte *data() { return B.data(); }
208 /// Return a pointer to the block.
209 Block *block() { return &B; }
210 const Block *block() const { return &B; }
211
212 private:
213 Block B;
214 };
215
216 /// Allocator for globals.
217 mutable PoolAllocTy Allocator;
218
219 /// Global objects.
220 std::vector<Global *> Globals;
221 /// Cached global indices.
222 llvm::DenseMap<const void *, unsigned> GlobalIndices;
223
224 /// Mapping from decls to record metadata.
225 llvm::DenseMap<const RecordDecl *, Record *> Records;
226
227 /// Dummy parameter to generate pointers from.
228 llvm::DenseMap<const void *, unsigned> DummyVariables;
229
230 /// Creates a new descriptor.
231 template <typename... Ts> Descriptor *allocateDescriptor(Ts &&...Args) {
232 return new (Allocator) Descriptor(std::forward<Ts>(Args)...);
233 }
234
235 /// No declaration ID.
236 static constexpr unsigned NoDeclaration = ~0u;
237 /// Last declaration ID.
238 unsigned LastDeclaration = 0;
239 /// Current declaration ID.
240 unsigned CurrentDeclaration = NoDeclaration;
241
242public:
243 /// Dumps the disassembled bytecode to \c llvm::errs().
244 void dump() const;
245 void dump(llvm::raw_ostream &OS) const;
246};
247
248} // namespace interp
249} // namespace clang
250
251inline void *operator new(size_t Bytes, const clang::interp::Program &C,
252 size_t Alignment = 8) {
253 return C.Allocate(Bytes, Alignment);
254}
255
256inline void operator delete(void *Ptr, const clang::interp::Program &C,
257 size_t) {
258 C.Deallocate(Ptr);
259}
260inline void *operator new[](size_t Bytes, const clang::interp::Program &C,
261 size_t Alignment = 8) {
262 return C.Allocate(Bytes, Alignment);
263}
264
265#endif
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
This represents one expression.
Definition Expr.h:112
Represents a function declaration or definition.
Definition Decl.h:2058
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:3790
A (possibly-)qualified type.
Definition TypeBase.h:938
Represents a struct/union/class.
Definition Decl.h:4459
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1810
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:712
Represents a variable declaration or definition.
Definition Decl.h:932
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:44
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:92
Holds all information required to evaluate constexpr code in a module.
Definition Context.h:47
Bytecode function.
Definition Function.h:99
A pointer to a memory block, live or dead.
Definition Pointer.h:405
bool isInitialized() const
Checks if an object was initialized.
Definition Pointer.cpp:570
Context to manage declaration lifetimes.
Definition Program.h:149
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:179
void * Allocate(size_t Size, unsigned Align=8) const
Definition Program.h:140
Function * getFunction(const FunctionDecl *F)
Returns a function.
Definition Program.cpp:295
Block * getGlobal(unsigned Idx)
Returns the value of a global.
Definition Program.h:74
const Context & getContext() const
Definition Program.h:58
UnsignedOrNone getOrCreateGlobal(const ValueDecl *VD, const Expr *Init=nullptr)
Returns or creates a global an creates an index to it.
Definition Program.cpp:115
unsigned getOrCreateDummy(DeclOrExpr D, bool IsConstexprUnknown=false)
Returns or creates a dummy value for unknown declarations.
Definition Program.cpp:127
unsigned getOrCreateNativePointer(const void *Ptr)
Marshals a native pointer to an ID for embedding in bytecode.
Definition Program.cpp:22
Function * createFunction(const FunctionDecl *Def, Ts &&...Args)
Creates a new function from a code range.
Definition Program.h:103
bool isGlobalInitialized(unsigned Index) const
Definition Program.h:79
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
Definition Program.cpp:84
void dump() const
Dumps the disassembled bytecode to llvm::errs().
Definition Disasm.cpp:287
const void * getNativePointer(unsigned Idx) const
Returns the value of a marshalled native pointer.
Definition Program.cpp:31
T * Allocate(size_t Num=1) const
Definition Program.h:143
void Deallocate(void *Ptr) const
Definition Program.h:146
unsigned createGlobalString(const StringLiteral *S, const Expr *Base=nullptr)
Emits a string literal among global data.
Definition Program.cpp:35
Function * createFunction(Ts &&...Args)
Creates an anonymous function.
Definition Program.h:110
Descriptor * createDescriptor(DeclOrExpr D, PrimType T, const Type *SourceTy=nullptr, Descriptor::MetadataSize MDSize=std::nullopt, bool IsConst=false, bool IsTemporary=false, bool IsMutable=false, bool IsVolatile=false)
Creates a descriptor for a primitive type.
Definition Program.h:123
UnsignedOrNone getCurrentDecl() const
Returns the current declaration ID.
Definition Program.h:163
Record * getOrCreateRecord(const RecordDecl *RD)
Returns a record or creates one if it does not exist.
Definition Program.cpp:302
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:3872
bool Init(InterpState &S, CodePtr OpPC)
Definition Interp.h:2410
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
std::optional< unsigned > MetadataSize
Definition Descriptor.h:143