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/Compiler.h
213799 views
1
//===--- Compiler.h - Code generator for expressions -----*- 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 constexpr bytecode compiler.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
14
#define LLVM_CLANG_AST_INTERP_BYTECODEEXPRGEN_H
15
16
#include "ByteCodeEmitter.h"
17
#include "EvalEmitter.h"
18
#include "Pointer.h"
19
#include "PrimType.h"
20
#include "Record.h"
21
#include "clang/AST/Decl.h"
22
#include "clang/AST/Expr.h"
23
#include "clang/AST/StmtVisitor.h"
24
#include "clang/Basic/TargetInfo.h"
25
26
namespace clang {
27
class QualType;
28
29
namespace interp {
30
31
template <class Emitter> class LocalScope;
32
template <class Emitter> class DestructorScope;
33
template <class Emitter> class VariableScope;
34
template <class Emitter> class DeclScope;
35
template <class Emitter> class InitLinkScope;
36
template <class Emitter> class InitStackScope;
37
template <class Emitter> class OptionScope;
38
template <class Emitter> class ArrayIndexScope;
39
template <class Emitter> class SourceLocScope;
40
template <class Emitter> class LoopScope;
41
template <class Emitter> class LabelScope;
42
template <class Emitter> class SwitchScope;
43
template <class Emitter> class StmtExprScope;
44
45
template <class Emitter> class Compiler;
46
struct InitLink {
47
public:
48
enum {
49
K_This = 0,
50
K_Field = 1,
51
K_Temp = 2,
52
K_Decl = 3,
53
K_Elem = 5,
54
K_RVO = 6,
55
K_InitList = 7
56
};
57
58
static InitLink This() { return InitLink{K_This}; }
59
static InitLink InitList() { return InitLink{K_InitList}; }
60
static InitLink RVO() { return InitLink{K_RVO}; }
61
static InitLink Field(unsigned Offset) {
62
InitLink IL{K_Field};
63
IL.Offset = Offset;
64
return IL;
65
}
66
static InitLink Temp(unsigned Offset) {
67
InitLink IL{K_Temp};
68
IL.Offset = Offset;
69
return IL;
70
}
71
static InitLink Decl(const ValueDecl *D) {
72
InitLink IL{K_Decl};
73
IL.D = D;
74
return IL;
75
}
76
static InitLink Elem(unsigned Index) {
77
InitLink IL{K_Elem};
78
IL.Offset = Index;
79
return IL;
80
}
81
82
InitLink(uint8_t Kind) : Kind(Kind) {}
83
template <class Emitter>
84
bool emit(Compiler<Emitter> *Ctx, const Expr *E) const;
85
86
uint32_t Kind;
87
union {
88
unsigned Offset;
89
const ValueDecl *D;
90
};
91
};
92
93
/// State encapsulating if a the variable creation has been successful,
94
/// unsuccessful, or no variable has been created at all.
95
struct VarCreationState {
96
std::optional<bool> S = std::nullopt;
97
VarCreationState() = default;
98
VarCreationState(bool b) : S(b) {}
99
static VarCreationState NotCreated() { return VarCreationState(); }
100
101
operator bool() const { return S && *S; }
102
bool notCreated() const { return !S; }
103
};
104
105
enum class ScopeKind { Call, Block };
106
107
/// Compilation context for expressions.
108
template <class Emitter>
109
class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
110
public Emitter {
111
protected:
112
// Aliases for types defined in the emitter.
113
using LabelTy = typename Emitter::LabelTy;
114
using AddrTy = typename Emitter::AddrTy;
115
using OptLabelTy = std::optional<LabelTy>;
116
using CaseMap = llvm::DenseMap<const SwitchCase *, LabelTy>;
117
118
/// Current compilation context.
119
Context &Ctx;
120
/// Program to link to.
121
Program &P;
122
123
public:
124
/// Initializes the compiler and the backend emitter.
125
template <typename... Tys>
126
Compiler(Context &Ctx, Program &P, Tys &&...Args)
127
: Emitter(Ctx, P, Args...), Ctx(Ctx), P(P) {}
128
129
// Expressions.
130
bool VisitCastExpr(const CastExpr *E);
131
bool VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *E);
132
bool VisitIntegerLiteral(const IntegerLiteral *E);
133
bool VisitFloatingLiteral(const FloatingLiteral *E);
134
bool VisitImaginaryLiteral(const ImaginaryLiteral *E);
135
bool VisitFixedPointLiteral(const FixedPointLiteral *E);
136
bool VisitParenExpr(const ParenExpr *E);
137
bool VisitBinaryOperator(const BinaryOperator *E);
138
bool VisitLogicalBinOp(const BinaryOperator *E);
139
bool VisitPointerArithBinOp(const BinaryOperator *E);
140
bool VisitComplexBinOp(const BinaryOperator *E);
141
bool VisitVectorBinOp(const BinaryOperator *E);
142
bool VisitFixedPointBinOp(const BinaryOperator *E);
143
bool VisitFixedPointUnaryOperator(const UnaryOperator *E);
144
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
145
bool VisitCallExpr(const CallExpr *E);
146
bool VisitBuiltinCallExpr(const CallExpr *E, unsigned BuiltinID);
147
bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E);
148
bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E);
149
bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E);
150
bool VisitGNUNullExpr(const GNUNullExpr *E);
151
bool VisitCXXThisExpr(const CXXThisExpr *E);
152
bool VisitUnaryOperator(const UnaryOperator *E);
153
bool VisitVectorUnaryOperator(const UnaryOperator *E);
154
bool VisitComplexUnaryOperator(const UnaryOperator *E);
155
bool VisitDeclRefExpr(const DeclRefExpr *E);
156
bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E);
157
bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E);
158
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
159
bool VisitInitListExpr(const InitListExpr *E);
160
bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E);
161
bool VisitConstantExpr(const ConstantExpr *E);
162
bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
163
bool VisitMemberExpr(const MemberExpr *E);
164
bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E);
165
bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E);
166
bool VisitOpaqueValueExpr(const OpaqueValueExpr *E);
167
bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E);
168
bool VisitStringLiteral(const StringLiteral *E);
169
bool VisitObjCStringLiteral(const ObjCStringLiteral *E);
170
bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
171
bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E);
172
bool VisitCharacterLiteral(const CharacterLiteral *E);
173
bool VisitCompoundAssignOperator(const CompoundAssignOperator *E);
174
bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E);
175
bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E);
176
bool VisitExprWithCleanups(const ExprWithCleanups *E);
177
bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
178
bool VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E);
179
bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
180
bool VisitTypeTraitExpr(const TypeTraitExpr *E);
181
bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E);
182
bool VisitLambdaExpr(const LambdaExpr *E);
183
bool VisitPredefinedExpr(const PredefinedExpr *E);
184
bool VisitCXXThrowExpr(const CXXThrowExpr *E);
185
bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E);
186
bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E);
187
bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
188
bool VisitCXXConstructExpr(const CXXConstructExpr *E);
189
bool VisitSourceLocExpr(const SourceLocExpr *E);
190
bool VisitOffsetOfExpr(const OffsetOfExpr *E);
191
bool VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E);
192
bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
193
bool VisitGenericSelectionExpr(const GenericSelectionExpr *E);
194
bool VisitChooseExpr(const ChooseExpr *E);
195
bool VisitEmbedExpr(const EmbedExpr *E);
196
bool VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E);
197
bool VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E);
198
bool VisitExpressionTraitExpr(const ExpressionTraitExpr *E);
199
bool VisitCXXUuidofExpr(const CXXUuidofExpr *E);
200
bool VisitRequiresExpr(const RequiresExpr *E);
201
bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E);
202
bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E);
203
bool VisitPseudoObjectExpr(const PseudoObjectExpr *E);
204
bool VisitPackIndexingExpr(const PackIndexingExpr *E);
205
bool VisitRecoveryExpr(const RecoveryExpr *E);
206
bool VisitAddrLabelExpr(const AddrLabelExpr *E);
207
bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
208
bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
209
bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E);
210
bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E);
211
bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E);
212
bool VisitStmtExpr(const StmtExpr *E);
213
bool VisitCXXNewExpr(const CXXNewExpr *E);
214
bool VisitCXXDeleteExpr(const CXXDeleteExpr *E);
215
bool VisitBlockExpr(const BlockExpr *E);
216
bool VisitCXXTypeidExpr(const CXXTypeidExpr *E);
217
218
// Statements.
219
bool visitCompoundStmt(const CompoundStmt *S);
220
bool visitDeclStmt(const DeclStmt *DS, bool EvaluateConditionDecl = false);
221
bool visitReturnStmt(const ReturnStmt *RS);
222
bool visitIfStmt(const IfStmt *IS);
223
bool visitWhileStmt(const WhileStmt *S);
224
bool visitDoStmt(const DoStmt *S);
225
bool visitForStmt(const ForStmt *S);
226
bool visitCXXForRangeStmt(const CXXForRangeStmt *S);
227
bool visitBreakStmt(const BreakStmt *S);
228
bool visitContinueStmt(const ContinueStmt *S);
229
bool visitSwitchStmt(const SwitchStmt *S);
230
bool visitCaseStmt(const CaseStmt *S);
231
bool visitDefaultStmt(const DefaultStmt *S);
232
bool visitAttributedStmt(const AttributedStmt *S);
233
bool visitCXXTryStmt(const CXXTryStmt *S);
234
235
protected:
236
bool visitStmt(const Stmt *S);
237
bool visitExpr(const Expr *E, bool DestroyToplevelScope) override;
238
bool visitFunc(const FunctionDecl *F) override;
239
240
bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) override;
241
242
protected:
243
/// Emits scope cleanup instructions.
244
void emitCleanup();
245
246
/// Returns a record type from a record or pointer type.
247
const RecordType *getRecordTy(QualType Ty);
248
249
/// Returns a record from a record or pointer type.
250
Record *getRecord(QualType Ty);
251
Record *getRecord(const RecordDecl *RD);
252
253
/// Returns a function for the given FunctionDecl.
254
/// If the function does not exist yet, it is compiled.
255
const Function *getFunction(const FunctionDecl *FD);
256
257
std::optional<PrimType> classify(const Expr *E) const {
258
return Ctx.classify(E);
259
}
260
std::optional<PrimType> classify(QualType Ty) const {
261
return Ctx.classify(Ty);
262
}
263
264
/// Classifies a known primitive type.
265
PrimType classifyPrim(QualType Ty) const {
266
if (auto T = classify(Ty)) {
267
return *T;
268
}
269
llvm_unreachable("not a primitive type");
270
}
271
/// Classifies a known primitive expression.
272
PrimType classifyPrim(const Expr *E) const {
273
if (auto T = classify(E))
274
return *T;
275
llvm_unreachable("not a primitive type");
276
}
277
278
/// Evaluates an expression and places the result on the stack. If the
279
/// expression is of composite type, a local variable will be created
280
/// and a pointer to said variable will be placed on the stack.
281
bool visit(const Expr *E) override;
282
/// Compiles an initializer. This is like visit() but it will never
283
/// create a variable and instead rely on a variable already having
284
/// been created. visitInitializer() then relies on a pointer to this
285
/// variable being on top of the stack.
286
bool visitInitializer(const Expr *E);
287
/// Evaluates an expression for side effects and discards the result.
288
bool discard(const Expr *E);
289
/// Just pass evaluation on to \p E. This leaves all the parsing flags
290
/// intact.
291
bool delegate(const Expr *E);
292
/// Creates and initializes a variable from the given decl.
293
VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false,
294
bool IsConstexprUnknown = false);
295
VarCreationState visitDecl(const VarDecl *VD,
296
bool IsConstexprUnknown = false);
297
/// Visit an APValue.
298
bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
299
bool visitAPValueInitializer(const APValue &Val, const Expr *E, QualType T);
300
/// Visit the given decl as if we have a reference to it.
301
bool visitDeclRef(const ValueDecl *D, const Expr *E);
302
303
/// Visits an expression and converts it to a boolean.
304
bool visitBool(const Expr *E);
305
306
bool visitInitList(ArrayRef<const Expr *> Inits, const Expr *ArrayFiller,
307
const Expr *E);
308
bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init,
309
std::optional<PrimType> InitT);
310
bool visitCallArgs(ArrayRef<const Expr *> Args, const FunctionDecl *FuncDecl);
311
312
/// Creates a local primitive value.
313
unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst,
314
const ValueDecl *ExtendingDecl = nullptr,
315
ScopeKind SC = ScopeKind::Block,
316
bool IsConstexprUnknown = false);
317
318
/// Allocates a space storing a local given its type.
319
std::optional<unsigned>
320
allocateLocal(DeclTy &&Decl, QualType Ty = QualType(),
321
const ValueDecl *ExtendingDecl = nullptr,
322
ScopeKind = ScopeKind::Block, bool IsConstexprUnknown = false);
323
std::optional<unsigned> allocateTemporary(const Expr *E);
324
325
private:
326
friend class VariableScope<Emitter>;
327
friend class LocalScope<Emitter>;
328
friend class DestructorScope<Emitter>;
329
friend class DeclScope<Emitter>;
330
friend class InitLinkScope<Emitter>;
331
friend class InitStackScope<Emitter>;
332
friend class OptionScope<Emitter>;
333
friend class ArrayIndexScope<Emitter>;
334
friend class SourceLocScope<Emitter>;
335
friend struct InitLink;
336
friend class LoopScope<Emitter>;
337
friend class LabelScope<Emitter>;
338
friend class SwitchScope<Emitter>;
339
friend class StmtExprScope<Emitter>;
340
341
/// Emits a zero initializer.
342
bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E);
343
bool visitZeroRecordInitializer(const Record *R, const Expr *E);
344
bool visitZeroArrayInitializer(QualType T, const Expr *E);
345
346
/// Emits an APSInt constant.
347
bool emitConst(const llvm::APSInt &Value, PrimType Ty, const Expr *E);
348
bool emitConst(const llvm::APSInt &Value, const Expr *E);
349
bool emitConst(const llvm::APInt &Value, const Expr *E) {
350
return emitConst(static_cast<llvm::APSInt>(Value), E);
351
}
352
353
/// Emits an integer constant.
354
template <typename T> bool emitConst(T Value, PrimType Ty, const Expr *E);
355
template <typename T> bool emitConst(T Value, const Expr *E);
356
bool emitBool(bool V, const Expr *E) override {
357
return this->emitConst(V, E);
358
}
359
360
llvm::RoundingMode getRoundingMode(const Expr *E) const {
361
FPOptions FPO = E->getFPFeaturesInEffect(Ctx.getLangOpts());
362
363
if (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic)
364
return llvm::RoundingMode::NearestTiesToEven;
365
366
return FPO.getRoundingMode();
367
}
368
369
uint32_t getFPOptions(const Expr *E) const {
370
return E->getFPFeaturesInEffect(Ctx.getLangOpts()).getAsOpaqueInt();
371
}
372
373
bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E);
374
PrimType classifyComplexElementType(QualType T) const {
375
assert(T->isAnyComplexType());
376
377
QualType ElemType = T->getAs<ComplexType>()->getElementType();
378
379
return *this->classify(ElemType);
380
}
381
382
PrimType classifyVectorElementType(QualType T) const {
383
assert(T->isVectorType());
384
return *this->classify(T->getAs<VectorType>()->getElementType());
385
}
386
387
bool emitComplexReal(const Expr *SubExpr);
388
bool emitComplexBoolCast(const Expr *E);
389
bool emitComplexComparison(const Expr *LHS, const Expr *RHS,
390
const BinaryOperator *E);
391
bool emitRecordDestruction(const Record *R, SourceInfo Loc);
392
bool emitDestruction(const Descriptor *Desc, SourceInfo Loc);
393
bool emitDummyPtr(const DeclTy &D, const Expr *E);
394
bool emitFloat(const APFloat &F, const Expr *E);
395
unsigned collectBaseOffset(const QualType BaseType,
396
const QualType DerivedType);
397
bool emitLambdaStaticInvokerBody(const CXXMethodDecl *MD);
398
bool emitBuiltinBitCast(const CastExpr *E);
399
bool compileConstructor(const CXXConstructorDecl *Ctor);
400
bool compileDestructor(const CXXDestructorDecl *Dtor);
401
bool compileUnionAssignmentOperator(const CXXMethodDecl *MD);
402
403
bool checkLiteralType(const Expr *E);
404
bool maybeEmitDeferredVarInit(const VarDecl *VD);
405
406
protected:
407
/// Variable to storage mapping.
408
llvm::DenseMap<const ValueDecl *, Scope::Local> Locals;
409
410
/// OpaqueValueExpr to location mapping.
411
llvm::DenseMap<const OpaqueValueExpr *, unsigned> OpaqueExprs;
412
413
/// Current scope.
414
VariableScope<Emitter> *VarScope = nullptr;
415
416
/// Current argument index. Needed to emit ArrayInitIndexExpr.
417
std::optional<uint64_t> ArrayIndex;
418
419
/// DefaultInit- or DefaultArgExpr, needed for SourceLocExpr.
420
const Expr *SourceLocDefaultExpr = nullptr;
421
422
/// Flag indicating if return value is to be discarded.
423
bool DiscardResult = false;
424
425
bool InStmtExpr = false;
426
427
/// Flag inidicating if we're initializing an already created
428
/// variable. This is set in visitInitializer().
429
bool Initializing = false;
430
const ValueDecl *InitializingDecl = nullptr;
431
432
llvm::SmallVector<InitLink> InitStack;
433
bool InitStackActive = false;
434
435
/// Type of the expression returned by the function.
436
std::optional<PrimType> ReturnType;
437
438
/// Switch case mapping.
439
CaseMap CaseLabels;
440
441
/// Scope to cleanup until when we see a break statement.
442
VariableScope<Emitter> *BreakVarScope = nullptr;
443
/// Point to break to.
444
OptLabelTy BreakLabel;
445
/// Scope to cleanup until when we see a continue statement.
446
VariableScope<Emitter> *ContinueVarScope = nullptr;
447
/// Point to continue to.
448
OptLabelTy ContinueLabel;
449
/// Default case label.
450
OptLabelTy DefaultLabel;
451
452
const FunctionDecl *CompilingFunction = nullptr;
453
};
454
455
extern template class Compiler<ByteCodeEmitter>;
456
extern template class Compiler<EvalEmitter>;
457
458
/// Scope chain managing the variable lifetimes.
459
template <class Emitter> class VariableScope {
460
public:
461
VariableScope(Compiler<Emitter> *Ctx, const ValueDecl *VD,
462
ScopeKind Kind = ScopeKind::Block)
463
: Ctx(Ctx), Parent(Ctx->VarScope), ValDecl(VD), Kind(Kind) {
464
Ctx->VarScope = this;
465
}
466
467
virtual ~VariableScope() { Ctx->VarScope = this->Parent; }
468
469
virtual void addLocal(const Scope::Local &Local) {
470
llvm_unreachable("Shouldn't be called");
471
}
472
473
void addExtended(const Scope::Local &Local, const ValueDecl *ExtendingDecl) {
474
// Walk up the chain of scopes until we find the one for ExtendingDecl.
475
// If there is no such scope, attach it to the parent one.
476
VariableScope *P = this;
477
while (P) {
478
if (P->ValDecl == ExtendingDecl) {
479
P->addLocal(Local);
480
return;
481
}
482
P = P->Parent;
483
if (!P)
484
break;
485
}
486
487
// Use the parent scope.
488
if (this->Parent)
489
this->Parent->addLocal(Local);
490
else
491
this->addLocal(Local);
492
}
493
494
/// Like addExtended, but adds to the nearest scope of the given kind.
495
void addForScopeKind(const Scope::Local &Local, ScopeKind Kind) {
496
VariableScope *P = this;
497
while (P) {
498
if (P->Kind == Kind) {
499
P->addLocal(Local);
500
return;
501
}
502
P = P->Parent;
503
if (!P)
504
break;
505
}
506
507
// Add to this scope.
508
this->addLocal(Local);
509
}
510
511
virtual void emitDestruction() {}
512
virtual bool emitDestructors(const Expr *E = nullptr) { return true; }
513
virtual bool destroyLocals(const Expr *E = nullptr) { return true; }
514
VariableScope *getParent() const { return Parent; }
515
ScopeKind getKind() const { return Kind; }
516
517
protected:
518
/// Compiler instance.
519
Compiler<Emitter> *Ctx;
520
/// Link to the parent scope.
521
VariableScope *Parent;
522
const ValueDecl *ValDecl = nullptr;
523
ScopeKind Kind;
524
};
525
526
/// Generic scope for local variables.
527
template <class Emitter> class LocalScope : public VariableScope<Emitter> {
528
public:
529
LocalScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block)
530
: VariableScope<Emitter>(Ctx, nullptr, Kind) {}
531
LocalScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
532
: VariableScope<Emitter>(Ctx, VD) {}
533
534
/// Emit a Destroy op for this scope.
535
~LocalScope() override {
536
if (!Idx)
537
return;
538
this->Ctx->emitDestroy(*Idx, SourceInfo{});
539
removeStoredOpaqueValues();
540
}
541
542
/// Overriden to support explicit destruction.
543
void emitDestruction() override {
544
if (!Idx)
545
return;
546
547
this->emitDestructors();
548
this->Ctx->emitDestroy(*Idx, SourceInfo{});
549
}
550
551
/// Explicit destruction of local variables.
552
bool destroyLocals(const Expr *E = nullptr) override {
553
if (!Idx)
554
return true;
555
556
// NB: We are *not* resetting Idx here as to allow multiple
557
// calls to destroyLocals().
558
bool Success = this->emitDestructors(E);
559
this->Ctx->emitDestroy(*Idx, E);
560
return Success;
561
}
562
563
void addLocal(const Scope::Local &Local) override {
564
if (!Idx) {
565
Idx = this->Ctx->Descriptors.size();
566
this->Ctx->Descriptors.emplace_back();
567
this->Ctx->emitInitScope(*Idx, {});
568
}
569
570
this->Ctx->Descriptors[*Idx].emplace_back(Local);
571
}
572
573
bool emitDestructors(const Expr *E = nullptr) override {
574
if (!Idx)
575
return true;
576
// Emit destructor calls for local variables of record
577
// type with a destructor.
578
for (Scope::Local &Local : llvm::reverse(this->Ctx->Descriptors[*Idx])) {
579
if (Local.Desc->hasTrivialDtor())
580
continue;
581
if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
582
return false;
583
584
if (!this->Ctx->emitDestruction(Local.Desc, Local.Desc->getLoc()))
585
return false;
586
587
if (!this->Ctx->emitPopPtr(E))
588
return false;
589
removeIfStoredOpaqueValue(Local);
590
}
591
return true;
592
}
593
594
void removeStoredOpaqueValues() {
595
if (!Idx)
596
return;
597
598
for (const Scope::Local &Local : this->Ctx->Descriptors[*Idx]) {
599
removeIfStoredOpaqueValue(Local);
600
}
601
}
602
603
void removeIfStoredOpaqueValue(const Scope::Local &Local) {
604
if (const auto *OVE =
605
llvm::dyn_cast_if_present<OpaqueValueExpr>(Local.Desc->asExpr())) {
606
if (auto It = this->Ctx->OpaqueExprs.find(OVE);
607
It != this->Ctx->OpaqueExprs.end())
608
this->Ctx->OpaqueExprs.erase(It);
609
};
610
}
611
612
/// Index of the scope in the chain.
613
std::optional<unsigned> Idx;
614
};
615
616
/// Scope for storage declared in a compound statement.
617
// FIXME: Remove?
618
template <class Emitter> class BlockScope final : public LocalScope<Emitter> {
619
public:
620
BlockScope(Compiler<Emitter> *Ctx, ScopeKind Kind = ScopeKind::Block)
621
: LocalScope<Emitter>(Ctx, Kind) {}
622
};
623
624
template <class Emitter> class ArrayIndexScope final {
625
public:
626
ArrayIndexScope(Compiler<Emitter> *Ctx, uint64_t Index) : Ctx(Ctx) {
627
OldArrayIndex = Ctx->ArrayIndex;
628
Ctx->ArrayIndex = Index;
629
}
630
631
~ArrayIndexScope() { Ctx->ArrayIndex = OldArrayIndex; }
632
633
private:
634
Compiler<Emitter> *Ctx;
635
std::optional<uint64_t> OldArrayIndex;
636
};
637
638
template <class Emitter> class SourceLocScope final {
639
public:
640
SourceLocScope(Compiler<Emitter> *Ctx, const Expr *DefaultExpr) : Ctx(Ctx) {
641
assert(DefaultExpr);
642
// We only switch if the current SourceLocDefaultExpr is null.
643
if (!Ctx->SourceLocDefaultExpr) {
644
Enabled = true;
645
Ctx->SourceLocDefaultExpr = DefaultExpr;
646
}
647
}
648
649
~SourceLocScope() {
650
if (Enabled)
651
Ctx->SourceLocDefaultExpr = nullptr;
652
}
653
654
private:
655
Compiler<Emitter> *Ctx;
656
bool Enabled = false;
657
};
658
659
template <class Emitter> class InitLinkScope final {
660
public:
661
InitLinkScope(Compiler<Emitter> *Ctx, InitLink &&Link) : Ctx(Ctx) {
662
Ctx->InitStack.push_back(std::move(Link));
663
}
664
665
~InitLinkScope() { this->Ctx->InitStack.pop_back(); }
666
667
private:
668
Compiler<Emitter> *Ctx;
669
};
670
671
template <class Emitter> class InitStackScope final {
672
public:
673
InitStackScope(Compiler<Emitter> *Ctx, bool Active)
674
: Ctx(Ctx), OldValue(Ctx->InitStackActive) {
675
Ctx->InitStackActive = Active;
676
}
677
678
~InitStackScope() { this->Ctx->InitStackActive = OldValue; }
679
680
private:
681
Compiler<Emitter> *Ctx;
682
bool OldValue;
683
};
684
685
} // namespace interp
686
} // namespace clang
687
688
#endif
689
690