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 "Reflect.h"
22#include "Source.h"
23#include "llvm/ADT/DenseMap.h"
24#include "llvm/Support/Allocator.h"
25#include <vector>
26
27namespace clang {
28class RecordDecl;
29class Expr;
30class FunctionDecl;
31class StringLiteral;
32class VarDecl;
33
34namespace interp {
35class Context;
36
37/// The program contains and links the bytecode for all functions.
38class Program final {
39public:
40 Program(Context &Ctx) : Ctx(Ctx) {}
41
43 // Manually destroy all the blocks. They are almost all harmless,
44 // but primitive arrays might have an InitMap* heap allocated and
45 // that needs to be freed.
46 for (Block *G : Globals)
47 if (G->isInitialized())
48 G->invokeDtor();
49
50 // Records might actually allocate memory themselves, but they
51 // are allocated using a BumpPtrAllocator. Call their desctructors
52 // here manually so they are properly freeing their resources.
53 for (const auto &RecordPair : Records) {
54 if (Record *R = RecordPair.second)
55 R->~Record();
56 }
57
58 for (Function *F : Funcs.values())
59 F->~Function();
60 }
61
62 const Context &getContext() const { return Ctx; }
63
64 /// Returns a pointer to a global.
65 Pointer getPtrGlobal(unsigned Idx) const;
66
67 /// Returns the value of a global.
68 Block *getGlobal(unsigned Idx) {
69 assert(Idx < Globals.size());
70 return Globals[Idx];
71 }
72
73 bool isGlobalInitialized(unsigned Index) const {
74 return getPtrGlobal(Index).isInitialized();
75 }
76
77 /// Finds a global's index.
80
81 /// Returns or creates a global an creates an index to it.
83 const Expr *Init = nullptr);
84
85 /// Creates a global and returns its index.
87 bool IsConstexprUnknown = false,
88 bool CanBeExtern = true);
89
90 /// Creates a global from a lifetime-extended temporary.
91 UnsignedOrNone createGlobal(const Expr *E, QualType ExprType);
92
93 /// Creates a new function from a code range.
94 template <typename... Ts>
95 Function *createFunction(const FunctionDecl *Def, Ts &&...Args) {
96 Def = Def->getFirstDecl();
97 auto *Func = new (Allocate(sizeof(Function)))
98 Function(Def, std::forward<Ts>(Args)...);
99 Funcs.insert({Def, Func});
100 return Func;
101 }
102 /// Creates an anonymous function.
103 template <typename... Ts> Function *createFunction(Ts &&...Args) {
104 auto *Func = new Function(std::forward<Ts>(Args)...);
105 AnonFuncs.emplace_back(Func);
106 return Func;
107 }
108
109 /// Returns a function.
111
112 /// Returns a record or creates one if it does not exist.
114
115 /// Creates a descriptor for a primitive type.
117 const Type *SourceTy = nullptr,
118 bool IsConst = false, bool IsTemporary = false,
119 bool IsMutable = false,
120 bool IsVolatile = false) {
121 return allocateDescriptor(D, SourceTy, T, IsConst, IsTemporary, IsMutable,
122 IsVolatile);
123 }
124
125 /// Creates a descriptor for a composite type.
127 bool IsConst = false, bool IsTemporary = false,
128 bool IsMutable = false, bool IsVolatile = false,
129 const Expr *Init = nullptr);
130
131 void *Allocate(size_t Size, unsigned Align = 8) {
132 return Allocator.Allocate(Size, Align);
133 }
134 template <typename T> T *Allocate(size_t Num = 1) {
135 return static_cast<T *>(Allocate(Num * sizeof(T), alignof(T)));
136 }
137 void Deallocate(void *Ptr) const {}
138
139 /// Context to manage declaration lifetimes.
140 class DeclScope {
141 public:
142 DeclScope(Program &P) : P(P), PrevDecl(P.CurrentDeclaration) {
143 ++P.LastDeclaration;
144 P.CurrentDeclaration = P.LastDeclaration;
145 }
146 ~DeclScope() { P.CurrentDeclaration = PrevDecl; }
147
148 private:
149 Program &P;
150 unsigned PrevDecl;
151 };
152
153 /// Returns the current declaration ID.
155 if (CurrentDeclaration == NoDeclaration)
156 return std::nullopt;
157 return CurrentDeclaration;
158 }
159
160private:
161 friend class DeclScope;
162
163 UnsignedOrNone createGlobal(DeclOrExpr D, QualType Ty, bool IsExtern,
164 bool IsWeak, bool IsConstexprUnknown,
165 const Expr *Init = nullptr);
166
167 /// Reference to the VM context.
168 Context &Ctx;
169 /// Mapping from decls to cached bytecode functions.
170 llvm::DenseMap<const FunctionDecl *, Function *> Funcs;
171 /// List of anonymous functions.
172 std::vector<std::unique_ptr<Function>> AnonFuncs;
173
174 /// Allocator for globals.
175 llvm::BumpPtrAllocator Allocator;
176
177 /// Global objects.
178 std::vector<Block *> Globals;
179 /// Cached global indices.
180 llvm::DenseMap<const void *, unsigned> GlobalIndices;
181
182 /// Mapping from decls to record metadata.
183 llvm::DenseMap<const RecordDecl *, Record *> Records;
184
185 /// Creates a new descriptor.
186 template <typename... Ts> Descriptor *allocateDescriptor(Ts &&...Args) {
187 return new (Allocator) Descriptor(std::forward<Ts>(Args)...);
188 }
189
190 /// No declaration ID.
191 static constexpr unsigned NoDeclaration = ~0u;
192 /// Last declaration ID.
193 unsigned LastDeclaration = 0;
194 /// Current declaration ID.
195 unsigned CurrentDeclaration = NoDeclaration;
196
197public:
198 /// Dumps the disassembled bytecode to \c llvm::errs().
199 void dump() const;
200 void dump(llvm::raw_ostream &OS) const;
201};
202
203} // namespace interp
204} // namespace clang
205
206inline void *operator new(size_t Bytes, clang::interp::Program &C,
207 size_t Alignment = 8) {
208 return C.Allocate(Bytes, Alignment);
209}
210
211inline void operator delete(void *Ptr, clang::interp::Program &C, size_t) {
212 C.Deallocate(Ptr);
213}
214inline void *operator new[](size_t Bytes, clang::interp::Program &C,
215 size_t Alignment = 8) {
216 return C.Allocate(Bytes, Alignment);
217}
218
219#endif
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
This represents one expression.
Definition Expr.h:114
Represents a function declaration or definition.
Definition Decl.h:2082
A (possibly-)qualified type.
Definition TypeBase.h:938
Represents a struct/union/class.
Definition Decl.h:4506
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:1844
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:714
Represents a variable declaration or definition.
Definition Decl.h:934
A memory block, either on the stack or in the heap.
Definition Block.h:68
Holds all information required to evaluate constexpr code in a module.
Definition Context.h:49
Bytecode function.
Definition Function.h:98
A pointer to a memory block, live or dead.
Definition Pointer.h:547
bool isInitialized() const
Checks if an object was initialized.
Definition Pointer.h:1232
Context to manage declaration lifetimes.
Definition Program.h:140
The program contains and links the bytecode for all functions.
Definition Program.h:38
Function * getFunction(const FunctionDecl *F)
Returns a function.
Definition Program.cpp:190
Block * getGlobal(unsigned Idx)
Returns the value of a global.
Definition Program.h:68
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:116
T * Allocate(size_t Num=1)
Definition Program.h:134
const Context & getContext() const
Definition Program.h:62
UnsignedOrNone getOrCreateGlobal(const ValueDecl *VD, const Expr *Init=nullptr)
Returns or creates a global an creates an index to it.
Definition Program.cpp:69
UnsignedOrNone createGlobal(const ValueDecl *VD, const Expr *Init, bool IsConstexprUnknown=false, bool CanBeExtern=true)
Creates a global and returns its index.
Definition Program.cpp:81
Function * createFunction(const FunctionDecl *Def, Ts &&...Args)
Creates a new function from a code range.
Definition Program.h:95
bool isGlobalInitialized(unsigned Index) const
Definition Program.h:73
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
void Deallocate(void *Ptr) const
Definition Program.h:137
Function * createFunction(Ts &&...Args)
Creates an anonymous function.
Definition Program.h:103
UnsignedOrNone getCurrentDecl() const
Returns the current declaration ID.
Definition Program.h:154
Record * getOrCreateRecord(const RecordDecl *RD)
Returns a record or creates one if it does not exist.
Definition Program.cpp:197
Program(Context &Ctx)
Definition Program.h:40
void * Allocate(size_t Size, unsigned Align=8)
Definition Program.h:131
Structure/Class descriptor.
Definition Record.h:27
PrimType
Enumeration of the primitive types of the VM.
Definition PrimType.h:35
bool Init(InterpState &S, CodePtr OpPC)
Definition Interp.h:2381
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:126