1 //===--- Function.h - Bytecode function for the VM --------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // Defines the Function class which holds all bytecode function-specific data.
11 // The scope class which describes local variables is also defined here.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_AST_INTERP_FUNCTION_H
16 #define LLVM_CLANG_AST_INTERP_FUNCTION_H
19 #include "Descriptor.h"
20 #include "clang/AST/ASTLambda.h"
21 #include "clang/AST/Decl.h"
22 #include "llvm/Support/raw_ostream.h"
27 class ByteCodeEmitter
;
29 enum PrimType
: uint32_t;
31 /// Describes a scope block.
33 /// The block gathers all the descriptors of the locals defined in this block.
36 /// Information about a local's storage.
38 /// Offset of the local in frame.
40 /// Descriptor of the local.
44 using LocalVectorTy
= llvm::SmallVector
<Local
, 8>;
46 Scope(LocalVectorTy
&&Descriptors
) : Descriptors(std::move(Descriptors
)) {}
48 llvm::iterator_range
<LocalVectorTy::const_iterator
> locals() const {
49 return llvm::make_range(Descriptors
.begin(), Descriptors
.end());
53 /// Object descriptors in this block.
54 LocalVectorTy Descriptors
;
57 /// Bytecode function.
59 /// Contains links to the bytecode of the function, as well as metadata
60 /// describing all arguments and stack-local variables.
62 /// # Calling Convention
64 /// When calling a function, all argument values must be on the stack.
66 /// If the function has a This pointer (i.e. hasThisPointer() returns true,
67 /// the argument values need to be preceeded by a Pointer for the This object.
69 /// If the function uses Return Value Optimization, the arguments (and
70 /// potentially the This pointer) need to be preceeded by a Pointer pointing
71 /// to the location to construct the returned value.
73 /// After the function has been called, it will remove all arguments,
74 /// including RVO and This pointer, from the stack.
76 class Function final
{
78 using ParamDescriptor
= std::pair
<PrimType
, Descriptor
*>;
80 /// Returns the size of the function's local stack.
81 unsigned getFrameSize() const { return FrameSize
; }
82 /// Returns the size of the argument stack.
83 unsigned getArgSize() const { return ArgSize
; }
85 /// Returns a pointer to the start of the code.
86 CodePtr
getCodeBegin() const { return Code
.data(); }
87 /// Returns a pointer to the end of the code.
88 CodePtr
getCodeEnd() const { return Code
.data() + Code
.size(); }
90 /// Returns the original FunctionDecl.
91 const FunctionDecl
*getDecl() const { return F
; }
93 /// Returns the name of the function decl this code
94 /// was generated for.
95 const std::string
getName() const {
99 return F
->getQualifiedNameAsString();
102 /// Returns the location.
103 SourceLocation
getLoc() const { return Loc
; }
105 /// Returns a parameter descriptor.
106 ParamDescriptor
getParamDescriptor(unsigned Offset
) const;
108 /// Checks if the first argument is a RVO pointer.
109 bool hasRVO() const { return HasRVO
; }
111 /// Range over the scope blocks.
112 llvm::iterator_range
<llvm::SmallVector
<Scope
, 2>::const_iterator
>
114 return llvm::make_range(Scopes
.begin(), Scopes
.end());
117 /// Range over argument types.
118 using arg_reverse_iterator
=
119 SmallVectorImpl
<PrimType
>::const_reverse_iterator
;
120 llvm::iterator_range
<arg_reverse_iterator
> args_reverse() const {
121 return llvm::reverse(ParamTypes
);
124 /// Returns a specific scope.
125 Scope
&getScope(unsigned Idx
) { return Scopes
[Idx
]; }
126 const Scope
&getScope(unsigned Idx
) const { return Scopes
[Idx
]; }
128 /// Returns the source information at a given PC.
129 SourceInfo
getSource(CodePtr PC
) const;
131 /// Checks if the function is valid to call in constexpr.
132 bool isConstexpr() const { return IsValid
|| isLambdaStaticInvoker(); }
134 /// Checks if the function is virtual.
135 bool isVirtual() const;
137 /// Checks if the function is a constructor.
138 bool isConstructor() const { return isa
<CXXConstructorDecl
>(F
); }
139 /// Checks if the function is a destructor.
140 bool isDestructor() const { return isa
<CXXDestructorDecl
>(F
); }
142 /// Returns the parent record decl, if any.
143 const CXXRecordDecl
*getParentDecl() const {
144 if (const auto *MD
= dyn_cast
<CXXMethodDecl
>(F
))
145 return MD
->getParent();
149 /// Returns whether this function is a lambda static invoker,
150 /// which we generate custom byte code for.
151 bool isLambdaStaticInvoker() const {
152 if (const auto *MD
= dyn_cast
<CXXMethodDecl
>(F
))
153 return MD
->isLambdaStaticInvoker();
157 /// Returns whether this function is the call operator
158 /// of a lambda record decl.
159 bool isLambdaCallOperator() const {
160 if (const auto *MD
= dyn_cast
<CXXMethodDecl
>(F
))
161 return clang::isLambdaCallOperator(MD
);
165 /// Checks if the function is fully done compiling.
166 bool isFullyCompiled() const { return IsFullyCompiled
; }
168 bool hasThisPointer() const { return HasThisPointer
; }
170 /// Checks if the function already has a body attached.
171 bool hasBody() const { return HasBody
; }
173 /// Checks if the function is defined.
174 bool isDefined() const { return Defined
; }
176 bool isVariadic() const { return Variadic
; }
178 unsigned getBuiltinID() const { return F
->getBuiltinID(); }
180 bool isBuiltin() const { return F
->getBuiltinID() != 0; }
182 /// Does this function need its arguments to be classified at runtime
183 /// rather than at bytecode-compile-time?
184 bool needsRuntimeArgPop(const ASTContext
&Ctx
) const;
186 unsigned getNumParams() const { return ParamTypes
.size(); }
188 unsigned getParamOffset(unsigned ParamIndex
) const {
189 return ParamOffsets
[ParamIndex
];
193 /// Construct a function representing an actual function.
194 Function(Program
&P
, const FunctionDecl
*F
, unsigned ArgSize
,
195 llvm::SmallVectorImpl
<PrimType
> &&ParamTypes
,
196 llvm::DenseMap
<unsigned, ParamDescriptor
> &&Params
,
197 llvm::SmallVectorImpl
<unsigned> &&ParamOffsets
, bool HasThisPointer
,
200 /// Sets the code of a function.
201 void setCode(unsigned NewFrameSize
, std::vector
<std::byte
> &&NewCode
,
202 SourceMap
&&NewSrcMap
, llvm::SmallVector
<Scope
, 2> &&NewScopes
,
204 FrameSize
= NewFrameSize
;
205 Code
= std::move(NewCode
);
206 SrcMap
= std::move(NewSrcMap
);
207 Scopes
= std::move(NewScopes
);
209 HasBody
= NewHasBody
;
212 void setIsFullyCompiled(bool FC
) { IsFullyCompiled
= FC
; }
213 void setDefined(bool D
) { Defined
= D
; }
216 friend class Program
;
217 friend class ByteCodeEmitter
;
219 /// Program reference.
221 /// Location of the executed code.
223 /// Declaration this function was compiled from.
224 const FunctionDecl
*F
;
225 /// Local area size: storage + metadata.
226 unsigned FrameSize
= 0;
227 /// Size of the argument stack.
230 std::vector
<std::byte
> Code
;
231 /// Opcode-to-expression mapping.
233 /// List of block descriptors.
234 llvm::SmallVector
<Scope
, 2> Scopes
;
235 /// List of argument types.
236 llvm::SmallVector
<PrimType
, 8> ParamTypes
;
237 /// Map from byte offset to parameter descriptor.
238 llvm::DenseMap
<unsigned, ParamDescriptor
> Params
;
239 /// List of parameter offsets.
240 llvm::SmallVector
<unsigned, 8> ParamOffsets
;
241 /// Flag to indicate if the function is valid.
242 bool IsValid
= false;
243 /// Flag to indicate if the function is done being
244 /// compiled to bytecode.
245 bool IsFullyCompiled
= false;
246 /// Flag indicating if this function takes the this pointer
247 /// as the first implicit argument
248 bool HasThisPointer
= false;
249 /// Whether this function has Return Value Optimization, i.e.
250 /// the return value is constructed in the caller's stack frame.
251 /// This is done for functions that return non-primive values.
253 /// If we've already compiled the function's body.
254 bool HasBody
= false;
255 bool Defined
= false;
256 bool Variadic
= false;
259 /// Dumps the disassembled bytecode to \c llvm::errs().
261 void dump(llvm::raw_ostream
&OS
) const;
264 } // namespace interp