xref: /openbsd/gnu/llvm/clang/lib/AST/Interp/Function.h (revision 12c85518)
1 //===--- Function.h - Bytecode function for the 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 the Function class which holds all bytecode function-specific data.
10 //
11 // The scope class which describes local variables is also defined here.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_AST_INTERP_FUNCTION_H
16 #define LLVM_CLANG_AST_INTERP_FUNCTION_H
17 
18 #include "Pointer.h"
19 #include "Source.h"
20 #include "clang/AST/Decl.h"
21 #include "llvm/Support/raw_ostream.h"
22 
23 namespace clang {
24 namespace interp {
25 class Program;
26 class ByteCodeEmitter;
27 enum PrimType : uint32_t;
28 
29 /// Describes a scope block.
30 ///
31 /// The block gathers all the descriptors of the locals defined in this block.
32 class Scope final {
33 public:
34   /// Information about a local's storage.
35   struct Local {
36     /// Offset of the local in frame.
37     unsigned Offset;
38     /// Descriptor of the local.
39     Descriptor *Desc;
40   };
41 
42   using LocalVectorTy = llvm::SmallVector<Local, 8>;
43 
Scope(LocalVectorTy && Descriptors)44   Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {}
45 
locals()46   llvm::iterator_range<LocalVectorTy::const_iterator> locals() const {
47     return llvm::make_range(Descriptors.begin(), Descriptors.end());
48   }
49 
50 private:
51   /// Object descriptors in this block.
52   LocalVectorTy Descriptors;
53 };
54 
55 /// Bytecode function.
56 ///
57 /// Contains links to the bytecode of the function, as well as metadata
58 /// describing all arguments and stack-local variables.
59 ///
60 /// # Calling Convention
61 ///
62 /// When calling a function, all argument values must be on the stack.
63 ///
64 /// If the function has a This pointer (i.e. hasThisPointer() returns true,
65 /// the argument values need to be preceeded by a Pointer for the This object.
66 ///
67 /// If the function uses Return Value Optimization, the arguments (and
68 /// potentially the This pointer) need to be proceeded by a Pointer pointing
69 /// to the location to construct the returned value.
70 ///
71 /// After the function has been called, it will remove all arguments,
72 /// including RVO and This pointer, from the stack.
73 ///
74 class Function final {
75 public:
76   using ParamDescriptor = std::pair<PrimType, Descriptor *>;
77 
78   /// Returns the size of the function's local stack.
getFrameSize()79   unsigned getFrameSize() const { return FrameSize; }
80   /// Returns the size of the argument stack.
getArgSize()81   unsigned getArgSize() const { return ArgSize; }
82 
83   /// Returns a pointer to the start of the code.
getCodeBegin()84   CodePtr getCodeBegin() const { return Code.data(); }
85   /// Returns a pointer to the end of the code.
getCodeEnd()86   CodePtr getCodeEnd() const { return Code.data() + Code.size(); }
87 
88   /// Returns the original FunctionDecl.
getDecl()89   const FunctionDecl *getDecl() const { return F; }
90 
91   /// Returns the name of the function decl this code
92   /// was generated for.
getName()93   const std::string getName() const { return F->getNameInfo().getAsString(); }
94 
95   /// Returns the location.
getLoc()96   SourceLocation getLoc() const { return Loc; }
97 
98   /// Returns a parameter descriptor.
99   ParamDescriptor getParamDescriptor(unsigned Offset) const;
100 
101   /// Checks if the first argument is a RVO pointer.
hasRVO()102   bool hasRVO() const { return HasRVO; }
103 
104   /// Range over the scope blocks.
105   llvm::iterator_range<llvm::SmallVector<Scope, 2>::const_iterator>
scopes()106   scopes() const {
107     return llvm::make_range(Scopes.begin(), Scopes.end());
108   }
109 
110   /// Range over argument types.
111   using arg_reverse_iterator =
112       SmallVectorImpl<PrimType>::const_reverse_iterator;
args_reverse()113   llvm::iterator_range<arg_reverse_iterator> args_reverse() const {
114     return llvm::reverse(ParamTypes);
115   }
116 
117   /// Returns a specific scope.
getScope(unsigned Idx)118   Scope &getScope(unsigned Idx) { return Scopes[Idx]; }
getScope(unsigned Idx)119   const Scope &getScope(unsigned Idx) const { return Scopes[Idx]; }
120 
121   /// Returns the source information at a given PC.
122   SourceInfo getSource(CodePtr PC) const;
123 
124   /// Checks if the function is valid to call in constexpr.
isConstexpr()125   bool isConstexpr() const { return IsValid; }
126 
127   /// Checks if the function is virtual.
128   bool isVirtual() const;
129 
130   /// Checks if the function is a constructor.
isConstructor()131   bool isConstructor() const { return isa<CXXConstructorDecl>(F); }
132 
133   /// Checks if the function is fully done compiling.
isFullyCompiled()134   bool isFullyCompiled() const { return IsFullyCompiled; }
135 
hasThisPointer()136   bool hasThisPointer() const { return HasThisPointer; }
137 
138   // Checks if the funtion already has a body attached.
hasBody()139   bool hasBody() const { return HasBody; }
140 
getNumParams()141   unsigned getNumParams() const { return ParamTypes.size(); }
142 
143 private:
144   /// Construct a function representing an actual function.
145   Function(Program &P, const FunctionDecl *F, unsigned ArgSize,
146            llvm::SmallVector<PrimType, 8> &&ParamTypes,
147            llvm::DenseMap<unsigned, ParamDescriptor> &&Params,
148            bool HasThisPointer, bool HasRVO);
149 
150   /// Sets the code of a function.
setCode(unsigned NewFrameSize,std::vector<char> && NewCode,SourceMap && NewSrcMap,llvm::SmallVector<Scope,2> && NewScopes)151   void setCode(unsigned NewFrameSize, std::vector<char> &&NewCode, SourceMap &&NewSrcMap,
152                llvm::SmallVector<Scope, 2> &&NewScopes) {
153     FrameSize = NewFrameSize;
154     Code = std::move(NewCode);
155     SrcMap = std::move(NewSrcMap);
156     Scopes = std::move(NewScopes);
157     IsValid = true;
158     HasBody = true;
159   }
160 
setIsFullyCompiled(bool FC)161   void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; }
162 
163 private:
164   friend class Program;
165   friend class ByteCodeEmitter;
166 
167   /// Program reference.
168   Program &P;
169   /// Location of the executed code.
170   SourceLocation Loc;
171   /// Declaration this function was compiled from.
172   const FunctionDecl *F;
173   /// Local area size: storage + metadata.
174   unsigned FrameSize = 0;
175   /// Size of the argument stack.
176   unsigned ArgSize;
177   /// Program code.
178   std::vector<char> Code;
179   /// Opcode-to-expression mapping.
180   SourceMap SrcMap;
181   /// List of block descriptors.
182   llvm::SmallVector<Scope, 2> Scopes;
183   /// List of argument types.
184   llvm::SmallVector<PrimType, 8> ParamTypes;
185   /// Map from byte offset to parameter descriptor.
186   llvm::DenseMap<unsigned, ParamDescriptor> Params;
187   /// Flag to indicate if the function is valid.
188   bool IsValid = false;
189   /// Flag to indicate if the function is done being
190   /// compiled to bytecode.
191   bool IsFullyCompiled = false;
192   /// Flag indicating if this function takes the this pointer
193   /// as the first implicit argument
194   bool HasThisPointer = false;
195   /// Whether this function has Return Value Optimization, i.e.
196   /// the return value is constructed in the caller's stack frame.
197   /// This is done for functions that return non-primive values.
198   bool HasRVO = false;
199   /// If we've already compiled the function's body.
200   bool HasBody = false;
201 
202 public:
203   /// Dumps the disassembled bytecode to \c llvm::errs().
204   void dump() const;
205   void dump(llvm::raw_ostream &OS) const;
206 };
207 
208 } // namespace interp
209 } // namespace clang
210 
211 #endif
212