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