xref: /freebsd/contrib/llvm-project/clang/lib/AST/ByteCode/Function.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 "Descriptor.h"
19 #include "Source.h"
20 #include "clang/AST/ASTLambda.h"
21 #include "clang/AST/Attr.h"
22 #include "clang/AST/Decl.h"
23 #include "llvm/ADT/PointerUnion.h"
24 #include "llvm/Support/raw_ostream.h"
25 
26 namespace clang {
27 namespace interp {
28 class Program;
29 class ByteCodeEmitter;
30 class Pointer;
31 enum PrimType : uint32_t;
32 
33 /// Describes a scope block.
34 ///
35 /// The block gathers all the descriptors of the locals defined in this block.
36 class Scope final {
37 public:
38   /// Information about a local's storage.
39   struct Local {
40     /// Offset of the local in frame.
41     unsigned Offset;
42     /// Descriptor of the local.
43     Descriptor *Desc;
44   };
45 
46   using LocalVectorTy = llvm::SmallVector<Local, 8>;
47 
Scope(LocalVectorTy && Descriptors)48   Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {}
49 
locals()50   llvm::iterator_range<LocalVectorTy::const_iterator> locals() const {
51     return llvm::make_range(Descriptors.begin(), Descriptors.end());
52   }
53 
54   llvm::iterator_range<LocalVectorTy::const_reverse_iterator>
locals_reverse()55   locals_reverse() const {
56     return llvm::reverse(Descriptors);
57   }
58 
59 private:
60   /// Object descriptors in this block.
61   LocalVectorTy Descriptors;
62 };
63 
64 using FunctionDeclTy =
65     llvm::PointerUnion<const FunctionDecl *, const BlockExpr *>;
66 
67 /// Bytecode function.
68 ///
69 /// Contains links to the bytecode of the function, as well as metadata
70 /// describing all arguments and stack-local variables.
71 ///
72 /// # Calling Convention
73 ///
74 /// When calling a function, all argument values must be on the stack.
75 ///
76 /// If the function has a This pointer (i.e. hasThisPointer() returns true,
77 /// the argument values need to be preceeded by a Pointer for the This object.
78 ///
79 /// If the function uses Return Value Optimization, the arguments (and
80 /// potentially the This pointer) need to be preceeded by a Pointer pointing
81 /// to the location to construct the returned value.
82 ///
83 /// After the function has been called, it will remove all arguments,
84 /// including RVO and This pointer, from the stack.
85 ///
86 class Function final {
87 public:
88   enum class FunctionKind {
89     Normal,
90     Ctor,
91     Dtor,
92     LambdaStaticInvoker,
93     LambdaCallOperator,
94     CopyOrMoveOperator,
95   };
96   using ParamDescriptor = std::pair<PrimType, Descriptor *>;
97 
98   /// Returns the size of the function's local stack.
getFrameSize()99   unsigned getFrameSize() const { return FrameSize; }
100   /// Returns the size of the argument stack.
getArgSize()101   unsigned getArgSize() const { return ArgSize; }
102 
103   /// Returns a pointer to the start of the code.
getCodeBegin()104   CodePtr getCodeBegin() const { return Code.data(); }
105   /// Returns a pointer to the end of the code.
getCodeEnd()106   CodePtr getCodeEnd() const { return Code.data() + Code.size(); }
107 
108   /// Returns the original FunctionDecl.
getDecl()109   const FunctionDecl *getDecl() const {
110     return dyn_cast<const FunctionDecl *>(Source);
111   }
getExpr()112   const BlockExpr *getExpr() const {
113     return dyn_cast<const BlockExpr *>(Source);
114   }
115 
116   /// Returns the name of the function decl this code
117   /// was generated for.
getName()118   std::string getName() const {
119     if (!Source || !getDecl())
120       return "<<expr>>";
121 
122     return getDecl()->getQualifiedNameAsString();
123   }
124 
125   /// Returns a parameter descriptor.
126   ParamDescriptor getParamDescriptor(unsigned Offset) const;
127 
128   /// Checks if the first argument is a RVO pointer.
hasRVO()129   bool hasRVO() const { return HasRVO; }
130 
hasNonNullAttr()131   bool hasNonNullAttr() const { return getDecl()->hasAttr<NonNullAttr>(); }
132 
133   /// Range over the scope blocks.
134   llvm::iterator_range<llvm::SmallVector<Scope, 2>::const_iterator>
scopes()135   scopes() const {
136     return llvm::make_range(Scopes.begin(), Scopes.end());
137   }
138 
139   /// Range over argument types.
140   using arg_reverse_iterator =
141       SmallVectorImpl<PrimType>::const_reverse_iterator;
args_reverse()142   llvm::iterator_range<arg_reverse_iterator> args_reverse() const {
143     return llvm::reverse(ParamTypes);
144   }
145 
146   /// Returns a specific scope.
getScope(unsigned Idx)147   Scope &getScope(unsigned Idx) { return Scopes[Idx]; }
getScope(unsigned Idx)148   const Scope &getScope(unsigned Idx) const { return Scopes[Idx]; }
149 
150   /// Returns the source information at a given PC.
151   SourceInfo getSource(CodePtr PC) const;
152 
153   /// Checks if the function is valid to call.
isValid()154   bool isValid() const { return IsValid || isLambdaStaticInvoker(); }
155 
156   /// Checks if the function is virtual.
isVirtual()157   bool isVirtual() const { return Virtual; };
isImmediate()158   bool isImmediate() const { return Immediate; }
isConstexpr()159   bool isConstexpr() const { return Constexpr; }
160 
161   /// Checks if the function is a constructor.
isConstructor()162   bool isConstructor() const { return Kind == FunctionKind::Ctor; }
163   /// Checks if the function is a destructor.
isDestructor()164   bool isDestructor() const { return Kind == FunctionKind::Dtor; }
165   /// Checks if the function is copy or move operator.
isCopyOrMoveOperator()166   bool isCopyOrMoveOperator() const {
167     return Kind == FunctionKind::CopyOrMoveOperator;
168   }
169 
170   /// Returns whether this function is a lambda static invoker,
171   /// which we generate custom byte code for.
isLambdaStaticInvoker()172   bool isLambdaStaticInvoker() const {
173     return Kind == FunctionKind::LambdaStaticInvoker;
174   }
175 
176   /// Returns whether this function is the call operator
177   /// of a lambda record decl.
isLambdaCallOperator()178   bool isLambdaCallOperator() const {
179     return Kind == FunctionKind::LambdaCallOperator;
180   }
181 
182   /// Returns the parent record decl, if any.
getParentDecl()183   const CXXRecordDecl *getParentDecl() const {
184     if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(
185             dyn_cast<const FunctionDecl *>(Source)))
186       return MD->getParent();
187     return nullptr;
188   }
189 
190   /// Checks if the function is fully done compiling.
isFullyCompiled()191   bool isFullyCompiled() const { return IsFullyCompiled; }
192 
hasThisPointer()193   bool hasThisPointer() const { return HasThisPointer; }
194 
195   /// Checks if the function already has a body attached.
hasBody()196   bool hasBody() const { return HasBody; }
197 
198   /// Checks if the function is defined.
isDefined()199   bool isDefined() const { return Defined; }
200 
isVariadic()201   bool isVariadic() const { return Variadic; }
202 
getNumParams()203   unsigned getNumParams() const { return ParamTypes.size(); }
204 
205   /// Returns the number of parameter this function takes when it's called,
206   /// i.e excluding the instance pointer and the RVO pointer.
getNumWrittenParams()207   unsigned getNumWrittenParams() const {
208     assert(getNumParams() >= (unsigned)(hasThisPointer() + hasRVO()));
209     return getNumParams() - hasThisPointer() - hasRVO();
210   }
getWrittenArgSize()211   unsigned getWrittenArgSize() const {
212     return ArgSize - (align(primSize(PT_Ptr)) * (hasThisPointer() + hasRVO()));
213   }
214 
isThisPointerExplicit()215   bool isThisPointerExplicit() const {
216     if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(
217             dyn_cast<const FunctionDecl *>(Source)))
218       return MD->isExplicitObjectMemberFunction();
219     return false;
220   }
221 
getParamOffset(unsigned ParamIndex)222   unsigned getParamOffset(unsigned ParamIndex) const {
223     return ParamOffsets[ParamIndex];
224   }
225 
getParamType(unsigned ParamIndex)226   PrimType getParamType(unsigned ParamIndex) const {
227     return ParamTypes[ParamIndex];
228   }
229 
230 private:
231   /// Construct a function representing an actual function.
232   Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,
233            llvm::SmallVectorImpl<PrimType> &&ParamTypes,
234            llvm::DenseMap<unsigned, ParamDescriptor> &&Params,
235            llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer,
236            bool HasRVO, bool IsLambdaStaticInvoker);
237 
238   /// Sets the code of a function.
setCode(unsigned NewFrameSize,std::vector<std::byte> && NewCode,SourceMap && NewSrcMap,llvm::SmallVector<Scope,2> && NewScopes,bool NewHasBody)239   void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode,
240                SourceMap &&NewSrcMap, llvm::SmallVector<Scope, 2> &&NewScopes,
241                bool NewHasBody) {
242     FrameSize = NewFrameSize;
243     Code = std::move(NewCode);
244     SrcMap = std::move(NewSrcMap);
245     Scopes = std::move(NewScopes);
246     IsValid = true;
247     HasBody = NewHasBody;
248   }
249 
setIsFullyCompiled(bool FC)250   void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; }
setDefined(bool D)251   void setDefined(bool D) { Defined = D; }
252 
253 private:
254   friend class Program;
255   friend class ByteCodeEmitter;
256   friend class Context;
257 
258   /// Program reference.
259   Program &P;
260   /// Function Kind.
261   FunctionKind Kind;
262   /// Declaration this function was compiled from.
263   FunctionDeclTy Source;
264   /// Local area size: storage + metadata.
265   unsigned FrameSize = 0;
266   /// Size of the argument stack.
267   unsigned ArgSize;
268   /// Program code.
269   std::vector<std::byte> Code;
270   /// Opcode-to-expression mapping.
271   SourceMap SrcMap;
272   /// List of block descriptors.
273   llvm::SmallVector<Scope, 2> Scopes;
274   /// List of argument types.
275   llvm::SmallVector<PrimType, 8> ParamTypes;
276   /// Map from byte offset to parameter descriptor.
277   llvm::DenseMap<unsigned, ParamDescriptor> Params;
278   /// List of parameter offsets.
279   llvm::SmallVector<unsigned, 8> ParamOffsets;
280   /// Flag to indicate if the function is valid.
281   LLVM_PREFERRED_TYPE(bool)
282   unsigned IsValid : 1;
283   /// Flag to indicate if the function is done being
284   /// compiled to bytecode.
285   LLVM_PREFERRED_TYPE(bool)
286   unsigned IsFullyCompiled : 1;
287   /// Flag indicating if this function takes the this pointer
288   /// as the first implicit argument
289   LLVM_PREFERRED_TYPE(bool)
290   unsigned HasThisPointer : 1;
291   /// Whether this function has Return Value Optimization, i.e.
292   /// the return value is constructed in the caller's stack frame.
293   /// This is done for functions that return non-primive values.
294   LLVM_PREFERRED_TYPE(bool)
295   unsigned HasRVO : 1;
296   /// If we've already compiled the function's body.
297   LLVM_PREFERRED_TYPE(bool)
298   unsigned HasBody : 1;
299   LLVM_PREFERRED_TYPE(bool)
300   unsigned Defined : 1;
301   LLVM_PREFERRED_TYPE(bool)
302   unsigned Variadic : 1;
303   LLVM_PREFERRED_TYPE(bool)
304   unsigned Virtual : 1;
305   LLVM_PREFERRED_TYPE(bool)
306   unsigned Immediate : 1;
307   LLVM_PREFERRED_TYPE(bool)
308   unsigned Constexpr : 1;
309 
310 public:
311   /// Dumps the disassembled bytecode to \c llvm::errs().
312   void dump() const;
313   void dump(llvm::raw_ostream &OS) const;
314 };
315 
316 } // namespace interp
317 } // namespace clang
318 
319 #endif
320