xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/Interp/Program.h (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
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