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 "Source.h"
19#include "Descriptor.h"
20#include "clang/AST/ASTLambda.h"
21#include "clang/AST/Decl.h"
22#include "llvm/Support/raw_ostream.h"
23
24namespace clang {
25namespace interp {
26class Program;
27class ByteCodeEmitter;
28class Pointer;
29enum PrimType : uint32_t;
30
31/// Describes a scope block.
32///
33/// The block gathers all the descriptors of the locals defined in this block.
34class Scope final {
35public:
36  /// Information about a local's storage.
37  struct Local {
38    /// Offset of the local in frame.
39    unsigned Offset;
40    /// Descriptor of the local.
41    Descriptor *Desc;
42  };
43
44  using LocalVectorTy = llvm::SmallVector<Local, 8>;
45
46  Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {}
47
48  llvm::iterator_range<LocalVectorTy::const_iterator> locals() const {
49    return llvm::make_range(Descriptors.begin(), Descriptors.end());
50  }
51
52private:
53  /// Object descriptors in this block.
54  LocalVectorTy Descriptors;
55};
56
57/// Bytecode function.
58///
59/// Contains links to the bytecode of the function, as well as metadata
60/// describing all arguments and stack-local variables.
61///
62/// # Calling Convention
63///
64/// When calling a function, all argument values must be on the stack.
65///
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.
68///
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.
72///
73/// After the function has been called, it will remove all arguments,
74/// including RVO and This pointer, from the stack.
75///
76class Function final {
77public:
78  using ParamDescriptor = std::pair<PrimType, Descriptor *>;
79
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; }
84
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(); }
89
90  /// Returns the original FunctionDecl.
91  const FunctionDecl *getDecl() const { return F; }
92
93  /// Returns the name of the function decl this code
94  /// was generated for.
95  const std::string getName() const {
96    if (!F)
97      return "<<expr>>";
98
99    return F->getQualifiedNameAsString();
100  }
101
102  /// Returns the location.
103  SourceLocation getLoc() const { return Loc; }
104
105  /// Returns a parameter descriptor.
106  ParamDescriptor getParamDescriptor(unsigned Offset) const;
107
108  /// Checks if the first argument is a RVO pointer.
109  bool hasRVO() const { return HasRVO; }
110
111  /// Range over the scope blocks.
112  llvm::iterator_range<llvm::SmallVector<Scope, 2>::const_iterator>
113  scopes() const {
114    return llvm::make_range(Scopes.begin(), Scopes.end());
115  }
116
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);
122  }
123
124  /// Returns a specific scope.
125  Scope &getScope(unsigned Idx) { return Scopes[Idx]; }
126  const Scope &getScope(unsigned Idx) const { return Scopes[Idx]; }
127
128  /// Returns the source information at a given PC.
129  SourceInfo getSource(CodePtr PC) const;
130
131  /// Checks if the function is valid to call in constexpr.
132  bool isConstexpr() const { return IsValid || isLambdaStaticInvoker(); }
133
134  /// Checks if the function is virtual.
135  bool isVirtual() const;
136
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); }
141
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();
146    return nullptr;
147  }
148
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();
154    return false;
155  }
156
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);
162    return false;
163  }
164
165  /// Checks if the function is fully done compiling.
166  bool isFullyCompiled() const { return IsFullyCompiled; }
167
168  bool hasThisPointer() const { return HasThisPointer; }
169
170  /// Checks if the function already has a body attached.
171  bool hasBody() const { return HasBody; }
172
173  /// Checks if the function is defined.
174  bool isDefined() const { return Defined; }
175
176  bool isVariadic() const { return Variadic; }
177
178  unsigned getBuiltinID() const { return F->getBuiltinID(); }
179
180  bool isBuiltin() const { return F->getBuiltinID() != 0; }
181
182  bool isUnevaluatedBuiltin() const { return IsUnevaluatedBuiltin; }
183
184  unsigned getNumParams() const { return ParamTypes.size(); }
185
186  unsigned getParamOffset(unsigned ParamIndex) const {
187    return ParamOffsets[ParamIndex];
188  }
189
190private:
191  /// Construct a function representing an actual function.
192  Function(Program &P, const FunctionDecl *F, unsigned ArgSize,
193           llvm::SmallVectorImpl<PrimType> &&ParamTypes,
194           llvm::DenseMap<unsigned, ParamDescriptor> &&Params,
195           llvm::SmallVectorImpl<unsigned> &&ParamOffsets, bool HasThisPointer,
196           bool HasRVO, bool UnevaluatedBuiltin);
197
198  /// Sets the code of a function.
199  void setCode(unsigned NewFrameSize, std::vector<std::byte> &&NewCode,
200               SourceMap &&NewSrcMap, llvm::SmallVector<Scope, 2> &&NewScopes,
201               bool NewHasBody) {
202    FrameSize = NewFrameSize;
203    Code = std::move(NewCode);
204    SrcMap = std::move(NewSrcMap);
205    Scopes = std::move(NewScopes);
206    IsValid = true;
207    HasBody = NewHasBody;
208  }
209
210  void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; }
211  void setDefined(bool D) { Defined = D; }
212
213private:
214  friend class Program;
215  friend class ByteCodeEmitter;
216
217  /// Program reference.
218  Program &P;
219  /// Location of the executed code.
220  SourceLocation Loc;
221  /// Declaration this function was compiled from.
222  const FunctionDecl *F;
223  /// Local area size: storage + metadata.
224  unsigned FrameSize = 0;
225  /// Size of the argument stack.
226  unsigned ArgSize;
227  /// Program code.
228  std::vector<std::byte> Code;
229  /// Opcode-to-expression mapping.
230  SourceMap SrcMap;
231  /// List of block descriptors.
232  llvm::SmallVector<Scope, 2> Scopes;
233  /// List of argument types.
234  llvm::SmallVector<PrimType, 8> ParamTypes;
235  /// Map from byte offset to parameter descriptor.
236  llvm::DenseMap<unsigned, ParamDescriptor> Params;
237  /// List of parameter offsets.
238  llvm::SmallVector<unsigned, 8> ParamOffsets;
239  /// Flag to indicate if the function is valid.
240  bool IsValid = false;
241  /// Flag to indicate if the function is done being
242  /// compiled to bytecode.
243  bool IsFullyCompiled = false;
244  /// Flag indicating if this function takes the this pointer
245  /// as the first implicit argument
246  bool HasThisPointer = false;
247  /// Whether this function has Return Value Optimization, i.e.
248  /// the return value is constructed in the caller's stack frame.
249  /// This is done for functions that return non-primive values.
250  bool HasRVO = false;
251  /// If we've already compiled the function's body.
252  bool HasBody = false;
253  bool Defined = false;
254  bool Variadic = false;
255  bool IsUnevaluatedBuiltin = false;
256
257public:
258  /// Dumps the disassembled bytecode to \c llvm::errs().
259  void dump() const;
260  void dump(llvm::raw_ostream &OS) const;
261};
262
263} // namespace interp
264} // namespace clang
265
266#endif
267