Program.h 7.7 KB

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