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