clang 20.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 "Function.h"
17#include "Pointer.h"
18#include "PrimType.h"
19#include "Record.h"
20#include "Source.h"
21#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/PointerUnion.h"
23#include "llvm/ADT/StringRef.h"
24#include "llvm/Support/Allocator.h"
25#include <map>
26#include <vector>
27
28namespace clang {
29class RecordDecl;
30class Expr;
31class FunctionDecl;
32class StringLiteral;
33class VarDecl;
34
35namespace interp {
36class Context;
37
38/// The program contains and links the bytecode for all functions.
39class Program final {
40public:
41 Program(Context &Ctx) : Ctx(Ctx) {}
42
44 // Manually destroy all the blocks. They are almost all harmless,
45 // but primitive arrays might have an InitMap* heap allocated and
46 // that needs to be freed.
47 for (Global *G : Globals)
48 if (Block *B = G->block(); B->isInitialized())
49 B->invokeDtor();
50
51 // Records might actually allocate memory themselves, but they
52 // are allocated using a BumpPtrAllocator. Call their desctructors
53 // here manually so they are properly freeing their resources.
54 for (auto RecordPair : Records) {
55 if (Record *R = RecordPair.second)
56 R->~Record();
57 }
58 }
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);
65
66 /// Emits a string literal among global data.
67 unsigned createGlobalString(const StringLiteral *S);
68
69 /// Returns a pointer to a global.
70 Pointer getPtrGlobal(unsigned Idx) const;
71
72 /// Returns the value of a global.
73 Block *getGlobal(unsigned Idx) {
74 assert(Idx < Globals.size());
75 return Globals[Idx]->block();
76 }
77
78 /// Finds a global's index.
79 std::optional<unsigned> getGlobal(const ValueDecl *VD);
80 std::optional<unsigned> getGlobal(const Expr *E);
81
82 /// Returns or creates a global an creates an index to it.
83 std::optional<unsigned> getOrCreateGlobal(const ValueDecl *VD,
84 const Expr *Init = nullptr);
85
86 /// Returns or creates a dummy value for unknown declarations.
87 std::optional<unsigned> getOrCreateDummy(const ValueDecl *VD);
88
89 /// Creates a global and returns its index.
90 std::optional<unsigned> createGlobal(const ValueDecl *VD, const Expr *Init);
91
92 /// Creates a global from a lifetime-extended temporary.
93 std::optional<unsigned> createGlobal(const Expr *E);
94
95 /// Creates a new function from a code range.
96 template <typename... Ts>
97 Function *createFunction(const FunctionDecl *Def, Ts &&...Args) {
98 Def = Def->getCanonicalDecl();
99 auto *Func = new Function(*this, Def, std::forward<Ts>(Args)...);
100 Funcs.insert({Def, std::unique_ptr<Function>(Func)});
101 return Func;
102 }
103 /// Creates an anonymous function.
104 template <typename... Ts> Function *createFunction(Ts &&...Args) {
105 auto *Func = new Function(*this, 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 Descriptor::MetadataSize MDSize = std::nullopt,
119 bool IsConst = false, bool IsTemporary = false,
120 bool IsMutable = false) {
121 return allocateDescriptor(D, Type, MDSize, IsConst, IsTemporary, IsMutable);
122 }
123
124 /// Creates a descriptor for a composite type.
125 Descriptor *createDescriptor(const DeclTy &D, const Type *Ty,
126 Descriptor::MetadataSize MDSize = std::nullopt,
127 bool IsConst = false, bool IsTemporary = false,
128 bool IsMutable = false,
129 const Expr *Init = nullptr);
130
131 /// Context to manage declaration lifetimes.
132 class DeclScope {
133 public:
134 DeclScope(Program &P, const ValueDecl *VD) : P(P) {
135 P.startDeclaration(VD);
136 }
137 ~DeclScope() { P.endDeclaration(); }
138
139 private:
140 Program &P;
141 };
142
143 /// Returns the current declaration ID.
144 std::optional<unsigned> getCurrentDecl() const {
145 if (CurrentDeclaration == NoDeclaration)
146 return std::optional<unsigned>{};
147 return LastDeclaration;
148 }
149
150private:
151 friend class DeclScope;
152
153 std::optional<unsigned> createGlobal(const DeclTy &D, QualType Ty,
154 bool IsStatic, bool IsExtern,
155 const Expr *Init = nullptr);
156
157 /// Reference to the VM context.
158 Context &Ctx;
159 /// Mapping from decls to cached bytecode functions.
160 llvm::DenseMap<const FunctionDecl *, std::unique_ptr<Function>> Funcs;
161 /// List of anonymous functions.
162 std::vector<std::unique_ptr<Function>> AnonFuncs;
163
164 /// Function relocation locations.
165 llvm::DenseMap<const FunctionDecl *, std::vector<unsigned>> Relocs;
166
167 /// Native pointers referenced by bytecode.
168 std::vector<const void *> NativePointers;
169 /// Cached native pointer indices.
170 llvm::DenseMap<const void *, unsigned> NativePointerIndices;
171
172 /// Custom allocator for global storage.
173 using PoolAllocTy = llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator>;
174
175 /// Descriptor + storage for a global object.
176 ///
177 /// Global objects never go out of scope, thus they do not track pointers.
178 class Global {
179 public:
180 /// Create a global descriptor for string literals.
181 template <typename... Tys>
182 Global(Tys... Args) : B(std::forward<Tys>(Args)...) {}
183
184 /// Allocates the global in the pool, reserving storate for data.
185 void *operator new(size_t Meta, PoolAllocTy &Alloc, size_t Data) {
186 return Alloc.Allocate(Meta + Data, alignof(void *));
187 }
188
189 /// Return a pointer to the data.
190 std::byte *data() { return B.data(); }
191 /// Return a pointer to the block.
192 Block *block() { return &B; }
193 const Block *block() const { return &B; }
194
195 private:
196 /// Required metadata - does not actually track pointers.
197 Block B;
198 };
199
200 /// Allocator for globals.
201 PoolAllocTy Allocator;
202
203 /// Global objects.
204 std::vector<Global *> Globals;
205 /// Cached global indices.
206 llvm::DenseMap<const void *, unsigned> GlobalIndices;
207
208 /// Mapping from decls to record metadata.
209 llvm::DenseMap<const RecordDecl *, Record *> Records;
210
211 /// Dummy parameter to generate pointers from.
212 llvm::DenseMap<const ValueDecl *, unsigned> DummyVariables;
213
214 /// Creates a new descriptor.
215 template <typename... Ts> Descriptor *allocateDescriptor(Ts &&...Args) {
216 return new (Allocator) Descriptor(std::forward<Ts>(Args)...);
217 }
218
219 /// No declaration ID.
220 static constexpr unsigned NoDeclaration = (unsigned)-1;
221 /// Last declaration ID.
222 unsigned LastDeclaration = 0;
223 /// Current declaration ID.
224 unsigned CurrentDeclaration = NoDeclaration;
225
226 /// Starts evaluating a declaration.
227 void startDeclaration(const ValueDecl *Decl) {
228 LastDeclaration += 1;
229 CurrentDeclaration = LastDeclaration;
230 }
231
232 /// Ends a global declaration.
233 void endDeclaration() { CurrentDeclaration = NoDeclaration; }
234
235public:
236 /// Dumps the disassembled bytecode to \c llvm::errs().
237 void dump() const;
238 void dump(llvm::raw_ostream &OS) const;
239};
240
241} // namespace interp
242} // namespace clang
243
244#endif
StringRef P
const Decl * D
Expr * E
bool IsStatic
Definition: Format.cpp:3013
const CFGBlock * Block
Definition: HTMLLogger.cpp:153
llvm::MachO::Records Records
Definition: MachO.h:40
This represents one expression.
Definition: Expr.h:110
Represents a function declaration or definition.
Definition: Decl.h:1932
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:3603
A (possibly-)qualified type.
Definition: Type.h:941
Represents a struct/union/class.
Definition: Decl.h:4145
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1778
The base class of the type hierarchy.
Definition: Type.h:1829
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:667
A memory block, either on the stack or in the heap.
Definition: InterpBlock.h:49
bool isInitialized() const
Returns whether the data of this block has been initialized via invoking the Ctor func.
Definition: InterpBlock.h:83
Holds all information required to evaluate constexpr code in a module.
Definition: Context.h:40
Bytecode function.
Definition: Function.h:77
A pointer to a memory block, live or dead.
Definition: Pointer.h:82
Context to manage declaration lifetimes.
Definition: Program.h:132
DeclScope(Program &P, const ValueDecl *VD)
Definition: Program.h:134
The program contains and links the bytecode for all functions.
Definition: Program.h:39
std::optional< unsigned > getOrCreateGlobal(const ValueDecl *VD, const Expr *Init=nullptr)
Returns or creates a global an creates an index to it.
Definition: Program.cpp:135
Function * getFunction(const FunctionDecl *F)
Returns a function.
Definition: Program.cpp:247
Block * getGlobal(unsigned Idx)
Returns the value of a global.
Definition: Program.h:73
std::optional< unsigned > createGlobal(const ValueDecl *VD, const Expr *Init)
Creates a global and returns its index.
Definition: Program.cpp:182
const void * getNativePointer(unsigned Idx)
Returns the value of a marshalled native pointer.
Definition: Program.cpp:32
Descriptor * createDescriptor(const DeclTy &D, PrimType Type, Descriptor::MetadataSize MDSize=std::nullopt, bool IsConst=false, bool IsTemporary=false, bool IsMutable=false)
Creates a descriptor for a primitive type.
Definition: Program.h:117
unsigned getOrCreateNativePointer(const void *Ptr)
Marshals a native pointer to an ID for embedding in bytecode.
Definition: Program.cpp:21
Function * createFunction(const FunctionDecl *Def, Ts &&...Args)
Creates a new function from a code range.
Definition: Program.h:97
unsigned createGlobalString(const StringLiteral *S)
Emits a string literal among global data.
Definition: Program.cpp:36
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
Definition: Program.cpp:104
void dump() const
Dumps the disassembled bytecode to llvm::errs().
Definition: Disasm.cpp:95
std::optional< unsigned > getCurrentDecl() const
Returns the current declaration ID.
Definition: Program.h:144
std::optional< unsigned > getOrCreateDummy(const ValueDecl *VD)
Returns or creates a dummy value for unknown declarations.
Definition: Program.cpp:147
Function * createFunction(Ts &&...Args)
Creates an anonymous function.
Definition: Program.h:104
Record * getOrCreateRecord(const RecordDecl *RD)
Returns a record or creates one if it does not exist.
Definition: Program.cpp:254
Program(Context &Ctx)
Definition: Program.h:41
Structure/Class descriptor.
Definition: Record.h:25
Code completion in a.
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:33
bool Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc)
Definition: Interp.h:2918
llvm::PointerUnion< const Decl *, const Expr * > DeclTy
Definition: Descriptor.h:28
The JSON file list parser is used to communicate input to InstallAPI.
Describes a memory block created by an allocation site.
Definition: Descriptor.h:111
std::optional< unsigned > MetadataSize
Definition: Descriptor.h:131