1 //===--- Program.h - Bytecode for the constexpr VM --------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Defines a program which organises and links multiple bytecode functions.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_AST_INTERP_PROGRAM_H
14 #define LLVM_CLANG_AST_INTERP_PROGRAM_H
23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/ADT/PointerUnion.h"
25 #include "llvm/ADT/StringRef.h"
26 #include "llvm/Support/Allocator.h"
42 /// The program contains and links the bytecode for all functions.
45 Program(Context &Ctx) : Ctx(Ctx) {}
47 /// Emits a string literal among global data.
48 unsigned createGlobalString(const StringLiteral *S);
50 /// Returns a pointer to a global.
51 Pointer getPtrGlobal(unsigned Idx);
53 /// Returns the value of a global.
54 Block *getGlobal(unsigned Idx) {
55 assert(Idx < Globals.size());
56 return Globals[Idx]->block();
59 /// Finds a global's index.
60 llvm::Optional<unsigned> getGlobal(const ValueDecl *VD);
62 /// Returns or creates a global an creates an index to it.
63 llvm::Optional<unsigned> getOrCreateGlobal(const ValueDecl *VD);
65 /// Returns or creates a dummy value for parameters.
66 llvm::Optional<unsigned> getOrCreateDummy(const ParmVarDecl *PD);
68 /// Creates a global and returns its index.
69 llvm::Optional<unsigned> createGlobal(const ValueDecl *VD);
71 /// Creates a global from a lifetime-extended temporary.
72 llvm::Optional<unsigned> createGlobal(const Expr *E);
74 /// Creates a new function from a code range.
75 template <typename... Ts>
76 Function *createFunction(const FunctionDecl *Def, Ts &&... Args) {
77 auto *Func = new Function(*this, Def, std::forward<Ts>(Args)...);
78 Funcs.insert({Def, std::unique_ptr<Function>(Func)});
81 /// Creates an anonymous function.
82 template <typename... Ts>
83 Function *createFunction(Ts &&... Args) {
84 auto *Func = new Function(*this, std::forward<Ts>(Args)...);
85 AnonFuncs.emplace_back(Func);
89 /// Returns a function.
90 Function *getFunction(const FunctionDecl *F);
92 /// Returns a pointer to a function if it exists and can be compiled.
93 /// If a function couldn't be compiled, an error is returned.
94 /// If a function was not yet defined, a null pointer is returned.
95 llvm::Expected<Function *> getOrCreateFunction(const FunctionDecl *F);
97 /// Returns a record or creates one if it does not exist.
98 Record *getOrCreateRecord(const RecordDecl *RD);
100 /// Creates a descriptor for a primitive type.
101 Descriptor *createDescriptor(const DeclTy &D, PrimType Type,
102 bool IsConst = false,
103 bool IsTemporary = false,
104 bool IsMutable = false) {
105 return allocateDescriptor(D, Type, IsConst, IsTemporary, IsMutable);
108 /// Creates a descriptor for a composite type.
109 Descriptor *createDescriptor(const DeclTy &D, const Type *Ty,
110 bool IsConst = false, bool IsTemporary = false,
111 bool IsMutable = false);
113 /// Context to manage declaration lifetimes.
116 DeclScope(Program &P, const VarDecl *VD) : P(P) { P.startDeclaration(VD); }
117 ~DeclScope() { P.endDeclaration(); }
123 /// Returns the current declaration ID.
124 llvm::Optional<unsigned> getCurrentDecl() const {
125 if (CurrentDeclaration == NoDeclaration)
126 return llvm::Optional<unsigned>{};
127 return LastDeclaration;
131 friend class DeclScope;
133 llvm::Optional<unsigned> createGlobal(const DeclTy &D, QualType Ty,
134 bool IsStatic, bool IsExtern);
136 /// Reference to the VM context.
138 /// Mapping from decls to cached bytecode functions.
139 llvm::DenseMap<const FunctionDecl *, std::unique_ptr<Function>> Funcs;
140 /// List of anonymous functions.
141 std::vector<std::unique_ptr<Function>> AnonFuncs;
143 /// Function relocation locations.
144 llvm::DenseMap<const FunctionDecl *, std::vector<unsigned>> Relocs;
146 /// Custom allocator for global storage.
147 using PoolAllocTy = llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator>;
149 /// Descriptor + storage for a global object.
151 /// Global objects never go out of scope, thus they do not track pointers.
154 /// Create a global descriptor for string literals.
155 template <typename... Tys>
156 Global(Tys... Args) : B(std::forward<Tys>(Args)...) {}
158 /// Allocates the global in the pool, reserving storate for data.
159 void *operator new(size_t Meta, PoolAllocTy &Alloc, size_t Data) {
160 return Alloc.Allocate(Meta + Data, alignof(void *));
163 /// Return a pointer to the data.
164 char *data() { return B.data(); }
165 /// Return a pointer to the block.
166 Block *block() { return &B; }
169 /// Required metadata - does not actually track pointers.
173 /// Allocator for globals.
174 PoolAllocTy Allocator;
177 std::vector<Global *> Globals;
178 /// Cached global indices.
179 llvm::DenseMap<const void *, unsigned> GlobalIndices;
181 /// Mapping from decls to record metadata.
182 llvm::DenseMap<const RecordDecl *, Record *> Records;
184 /// Dummy parameter to generate pointers from.
185 llvm::DenseMap<const ParmVarDecl *, unsigned> DummyParams;
187 /// Creates a new descriptor.
188 template <typename... Ts>
189 Descriptor *allocateDescriptor(Ts &&... Args) {
190 return new (Allocator) Descriptor(std::forward<Ts>(Args)...);
193 /// No declaration ID.
194 static constexpr unsigned NoDeclaration = (unsigned)-1;
195 /// Last declaration ID.
196 unsigned LastDeclaration = 0;
197 /// Current declaration ID.
198 unsigned CurrentDeclaration = NoDeclaration;
200 /// Starts evaluating a declaration.
201 void startDeclaration(const VarDecl *Decl) {
202 LastDeclaration += 1;
203 CurrentDeclaration = LastDeclaration;
206 /// Ends a global declaration.
207 void endDeclaration() {
208 CurrentDeclaration = NoDeclaration;
212 /// Dumps the disassembled bytecode to \c llvm::errs().
214 void dump(llvm::raw_ostream &OS) const;
217 } // namespace interp