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