Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/Function.h
213799 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/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
48
Scope(LocalVectorTy &&Descriptors) : Descriptors(std::move(Descriptors)) {}
49
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>
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.
99
unsigned getFrameSize() const { return FrameSize; }
100
/// Returns the size of the argument stack.
101
unsigned getArgSize() const { return ArgSize; }
102
103
/// Returns a pointer to the start of the code.
104
CodePtr getCodeBegin() const { return Code.data(); }
105
/// Returns a pointer to the end of the code.
106
CodePtr getCodeEnd() const { return Code.data() + Code.size(); }
107
108
/// Returns the original FunctionDecl.
109
const FunctionDecl *getDecl() const {
110
return dyn_cast<const FunctionDecl *>(Source);
111
}
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.
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.
129
bool hasRVO() const { return HasRVO; }
130
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>
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;
142
llvm::iterator_range<arg_reverse_iterator> args_reverse() const {
143
return llvm::reverse(ParamTypes);
144
}
145
146
/// Returns a specific scope.
147
Scope &getScope(unsigned Idx) { return Scopes[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.
154
bool isValid() const { return IsValid || isLambdaStaticInvoker(); }
155
156
/// Checks if the function is virtual.
157
bool isVirtual() const { return Virtual; };
158
bool isImmediate() const { return Immediate; }
159
bool isConstexpr() const { return Constexpr; }
160
161
/// Checks if the function is a constructor.
162
bool isConstructor() const { return Kind == FunctionKind::Ctor; }
163
/// Checks if the function is a destructor.
164
bool isDestructor() const { return Kind == FunctionKind::Dtor; }
165
/// Checks if the function is copy or move operator.
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.
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.
178
bool isLambdaCallOperator() const {
179
return Kind == FunctionKind::LambdaCallOperator;
180
}
181
182
/// Returns the parent record decl, if any.
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.
191
bool isFullyCompiled() const { return IsFullyCompiled; }
192
193
bool hasThisPointer() const { return HasThisPointer; }
194
195
/// Checks if the function already has a body attached.
196
bool hasBody() const { return HasBody; }
197
198
/// Checks if the function is defined.
199
bool isDefined() const { return Defined; }
200
201
bool isVariadic() const { return Variadic; }
202
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.
207
unsigned getNumWrittenParams() const {
208
assert(getNumParams() >= (unsigned)(hasThisPointer() + hasRVO()));
209
return getNumParams() - hasThisPointer() - hasRVO();
210
}
211
unsigned getWrittenArgSize() const {
212
return ArgSize - (align(primSize(PT_Ptr)) * (hasThisPointer() + hasRVO()));
213
}
214
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
222
unsigned getParamOffset(unsigned ParamIndex) const {
223
return ParamOffsets[ParamIndex];
224
}
225
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.
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
250
void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; }
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
321