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