Program.h 6.7 KB

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