clang 23.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/Support/Allocator.h"
23#include <vector>
24
25namespace clang {
26class RecordDecl;
27class Expr;
28class FunctionDecl;
29class StringLiteral;
30class VarDecl;
31
32namespace interp {
33class Context;
34
35/// The program contains and links the bytecode for all functions.
36class Program final {
37public:
38 Program(Context &Ctx) : Ctx(Ctx) {}
39
41 // Manually destroy all the blocks. They are almost all harmless,
42 // but primitive arrays might have an InitMap* heap allocated and
43 // that needs to be freed.
44 for (Global *G : Globals)
45 if (Block *B = G->block(); B->isInitialized())
46 B->invokeDtor();
47
48 // Records might actually allocate memory themselves, but they
49 // are allocated using a BumpPtrAllocator. Call their desctructors
50 // here manually so they are properly freeing their resources.
51 for (auto RecordPair : Records) {
52 if (Record *R = RecordPair.second)
53 R->~Record();
54 }
55 }
56
57 const Context &getContext() const { return Ctx; }
58
59 /// Marshals a native pointer to an ID for embedding in bytecode.
60 unsigned getOrCreateNativePointer(const void *Ptr);
61
62 /// Returns the value of a marshalled native pointer.
63 const void *getNativePointer(unsigned Idx) const;
64
65 /// Emits a string literal among global data.
66 unsigned createGlobalString(const StringLiteral *S,
67 const Expr *Base = nullptr);
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 bool isGlobalInitialized(unsigned Index) const {
79 return getPtrGlobal(Index).isInitialized();
80 }
81
82 /// Finds a global's index.
85
86 /// Returns or creates a global an creates an index to it.
88 const Expr *Init = nullptr);
89
90 /// Returns or creates a dummy value for unknown declarations.
91 unsigned getOrCreateDummy(const DeclTy &D);
92
93 /// Creates a global and returns its index.
95
96 /// Creates a global from a lifetime-extended temporary.
97 UnsignedOrNone createGlobal(const Expr *E, QualType ExprType);
98
99 /// Creates a new function from a code range.
100 template <typename... Ts>
101 Function *createFunction(const FunctionDecl *Def, Ts &&...Args) {
102 Def = Def->getCanonicalDecl();
103 auto *Func = new Function(*this, Def, std::forward<Ts>(Args)...);
104 Funcs.insert({Def, std::unique_ptr<Function>(Func)});
105 return Func;
106 }
107 /// Creates an anonymous function.
108 template <typename... Ts> Function *createFunction(Ts &&...Args) {
109 auto *Func = new Function(*this, std::forward<Ts>(Args)...);
110 AnonFuncs.emplace_back(Func);
111 return Func;
112 }
113
114 /// Returns a function.
116
117 /// Returns a record or creates one if it does not exist.
119
120 /// Creates a descriptor for a primitive type.
122 const Type *SourceTy = nullptr,
123 Descriptor::MetadataSize MDSize = std::nullopt,
124 bool IsConst = false, bool IsTemporary = false,
125 bool IsMutable = false,
126 bool IsVolatile = false) {
127 return allocateDescriptor(D, SourceTy, T, MDSize, IsConst, IsTemporary,
128 IsMutable, IsVolatile);
129 }
130
131 /// Creates a descriptor for a composite type.
132 Descriptor *createDescriptor(const DeclTy &D, const Type *Ty,
133 Descriptor::MetadataSize MDSize = std::nullopt,
134 bool IsConst = false, bool IsTemporary = false,
135 bool IsMutable = false, bool IsVolatile = false,
136 const Expr *Init = nullptr);
137
138 void *Allocate(size_t Size, unsigned Align = 8) const {
139 return Allocator.Allocate(Size, Align);
140 }
141 template <typename T> T *Allocate(size_t Num = 1) const {
142 return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
143 }
144 void Deallocate(void *Ptr) const {}
145
146 /// Context to manage declaration lifetimes.
147 class DeclScope {
148 public:
149 DeclScope(Program &P) : P(P), PrevDecl(P.CurrentDeclaration) {
150 ++P.LastDeclaration;
151 P.CurrentDeclaration = P.LastDeclaration;
152 }
153 ~DeclScope() { P.CurrentDeclaration = PrevDecl; }
154
155 private:
156 Program &P;
157 unsigned PrevDecl;
158 };
159
160 /// Returns the current declaration ID.
162 if (CurrentDeclaration == NoDeclaration)
163 return std::nullopt;
164 return CurrentDeclaration;
165 }
166
167private:
168 friend class DeclScope;
169
170 UnsignedOrNone createGlobal(const DeclTy &D, QualType Ty, bool IsStatic,
171 bool IsExtern, bool IsWeak,
172 const Expr *Init = nullptr);
173
174 /// Reference to the VM context.
175 Context &Ctx;
176 /// Mapping from decls to cached bytecode functions.
177 llvm::DenseMap<const FunctionDecl *, std::unique_ptr<Function>> Funcs;
178 /// List of anonymous functions.
179 std::vector<std::unique_ptr<Function>> AnonFuncs;
180
181 /// Native pointers referenced by bytecode.
182 std::vector<const void *> NativePointers;
183 /// Cached native pointer indices.
184 llvm::DenseMap<const void *, unsigned> NativePointerIndices;
185
186 /// Custom allocator for global storage.
187 using PoolAllocTy = llvm::BumpPtrAllocator;
188
189 /// Descriptor + storage for a global object.
190 ///
191 /// Global objects never go out of scope, thus they do not track pointers.
192 class Global {
193 public:
194 /// Create a global descriptor for string literals.
195 template <typename... Tys>
196 Global(Tys... Args) : B(std::forward<Tys>(Args)...) {}
197
198 /// Allocates the global in the pool, reserving storate for data.
199 void *operator new(size_t Meta, PoolAllocTy &Alloc, size_t Data) {
200 return Alloc.Allocate(Meta + Data, alignof(void *));
201 }
202
203 /// Return a pointer to the data.
204 std::byte *data() { return B.data(); }
205 /// Return a pointer to the block.
206 Block *block() { return &B; }
207 const Block *block() const { return &B; }
208
209 private:
210 Block B;
211 };
212
213 /// Allocator for globals.
214 mutable PoolAllocTy Allocator;
215
216 /// Global objects.
217 std::vector<Global *> Globals;
218 /// Cached global indices.
219 llvm::DenseMap<const void *, unsigned> GlobalIndices;
220
221 /// Mapping from decls to record metadata.
222 llvm::DenseMap<const RecordDecl *, Record *> Records;
223
224 /// Dummy parameter to generate pointers from.
225 llvm::DenseMap<const void *, unsigned> DummyVariables;
226
227 /// Creates a new descriptor.
228 template <typename... Ts> Descriptor *allocateDescriptor(Ts &&...Args) {
229 return new (Allocator) Descriptor(std::forward<Ts>(Args)...);
230 }
231
232 /// No declaration ID.
233 static constexpr unsigned NoDeclaration = ~0u;
234 /// Last declaration ID.
235 unsigned LastDeclaration = 0;
236 /// Current declaration ID.
237 unsigned CurrentDeclaration = NoDeclaration;
238
239public:
240 /// Dumps the disassembled bytecode to \c llvm::errs().
241 void dump() const;
242 void dump(llvm::raw_ostream &OS) const;
243};
244
245} // namespace interp
246} // namespace clang
247
248inline void *operator new(size_t Bytes, const clang::interp::Program &C,
249 size_t Alignment = 8) {
250 return C.Allocate(Bytes, Alignment);
251}
252
253inline void operator delete(void *Ptr, const clang::interp::Program &C,
254 size_t) {
255 C.Deallocate(Ptr);
256}
257inline void *operator new[](size_t Bytes, const clang::interp::Program &C,
258 size_t Alignment = 8) {
259 return C.Allocate(Bytes, Alignment);
260}
261
262#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:2013
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:3715
A (possibly-)qualified type.
Definition TypeBase.h:937
Represents a struct/union/class.
Definition Decl.h:4338
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1802
The base class of the type hierarchy.
Definition TypeBase.h:1871
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:924
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:97
bool isInitialized() const
Checks if an object was initialized.
Definition Pointer.cpp:443
Context to manage declaration lifetimes.
Definition Program.h:147
The program contains and links the bytecode for all functions.
Definition Program.h:36
void * Allocate(size_t Size, unsigned Align=8) const
Definition Program.h:138
Function * getFunction(const FunctionDecl *F)
Returns a function.
Definition Program.cpp:281
Block * getGlobal(unsigned Idx)
Returns the value of a global.
Definition Program.h:73
const Context & getContext() const
Definition Program.h:57
UnsignedOrNone getOrCreateGlobal(const ValueDecl *VD, const Expr *Init=nullptr)
Returns or creates a global an creates an index to it.
Definition Program.cpp:113
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:101
bool isGlobalInitialized(unsigned Index) const
Definition Program.h:78
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
Definition Program.cpp:82
unsigned getOrCreateDummy(const DeclTy &D)
Returns or creates a dummy value for unknown declarations.
Definition Program.cpp:125
void dump() const
Dumps the disassembled bytecode to llvm::errs().
Definition Disasm.cpp:286
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:141
void Deallocate(void *Ptr) const
Definition Program.h:144
UnsignedOrNone createGlobal(const ValueDecl *VD, const Expr *Init)
Creates a global and returns its index.
Definition Program.cpp:171
Descriptor * createDescriptor(const DeclTy &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:121
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:108
UnsignedOrNone getCurrentDecl() const
Returns the current declaration ID.
Definition Program.h:161
Record * getOrCreateRecord(const RecordDecl *RD)
Returns a record or creates one if it does not exist.
Definition Program.cpp:288
Program(Context &Ctx)
Definition Program.h:38
Structure/Class descriptor.
Definition Record.h:25
Code completion in a.
llvm::PointerUnion< const Decl *, const Expr * > DeclTy
Definition Descriptor.h:29
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:3734
bool Init(InterpState &S, CodePtr OpPC)
Definition Interp.h:2271
The JSON file list parser is used to communicate input to InstallAPI.
OptionalUnsigned< unsigned > UnsignedOrNone
Describes a memory block created by an allocation site.
Definition Descriptor.h:123
std::optional< unsigned > MetadataSize
Definition Descriptor.h:144