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