clang  19.0.0git
Program.h
Go to the documentation of this file.
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 StringLiteral;
33 class VarDecl;
34 
35 namespace interp {
36 class Context;
37 
38 /// The program contains and links the bytecode for all functions.
39 class Program final {
40 public:
41  Program(Context &Ctx) : Ctx(Ctx) {}
42 
44  // Manually destroy all the blocks. They are almost all harmless,
45  // but primitive arrays might have an InitMap* heap allocated and
46  // that needs to be freed.
47  for (Global *G : Globals)
48  G->block()->invokeDtor();
49 
50  // Records might actually allocate memory themselves, but they
51  // are allocated using a BumpPtrAllocator. Call their desctructors
52  // here manually so they are properly freeing their resources.
53  for (auto RecordPair : Records) {
54  if (Record *R = RecordPair.second)
55  R->~Record();
56  }
57  }
58 
59  /// Marshals a native pointer to an ID for embedding in bytecode.
60  unsigned getOrCreateNativePointer(const void *Ptr);
61 
62  /// Returns the value of a marshalled native pointer.
63  const void *getNativePointer(unsigned Idx);
64 
65  /// Emits a string literal among global data.
66  unsigned createGlobalString(const StringLiteral *S);
67 
68  /// Returns a pointer to a global.
69  Pointer getPtrGlobal(unsigned Idx) const;
70 
71  /// Returns the value of a global.
72  Block *getGlobal(unsigned Idx) {
73  assert(Idx < Globals.size());
74  return Globals[Idx]->block();
75  }
76 
77  /// Finds a global's index.
78  std::optional<unsigned> getGlobal(const ValueDecl *VD);
79 
80  /// Returns or creates a global an creates an index to it.
81  std::optional<unsigned> getOrCreateGlobal(const ValueDecl *VD,
82  const Expr *Init = nullptr);
83 
84  /// Returns or creates a dummy value for unknown declarations.
85  std::optional<unsigned> getOrCreateDummy(const ValueDecl *VD);
86 
87  /// Creates a global and returns its index.
88  std::optional<unsigned> createGlobal(const ValueDecl *VD, const Expr *Init);
89 
90  /// Creates a global from a lifetime-extended temporary.
91  std::optional<unsigned> createGlobal(const Expr *E);
92 
93  /// Creates a new function from a code range.
94  template <typename... Ts>
95  Function *createFunction(const FunctionDecl *Def, Ts &&... Args) {
96  Def = Def->getCanonicalDecl();
97  auto *Func = new Function(*this, Def, std::forward<Ts>(Args)...);
98  Funcs.insert({Def, std::unique_ptr<Function>(Func)});
99  return Func;
100  }
101  /// Creates an anonymous function.
102  template <typename... Ts>
103  Function *createFunction(Ts &&... Args) {
104  auto *Func = new Function(*this, std::forward<Ts>(Args)...);
105  AnonFuncs.emplace_back(Func);
106  return Func;
107  }
108 
109  /// Returns a function.
110  Function *getFunction(const FunctionDecl *F);
111 
112  /// Returns a record or creates one if it does not exist.
113  Record *getOrCreateRecord(const RecordDecl *RD);
114 
115  /// Creates a descriptor for a primitive type.
117  Descriptor::MetadataSize MDSize = std::nullopt,
118  bool IsConst = false, bool IsTemporary = false,
119  bool IsMutable = false) {
120  return allocateDescriptor(D, Type, MDSize, IsConst, IsTemporary, IsMutable);
121  }
122 
123  /// Creates a descriptor for a composite type.
124  Descriptor *createDescriptor(const DeclTy &D, const Type *Ty,
125  Descriptor::MetadataSize MDSize = std::nullopt,
126  bool IsConst = false, bool IsTemporary = false,
127  bool IsMutable = false,
128  const Expr *Init = nullptr);
129 
130  /// Context to manage declaration lifetimes.
131  class DeclScope {
132  public:
133  DeclScope(Program &P, const ValueDecl *VD) : P(P) {
134  P.startDeclaration(VD);
135  }
136  ~DeclScope() { P.endDeclaration(); }
137 
138  private:
139  Program &P;
140  };
141 
142  /// Returns the current declaration ID.
143  std::optional<unsigned> getCurrentDecl() const {
144  if (CurrentDeclaration == NoDeclaration)
145  return std::optional<unsigned>{};
146  return LastDeclaration;
147  }
148 
149 private:
150  friend class DeclScope;
151 
152  std::optional<unsigned> createGlobal(const DeclTy &D, QualType Ty,
153  bool IsStatic, bool IsExtern,
154  const Expr *Init = nullptr);
155 
156  /// Reference to the VM context.
157  Context &Ctx;
158  /// Mapping from decls to cached bytecode functions.
159  llvm::DenseMap<const FunctionDecl *, std::unique_ptr<Function>> Funcs;
160  /// List of anonymous functions.
161  std::vector<std::unique_ptr<Function>> AnonFuncs;
162 
163  /// Function relocation locations.
164  llvm::DenseMap<const FunctionDecl *, std::vector<unsigned>> Relocs;
165 
166  /// Native pointers referenced by bytecode.
167  std::vector<const void *> NativePointers;
168  /// Cached native pointer indices.
169  llvm::DenseMap<const void *, unsigned> NativePointerIndices;
170 
171  /// Custom allocator for global storage.
172  using PoolAllocTy = llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator>;
173 
174  /// Descriptor + storage for a global object.
175  ///
176  /// Global objects never go out of scope, thus they do not track pointers.
177  class Global {
178  public:
179  /// Create a global descriptor for string literals.
180  template <typename... Tys>
181  Global(Tys... Args) : B(std::forward<Tys>(Args)...) {}
182 
183  /// Allocates the global in the pool, reserving storate for data.
184  void *operator new(size_t Meta, PoolAllocTy &Alloc, size_t Data) {
185  return Alloc.Allocate(Meta + Data, alignof(void *));
186  }
187 
188  /// Return a pointer to the data.
189  std::byte *data() { return B.data(); }
190  /// Return a pointer to the block.
191  Block *block() { return &B; }
192  const Block *block() const { return &B; }
193 
194  private:
195  /// Required metadata - does not actually track pointers.
196  Block B;
197  };
198 
199  /// Allocator for globals.
200  PoolAllocTy Allocator;
201 
202  /// Global objects.
203  std::vector<Global *> Globals;
204  /// Cached global indices.
205  llvm::DenseMap<const void *, unsigned> GlobalIndices;
206 
207  /// Mapping from decls to record metadata.
208  llvm::DenseMap<const RecordDecl *, Record *> Records;
209 
210  /// Dummy parameter to generate pointers from.
211  llvm::DenseMap<const ValueDecl *, unsigned> DummyVariables;
212 
213  /// Creates a new descriptor.
214  template <typename... Ts>
215  Descriptor *allocateDescriptor(Ts &&... Args) {
216  return new (Allocator) Descriptor(std::forward<Ts>(Args)...);
217  }
218 
219  /// No declaration ID.
220  static constexpr unsigned NoDeclaration = (unsigned)-1;
221  /// Last declaration ID.
222  unsigned LastDeclaration = 0;
223  /// Current declaration ID.
224  unsigned CurrentDeclaration = NoDeclaration;
225 
226  /// Starts evaluating a declaration.
227  void startDeclaration(const ValueDecl *Decl) {
228  LastDeclaration += 1;
229  CurrentDeclaration = LastDeclaration;
230  }
231 
232  /// Ends a global declaration.
233  void endDeclaration() {
234  CurrentDeclaration = NoDeclaration;
235  }
236 
237 public:
238  /// Dumps the disassembled bytecode to \c llvm::errs().
239  void dump() const;
240  void dump(llvm::raw_ostream &OS) const;
241 };
242 
243 } // namespace interp
244 } // namespace clang
245 
246 #endif
StringRef P
bool IsStatic
Definition: Format.cpp:2988
const CFGBlock * Block
Definition: HTMLLogger.cpp:153
llvm::MachO::Records Records
Definition: MachO.h:39
const char * Data
This represents one expression.
Definition: Expr.h:110
Represents a function declaration or definition.
Definition: Decl.h:1972
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:3621
A (possibly-)qualified type.
Definition: Type.h:940
Represents a struct/union/class.
Definition: Decl.h:4171
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1773
The base class of the type hierarchy.
Definition: Type.h:1813
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:707
A memory block, either on the stack or in the heap.
Definition: InterpBlock.h:49
Holds all information required to evaluate constexpr code in a module.
Definition: Context.h:40
Bytecode function.
Definition: Function.h:77
A pointer to a memory block, live or dead.
Definition: Pointer.h:80
Context to manage declaration lifetimes.
Definition: Program.h:131
DeclScope(Program &P, const ValueDecl *VD)
Definition: Program.h:133
The program contains and links the bytecode for all functions.
Definition: Program.h:39
Block * getGlobal(unsigned Idx)
Returns the value of a global.
Definition: Program.h:72
std::optional< unsigned > getOrCreateGlobal(const ValueDecl *VD, const Expr *Init=nullptr)
Returns or creates a global an creates an index to it.
Definition: Program.cpp:130
Function * createFunction(Ts &&... Args)
Creates an anonymous function.
Definition: Program.h:103
Function * getFunction(const FunctionDecl *F)
Returns a function.
Definition: Program.cpp:233
std::optional< unsigned > createGlobal(const ValueDecl *VD, const Expr *Init)
Creates a global and returns its index.
Definition: Program.cpp:176
const void * getNativePointer(unsigned Idx)
Returns the value of a marshalled native pointer.
Definition: Program.cpp:33
unsigned getOrCreateNativePointer(const void *Ptr)
Marshals a native pointer to an ID for embedding in bytecode.
Definition: Program.cpp:22
unsigned createGlobalString(const StringLiteral *S)
Emits a string literal among global data.
Definition: Program.cpp:37
Pointer getPtrGlobal(unsigned Idx) const
Returns a pointer to a global.
Definition: Program.cpp:105
void dump() const
Dumps the disassembled bytecode to llvm::errs().
Definition: Disasm.cpp:91
Descriptor * createDescriptor(const DeclTy &D, PrimType Type, Descriptor::MetadataSize MDSize=std::nullopt, bool IsConst=false, bool IsTemporary=false, bool IsMutable=false)
Creates a descriptor for a primitive type.
Definition: Program.h:116
Function * createFunction(const FunctionDecl *Def, Ts &&... Args)
Creates a new function from a code range.
Definition: Program.h:95
std::optional< unsigned > getOrCreateDummy(const ValueDecl *VD)
Returns or creates a dummy value for unknown declarations.
Definition: Program.cpp:142
Record * getOrCreateRecord(const RecordDecl *RD)
Returns a record or creates one if it does not exist.
Definition: Program.cpp:240
Program(Context &Ctx)
Definition: Program.h:41
std::optional< unsigned > getCurrentDecl() const
Returns the current declaration ID.
Definition: Program.h:143
Structure/Class descriptor.
Definition: Record.h:25
Code completion in a.
unsigned llvm::PointerUnion< const Decl *, const Expr * > DeclTy
Definition: Descriptor.h:27
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:32
bool Init(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1472
The JSON file list parser is used to communicate input to InstallAPI.
Definition: Format.h:5433
Describes a memory block created by an allocation site.
Definition: Descriptor.h:91
std::optional< unsigned > MetadataSize
Definition: Descriptor.h:111