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