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 <map> 17 #include <vector> 18 #include "Function.h" 19 #include "Pointer.h" 20 #include "PrimType.h" 21 #include "Record.h" 22 #include "Source.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" 27 28 namespace clang { 29 class RecordDecl; 30 class Expr; 31 class FunctionDecl; 32 class Stmt; 33 class StringLiteral; 34 class VarDecl; 35 36 namespace interp { 37 class Context; 38 class State; 39 class Record; 40 class Scope; 41 42 /// The program contains and links the bytecode for all functions. 43 class Program { 44 public: 45 Program(Context &Ctx) : Ctx(Ctx) {} 46 47 /// Marshals a native pointer to an ID for embedding in bytecode. 48 unsigned getOrCreateNativePointer(const void *Ptr); 49 50 /// Returns the value of a marshalled native pointer. 51 const void *getNativePointer(unsigned Idx); 52 53 /// Emits a string literal among global data. 54 unsigned createGlobalString(const StringLiteral *S); 55 56 /// Returns a pointer to a global. 57 Pointer getPtrGlobal(unsigned Idx); 58 59 /// Returns the value of a global. 60 Block *getGlobal(unsigned Idx) { 61 assert(Idx < Globals.size()); 62 return Globals[Idx]->block(); 63 } 64 65 /// Finds a global's index. 66 llvm::Optional<unsigned> getGlobal(const ValueDecl *VD); 67 68 /// Returns or creates a global an creates an index to it. 69 llvm::Optional<unsigned> getOrCreateGlobal(const ValueDecl *VD); 70 71 /// Returns or creates a dummy value for parameters. 72 llvm::Optional<unsigned> getOrCreateDummy(const ParmVarDecl *PD); 73 74 /// Creates a global and returns its index. 75 llvm::Optional<unsigned> createGlobal(const ValueDecl *VD); 76 77 /// Creates a global from a lifetime-extended temporary. 78 llvm::Optional<unsigned> createGlobal(const Expr *E); 79 80 /// Creates a new function from a code range. 81 template <typename... Ts> 82 Function *createFunction(const FunctionDecl *Def, Ts &&... Args) { 83 auto *Func = new Function(*this, Def, std::forward<Ts>(Args)...); 84 Funcs.insert({Def, std::unique_ptr<Function>(Func)}); 85 return Func; 86 } 87 /// Creates an anonymous function. 88 template <typename... Ts> 89 Function *createFunction(Ts &&... Args) { 90 auto *Func = new Function(*this, std::forward<Ts>(Args)...); 91 AnonFuncs.emplace_back(Func); 92 return Func; 93 } 94 95 /// Returns a function. 96 Function *getFunction(const FunctionDecl *F); 97 98 /// Returns a pointer to a function if it exists and can be compiled. 99 /// If a function couldn't be compiled, an error is returned. 100 /// If a function was not yet defined, a null pointer is returned. 101 llvm::Expected<Function *> getOrCreateFunction(const FunctionDecl *F); 102 103 /// Returns a record or creates one if it does not exist. 104 Record *getOrCreateRecord(const RecordDecl *RD); 105 106 /// Creates a descriptor for a primitive type. 107 Descriptor *createDescriptor(const DeclTy &D, PrimType Type, 108 bool IsConst = false, 109 bool IsTemporary = false, 110 bool IsMutable = false) { 111 return allocateDescriptor(D, Type, IsConst, IsTemporary, IsMutable); 112 } 113 114 /// Creates a descriptor for a composite type. 115 Descriptor *createDescriptor(const DeclTy &D, const Type *Ty, 116 bool IsConst = false, bool IsTemporary = false, 117 bool IsMutable = false); 118 119 /// Context to manage declaration lifetimes. 120 class DeclScope { 121 public: 122 DeclScope(Program &P, const VarDecl *VD) : P(P) { P.startDeclaration(VD); } 123 ~DeclScope() { P.endDeclaration(); } 124 125 private: 126 Program &P; 127 }; 128 129 /// Returns the current declaration ID. 130 llvm::Optional<unsigned> getCurrentDecl() const { 131 if (CurrentDeclaration == NoDeclaration) 132 return llvm::Optional<unsigned>{}; 133 return LastDeclaration; 134 } 135 136 private: 137 friend class DeclScope; 138 139 llvm::Optional<unsigned> createGlobal(const DeclTy &D, QualType Ty, 140 bool IsStatic, bool IsExtern); 141 142 /// Reference to the VM context. 143 Context &Ctx; 144 /// Mapping from decls to cached bytecode functions. 145 llvm::DenseMap<const FunctionDecl *, std::unique_ptr<Function>> Funcs; 146 /// List of anonymous functions. 147 std::vector<std::unique_ptr<Function>> AnonFuncs; 148 149 /// Function relocation locations. 150 llvm::DenseMap<const FunctionDecl *, std::vector<unsigned>> Relocs; 151 152 /// Native pointers referenced by bytecode. 153 std::vector<const void *> NativePointers; 154 /// Cached native pointer indices. 155 llvm::DenseMap<const void *, unsigned> NativePointerIndices; 156 157 /// Custom allocator for global storage. 158 using PoolAllocTy = llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator>; 159 160 /// Descriptor + storage for a global object. 161 /// 162 /// Global objects never go out of scope, thus they do not track pointers. 163 class Global { 164 public: 165 /// Create a global descriptor for string literals. 166 template <typename... Tys> 167 Global(Tys... Args) : B(std::forward<Tys>(Args)...) {} 168 169 /// Allocates the global in the pool, reserving storate for data. 170 void *operator new(size_t Meta, PoolAllocTy &Alloc, size_t Data) { 171 return Alloc.Allocate(Meta + Data, alignof(void *)); 172 } 173 174 /// Return a pointer to the data. 175 char *data() { return B.data(); } 176 /// Return a pointer to the block. 177 Block *block() { return &B; } 178 179 private: 180 /// Required metadata - does not actually track pointers. 181 Block B; 182 }; 183 184 /// Allocator for globals. 185 PoolAllocTy Allocator; 186 187 /// Global objects. 188 std::vector<Global *> Globals; 189 /// Cached global indices. 190 llvm::DenseMap<const void *, unsigned> GlobalIndices; 191 192 /// Mapping from decls to record metadata. 193 llvm::DenseMap<const RecordDecl *, Record *> Records; 194 195 /// Dummy parameter to generate pointers from. 196 llvm::DenseMap<const ParmVarDecl *, unsigned> DummyParams; 197 198 /// Creates a new descriptor. 199 template <typename... Ts> 200 Descriptor *allocateDescriptor(Ts &&... Args) { 201 return new (Allocator) Descriptor(std::forward<Ts>(Args)...); 202 } 203 204 /// No declaration ID. 205 static constexpr unsigned NoDeclaration = (unsigned)-1; 206 /// Last declaration ID. 207 unsigned LastDeclaration = 0; 208 /// Current declaration ID. 209 unsigned CurrentDeclaration = NoDeclaration; 210 211 /// Starts evaluating a declaration. 212 void startDeclaration(const VarDecl *Decl) { 213 LastDeclaration += 1; 214 CurrentDeclaration = LastDeclaration; 215 } 216 217 /// Ends a global declaration. 218 void endDeclaration() { 219 CurrentDeclaration = NoDeclaration; 220 } 221 222 public: 223 /// Dumps the disassembled bytecode to \c llvm::errs(). 224 void dump() const; 225 void dump(llvm::raw_ostream &OS) const; 226 }; 227 228 } // namespace interp 229 } // namespace clang 230 231 #endif 232