1a7dea167SDimitry Andric //===--- ByteCodeExprGen.cpp - Code generator for expressions ---*- C++ -*-===// 2a7dea167SDimitry Andric // 3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric 9a7dea167SDimitry Andric #include "ByteCodeExprGen.h" 10a7dea167SDimitry Andric #include "ByteCodeEmitter.h" 11a7dea167SDimitry Andric #include "ByteCodeGenError.h" 12bdd1243dSDimitry Andric #include "ByteCodeStmtGen.h" 13a7dea167SDimitry Andric #include "Context.h" 14*fe013be4SDimitry Andric #include "Floating.h" 15a7dea167SDimitry Andric #include "Function.h" 16a7dea167SDimitry Andric #include "PrimType.h" 17a7dea167SDimitry Andric #include "Program.h" 18a7dea167SDimitry Andric #include "State.h" 19a7dea167SDimitry Andric 20a7dea167SDimitry Andric using namespace clang; 21a7dea167SDimitry Andric using namespace clang::interp; 22a7dea167SDimitry Andric 23a7dea167SDimitry Andric using APSInt = llvm::APSInt; 24a7dea167SDimitry Andric 25a7dea167SDimitry Andric namespace clang { 26a7dea167SDimitry Andric namespace interp { 27a7dea167SDimitry Andric 28a7dea167SDimitry Andric /// Scope used to handle temporaries in toplevel variable declarations. 29*fe013be4SDimitry Andric template <class Emitter> class DeclScope final : public VariableScope<Emitter> { 30a7dea167SDimitry Andric public: 31*fe013be4SDimitry Andric DeclScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD) 32*fe013be4SDimitry Andric : VariableScope<Emitter>(Ctx), Scope(Ctx->P, VD) {} 33a7dea167SDimitry Andric 34a7dea167SDimitry Andric void addExtended(const Scope::Local &Local) override { 35a7dea167SDimitry Andric return this->addLocal(Local); 36a7dea167SDimitry Andric } 37a7dea167SDimitry Andric 38a7dea167SDimitry Andric private: 39a7dea167SDimitry Andric Program::DeclScope Scope; 40a7dea167SDimitry Andric }; 41a7dea167SDimitry Andric 42a7dea167SDimitry Andric /// Scope used to handle initialization methods. 43*fe013be4SDimitry Andric template <class Emitter> class OptionScope final { 44a7dea167SDimitry Andric public: 45a7dea167SDimitry Andric /// Root constructor, compiling or discarding primitives. 46a7dea167SDimitry Andric OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult) 47bdd1243dSDimitry Andric : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult) { 48a7dea167SDimitry Andric Ctx->DiscardResult = NewDiscardResult; 49a7dea167SDimitry Andric } 50a7dea167SDimitry Andric 51bdd1243dSDimitry Andric ~OptionScope() { Ctx->DiscardResult = OldDiscardResult; } 52a7dea167SDimitry Andric 53a7dea167SDimitry Andric private: 54a7dea167SDimitry Andric /// Parent context. 55a7dea167SDimitry Andric ByteCodeExprGen<Emitter> *Ctx; 56a7dea167SDimitry Andric /// Old discard flag to restore. 57a7dea167SDimitry Andric bool OldDiscardResult; 58a7dea167SDimitry Andric }; 59a7dea167SDimitry Andric 60a7dea167SDimitry Andric } // namespace interp 61a7dea167SDimitry Andric } // namespace clang 62a7dea167SDimitry Andric 63a7dea167SDimitry Andric template <class Emitter> 64a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) { 65a7dea167SDimitry Andric auto *SubExpr = CE->getSubExpr(); 66a7dea167SDimitry Andric switch (CE->getCastKind()) { 67a7dea167SDimitry Andric 68a7dea167SDimitry Andric case CK_LValueToRValue: { 69a7dea167SDimitry Andric return dereference( 70*fe013be4SDimitry Andric SubExpr, DerefKind::Read, 71a7dea167SDimitry Andric [](PrimType) { 72a7dea167SDimitry Andric // Value loaded - nothing to do here. 73a7dea167SDimitry Andric return true; 74a7dea167SDimitry Andric }, 75a7dea167SDimitry Andric [this, CE](PrimType T) { 76a7dea167SDimitry Andric // Pointer on stack - dereference it. 77a7dea167SDimitry Andric if (!this->emitLoadPop(T, CE)) 78a7dea167SDimitry Andric return false; 79a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, CE) : true; 80a7dea167SDimitry Andric }); 81a7dea167SDimitry Andric } 82a7dea167SDimitry Andric 83bdd1243dSDimitry Andric case CK_UncheckedDerivedToBase: 84bdd1243dSDimitry Andric case CK_DerivedToBase: { 85bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 86bdd1243dSDimitry Andric return false; 87bdd1243dSDimitry Andric 88*fe013be4SDimitry Andric return this->emitDerivedToBaseCasts(getRecordTy(SubExpr->getType()), 89*fe013be4SDimitry Andric getRecordTy(CE->getType()), CE); 90bdd1243dSDimitry Andric } 91bdd1243dSDimitry Andric 92*fe013be4SDimitry Andric case CK_FloatingCast: { 93*fe013be4SDimitry Andric if (!this->visit(SubExpr)) 94*fe013be4SDimitry Andric return false; 95*fe013be4SDimitry Andric const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType()); 96*fe013be4SDimitry Andric return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE); 97*fe013be4SDimitry Andric } 98*fe013be4SDimitry Andric 99*fe013be4SDimitry Andric case CK_IntegralToFloating: { 100*fe013be4SDimitry Andric std::optional<PrimType> FromT = classify(SubExpr->getType()); 101*fe013be4SDimitry Andric if (!FromT) 102*fe013be4SDimitry Andric return false; 103*fe013be4SDimitry Andric 104*fe013be4SDimitry Andric if (!this->visit(SubExpr)) 105*fe013be4SDimitry Andric return false; 106*fe013be4SDimitry Andric 107*fe013be4SDimitry Andric const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType()); 108*fe013be4SDimitry Andric llvm::RoundingMode RM = getRoundingMode(CE); 109*fe013be4SDimitry Andric return this->emitCastIntegralFloating(*FromT, TargetSemantics, RM, CE); 110*fe013be4SDimitry Andric } 111*fe013be4SDimitry Andric 112*fe013be4SDimitry Andric case CK_FloatingToBoolean: 113*fe013be4SDimitry Andric case CK_FloatingToIntegral: { 114*fe013be4SDimitry Andric std::optional<PrimType> ToT = classify(CE->getType()); 115*fe013be4SDimitry Andric 116*fe013be4SDimitry Andric if (!ToT) 117*fe013be4SDimitry Andric return false; 118*fe013be4SDimitry Andric 119*fe013be4SDimitry Andric if (!this->visit(SubExpr)) 120*fe013be4SDimitry Andric return false; 121*fe013be4SDimitry Andric 122*fe013be4SDimitry Andric return this->emitCastFloatingIntegral(*ToT, CE); 123*fe013be4SDimitry Andric } 124*fe013be4SDimitry Andric 125*fe013be4SDimitry Andric case CK_NullToPointer: 126*fe013be4SDimitry Andric if (DiscardResult) 127*fe013be4SDimitry Andric return true; 128*fe013be4SDimitry Andric return this->emitNull(classifyPrim(CE->getType()), CE); 129*fe013be4SDimitry Andric 130a7dea167SDimitry Andric case CK_ArrayToPointerDecay: 131a7dea167SDimitry Andric case CK_AtomicToNonAtomic: 132a7dea167SDimitry Andric case CK_ConstructorConversion: 133a7dea167SDimitry Andric case CK_FunctionToPointerDecay: 134a7dea167SDimitry Andric case CK_NonAtomicToAtomic: 135a7dea167SDimitry Andric case CK_NoOp: 136a7dea167SDimitry Andric case CK_UserDefinedConversion: 137bdd1243dSDimitry Andric return this->visit(SubExpr); 138bdd1243dSDimitry Andric 139bdd1243dSDimitry Andric case CK_IntegralToBoolean: 140bdd1243dSDimitry Andric case CK_IntegralCast: { 141bdd1243dSDimitry Andric std::optional<PrimType> FromT = classify(SubExpr->getType()); 142bdd1243dSDimitry Andric std::optional<PrimType> ToT = classify(CE->getType()); 143bdd1243dSDimitry Andric if (!FromT || !ToT) 144bdd1243dSDimitry Andric return false; 145bdd1243dSDimitry Andric 146bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 147bdd1243dSDimitry Andric return false; 148bdd1243dSDimitry Andric 149*fe013be4SDimitry Andric if (FromT == ToT) 150*fe013be4SDimitry Andric return true; 151*fe013be4SDimitry Andric 152bdd1243dSDimitry Andric return this->emitCast(*FromT, *ToT, CE); 153bdd1243dSDimitry Andric } 154a7dea167SDimitry Andric 155*fe013be4SDimitry Andric case CK_PointerToBoolean: { 156*fe013be4SDimitry Andric // Just emit p != nullptr for this. 157*fe013be4SDimitry Andric if (!this->visit(SubExpr)) 158*fe013be4SDimitry Andric return false; 159*fe013be4SDimitry Andric 160*fe013be4SDimitry Andric if (!this->emitNullPtr(CE)) 161*fe013be4SDimitry Andric return false; 162*fe013be4SDimitry Andric 163*fe013be4SDimitry Andric return this->emitNEPtr(CE); 164*fe013be4SDimitry Andric } 165*fe013be4SDimitry Andric 166a7dea167SDimitry Andric case CK_ToVoid: 167a7dea167SDimitry Andric return discard(SubExpr); 168a7dea167SDimitry Andric 169bdd1243dSDimitry Andric default: 170bdd1243dSDimitry Andric assert(false && "Cast not implemented"); 171a7dea167SDimitry Andric } 172bdd1243dSDimitry Andric llvm_unreachable("Unhandled clang::CastKind enum"); 173a7dea167SDimitry Andric } 174a7dea167SDimitry Andric 175a7dea167SDimitry Andric template <class Emitter> 176a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) { 177a7dea167SDimitry Andric if (DiscardResult) 178a7dea167SDimitry Andric return true; 179a7dea167SDimitry Andric 180bdd1243dSDimitry Andric return this->emitConst(LE->getValue(), LE); 181a7dea167SDimitry Andric } 182a7dea167SDimitry Andric 183a7dea167SDimitry Andric template <class Emitter> 184*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) { 185*fe013be4SDimitry Andric if (DiscardResult) 186*fe013be4SDimitry Andric return true; 187*fe013be4SDimitry Andric 188*fe013be4SDimitry Andric return this->emitConstFloat(E->getValue(), E); 189*fe013be4SDimitry Andric } 190*fe013be4SDimitry Andric 191*fe013be4SDimitry Andric template <class Emitter> 192a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) { 193*fe013be4SDimitry Andric const Expr *SubExpr = PE->getSubExpr(); 194*fe013be4SDimitry Andric 195*fe013be4SDimitry Andric if (DiscardResult) 196*fe013be4SDimitry Andric return this->discard(SubExpr); 197*fe013be4SDimitry Andric 198*fe013be4SDimitry Andric return this->visit(SubExpr); 199a7dea167SDimitry Andric } 200a7dea167SDimitry Andric 201a7dea167SDimitry Andric template <class Emitter> 202a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) { 203*fe013be4SDimitry Andric // Need short-circuiting for these. 204*fe013be4SDimitry Andric if (BO->isLogicalOp()) 205*fe013be4SDimitry Andric return this->VisitLogicalBinOp(BO); 206*fe013be4SDimitry Andric 207a7dea167SDimitry Andric const Expr *LHS = BO->getLHS(); 208a7dea167SDimitry Andric const Expr *RHS = BO->getRHS(); 209a7dea167SDimitry Andric 210a7dea167SDimitry Andric // Typecheck the args. 211bdd1243dSDimitry Andric std::optional<PrimType> LT = classify(LHS->getType()); 212bdd1243dSDimitry Andric std::optional<PrimType> RT = classify(RHS->getType()); 213bdd1243dSDimitry Andric std::optional<PrimType> T = classify(BO->getType()); 214bdd1243dSDimitry Andric if (!LT || !RT || !T) { 215a7dea167SDimitry Andric return this->bail(BO); 216a7dea167SDimitry Andric } 217a7dea167SDimitry Andric 218a7dea167SDimitry Andric auto Discard = [this, T, BO](bool Result) { 219a7dea167SDimitry Andric if (!Result) 220a7dea167SDimitry Andric return false; 221a7dea167SDimitry Andric return DiscardResult ? this->emitPop(*T, BO) : true; 222a7dea167SDimitry Andric }; 223a7dea167SDimitry Andric 224*fe013be4SDimitry Andric // Deal with operations which have composite or void types. 225*fe013be4SDimitry Andric if (BO->isCommaOp()) { 226*fe013be4SDimitry Andric if (!discard(LHS)) 227*fe013be4SDimitry Andric return false; 228*fe013be4SDimitry Andric return Discard(this->visit(RHS)); 229*fe013be4SDimitry Andric } 230*fe013be4SDimitry Andric 231bdd1243dSDimitry Andric // Pointer arithmetic special case. 232bdd1243dSDimitry Andric if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) { 233*fe013be4SDimitry Andric if (T == PT_Ptr || (LT == PT_Ptr && RT == PT_Ptr)) 234bdd1243dSDimitry Andric return this->VisitPointerArithBinOp(BO); 235bdd1243dSDimitry Andric } 236bdd1243dSDimitry Andric 237bdd1243dSDimitry Andric if (!visit(LHS) || !visit(RHS)) 238bdd1243dSDimitry Andric return false; 239bdd1243dSDimitry Andric 240*fe013be4SDimitry Andric // For languages such as C, cast the result of one 241*fe013be4SDimitry Andric // of our comparision opcodes to T (which is usually int). 242*fe013be4SDimitry Andric auto MaybeCastToBool = [this, T, BO](bool Result) { 243*fe013be4SDimitry Andric if (!Result) 244*fe013be4SDimitry Andric return false; 245*fe013be4SDimitry Andric if (DiscardResult) 246*fe013be4SDimitry Andric return this->emitPop(*T, BO); 247*fe013be4SDimitry Andric if (T != PT_Bool) 248*fe013be4SDimitry Andric return this->emitCast(PT_Bool, *T, BO); 249*fe013be4SDimitry Andric return true; 250*fe013be4SDimitry Andric }; 251*fe013be4SDimitry Andric 252a7dea167SDimitry Andric switch (BO->getOpcode()) { 253a7dea167SDimitry Andric case BO_EQ: 254*fe013be4SDimitry Andric return MaybeCastToBool(this->emitEQ(*LT, BO)); 255a7dea167SDimitry Andric case BO_NE: 256*fe013be4SDimitry Andric return MaybeCastToBool(this->emitNE(*LT, BO)); 257a7dea167SDimitry Andric case BO_LT: 258*fe013be4SDimitry Andric return MaybeCastToBool(this->emitLT(*LT, BO)); 259a7dea167SDimitry Andric case BO_LE: 260*fe013be4SDimitry Andric return MaybeCastToBool(this->emitLE(*LT, BO)); 261a7dea167SDimitry Andric case BO_GT: 262*fe013be4SDimitry Andric return MaybeCastToBool(this->emitGT(*LT, BO)); 263a7dea167SDimitry Andric case BO_GE: 264*fe013be4SDimitry Andric return MaybeCastToBool(this->emitGE(*LT, BO)); 265a7dea167SDimitry Andric case BO_Sub: 266*fe013be4SDimitry Andric if (BO->getType()->isFloatingType()) 267*fe013be4SDimitry Andric return Discard(this->emitSubf(getRoundingMode(BO), BO)); 268a7dea167SDimitry Andric return Discard(this->emitSub(*T, BO)); 269a7dea167SDimitry Andric case BO_Add: 270*fe013be4SDimitry Andric if (BO->getType()->isFloatingType()) 271*fe013be4SDimitry Andric return Discard(this->emitAddf(getRoundingMode(BO), BO)); 272a7dea167SDimitry Andric return Discard(this->emitAdd(*T, BO)); 273a7dea167SDimitry Andric case BO_Mul: 274*fe013be4SDimitry Andric if (BO->getType()->isFloatingType()) 275*fe013be4SDimitry Andric return Discard(this->emitMulf(getRoundingMode(BO), BO)); 276a7dea167SDimitry Andric return Discard(this->emitMul(*T, BO)); 277bdd1243dSDimitry Andric case BO_Rem: 278bdd1243dSDimitry Andric return Discard(this->emitRem(*T, BO)); 279bdd1243dSDimitry Andric case BO_Div: 280*fe013be4SDimitry Andric if (BO->getType()->isFloatingType()) 281*fe013be4SDimitry Andric return Discard(this->emitDivf(getRoundingMode(BO), BO)); 282bdd1243dSDimitry Andric return Discard(this->emitDiv(*T, BO)); 283bdd1243dSDimitry Andric case BO_Assign: 284bdd1243dSDimitry Andric if (DiscardResult) 285bdd1243dSDimitry Andric return this->emitStorePop(*T, BO); 286bdd1243dSDimitry Andric return this->emitStore(*T, BO); 287bdd1243dSDimitry Andric case BO_And: 288bdd1243dSDimitry Andric return Discard(this->emitBitAnd(*T, BO)); 289bdd1243dSDimitry Andric case BO_Or: 290bdd1243dSDimitry Andric return Discard(this->emitBitOr(*T, BO)); 291bdd1243dSDimitry Andric case BO_Shl: 292bdd1243dSDimitry Andric return Discard(this->emitShl(*LT, *RT, BO)); 293bdd1243dSDimitry Andric case BO_Shr: 294bdd1243dSDimitry Andric return Discard(this->emitShr(*LT, *RT, BO)); 295bdd1243dSDimitry Andric case BO_Xor: 296bdd1243dSDimitry Andric return Discard(this->emitBitXor(*T, BO)); 297bdd1243dSDimitry Andric case BO_LOr: 298*fe013be4SDimitry Andric case BO_LAnd: 299*fe013be4SDimitry Andric llvm_unreachable("Already handled earlier"); 300a7dea167SDimitry Andric default: 301a7dea167SDimitry Andric return this->bail(BO); 302a7dea167SDimitry Andric } 303bdd1243dSDimitry Andric 304bdd1243dSDimitry Andric llvm_unreachable("Unhandled binary op"); 305a7dea167SDimitry Andric } 306a7dea167SDimitry Andric 307bdd1243dSDimitry Andric /// Perform addition/subtraction of a pointer and an integer or 308bdd1243dSDimitry Andric /// subtraction of two pointers. 309bdd1243dSDimitry Andric template <class Emitter> 310bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) { 311bdd1243dSDimitry Andric BinaryOperatorKind Op = E->getOpcode(); 312bdd1243dSDimitry Andric const Expr *LHS = E->getLHS(); 313bdd1243dSDimitry Andric const Expr *RHS = E->getRHS(); 314bdd1243dSDimitry Andric 315bdd1243dSDimitry Andric if ((Op != BO_Add && Op != BO_Sub) || 316bdd1243dSDimitry Andric (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType())) 317bdd1243dSDimitry Andric return false; 318bdd1243dSDimitry Andric 319bdd1243dSDimitry Andric std::optional<PrimType> LT = classify(LHS); 320bdd1243dSDimitry Andric std::optional<PrimType> RT = classify(RHS); 321bdd1243dSDimitry Andric 322bdd1243dSDimitry Andric if (!LT || !RT) 323bdd1243dSDimitry Andric return false; 324bdd1243dSDimitry Andric 325bdd1243dSDimitry Andric if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) { 326bdd1243dSDimitry Andric if (Op != BO_Sub) 327bdd1243dSDimitry Andric return false; 328bdd1243dSDimitry Andric 329bdd1243dSDimitry Andric assert(E->getType()->isIntegerType()); 330bdd1243dSDimitry Andric if (!visit(RHS) || !visit(LHS)) 331bdd1243dSDimitry Andric return false; 332bdd1243dSDimitry Andric 333bdd1243dSDimitry Andric return this->emitSubPtr(classifyPrim(E->getType()), E); 334bdd1243dSDimitry Andric } 335bdd1243dSDimitry Andric 336bdd1243dSDimitry Andric PrimType OffsetType; 337bdd1243dSDimitry Andric if (LHS->getType()->isIntegerType()) { 338bdd1243dSDimitry Andric if (!visit(RHS) || !visit(LHS)) 339bdd1243dSDimitry Andric return false; 340bdd1243dSDimitry Andric OffsetType = *LT; 341bdd1243dSDimitry Andric } else if (RHS->getType()->isIntegerType()) { 342bdd1243dSDimitry Andric if (!visit(LHS) || !visit(RHS)) 343bdd1243dSDimitry Andric return false; 344bdd1243dSDimitry Andric OffsetType = *RT; 345bdd1243dSDimitry Andric } else { 346bdd1243dSDimitry Andric return false; 347bdd1243dSDimitry Andric } 348bdd1243dSDimitry Andric 349bdd1243dSDimitry Andric if (Op == BO_Add) 350bdd1243dSDimitry Andric return this->emitAddOffset(OffsetType, E); 351bdd1243dSDimitry Andric else if (Op == BO_Sub) 352bdd1243dSDimitry Andric return this->emitSubOffset(OffsetType, E); 353bdd1243dSDimitry Andric 354bdd1243dSDimitry Andric return this->bail(E); 355a7dea167SDimitry Andric } 356a7dea167SDimitry Andric 357a7dea167SDimitry Andric template <class Emitter> 358*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) { 359*fe013be4SDimitry Andric assert(E->isLogicalOp()); 360*fe013be4SDimitry Andric BinaryOperatorKind Op = E->getOpcode(); 361*fe013be4SDimitry Andric const Expr *LHS = E->getLHS(); 362*fe013be4SDimitry Andric const Expr *RHS = E->getRHS(); 363bdd1243dSDimitry Andric 364*fe013be4SDimitry Andric if (Op == BO_LOr) { 365*fe013be4SDimitry Andric // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE. 366*fe013be4SDimitry Andric LabelTy LabelTrue = this->getLabel(); 367*fe013be4SDimitry Andric LabelTy LabelEnd = this->getLabel(); 368*fe013be4SDimitry Andric 369*fe013be4SDimitry Andric if (!this->visit(LHS)) 370bdd1243dSDimitry Andric return false; 371*fe013be4SDimitry Andric if (!this->jumpTrue(LabelTrue)) 372*fe013be4SDimitry Andric return false; 373*fe013be4SDimitry Andric 374*fe013be4SDimitry Andric if (!this->visit(RHS)) 375*fe013be4SDimitry Andric return false; 376*fe013be4SDimitry Andric if (!this->jump(LabelEnd)) 377*fe013be4SDimitry Andric return false; 378*fe013be4SDimitry Andric 379*fe013be4SDimitry Andric this->emitLabel(LabelTrue); 380*fe013be4SDimitry Andric this->emitConstBool(true, E); 381*fe013be4SDimitry Andric this->fallthrough(LabelEnd); 382*fe013be4SDimitry Andric this->emitLabel(LabelEnd); 383*fe013be4SDimitry Andric 384*fe013be4SDimitry Andric if (DiscardResult) 385*fe013be4SDimitry Andric return this->emitPopBool(E); 386*fe013be4SDimitry Andric 387*fe013be4SDimitry Andric return true; 388*fe013be4SDimitry Andric } 389*fe013be4SDimitry Andric 390*fe013be4SDimitry Andric // Logical AND. 391*fe013be4SDimitry Andric // Visit LHS. Only visit RHS if LHS was TRUE. 392*fe013be4SDimitry Andric LabelTy LabelFalse = this->getLabel(); 393*fe013be4SDimitry Andric LabelTy LabelEnd = this->getLabel(); 394*fe013be4SDimitry Andric 395*fe013be4SDimitry Andric if (!this->visit(LHS)) 396*fe013be4SDimitry Andric return false; 397*fe013be4SDimitry Andric if (!this->jumpFalse(LabelFalse)) 398*fe013be4SDimitry Andric return false; 399*fe013be4SDimitry Andric 400*fe013be4SDimitry Andric if (!this->visit(RHS)) 401*fe013be4SDimitry Andric return false; 402*fe013be4SDimitry Andric if (!this->jump(LabelEnd)) 403*fe013be4SDimitry Andric return false; 404*fe013be4SDimitry Andric 405*fe013be4SDimitry Andric this->emitLabel(LabelFalse); 406*fe013be4SDimitry Andric this->emitConstBool(false, E); 407*fe013be4SDimitry Andric this->fallthrough(LabelEnd); 408*fe013be4SDimitry Andric this->emitLabel(LabelEnd); 409*fe013be4SDimitry Andric 410*fe013be4SDimitry Andric if (DiscardResult) 411*fe013be4SDimitry Andric return this->emitPopBool(E); 412*fe013be4SDimitry Andric 413*fe013be4SDimitry Andric return true; 414*fe013be4SDimitry Andric } 415*fe013be4SDimitry Andric 416*fe013be4SDimitry Andric template <class Emitter> 417*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { 418*fe013be4SDimitry Andric std::optional<PrimType> T = classify(E); 419*fe013be4SDimitry Andric 420*fe013be4SDimitry Andric if (!T) 421*fe013be4SDimitry Andric return false; 422*fe013be4SDimitry Andric 423*fe013be4SDimitry Andric return this->visitZeroInitializer(E->getType(), E); 424bdd1243dSDimitry Andric } 425bdd1243dSDimitry Andric 426bdd1243dSDimitry Andric template <class Emitter> 427bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr( 428bdd1243dSDimitry Andric const ArraySubscriptExpr *E) { 429bdd1243dSDimitry Andric const Expr *Base = E->getBase(); 430bdd1243dSDimitry Andric const Expr *Index = E->getIdx(); 431bdd1243dSDimitry Andric PrimType IndexT = classifyPrim(Index->getType()); 432bdd1243dSDimitry Andric 433*fe013be4SDimitry Andric // Take pointer of LHS, add offset from RHS. 434bdd1243dSDimitry Andric // What's left on the stack after this is a pointer. 435bdd1243dSDimitry Andric if (!this->visit(Base)) 436bdd1243dSDimitry Andric return false; 437bdd1243dSDimitry Andric 438bdd1243dSDimitry Andric if (!this->visit(Index)) 439bdd1243dSDimitry Andric return false; 440bdd1243dSDimitry Andric 441*fe013be4SDimitry Andric if (!this->emitArrayElemPtrPop(IndexT, E)) 442bdd1243dSDimitry Andric return false; 443bdd1243dSDimitry Andric 444bdd1243dSDimitry Andric if (DiscardResult) 445bdd1243dSDimitry Andric return this->emitPopPtr(E); 446bdd1243dSDimitry Andric 447bdd1243dSDimitry Andric return true; 448bdd1243dSDimitry Andric } 449bdd1243dSDimitry Andric 450bdd1243dSDimitry Andric template <class Emitter> 451bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) { 452bdd1243dSDimitry Andric for (const Expr *Init : E->inits()) { 453bdd1243dSDimitry Andric if (!this->visit(Init)) 454bdd1243dSDimitry Andric return false; 455bdd1243dSDimitry Andric } 456bdd1243dSDimitry Andric return true; 457bdd1243dSDimitry Andric } 458bdd1243dSDimitry Andric 459bdd1243dSDimitry Andric template <class Emitter> 460bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitSubstNonTypeTemplateParmExpr( 461bdd1243dSDimitry Andric const SubstNonTypeTemplateParmExpr *E) { 462bdd1243dSDimitry Andric return this->visit(E->getReplacement()); 463bdd1243dSDimitry Andric } 464bdd1243dSDimitry Andric 465bdd1243dSDimitry Andric template <class Emitter> 466bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitConstantExpr(const ConstantExpr *E) { 467bdd1243dSDimitry Andric // TODO: Check if the ConstantExpr already has a value set and if so, 468bdd1243dSDimitry Andric // use that instead of evaluating it again. 469bdd1243dSDimitry Andric return this->visit(E->getSubExpr()); 470bdd1243dSDimitry Andric } 471bdd1243dSDimitry Andric 472bdd1243dSDimitry Andric static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx, 473bdd1243dSDimitry Andric UnaryExprOrTypeTrait Kind) { 474bdd1243dSDimitry Andric bool AlignOfReturnsPreferred = 475bdd1243dSDimitry Andric ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7; 476bdd1243dSDimitry Andric 477bdd1243dSDimitry Andric // C++ [expr.alignof]p3: 478bdd1243dSDimitry Andric // When alignof is applied to a reference type, the result is the 479bdd1243dSDimitry Andric // alignment of the referenced type. 480bdd1243dSDimitry Andric if (const auto *Ref = T->getAs<ReferenceType>()) 481bdd1243dSDimitry Andric T = Ref->getPointeeType(); 482bdd1243dSDimitry Andric 483bdd1243dSDimitry Andric // __alignof is defined to return the preferred alignment. 484bdd1243dSDimitry Andric // Before 8, clang returned the preferred alignment for alignof and 485bdd1243dSDimitry Andric // _Alignof as well. 486bdd1243dSDimitry Andric if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred) 487bdd1243dSDimitry Andric return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T)); 488bdd1243dSDimitry Andric 489bdd1243dSDimitry Andric return ASTCtx.getTypeAlignInChars(T); 490bdd1243dSDimitry Andric } 491bdd1243dSDimitry Andric 492bdd1243dSDimitry Andric template <class Emitter> 493bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryExprOrTypeTraitExpr( 494bdd1243dSDimitry Andric const UnaryExprOrTypeTraitExpr *E) { 495bdd1243dSDimitry Andric UnaryExprOrTypeTrait Kind = E->getKind(); 496bdd1243dSDimitry Andric ASTContext &ASTCtx = Ctx.getASTContext(); 497bdd1243dSDimitry Andric 498bdd1243dSDimitry Andric if (Kind == UETT_SizeOf) { 499bdd1243dSDimitry Andric QualType ArgType = E->getTypeOfArgument(); 500bdd1243dSDimitry Andric CharUnits Size; 501bdd1243dSDimitry Andric if (ArgType->isVoidType() || ArgType->isFunctionType()) 502bdd1243dSDimitry Andric Size = CharUnits::One(); 503bdd1243dSDimitry Andric else { 504bdd1243dSDimitry Andric if (ArgType->isDependentType() || !ArgType->isConstantSizeType()) 505bdd1243dSDimitry Andric return false; 506bdd1243dSDimitry Andric 507bdd1243dSDimitry Andric Size = ASTCtx.getTypeSizeInChars(ArgType); 508bdd1243dSDimitry Andric } 509bdd1243dSDimitry Andric 510bdd1243dSDimitry Andric return this->emitConst(Size.getQuantity(), E); 511bdd1243dSDimitry Andric } 512bdd1243dSDimitry Andric 513bdd1243dSDimitry Andric if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) { 514bdd1243dSDimitry Andric CharUnits Size; 515bdd1243dSDimitry Andric 516bdd1243dSDimitry Andric if (E->isArgumentType()) { 517bdd1243dSDimitry Andric QualType ArgType = E->getTypeOfArgument(); 518bdd1243dSDimitry Andric 519bdd1243dSDimitry Andric Size = AlignOfType(ArgType, ASTCtx, Kind); 520bdd1243dSDimitry Andric } else { 521bdd1243dSDimitry Andric // Argument is an expression, not a type. 522bdd1243dSDimitry Andric const Expr *Arg = E->getArgumentExpr()->IgnoreParens(); 523bdd1243dSDimitry Andric 524bdd1243dSDimitry Andric // The kinds of expressions that we have special-case logic here for 525bdd1243dSDimitry Andric // should be kept up to date with the special checks for those 526bdd1243dSDimitry Andric // expressions in Sema. 527bdd1243dSDimitry Andric 528bdd1243dSDimitry Andric // alignof decl is always accepted, even if it doesn't make sense: we 529bdd1243dSDimitry Andric // default to 1 in those cases. 530bdd1243dSDimitry Andric if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg)) 531bdd1243dSDimitry Andric Size = ASTCtx.getDeclAlign(DRE->getDecl(), 532bdd1243dSDimitry Andric /*RefAsPointee*/ true); 533bdd1243dSDimitry Andric else if (const auto *ME = dyn_cast<MemberExpr>(Arg)) 534bdd1243dSDimitry Andric Size = ASTCtx.getDeclAlign(ME->getMemberDecl(), 535bdd1243dSDimitry Andric /*RefAsPointee*/ true); 536bdd1243dSDimitry Andric else 537bdd1243dSDimitry Andric Size = AlignOfType(Arg->getType(), ASTCtx, Kind); 538bdd1243dSDimitry Andric } 539bdd1243dSDimitry Andric 540bdd1243dSDimitry Andric return this->emitConst(Size.getQuantity(), E); 541bdd1243dSDimitry Andric } 542bdd1243dSDimitry Andric 543bdd1243dSDimitry Andric return false; 544bdd1243dSDimitry Andric } 545bdd1243dSDimitry Andric 546bdd1243dSDimitry Andric template <class Emitter> 547bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) { 548bdd1243dSDimitry Andric if (DiscardResult) 549bdd1243dSDimitry Andric return true; 550bdd1243dSDimitry Andric 551bdd1243dSDimitry Andric // 'Base.Member' 552bdd1243dSDimitry Andric const Expr *Base = E->getBase(); 553bdd1243dSDimitry Andric const ValueDecl *Member = E->getMemberDecl(); 554bdd1243dSDimitry Andric 555bdd1243dSDimitry Andric if (!this->visit(Base)) 556bdd1243dSDimitry Andric return false; 557bdd1243dSDimitry Andric 558bdd1243dSDimitry Andric // Base above gives us a pointer on the stack. 559bdd1243dSDimitry Andric // TODO: Implement non-FieldDecl members. 560bdd1243dSDimitry Andric if (const auto *FD = dyn_cast<FieldDecl>(Member)) { 561bdd1243dSDimitry Andric const RecordDecl *RD = FD->getParent(); 562bdd1243dSDimitry Andric const Record *R = getRecord(RD); 563bdd1243dSDimitry Andric const Record::Field *F = R->getField(FD); 564bdd1243dSDimitry Andric // Leave a pointer to the field on the stack. 565bdd1243dSDimitry Andric if (F->Decl->getType()->isReferenceType()) 566bdd1243dSDimitry Andric return this->emitGetFieldPop(PT_Ptr, F->Offset, E); 567bdd1243dSDimitry Andric return this->emitGetPtrField(F->Offset, E); 568bdd1243dSDimitry Andric } 569bdd1243dSDimitry Andric 570bdd1243dSDimitry Andric return false; 571bdd1243dSDimitry Andric } 572bdd1243dSDimitry Andric 573bdd1243dSDimitry Andric template <class Emitter> 574bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArrayInitIndexExpr( 575bdd1243dSDimitry Andric const ArrayInitIndexExpr *E) { 576bdd1243dSDimitry Andric // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated 577bdd1243dSDimitry Andric // stand-alone, e.g. via EvaluateAsInt(). 578bdd1243dSDimitry Andric if (!ArrayIndex) 579bdd1243dSDimitry Andric return false; 580bdd1243dSDimitry Andric return this->emitConst(*ArrayIndex, E); 581bdd1243dSDimitry Andric } 582bdd1243dSDimitry Andric 583bdd1243dSDimitry Andric template <class Emitter> 584bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) { 585bdd1243dSDimitry Andric return this->visit(E->getSourceExpr()); 586bdd1243dSDimitry Andric } 587bdd1243dSDimitry Andric 588bdd1243dSDimitry Andric template <class Emitter> 589bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitAbstractConditionalOperator( 590bdd1243dSDimitry Andric const AbstractConditionalOperator *E) { 591*fe013be4SDimitry Andric return this->visitConditional( 592*fe013be4SDimitry Andric E, [this](const Expr *E) { return this->visit(E); }); 593bdd1243dSDimitry Andric } 594bdd1243dSDimitry Andric 595bdd1243dSDimitry Andric template <class Emitter> 596bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitStringLiteral(const StringLiteral *E) { 597bdd1243dSDimitry Andric unsigned StringIndex = P.createGlobalString(E); 598bdd1243dSDimitry Andric return this->emitGetPtrGlobal(StringIndex, E); 599bdd1243dSDimitry Andric } 600bdd1243dSDimitry Andric 601bdd1243dSDimitry Andric template <class Emitter> 602bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral( 603bdd1243dSDimitry Andric const CharacterLiteral *E) { 604bdd1243dSDimitry Andric return this->emitConst(E->getValue(), E); 605bdd1243dSDimitry Andric } 606bdd1243dSDimitry Andric 607bdd1243dSDimitry Andric template <class Emitter> 608*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitFloatCompoundAssignOperator( 609bdd1243dSDimitry Andric const CompoundAssignOperator *E) { 610*fe013be4SDimitry Andric assert(E->getType()->isFloatingType()); 611*fe013be4SDimitry Andric 612bdd1243dSDimitry Andric const Expr *LHS = E->getLHS(); 613bdd1243dSDimitry Andric const Expr *RHS = E->getRHS(); 614*fe013be4SDimitry Andric llvm::RoundingMode RM = getRoundingMode(E); 615*fe013be4SDimitry Andric QualType LHSComputationType = E->getComputationLHSType(); 616*fe013be4SDimitry Andric QualType ResultType = E->getComputationResultType(); 617*fe013be4SDimitry Andric std::optional<PrimType> LT = classify(LHSComputationType); 618*fe013be4SDimitry Andric std::optional<PrimType> RT = classify(ResultType); 619bdd1243dSDimitry Andric 620bdd1243dSDimitry Andric if (!LT || !RT) 621bdd1243dSDimitry Andric return false; 622bdd1243dSDimitry Andric 623*fe013be4SDimitry Andric // C++17 onwards require that we evaluate the RHS first. 624*fe013be4SDimitry Andric // Compute RHS and save it in a temporary variable so we can 625*fe013be4SDimitry Andric // load it again later. 626*fe013be4SDimitry Andric if (!visit(RHS)) 627*fe013be4SDimitry Andric return false; 628bdd1243dSDimitry Andric 629*fe013be4SDimitry Andric unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true); 630*fe013be4SDimitry Andric if (!this->emitSetLocal(*RT, TempOffset, E)) 631*fe013be4SDimitry Andric return false; 632*fe013be4SDimitry Andric 633*fe013be4SDimitry Andric // First, visit LHS. 634bdd1243dSDimitry Andric if (!visit(LHS)) 635bdd1243dSDimitry Andric return false; 636bdd1243dSDimitry Andric if (!this->emitLoad(*LT, E)) 637bdd1243dSDimitry Andric return false; 638*fe013be4SDimitry Andric 639*fe013be4SDimitry Andric // If necessary, convert LHS to its computation type. 640*fe013be4SDimitry Andric if (LHS->getType() != LHSComputationType) { 641*fe013be4SDimitry Andric const auto *TargetSemantics = &Ctx.getFloatSemantics(LHSComputationType); 642*fe013be4SDimitry Andric 643*fe013be4SDimitry Andric if (!this->emitCastFP(TargetSemantics, RM, E)) 644*fe013be4SDimitry Andric return false; 645*fe013be4SDimitry Andric } 646*fe013be4SDimitry Andric 647*fe013be4SDimitry Andric // Now load RHS. 648*fe013be4SDimitry Andric if (!this->emitGetLocal(*RT, TempOffset, E)) 649bdd1243dSDimitry Andric return false; 650bdd1243dSDimitry Andric 651bdd1243dSDimitry Andric switch (E->getOpcode()) { 652bdd1243dSDimitry Andric case BO_AddAssign: 653*fe013be4SDimitry Andric if (!this->emitAddf(RM, E)) 654bdd1243dSDimitry Andric return false; 655bdd1243dSDimitry Andric break; 656bdd1243dSDimitry Andric case BO_SubAssign: 657*fe013be4SDimitry Andric if (!this->emitSubf(RM, E)) 658bdd1243dSDimitry Andric return false; 659bdd1243dSDimitry Andric break; 660bdd1243dSDimitry Andric case BO_MulAssign: 661*fe013be4SDimitry Andric if (!this->emitMulf(RM, E)) 662*fe013be4SDimitry Andric return false; 663*fe013be4SDimitry Andric break; 664bdd1243dSDimitry Andric case BO_DivAssign: 665*fe013be4SDimitry Andric if (!this->emitDivf(RM, E)) 666bdd1243dSDimitry Andric return false; 667bdd1243dSDimitry Andric break; 668bdd1243dSDimitry Andric default: 669*fe013be4SDimitry Andric return false; 670bdd1243dSDimitry Andric } 671bdd1243dSDimitry Andric 672*fe013be4SDimitry Andric // If necessary, convert result to LHS's type. 673*fe013be4SDimitry Andric if (LHS->getType() != ResultType) { 674*fe013be4SDimitry Andric const auto *TargetSemantics = &Ctx.getFloatSemantics(LHS->getType()); 675*fe013be4SDimitry Andric 676*fe013be4SDimitry Andric if (!this->emitCastFP(TargetSemantics, RM, E)) 677*fe013be4SDimitry Andric return false; 678*fe013be4SDimitry Andric } 679*fe013be4SDimitry Andric 680bdd1243dSDimitry Andric if (DiscardResult) 681bdd1243dSDimitry Andric return this->emitStorePop(*LT, E); 682bdd1243dSDimitry Andric return this->emitStore(*LT, E); 683bdd1243dSDimitry Andric } 684bdd1243dSDimitry Andric 685*fe013be4SDimitry Andric template <class Emitter> 686*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPointerCompoundAssignOperator( 687*fe013be4SDimitry Andric const CompoundAssignOperator *E) { 688*fe013be4SDimitry Andric BinaryOperatorKind Op = E->getOpcode(); 689*fe013be4SDimitry Andric const Expr *LHS = E->getLHS(); 690*fe013be4SDimitry Andric const Expr *RHS = E->getRHS(); 691*fe013be4SDimitry Andric std::optional<PrimType> LT = classify(LHS->getType()); 692*fe013be4SDimitry Andric std::optional<PrimType> RT = classify(RHS->getType()); 693*fe013be4SDimitry Andric 694*fe013be4SDimitry Andric if (Op != BO_AddAssign && Op != BO_SubAssign) 695*fe013be4SDimitry Andric return false; 696*fe013be4SDimitry Andric 697*fe013be4SDimitry Andric if (!LT || !RT) 698*fe013be4SDimitry Andric return false; 699*fe013be4SDimitry Andric assert(*LT == PT_Ptr); 700*fe013be4SDimitry Andric 701*fe013be4SDimitry Andric if (!visit(LHS)) 702*fe013be4SDimitry Andric return false; 703*fe013be4SDimitry Andric 704*fe013be4SDimitry Andric if (!this->emitLoadPtr(LHS)) 705*fe013be4SDimitry Andric return false; 706*fe013be4SDimitry Andric 707*fe013be4SDimitry Andric if (!visit(RHS)) 708*fe013be4SDimitry Andric return false; 709*fe013be4SDimitry Andric 710*fe013be4SDimitry Andric if (Op == BO_AddAssign) 711*fe013be4SDimitry Andric this->emitAddOffset(*RT, E); 712*fe013be4SDimitry Andric else 713*fe013be4SDimitry Andric this->emitSubOffset(*RT, E); 714*fe013be4SDimitry Andric 715*fe013be4SDimitry Andric if (DiscardResult) 716*fe013be4SDimitry Andric return this->emitStorePopPtr(E); 717*fe013be4SDimitry Andric return this->emitStorePtr(E); 718*fe013be4SDimitry Andric } 719*fe013be4SDimitry Andric 720*fe013be4SDimitry Andric template <class Emitter> 721*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator( 722*fe013be4SDimitry Andric const CompoundAssignOperator *E) { 723*fe013be4SDimitry Andric 724*fe013be4SDimitry Andric // Handle floating point operations separately here, since they 725*fe013be4SDimitry Andric // require special care. 726*fe013be4SDimitry Andric if (E->getType()->isFloatingType()) 727*fe013be4SDimitry Andric return VisitFloatCompoundAssignOperator(E); 728*fe013be4SDimitry Andric 729*fe013be4SDimitry Andric if (E->getType()->isPointerType()) 730*fe013be4SDimitry Andric return VisitPointerCompoundAssignOperator(E); 731*fe013be4SDimitry Andric 732*fe013be4SDimitry Andric const Expr *LHS = E->getLHS(); 733*fe013be4SDimitry Andric const Expr *RHS = E->getRHS(); 734*fe013be4SDimitry Andric std::optional<PrimType> LHSComputationT = 735*fe013be4SDimitry Andric classify(E->getComputationLHSType()); 736*fe013be4SDimitry Andric std::optional<PrimType> LT = classify(LHS->getType()); 737*fe013be4SDimitry Andric std::optional<PrimType> RT = classify(E->getComputationResultType()); 738*fe013be4SDimitry Andric std::optional<PrimType> ResultT = classify(E->getType()); 739*fe013be4SDimitry Andric 740*fe013be4SDimitry Andric if (!LT || !RT || !ResultT || !LHSComputationT) 741*fe013be4SDimitry Andric return false; 742*fe013be4SDimitry Andric 743*fe013be4SDimitry Andric assert(!E->getType()->isPointerType() && "Handled above"); 744*fe013be4SDimitry Andric assert(!E->getType()->isFloatingType() && "Handled above"); 745*fe013be4SDimitry Andric 746*fe013be4SDimitry Andric // C++17 onwards require that we evaluate the RHS first. 747*fe013be4SDimitry Andric // Compute RHS and save it in a temporary variable so we can 748*fe013be4SDimitry Andric // load it again later. 749*fe013be4SDimitry Andric // FIXME: Compound assignments are unsequenced in C, so we might 750*fe013be4SDimitry Andric // have to figure out how to reject them. 751*fe013be4SDimitry Andric if (!visit(RHS)) 752*fe013be4SDimitry Andric return false; 753*fe013be4SDimitry Andric 754*fe013be4SDimitry Andric unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true); 755*fe013be4SDimitry Andric 756*fe013be4SDimitry Andric if (!this->emitSetLocal(*RT, TempOffset, E)) 757*fe013be4SDimitry Andric return false; 758*fe013be4SDimitry Andric 759*fe013be4SDimitry Andric // Get LHS pointer, load its value and cast it to the 760*fe013be4SDimitry Andric // computation type if necessary. 761*fe013be4SDimitry Andric if (!visit(LHS)) 762*fe013be4SDimitry Andric return false; 763*fe013be4SDimitry Andric if (!this->emitLoad(*LT, E)) 764*fe013be4SDimitry Andric return false; 765*fe013be4SDimitry Andric if (*LT != *LHSComputationT) { 766*fe013be4SDimitry Andric if (!this->emitCast(*LT, *LHSComputationT, E)) 767*fe013be4SDimitry Andric return false; 768*fe013be4SDimitry Andric } 769*fe013be4SDimitry Andric 770*fe013be4SDimitry Andric // Get the RHS value on the stack. 771*fe013be4SDimitry Andric if (!this->emitGetLocal(*RT, TempOffset, E)) 772*fe013be4SDimitry Andric return false; 773*fe013be4SDimitry Andric 774*fe013be4SDimitry Andric // Perform operation. 775*fe013be4SDimitry Andric switch (E->getOpcode()) { 776*fe013be4SDimitry Andric case BO_AddAssign: 777*fe013be4SDimitry Andric if (!this->emitAdd(*LHSComputationT, E)) 778*fe013be4SDimitry Andric return false; 779*fe013be4SDimitry Andric break; 780*fe013be4SDimitry Andric case BO_SubAssign: 781*fe013be4SDimitry Andric if (!this->emitSub(*LHSComputationT, E)) 782*fe013be4SDimitry Andric return false; 783*fe013be4SDimitry Andric break; 784*fe013be4SDimitry Andric case BO_MulAssign: 785*fe013be4SDimitry Andric if (!this->emitMul(*LHSComputationT, E)) 786*fe013be4SDimitry Andric return false; 787*fe013be4SDimitry Andric break; 788*fe013be4SDimitry Andric case BO_DivAssign: 789*fe013be4SDimitry Andric if (!this->emitDiv(*LHSComputationT, E)) 790*fe013be4SDimitry Andric return false; 791*fe013be4SDimitry Andric break; 792*fe013be4SDimitry Andric case BO_RemAssign: 793*fe013be4SDimitry Andric if (!this->emitRem(*LHSComputationT, E)) 794*fe013be4SDimitry Andric return false; 795*fe013be4SDimitry Andric break; 796*fe013be4SDimitry Andric case BO_ShlAssign: 797*fe013be4SDimitry Andric if (!this->emitShl(*LHSComputationT, *RT, E)) 798*fe013be4SDimitry Andric return false; 799*fe013be4SDimitry Andric break; 800*fe013be4SDimitry Andric case BO_ShrAssign: 801*fe013be4SDimitry Andric if (!this->emitShr(*LHSComputationT, *RT, E)) 802*fe013be4SDimitry Andric return false; 803*fe013be4SDimitry Andric break; 804*fe013be4SDimitry Andric case BO_AndAssign: 805*fe013be4SDimitry Andric if (!this->emitBitAnd(*LHSComputationT, E)) 806*fe013be4SDimitry Andric return false; 807*fe013be4SDimitry Andric break; 808*fe013be4SDimitry Andric case BO_XorAssign: 809*fe013be4SDimitry Andric if (!this->emitBitXor(*LHSComputationT, E)) 810*fe013be4SDimitry Andric return false; 811*fe013be4SDimitry Andric break; 812*fe013be4SDimitry Andric case BO_OrAssign: 813*fe013be4SDimitry Andric if (!this->emitBitOr(*LHSComputationT, E)) 814*fe013be4SDimitry Andric return false; 815*fe013be4SDimitry Andric break; 816*fe013be4SDimitry Andric default: 817*fe013be4SDimitry Andric llvm_unreachable("Unimplemented compound assign operator"); 818*fe013be4SDimitry Andric } 819*fe013be4SDimitry Andric 820*fe013be4SDimitry Andric // And now cast from LHSComputationT to ResultT. 821*fe013be4SDimitry Andric if (*ResultT != *LHSComputationT) { 822*fe013be4SDimitry Andric if (!this->emitCast(*LHSComputationT, *ResultT, E)) 823*fe013be4SDimitry Andric return false; 824*fe013be4SDimitry Andric } 825*fe013be4SDimitry Andric 826*fe013be4SDimitry Andric // And store the result in LHS. 827*fe013be4SDimitry Andric if (DiscardResult) 828*fe013be4SDimitry Andric return this->emitStorePop(*ResultT, E); 829*fe013be4SDimitry Andric return this->emitStore(*ResultT, E); 830*fe013be4SDimitry Andric } 831*fe013be4SDimitry Andric 832*fe013be4SDimitry Andric template <class Emitter> 833*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitExprWithCleanups( 834*fe013be4SDimitry Andric const ExprWithCleanups *E) { 835*fe013be4SDimitry Andric const Expr *SubExpr = E->getSubExpr(); 836*fe013be4SDimitry Andric 837*fe013be4SDimitry Andric assert(E->getNumObjects() == 0 && "TODO: Implement cleanups"); 838*fe013be4SDimitry Andric if (DiscardResult) 839*fe013be4SDimitry Andric return this->discard(SubExpr); 840*fe013be4SDimitry Andric 841*fe013be4SDimitry Andric return this->visit(SubExpr); 842*fe013be4SDimitry Andric } 843*fe013be4SDimitry Andric 844*fe013be4SDimitry Andric template <class Emitter> 845*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr( 846*fe013be4SDimitry Andric const MaterializeTemporaryExpr *E) { 847*fe013be4SDimitry Andric const Expr *SubExpr = E->getSubExpr(); 848*fe013be4SDimitry Andric std::optional<PrimType> SubExprT = classify(SubExpr); 849*fe013be4SDimitry Andric 850*fe013be4SDimitry Andric if (E->getStorageDuration() == SD_Static) { 851*fe013be4SDimitry Andric if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) { 852*fe013be4SDimitry Andric const LifetimeExtendedTemporaryDecl *TempDecl = 853*fe013be4SDimitry Andric E->getLifetimeExtendedTemporaryDecl(); 854*fe013be4SDimitry Andric 855*fe013be4SDimitry Andric if (!this->visitInitializer(SubExpr)) 856*fe013be4SDimitry Andric return false; 857*fe013be4SDimitry Andric 858*fe013be4SDimitry Andric if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E)) 859*fe013be4SDimitry Andric return false; 860*fe013be4SDimitry Andric return this->emitGetPtrGlobal(*GlobalIndex, E); 861*fe013be4SDimitry Andric } 862*fe013be4SDimitry Andric 863*fe013be4SDimitry Andric return false; 864*fe013be4SDimitry Andric } 865*fe013be4SDimitry Andric 866*fe013be4SDimitry Andric // For everyhing else, use local variables. 867*fe013be4SDimitry Andric if (SubExprT) { 868*fe013be4SDimitry Andric if (std::optional<unsigned> LocalIndex = allocateLocalPrimitive( 869*fe013be4SDimitry Andric SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true)) { 870*fe013be4SDimitry Andric if (!this->visitInitializer(SubExpr)) 871*fe013be4SDimitry Andric return false; 872*fe013be4SDimitry Andric this->emitSetLocal(*SubExprT, *LocalIndex, E); 873*fe013be4SDimitry Andric return this->emitGetPtrLocal(*LocalIndex, E); 874*fe013be4SDimitry Andric } 875*fe013be4SDimitry Andric } else { 876*fe013be4SDimitry Andric if (std::optional<unsigned> LocalIndex = 877*fe013be4SDimitry Andric allocateLocal(SubExpr, /*IsExtended=*/true)) { 878*fe013be4SDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E)) 879*fe013be4SDimitry Andric return false; 880*fe013be4SDimitry Andric return this->visitInitializer(SubExpr); 881*fe013be4SDimitry Andric } 882*fe013be4SDimitry Andric } 883*fe013be4SDimitry Andric return false; 884*fe013be4SDimitry Andric } 885*fe013be4SDimitry Andric 886*fe013be4SDimitry Andric template <class Emitter> 887*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr( 888*fe013be4SDimitry Andric const CompoundLiteralExpr *E) { 889*fe013be4SDimitry Andric std::optional<PrimType> T = classify(E->getType()); 890*fe013be4SDimitry Andric const Expr *Init = E->getInitializer(); 891*fe013be4SDimitry Andric if (E->isFileScope()) { 892*fe013be4SDimitry Andric if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) { 893*fe013be4SDimitry Andric if (classify(E->getType())) 894*fe013be4SDimitry Andric return this->visit(Init); 895*fe013be4SDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, E)) 896*fe013be4SDimitry Andric return false; 897*fe013be4SDimitry Andric return this->visitInitializer(Init); 898*fe013be4SDimitry Andric } 899*fe013be4SDimitry Andric } 900*fe013be4SDimitry Andric 901*fe013be4SDimitry Andric // Otherwise, use a local variable. 902*fe013be4SDimitry Andric if (T) { 903*fe013be4SDimitry Andric // For primitive types, we just visit the initializer. 904*fe013be4SDimitry Andric return this->visit(Init); 905*fe013be4SDimitry Andric } else { 906*fe013be4SDimitry Andric if (std::optional<unsigned> LocalIndex = allocateLocal(Init)) { 907*fe013be4SDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E)) 908*fe013be4SDimitry Andric return false; 909*fe013be4SDimitry Andric return this->visitInitializer(Init); 910*fe013be4SDimitry Andric } 911*fe013be4SDimitry Andric } 912*fe013be4SDimitry Andric 913*fe013be4SDimitry Andric return false; 914*fe013be4SDimitry Andric } 915*fe013be4SDimitry Andric 916*fe013be4SDimitry Andric template <class Emitter> 917*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) { 918*fe013be4SDimitry Andric return this->emitConstBool(E->getValue(), E); 919*fe013be4SDimitry Andric } 920*fe013be4SDimitry Andric 921*fe013be4SDimitry Andric template <class Emitter> 922*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) { 923*fe013be4SDimitry Andric // XXX We assume here that a pointer-to-initialize is on the stack. 924*fe013be4SDimitry Andric 925*fe013be4SDimitry Andric const Record *R = P.getOrCreateRecord(E->getLambdaClass()); 926*fe013be4SDimitry Andric 927*fe013be4SDimitry Andric auto *CaptureInitIt = E->capture_init_begin(); 928*fe013be4SDimitry Andric // Initialize all fields (which represent lambda captures) of the 929*fe013be4SDimitry Andric // record with their initializers. 930*fe013be4SDimitry Andric for (const Record::Field &F : R->fields()) { 931*fe013be4SDimitry Andric const Expr *Init = *CaptureInitIt; 932*fe013be4SDimitry Andric ++CaptureInitIt; 933*fe013be4SDimitry Andric 934*fe013be4SDimitry Andric if (std::optional<PrimType> T = classify(Init)) { 935*fe013be4SDimitry Andric if (!this->visit(Init)) 936*fe013be4SDimitry Andric return false; 937*fe013be4SDimitry Andric 938*fe013be4SDimitry Andric if (!this->emitSetField(*T, F.Offset, E)) 939*fe013be4SDimitry Andric return false; 940*fe013be4SDimitry Andric } else { 941*fe013be4SDimitry Andric if (!this->emitDupPtr(E)) 942*fe013be4SDimitry Andric return false; 943*fe013be4SDimitry Andric 944*fe013be4SDimitry Andric if (!this->emitGetPtrField(F.Offset, E)) 945*fe013be4SDimitry Andric return false; 946*fe013be4SDimitry Andric 947*fe013be4SDimitry Andric if (!this->visitInitializer(Init)) 948*fe013be4SDimitry Andric return false; 949*fe013be4SDimitry Andric 950*fe013be4SDimitry Andric if (!this->emitPopPtr(E)) 951*fe013be4SDimitry Andric return false; 952*fe013be4SDimitry Andric } 953*fe013be4SDimitry Andric } 954*fe013be4SDimitry Andric 955*fe013be4SDimitry Andric return true; 956*fe013be4SDimitry Andric } 957*fe013be4SDimitry Andric 958*fe013be4SDimitry Andric template <class Emitter> 959*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) { 960*fe013be4SDimitry Andric if (DiscardResult) 961*fe013be4SDimitry Andric return true; 962*fe013be4SDimitry Andric 963*fe013be4SDimitry Andric return this->visit(E->getFunctionName()); 964*fe013be4SDimitry Andric } 965*fe013be4SDimitry Andric 966bdd1243dSDimitry Andric template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) { 967*fe013be4SDimitry Andric if (E->containsErrors()) 968*fe013be4SDimitry Andric return false; 969*fe013be4SDimitry Andric 97004eeddc0SDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true); 971a7dea167SDimitry Andric return this->Visit(E); 972a7dea167SDimitry Andric } 973a7dea167SDimitry Andric 974a7dea167SDimitry Andric template <class Emitter> 975a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visit(const Expr *E) { 976*fe013be4SDimitry Andric if (E->containsErrors()) 977*fe013be4SDimitry Andric return false; 978*fe013be4SDimitry Andric 97904eeddc0SDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false); 980a7dea167SDimitry Andric return this->Visit(E); 981a7dea167SDimitry Andric } 982a7dea167SDimitry Andric 983a7dea167SDimitry Andric template <class Emitter> 984a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) { 985bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(E->getType())) { 986a7dea167SDimitry Andric return visit(E); 987a7dea167SDimitry Andric } else { 988a7dea167SDimitry Andric return this->bail(E); 989a7dea167SDimitry Andric } 990a7dea167SDimitry Andric } 991a7dea167SDimitry Andric 992*fe013be4SDimitry Andric /// Visit a conditional operator, i.e. `A ? B : C`. 993*fe013be4SDimitry Andric /// \V determines what function to call for the B and C expressions. 994a7dea167SDimitry Andric template <class Emitter> 995*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::visitConditional( 996*fe013be4SDimitry Andric const AbstractConditionalOperator *E, 997*fe013be4SDimitry Andric llvm::function_ref<bool(const Expr *)> V) { 998*fe013be4SDimitry Andric 999*fe013be4SDimitry Andric const Expr *Condition = E->getCond(); 1000*fe013be4SDimitry Andric const Expr *TrueExpr = E->getTrueExpr(); 1001*fe013be4SDimitry Andric const Expr *FalseExpr = E->getFalseExpr(); 1002*fe013be4SDimitry Andric 1003*fe013be4SDimitry Andric LabelTy LabelEnd = this->getLabel(); // Label after the operator. 1004*fe013be4SDimitry Andric LabelTy LabelFalse = this->getLabel(); // Label for the false expr. 1005*fe013be4SDimitry Andric 1006*fe013be4SDimitry Andric if (!this->visit(Condition)) 1007*fe013be4SDimitry Andric return false; 1008*fe013be4SDimitry Andric 1009*fe013be4SDimitry Andric // C special case: Convert to bool because our jump ops need that. 1010*fe013be4SDimitry Andric // TODO: We probably want this to be done in visitBool(). 1011*fe013be4SDimitry Andric if (std::optional<PrimType> CondT = classify(Condition->getType()); 1012*fe013be4SDimitry Andric CondT && CondT != PT_Bool) { 1013*fe013be4SDimitry Andric if (!this->emitCast(*CondT, PT_Bool, E)) 1014*fe013be4SDimitry Andric return false; 1015*fe013be4SDimitry Andric } 1016*fe013be4SDimitry Andric 1017*fe013be4SDimitry Andric if (!this->jumpFalse(LabelFalse)) 1018*fe013be4SDimitry Andric return false; 1019*fe013be4SDimitry Andric 1020*fe013be4SDimitry Andric if (!V(TrueExpr)) 1021*fe013be4SDimitry Andric return false; 1022*fe013be4SDimitry Andric if (!this->jump(LabelEnd)) 1023*fe013be4SDimitry Andric return false; 1024*fe013be4SDimitry Andric 1025*fe013be4SDimitry Andric this->emitLabel(LabelFalse); 1026*fe013be4SDimitry Andric 1027*fe013be4SDimitry Andric if (!V(FalseExpr)) 1028*fe013be4SDimitry Andric return false; 1029*fe013be4SDimitry Andric 1030*fe013be4SDimitry Andric this->fallthrough(LabelEnd); 1031*fe013be4SDimitry Andric this->emitLabel(LabelEnd); 1032*fe013be4SDimitry Andric 1033*fe013be4SDimitry Andric return true; 1034*fe013be4SDimitry Andric } 1035*fe013be4SDimitry Andric 1036*fe013be4SDimitry Andric template <class Emitter> 1037*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::visitZeroInitializer(QualType QT, 1038*fe013be4SDimitry Andric const Expr *E) { 1039*fe013be4SDimitry Andric // FIXME: We need the QualType to get the float semantics, but that means we 1040*fe013be4SDimitry Andric // classify it over and over again in array situations. 1041*fe013be4SDimitry Andric PrimType T = classifyPrim(QT); 1042*fe013be4SDimitry Andric 1043a7dea167SDimitry Andric switch (T) { 1044a7dea167SDimitry Andric case PT_Bool: 1045a7dea167SDimitry Andric return this->emitZeroBool(E); 1046a7dea167SDimitry Andric case PT_Sint8: 1047a7dea167SDimitry Andric return this->emitZeroSint8(E); 1048a7dea167SDimitry Andric case PT_Uint8: 1049a7dea167SDimitry Andric return this->emitZeroUint8(E); 1050a7dea167SDimitry Andric case PT_Sint16: 1051a7dea167SDimitry Andric return this->emitZeroSint16(E); 1052a7dea167SDimitry Andric case PT_Uint16: 1053a7dea167SDimitry Andric return this->emitZeroUint16(E); 1054a7dea167SDimitry Andric case PT_Sint32: 1055a7dea167SDimitry Andric return this->emitZeroSint32(E); 1056a7dea167SDimitry Andric case PT_Uint32: 1057a7dea167SDimitry Andric return this->emitZeroUint32(E); 1058a7dea167SDimitry Andric case PT_Sint64: 1059a7dea167SDimitry Andric return this->emitZeroSint64(E); 1060a7dea167SDimitry Andric case PT_Uint64: 1061a7dea167SDimitry Andric return this->emitZeroUint64(E); 1062a7dea167SDimitry Andric case PT_Ptr: 1063a7dea167SDimitry Andric return this->emitNullPtr(E); 1064*fe013be4SDimitry Andric case PT_FnPtr: 1065*fe013be4SDimitry Andric return this->emitNullFnPtr(E); 1066*fe013be4SDimitry Andric case PT_Float: { 1067*fe013be4SDimitry Andric return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E); 1068*fe013be4SDimitry Andric } 1069a7dea167SDimitry Andric } 1070a7dea167SDimitry Andric llvm_unreachable("unknown primitive type"); 1071a7dea167SDimitry Andric } 1072a7dea167SDimitry Andric 1073a7dea167SDimitry Andric template <class Emitter> 1074a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereference( 1075a7dea167SDimitry Andric const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct, 1076a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 1077bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(LV->getType())) { 1078a7dea167SDimitry Andric if (!LV->refersToBitField()) { 1079a7dea167SDimitry Andric // Only primitive, non bit-field types can be dereferenced directly. 1080*fe013be4SDimitry Andric if (const auto *DE = dyn_cast<DeclRefExpr>(LV)) { 1081a7dea167SDimitry Andric if (!DE->getDecl()->getType()->isReferenceType()) { 1082*fe013be4SDimitry Andric if (const auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl())) 1083a7dea167SDimitry Andric return dereferenceParam(LV, *T, PD, AK, Direct, Indirect); 1084*fe013be4SDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(DE->getDecl())) 1085a7dea167SDimitry Andric return dereferenceVar(LV, *T, VD, AK, Direct, Indirect); 1086a7dea167SDimitry Andric } 1087a7dea167SDimitry Andric } 1088a7dea167SDimitry Andric } 1089a7dea167SDimitry Andric 1090a7dea167SDimitry Andric if (!visit(LV)) 1091a7dea167SDimitry Andric return false; 1092a7dea167SDimitry Andric return Indirect(*T); 1093a7dea167SDimitry Andric } 1094a7dea167SDimitry Andric 1095a7dea167SDimitry Andric return false; 1096a7dea167SDimitry Andric } 1097a7dea167SDimitry Andric 1098a7dea167SDimitry Andric template <class Emitter> 1099a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceParam( 1100a7dea167SDimitry Andric const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK, 1101a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Direct, 1102a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 1103a7dea167SDimitry Andric auto It = this->Params.find(PD); 1104a7dea167SDimitry Andric if (It != this->Params.end()) { 1105a7dea167SDimitry Andric unsigned Idx = It->second; 1106a7dea167SDimitry Andric switch (AK) { 1107a7dea167SDimitry Andric case DerefKind::Read: 1108a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetParam(T, Idx, LV); 1109a7dea167SDimitry Andric 1110a7dea167SDimitry Andric case DerefKind::Write: 1111a7dea167SDimitry Andric if (!Direct(T)) 1112a7dea167SDimitry Andric return false; 1113a7dea167SDimitry Andric if (!this->emitSetParam(T, Idx, LV)) 1114a7dea167SDimitry Andric return false; 1115a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 1116a7dea167SDimitry Andric 1117a7dea167SDimitry Andric case DerefKind::ReadWrite: 1118a7dea167SDimitry Andric if (!this->emitGetParam(T, Idx, LV)) 1119a7dea167SDimitry Andric return false; 1120a7dea167SDimitry Andric if (!Direct(T)) 1121a7dea167SDimitry Andric return false; 1122a7dea167SDimitry Andric if (!this->emitSetParam(T, Idx, LV)) 1123a7dea167SDimitry Andric return false; 1124a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 1125a7dea167SDimitry Andric } 1126a7dea167SDimitry Andric return true; 1127a7dea167SDimitry Andric } 1128a7dea167SDimitry Andric 1129a7dea167SDimitry Andric // If the param is a pointer, we can dereference a dummy value. 1130a7dea167SDimitry Andric if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) { 1131a7dea167SDimitry Andric if (auto Idx = P.getOrCreateDummy(PD)) 1132a7dea167SDimitry Andric return this->emitGetPtrGlobal(*Idx, PD); 1133a7dea167SDimitry Andric return false; 1134a7dea167SDimitry Andric } 1135a7dea167SDimitry Andric 1136a7dea167SDimitry Andric // Value cannot be produced - try to emit pointer and do stuff with it. 1137a7dea167SDimitry Andric return visit(LV) && Indirect(T); 1138a7dea167SDimitry Andric } 1139a7dea167SDimitry Andric 1140a7dea167SDimitry Andric template <class Emitter> 1141a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceVar( 1142a7dea167SDimitry Andric const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK, 1143a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Direct, 1144a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 1145a7dea167SDimitry Andric auto It = Locals.find(VD); 1146a7dea167SDimitry Andric if (It != Locals.end()) { 1147a7dea167SDimitry Andric const auto &L = It->second; 1148a7dea167SDimitry Andric switch (AK) { 1149a7dea167SDimitry Andric case DerefKind::Read: 1150a7dea167SDimitry Andric if (!this->emitGetLocal(T, L.Offset, LV)) 1151a7dea167SDimitry Andric return false; 1152a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, LV) : true; 1153a7dea167SDimitry Andric 1154a7dea167SDimitry Andric case DerefKind::Write: 1155a7dea167SDimitry Andric if (!Direct(T)) 1156a7dea167SDimitry Andric return false; 1157a7dea167SDimitry Andric if (!this->emitSetLocal(T, L.Offset, LV)) 1158a7dea167SDimitry Andric return false; 1159a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 1160a7dea167SDimitry Andric 1161a7dea167SDimitry Andric case DerefKind::ReadWrite: 1162a7dea167SDimitry Andric if (!this->emitGetLocal(T, L.Offset, LV)) 1163a7dea167SDimitry Andric return false; 1164a7dea167SDimitry Andric if (!Direct(T)) 1165a7dea167SDimitry Andric return false; 1166a7dea167SDimitry Andric if (!this->emitSetLocal(T, L.Offset, LV)) 1167a7dea167SDimitry Andric return false; 1168a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 1169a7dea167SDimitry Andric } 1170bdd1243dSDimitry Andric } else if (auto Idx = P.getGlobal(VD)) { 1171a7dea167SDimitry Andric switch (AK) { 1172a7dea167SDimitry Andric case DerefKind::Read: 1173a7dea167SDimitry Andric if (!this->emitGetGlobal(T, *Idx, LV)) 1174a7dea167SDimitry Andric return false; 1175a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, LV) : true; 1176a7dea167SDimitry Andric 1177a7dea167SDimitry Andric case DerefKind::Write: 1178a7dea167SDimitry Andric if (!Direct(T)) 1179a7dea167SDimitry Andric return false; 1180a7dea167SDimitry Andric if (!this->emitSetGlobal(T, *Idx, LV)) 1181a7dea167SDimitry Andric return false; 1182a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 1183a7dea167SDimitry Andric 1184a7dea167SDimitry Andric case DerefKind::ReadWrite: 1185a7dea167SDimitry Andric if (!this->emitGetGlobal(T, *Idx, LV)) 1186a7dea167SDimitry Andric return false; 1187a7dea167SDimitry Andric if (!Direct(T)) 1188a7dea167SDimitry Andric return false; 1189a7dea167SDimitry Andric if (!this->emitSetGlobal(T, *Idx, LV)) 1190a7dea167SDimitry Andric return false; 1191a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 1192a7dea167SDimitry Andric } 1193a7dea167SDimitry Andric } 1194a7dea167SDimitry Andric 1195a7dea167SDimitry Andric // If the declaration is a constant value, emit it here even 1196a7dea167SDimitry Andric // though the declaration was not evaluated in the current scope. 1197a7dea167SDimitry Andric // The access mode can only be read in this case. 1198a7dea167SDimitry Andric if (!DiscardResult && AK == DerefKind::Read) { 1199a7dea167SDimitry Andric if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) { 1200a7dea167SDimitry Andric QualType VT = VD->getType(); 1201a7dea167SDimitry Andric if (VT.isConstQualified() && VT->isFundamentalType()) 1202bdd1243dSDimitry Andric return this->visit(VD->getInit()); 1203a7dea167SDimitry Andric } 1204a7dea167SDimitry Andric } 1205a7dea167SDimitry Andric 1206a7dea167SDimitry Andric // Value cannot be produced - try to emit pointer. 1207a7dea167SDimitry Andric return visit(LV) && Indirect(T); 1208a7dea167SDimitry Andric } 1209a7dea167SDimitry Andric 1210a7dea167SDimitry Andric template <class Emitter> 1211bdd1243dSDimitry Andric template <typename T> 1212bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(T Value, const Expr *E) { 1213bdd1243dSDimitry Andric switch (classifyPrim(E->getType())) { 1214a7dea167SDimitry Andric case PT_Sint8: 1215bdd1243dSDimitry Andric return this->emitConstSint8(Value, E); 1216a7dea167SDimitry Andric case PT_Uint8: 1217bdd1243dSDimitry Andric return this->emitConstUint8(Value, E); 1218a7dea167SDimitry Andric case PT_Sint16: 1219bdd1243dSDimitry Andric return this->emitConstSint16(Value, E); 1220a7dea167SDimitry Andric case PT_Uint16: 1221bdd1243dSDimitry Andric return this->emitConstUint16(Value, E); 1222a7dea167SDimitry Andric case PT_Sint32: 1223bdd1243dSDimitry Andric return this->emitConstSint32(Value, E); 1224a7dea167SDimitry Andric case PT_Uint32: 1225bdd1243dSDimitry Andric return this->emitConstUint32(Value, E); 1226a7dea167SDimitry Andric case PT_Sint64: 1227bdd1243dSDimitry Andric return this->emitConstSint64(Value, E); 1228a7dea167SDimitry Andric case PT_Uint64: 1229bdd1243dSDimitry Andric return this->emitConstUint64(Value, E); 1230a7dea167SDimitry Andric case PT_Bool: 1231bdd1243dSDimitry Andric return this->emitConstBool(Value, E); 1232a7dea167SDimitry Andric case PT_Ptr: 1233*fe013be4SDimitry Andric case PT_FnPtr: 1234*fe013be4SDimitry Andric case PT_Float: 1235a7dea167SDimitry Andric llvm_unreachable("Invalid integral type"); 1236a7dea167SDimitry Andric break; 1237a7dea167SDimitry Andric } 1238a7dea167SDimitry Andric llvm_unreachable("unknown primitive type"); 1239a7dea167SDimitry Andric } 1240a7dea167SDimitry Andric 1241a7dea167SDimitry Andric template <class Emitter> 1242bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, const Expr *E) { 1243bdd1243dSDimitry Andric if (Value.isSigned()) 1244bdd1243dSDimitry Andric return this->emitConst(Value.getSExtValue(), E); 1245bdd1243dSDimitry Andric return this->emitConst(Value.getZExtValue(), E); 1246bdd1243dSDimitry Andric } 1247bdd1243dSDimitry Andric 1248bdd1243dSDimitry Andric template <class Emitter> 1249a7dea167SDimitry Andric unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src, 1250a7dea167SDimitry Andric PrimType Ty, 1251a7dea167SDimitry Andric bool IsConst, 1252a7dea167SDimitry Andric bool IsExtended) { 1253bdd1243dSDimitry Andric // Make sure we don't accidentally register the same decl twice. 1254bdd1243dSDimitry Andric if (const auto *VD = 1255bdd1243dSDimitry Andric dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { 1256bdd1243dSDimitry Andric assert(!P.getGlobal(VD)); 1257*fe013be4SDimitry Andric assert(!Locals.contains(VD)); 1258bdd1243dSDimitry Andric } 1259bdd1243dSDimitry Andric 1260bdd1243dSDimitry Andric // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g. 1261bdd1243dSDimitry Andric // (int){12} in C. Consider using Expr::isTemporaryObject() instead 1262bdd1243dSDimitry Andric // or isa<MaterializeTemporaryExpr>(). 1263bdd1243dSDimitry Andric Descriptor *D = P.createDescriptor(Src, Ty, Descriptor::InlineDescMD, IsConst, 1264bdd1243dSDimitry Andric Src.is<const Expr *>()); 1265a7dea167SDimitry Andric Scope::Local Local = this->createLocal(D); 1266*fe013be4SDimitry Andric if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) 1267a7dea167SDimitry Andric Locals.insert({VD, Local}); 1268a7dea167SDimitry Andric VarScope->add(Local, IsExtended); 1269a7dea167SDimitry Andric return Local.Offset; 1270a7dea167SDimitry Andric } 1271a7dea167SDimitry Andric 1272a7dea167SDimitry Andric template <class Emitter> 1273bdd1243dSDimitry Andric std::optional<unsigned> 1274a7dea167SDimitry Andric ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) { 1275bdd1243dSDimitry Andric // Make sure we don't accidentally register the same decl twice. 1276bdd1243dSDimitry Andric if (const auto *VD = 1277bdd1243dSDimitry Andric dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { 1278bdd1243dSDimitry Andric assert(!P.getGlobal(VD)); 1279*fe013be4SDimitry Andric assert(!Locals.contains(VD)); 1280bdd1243dSDimitry Andric } 1281a7dea167SDimitry Andric 1282bdd1243dSDimitry Andric QualType Ty; 1283a7dea167SDimitry Andric const ValueDecl *Key = nullptr; 1284bdd1243dSDimitry Andric const Expr *Init = nullptr; 1285a7dea167SDimitry Andric bool IsTemporary = false; 1286bdd1243dSDimitry Andric if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { 1287a7dea167SDimitry Andric Key = VD; 1288a7dea167SDimitry Andric Ty = VD->getType(); 1289bdd1243dSDimitry Andric 1290bdd1243dSDimitry Andric if (const auto *VarD = dyn_cast<VarDecl>(VD)) 1291bdd1243dSDimitry Andric Init = VarD->getInit(); 1292a7dea167SDimitry Andric } 1293a7dea167SDimitry Andric if (auto *E = Src.dyn_cast<const Expr *>()) { 1294a7dea167SDimitry Andric IsTemporary = true; 1295a7dea167SDimitry Andric Ty = E->getType(); 1296a7dea167SDimitry Andric } 1297a7dea167SDimitry Andric 1298bdd1243dSDimitry Andric Descriptor *D = P.createDescriptor( 1299bdd1243dSDimitry Andric Src, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(), 1300bdd1243dSDimitry Andric IsTemporary, /*IsMutable=*/false, Init); 1301a7dea167SDimitry Andric if (!D) 1302a7dea167SDimitry Andric return {}; 1303a7dea167SDimitry Andric 1304a7dea167SDimitry Andric Scope::Local Local = this->createLocal(D); 1305a7dea167SDimitry Andric if (Key) 1306a7dea167SDimitry Andric Locals.insert({Key, Local}); 1307a7dea167SDimitry Andric VarScope->add(Local, IsExtended); 1308a7dea167SDimitry Andric return Local.Offset; 1309a7dea167SDimitry Andric } 1310a7dea167SDimitry Andric 1311bdd1243dSDimitry Andric // NB: When calling this function, we have a pointer to the 1312bdd1243dSDimitry Andric // array-to-initialize on the stack. 1313a7dea167SDimitry Andric template <class Emitter> 1314bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitArrayInitializer(const Expr *Initializer) { 1315bdd1243dSDimitry Andric assert(Initializer->getType()->isArrayType()); 1316bdd1243dSDimitry Andric 1317bdd1243dSDimitry Andric // TODO: Fillers? 1318bdd1243dSDimitry Andric if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) { 1319bdd1243dSDimitry Andric unsigned ElementIndex = 0; 1320bdd1243dSDimitry Andric for (const Expr *Init : InitList->inits()) { 1321bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(Init->getType())) { 1322bdd1243dSDimitry Andric // Visit the primitive element like normal. 1323bdd1243dSDimitry Andric if (!this->visit(Init)) 1324bdd1243dSDimitry Andric return false; 1325bdd1243dSDimitry Andric if (!this->emitInitElem(*T, ElementIndex, Init)) 1326bdd1243dSDimitry Andric return false; 1327bdd1243dSDimitry Andric } else { 1328bdd1243dSDimitry Andric // Advance the pointer currently on the stack to the given 1329*fe013be4SDimitry Andric // dimension. 1330bdd1243dSDimitry Andric if (!this->emitConstUint32(ElementIndex, Init)) 1331bdd1243dSDimitry Andric return false; 1332*fe013be4SDimitry Andric if (!this->emitArrayElemPtrUint32(Init)) 1333bdd1243dSDimitry Andric return false; 1334bdd1243dSDimitry Andric if (!visitInitializer(Init)) 1335bdd1243dSDimitry Andric return false; 1336bdd1243dSDimitry Andric if (!this->emitPopPtr(Init)) 1337bdd1243dSDimitry Andric return false; 1338*fe013be4SDimitry Andric } 1339bdd1243dSDimitry Andric 1340bdd1243dSDimitry Andric ++ElementIndex; 1341bdd1243dSDimitry Andric } 1342bdd1243dSDimitry Andric return true; 1343bdd1243dSDimitry Andric } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) { 1344bdd1243dSDimitry Andric return this->visitInitializer(DIE->getExpr()); 1345bdd1243dSDimitry Andric } else if (const auto *AILE = dyn_cast<ArrayInitLoopExpr>(Initializer)) { 1346bdd1243dSDimitry Andric // TODO: This compiles to quite a lot of bytecode if the array is larger. 1347bdd1243dSDimitry Andric // Investigate compiling this to a loop, or at least try to use 1348bdd1243dSDimitry Andric // the AILE's Common expr. 1349bdd1243dSDimitry Andric const Expr *SubExpr = AILE->getSubExpr(); 1350bdd1243dSDimitry Andric size_t Size = AILE->getArraySize().getZExtValue(); 1351bdd1243dSDimitry Andric std::optional<PrimType> ElemT = classify(SubExpr->getType()); 1352bdd1243dSDimitry Andric 1353bdd1243dSDimitry Andric // So, every iteration, we execute an assignment here 1354bdd1243dSDimitry Andric // where the LHS is on the stack (the target array) 1355bdd1243dSDimitry Andric // and the RHS is our SubExpr. 1356bdd1243dSDimitry Andric for (size_t I = 0; I != Size; ++I) { 1357bdd1243dSDimitry Andric ArrayIndexScope<Emitter> IndexScope(this, I); 1358bdd1243dSDimitry Andric 1359bdd1243dSDimitry Andric if (ElemT) { 1360bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1361bdd1243dSDimitry Andric return false; 1362bdd1243dSDimitry Andric if (!this->emitInitElem(*ElemT, I, Initializer)) 1363bdd1243dSDimitry Andric return false; 1364bdd1243dSDimitry Andric } else { 1365*fe013be4SDimitry Andric // Get to our array element and recurse into visitInitializer() 1366bdd1243dSDimitry Andric if (!this->emitConstUint64(I, SubExpr)) 1367bdd1243dSDimitry Andric return false; 1368*fe013be4SDimitry Andric if (!this->emitArrayElemPtrUint64(SubExpr)) 1369bdd1243dSDimitry Andric return false; 1370bdd1243dSDimitry Andric if (!visitInitializer(SubExpr)) 1371bdd1243dSDimitry Andric return false; 1372bdd1243dSDimitry Andric if (!this->emitPopPtr(Initializer)) 1373bdd1243dSDimitry Andric return false; 1374bdd1243dSDimitry Andric } 1375*fe013be4SDimitry Andric } 1376bdd1243dSDimitry Andric return true; 1377bdd1243dSDimitry Andric } else if (const auto *IVIE = dyn_cast<ImplicitValueInitExpr>(Initializer)) { 1378bdd1243dSDimitry Andric const ArrayType *AT = IVIE->getType()->getAsArrayTypeUnsafe(); 1379bdd1243dSDimitry Andric assert(AT); 1380bdd1243dSDimitry Andric const auto *CAT = cast<ConstantArrayType>(AT); 1381bdd1243dSDimitry Andric size_t NumElems = CAT->getSize().getZExtValue(); 1382bdd1243dSDimitry Andric 1383bdd1243dSDimitry Andric if (std::optional<PrimType> ElemT = classify(CAT->getElementType())) { 1384bdd1243dSDimitry Andric // TODO(perf): For int and bool types, we can probably just skip this 1385bdd1243dSDimitry Andric // since we memset our Block*s to 0 and so we have the desired value 1386bdd1243dSDimitry Andric // without this. 1387bdd1243dSDimitry Andric for (size_t I = 0; I != NumElems; ++I) { 1388*fe013be4SDimitry Andric if (!this->visitZeroInitializer(CAT->getElementType(), Initializer)) 1389bdd1243dSDimitry Andric return false; 1390bdd1243dSDimitry Andric if (!this->emitInitElem(*ElemT, I, Initializer)) 1391bdd1243dSDimitry Andric return false; 1392bdd1243dSDimitry Andric } 1393bdd1243dSDimitry Andric } else { 1394bdd1243dSDimitry Andric assert(false && "default initializer for non-primitive type"); 1395bdd1243dSDimitry Andric } 1396bdd1243dSDimitry Andric 1397bdd1243dSDimitry Andric return true; 1398bdd1243dSDimitry Andric } else if (const auto *Ctor = dyn_cast<CXXConstructExpr>(Initializer)) { 1399bdd1243dSDimitry Andric const ConstantArrayType *CAT = 1400bdd1243dSDimitry Andric Ctx.getASTContext().getAsConstantArrayType(Ctor->getType()); 1401bdd1243dSDimitry Andric assert(CAT); 1402bdd1243dSDimitry Andric size_t NumElems = CAT->getSize().getZExtValue(); 1403bdd1243dSDimitry Andric const Function *Func = getFunction(Ctor->getConstructor()); 1404bdd1243dSDimitry Andric if (!Func || !Func->isConstexpr()) 1405bdd1243dSDimitry Andric return false; 1406bdd1243dSDimitry Andric 1407bdd1243dSDimitry Andric // FIXME(perf): We're calling the constructor once per array element here, 1408bdd1243dSDimitry Andric // in the old intepreter we had a special-case for trivial constructors. 1409bdd1243dSDimitry Andric for (size_t I = 0; I != NumElems; ++I) { 1410bdd1243dSDimitry Andric if (!this->emitConstUint64(I, Initializer)) 1411bdd1243dSDimitry Andric return false; 1412*fe013be4SDimitry Andric if (!this->emitArrayElemPtrUint64(Initializer)) 1413bdd1243dSDimitry Andric return false; 1414bdd1243dSDimitry Andric 1415bdd1243dSDimitry Andric // Constructor arguments. 1416bdd1243dSDimitry Andric for (const auto *Arg : Ctor->arguments()) { 1417bdd1243dSDimitry Andric if (!this->visit(Arg)) 1418bdd1243dSDimitry Andric return false; 1419bdd1243dSDimitry Andric } 1420bdd1243dSDimitry Andric 1421bdd1243dSDimitry Andric if (!this->emitCall(Func, Initializer)) 1422bdd1243dSDimitry Andric return false; 1423bdd1243dSDimitry Andric } 1424bdd1243dSDimitry Andric return true; 1425*fe013be4SDimitry Andric } else if (const auto *SL = dyn_cast<StringLiteral>(Initializer)) { 1426*fe013be4SDimitry Andric const ConstantArrayType *CAT = 1427*fe013be4SDimitry Andric Ctx.getASTContext().getAsConstantArrayType(SL->getType()); 1428*fe013be4SDimitry Andric assert(CAT && "a string literal that's not a constant array?"); 1429*fe013be4SDimitry Andric 1430*fe013be4SDimitry Andric // If the initializer string is too long, a diagnostic has already been 1431*fe013be4SDimitry Andric // emitted. Read only the array length from the string literal. 1432*fe013be4SDimitry Andric unsigned N = 1433*fe013be4SDimitry Andric std::min(unsigned(CAT->getSize().getZExtValue()), SL->getLength()); 1434*fe013be4SDimitry Andric size_t CharWidth = SL->getCharByteWidth(); 1435*fe013be4SDimitry Andric 1436*fe013be4SDimitry Andric for (unsigned I = 0; I != N; ++I) { 1437*fe013be4SDimitry Andric uint32_t CodeUnit = SL->getCodeUnit(I); 1438*fe013be4SDimitry Andric 1439*fe013be4SDimitry Andric if (CharWidth == 1) { 1440*fe013be4SDimitry Andric this->emitConstSint8(CodeUnit, SL); 1441*fe013be4SDimitry Andric this->emitInitElemSint8(I, SL); 1442*fe013be4SDimitry Andric } else if (CharWidth == 2) { 1443*fe013be4SDimitry Andric this->emitConstUint16(CodeUnit, SL); 1444*fe013be4SDimitry Andric this->emitInitElemUint16(I, SL); 1445*fe013be4SDimitry Andric } else if (CharWidth == 4) { 1446*fe013be4SDimitry Andric this->emitConstUint32(CodeUnit, SL); 1447*fe013be4SDimitry Andric this->emitInitElemUint32(I, SL); 1448*fe013be4SDimitry Andric } else { 1449*fe013be4SDimitry Andric llvm_unreachable("unsupported character width"); 1450*fe013be4SDimitry Andric } 1451*fe013be4SDimitry Andric } 1452*fe013be4SDimitry Andric return true; 1453*fe013be4SDimitry Andric } else if (const auto *CLE = dyn_cast<CompoundLiteralExpr>(Initializer)) { 1454*fe013be4SDimitry Andric return visitInitializer(CLE->getInitializer()); 1455*fe013be4SDimitry Andric } else if (const auto *EWC = dyn_cast<ExprWithCleanups>(Initializer)) { 1456*fe013be4SDimitry Andric return visitInitializer(EWC->getSubExpr()); 1457bdd1243dSDimitry Andric } 1458bdd1243dSDimitry Andric 1459bdd1243dSDimitry Andric assert(false && "Unknown expression for array initialization"); 1460bdd1243dSDimitry Andric return false; 1461a7dea167SDimitry Andric } 1462a7dea167SDimitry Andric 1463a7dea167SDimitry Andric template <class Emitter> 1464bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitRecordInitializer(const Expr *Initializer) { 1465bdd1243dSDimitry Andric Initializer = Initializer->IgnoreParenImpCasts(); 1466bdd1243dSDimitry Andric assert(Initializer->getType()->isRecordType()); 1467bdd1243dSDimitry Andric 1468bdd1243dSDimitry Andric if (const auto CtorExpr = dyn_cast<CXXConstructExpr>(Initializer)) { 1469bdd1243dSDimitry Andric const Function *Func = getFunction(CtorExpr->getConstructor()); 1470bdd1243dSDimitry Andric 1471*fe013be4SDimitry Andric if (!Func) 1472bdd1243dSDimitry Andric return false; 1473bdd1243dSDimitry Andric 1474bdd1243dSDimitry Andric // The This pointer is already on the stack because this is an initializer, 1475bdd1243dSDimitry Andric // but we need to dup() so the call() below has its own copy. 1476bdd1243dSDimitry Andric if (!this->emitDupPtr(Initializer)) 1477bdd1243dSDimitry Andric return false; 1478bdd1243dSDimitry Andric 1479bdd1243dSDimitry Andric // Constructor arguments. 1480bdd1243dSDimitry Andric for (const auto *Arg : CtorExpr->arguments()) { 1481bdd1243dSDimitry Andric if (!this->visit(Arg)) 1482bdd1243dSDimitry Andric return false; 1483a7dea167SDimitry Andric } 1484bdd1243dSDimitry Andric 1485bdd1243dSDimitry Andric return this->emitCall(Func, Initializer); 1486bdd1243dSDimitry Andric } else if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) { 1487bdd1243dSDimitry Andric const Record *R = getRecord(InitList->getType()); 1488bdd1243dSDimitry Andric 1489bdd1243dSDimitry Andric unsigned InitIndex = 0; 1490bdd1243dSDimitry Andric for (const Expr *Init : InitList->inits()) { 1491bdd1243dSDimitry Andric 1492bdd1243dSDimitry Andric if (!this->emitDupPtr(Initializer)) 1493bdd1243dSDimitry Andric return false; 1494bdd1243dSDimitry Andric 1495bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(Init)) { 1496*fe013be4SDimitry Andric const Record::Field *FieldToInit = R->getField(InitIndex); 1497bdd1243dSDimitry Andric if (!this->visit(Init)) 1498bdd1243dSDimitry Andric return false; 1499bdd1243dSDimitry Andric 1500bdd1243dSDimitry Andric if (!this->emitInitField(*T, FieldToInit->Offset, Initializer)) 1501bdd1243dSDimitry Andric return false; 1502bdd1243dSDimitry Andric 1503bdd1243dSDimitry Andric if (!this->emitPopPtr(Initializer)) 1504bdd1243dSDimitry Andric return false; 1505*fe013be4SDimitry Andric ++InitIndex; 1506bdd1243dSDimitry Andric } else { 1507*fe013be4SDimitry Andric // Initializer for a direct base class. 1508*fe013be4SDimitry Andric if (const Record::Base *B = R->getBase(Init->getType())) { 1509*fe013be4SDimitry Andric if (!this->emitGetPtrBasePop(B->Offset, Init)) 1510*fe013be4SDimitry Andric return false; 1511*fe013be4SDimitry Andric 1512*fe013be4SDimitry Andric if (!this->visitInitializer(Init)) 1513*fe013be4SDimitry Andric return false; 1514*fe013be4SDimitry Andric 1515*fe013be4SDimitry Andric if (!this->emitPopPtr(Initializer)) 1516*fe013be4SDimitry Andric return false; 1517*fe013be4SDimitry Andric // Base initializers don't increase InitIndex, since they don't count 1518*fe013be4SDimitry Andric // into the Record's fields. 1519*fe013be4SDimitry Andric } else { 1520*fe013be4SDimitry Andric const Record::Field *FieldToInit = R->getField(InitIndex); 1521bdd1243dSDimitry Andric // Non-primitive case. Get a pointer to the field-to-initialize 1522bdd1243dSDimitry Andric // on the stack and recurse into visitInitializer(). 1523bdd1243dSDimitry Andric if (!this->emitGetPtrField(FieldToInit->Offset, Init)) 1524bdd1243dSDimitry Andric return false; 1525bdd1243dSDimitry Andric 1526bdd1243dSDimitry Andric if (!this->visitInitializer(Init)) 1527bdd1243dSDimitry Andric return false; 1528bdd1243dSDimitry Andric 1529bdd1243dSDimitry Andric if (!this->emitPopPtr(Initializer)) 1530bdd1243dSDimitry Andric return false; 1531bdd1243dSDimitry Andric ++InitIndex; 1532bdd1243dSDimitry Andric } 1533*fe013be4SDimitry Andric } 1534*fe013be4SDimitry Andric } 1535bdd1243dSDimitry Andric 1536bdd1243dSDimitry Andric return true; 1537bdd1243dSDimitry Andric } else if (const CallExpr *CE = dyn_cast<CallExpr>(Initializer)) { 1538bdd1243dSDimitry Andric // RVO functions expect a pointer to initialize on the stack. 1539bdd1243dSDimitry Andric // Dup our existing pointer so it has its own copy to use. 1540bdd1243dSDimitry Andric if (!this->emitDupPtr(Initializer)) 1541bdd1243dSDimitry Andric return false; 1542bdd1243dSDimitry Andric 1543*fe013be4SDimitry Andric return this->visit(CE); 1544bdd1243dSDimitry Andric } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) { 1545bdd1243dSDimitry Andric return this->visitInitializer(DIE->getExpr()); 1546*fe013be4SDimitry Andric } else if (const auto *CE = dyn_cast<CastExpr>(Initializer)) { 1547*fe013be4SDimitry Andric return this->visitInitializer(CE->getSubExpr()); 1548*fe013be4SDimitry Andric } else if (const auto *CE = dyn_cast<CXXBindTemporaryExpr>(Initializer)) { 1549*fe013be4SDimitry Andric return this->visitInitializer(CE->getSubExpr()); 1550*fe013be4SDimitry Andric } else if (const auto *ACO = 1551*fe013be4SDimitry Andric dyn_cast<AbstractConditionalOperator>(Initializer)) { 1552*fe013be4SDimitry Andric return this->visitConditional( 1553*fe013be4SDimitry Andric ACO, [this](const Expr *E) { return this->visitRecordInitializer(E); }); 1554*fe013be4SDimitry Andric } else if (const auto *LE = dyn_cast<LambdaExpr>(Initializer)) { 1555*fe013be4SDimitry Andric return this->VisitLambdaExpr(LE); 1556bdd1243dSDimitry Andric } 1557bdd1243dSDimitry Andric 1558bdd1243dSDimitry Andric return false; 1559a7dea167SDimitry Andric } 1560a7dea167SDimitry Andric 1561a7dea167SDimitry Andric template <class Emitter> 1562bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *Initializer) { 1563bdd1243dSDimitry Andric QualType InitializerType = Initializer->getType(); 1564bdd1243dSDimitry Andric 1565bdd1243dSDimitry Andric if (InitializerType->isArrayType()) 1566bdd1243dSDimitry Andric return visitArrayInitializer(Initializer); 1567bdd1243dSDimitry Andric 1568bdd1243dSDimitry Andric if (InitializerType->isRecordType()) 1569bdd1243dSDimitry Andric return visitRecordInitializer(Initializer); 1570bdd1243dSDimitry Andric 1571bdd1243dSDimitry Andric // Otherwise, visit the expression like normal. 1572bdd1243dSDimitry Andric return this->visit(Initializer); 1573a7dea167SDimitry Andric } 1574a7dea167SDimitry Andric 1575a7dea167SDimitry Andric template <class Emitter> 1576a7dea167SDimitry Andric const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) { 1577753f127fSDimitry Andric if (const PointerType *PT = dyn_cast<PointerType>(Ty)) 1578a7dea167SDimitry Andric return PT->getPointeeType()->getAs<RecordType>(); 1579a7dea167SDimitry Andric else 1580a7dea167SDimitry Andric return Ty->getAs<RecordType>(); 1581a7dea167SDimitry Andric } 1582a7dea167SDimitry Andric 1583a7dea167SDimitry Andric template <class Emitter> 1584a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) { 1585a7dea167SDimitry Andric if (auto *RecordTy = getRecordTy(Ty)) { 1586a7dea167SDimitry Andric return getRecord(RecordTy->getDecl()); 1587a7dea167SDimitry Andric } 1588a7dea167SDimitry Andric return nullptr; 1589a7dea167SDimitry Andric } 1590a7dea167SDimitry Andric 1591a7dea167SDimitry Andric template <class Emitter> 1592a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) { 1593a7dea167SDimitry Andric return P.getOrCreateRecord(RD); 1594a7dea167SDimitry Andric } 1595a7dea167SDimitry Andric 1596a7dea167SDimitry Andric template <class Emitter> 1597bdd1243dSDimitry Andric const Function *ByteCodeExprGen<Emitter>::getFunction(const FunctionDecl *FD) { 1598bdd1243dSDimitry Andric assert(FD); 1599bdd1243dSDimitry Andric const Function *Func = P.getFunction(FD); 1600bdd1243dSDimitry Andric bool IsBeingCompiled = Func && !Func->isFullyCompiled(); 1601*fe013be4SDimitry Andric bool WasNotDefined = Func && !Func->isConstexpr() && !Func->hasBody(); 1602bdd1243dSDimitry Andric 1603bdd1243dSDimitry Andric if (IsBeingCompiled) 1604bdd1243dSDimitry Andric return Func; 1605bdd1243dSDimitry Andric 1606bdd1243dSDimitry Andric if (!Func || WasNotDefined) { 1607bdd1243dSDimitry Andric if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(Ctx, P).compileFunc(FD)) 1608bdd1243dSDimitry Andric Func = *R; 1609bdd1243dSDimitry Andric else { 1610bdd1243dSDimitry Andric llvm::consumeError(R.takeError()); 1611bdd1243dSDimitry Andric return nullptr; 1612bdd1243dSDimitry Andric } 1613bdd1243dSDimitry Andric } 1614bdd1243dSDimitry Andric 1615bdd1243dSDimitry Andric return Func; 1616bdd1243dSDimitry Andric } 1617bdd1243dSDimitry Andric 1618bdd1243dSDimitry Andric template <class Emitter> 1619a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *Exp) { 1620a7dea167SDimitry Andric ExprScope<Emitter> RootScope(this); 1621a7dea167SDimitry Andric if (!visit(Exp)) 1622a7dea167SDimitry Andric return false; 1623a7dea167SDimitry Andric 1624bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(Exp)) 1625a7dea167SDimitry Andric return this->emitRet(*T, Exp); 1626a7dea167SDimitry Andric else 1627a7dea167SDimitry Andric return this->emitRetValue(Exp); 1628a7dea167SDimitry Andric } 1629a7dea167SDimitry Andric 1630bdd1243dSDimitry Andric /// Toplevel visitDecl(). 1631bdd1243dSDimitry Andric /// We get here from evaluateAsInitializer(). 1632bdd1243dSDimitry Andric /// We need to evaluate the initializer and return its value. 1633a7dea167SDimitry Andric template <class Emitter> 1634a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) { 1635*fe013be4SDimitry Andric assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl"); 1636a7dea167SDimitry Andric 1637bdd1243dSDimitry Andric // Create and initialize the variable. 1638bdd1243dSDimitry Andric if (!this->visitVarDecl(VD)) 1639a7dea167SDimitry Andric return false; 1640a7dea167SDimitry Andric 1641bdd1243dSDimitry Andric // Get a pointer to the variable 1642*fe013be4SDimitry Andric if (Context::shouldBeGloballyIndexed(VD)) { 1643bdd1243dSDimitry Andric auto GlobalIndex = P.getGlobal(VD); 1644bdd1243dSDimitry Andric assert(GlobalIndex); // visitVarDecl() didn't return false. 1645bdd1243dSDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, VD)) 1646a7dea167SDimitry Andric return false; 1647a7dea167SDimitry Andric } else { 1648bdd1243dSDimitry Andric auto Local = Locals.find(VD); 1649bdd1243dSDimitry Andric assert(Local != Locals.end()); // Same here. 1650bdd1243dSDimitry Andric if (!this->emitGetPtrLocal(Local->second.Offset, VD)) 1651a7dea167SDimitry Andric return false; 1652a7dea167SDimitry Andric } 1653a7dea167SDimitry Andric 1654bdd1243dSDimitry Andric // Return the value 1655*fe013be4SDimitry Andric if (std::optional<PrimType> VarT = classify(VD->getType())) { 1656bdd1243dSDimitry Andric if (!this->emitLoadPop(*VarT, VD)) 1657a7dea167SDimitry Andric return false; 1658bdd1243dSDimitry Andric 1659bdd1243dSDimitry Andric return this->emitRet(*VarT, VD); 1660bdd1243dSDimitry Andric } 1661bdd1243dSDimitry Andric 1662a7dea167SDimitry Andric return this->emitRetValue(VD); 1663a7dea167SDimitry Andric } 1664bdd1243dSDimitry Andric 1665bdd1243dSDimitry Andric template <class Emitter> 1666bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) { 1667*fe013be4SDimitry Andric // We don't know what to do with these, so just return false. 1668*fe013be4SDimitry Andric if (VD->getType().isNull()) 1669*fe013be4SDimitry Andric return false; 1670*fe013be4SDimitry Andric 1671bdd1243dSDimitry Andric const Expr *Init = VD->getInit(); 1672bdd1243dSDimitry Andric std::optional<PrimType> VarT = classify(VD->getType()); 1673bdd1243dSDimitry Andric 1674*fe013be4SDimitry Andric if (Context::shouldBeGloballyIndexed(VD)) { 1675*fe013be4SDimitry Andric // We've already seen and initialized this global. 1676*fe013be4SDimitry Andric if (P.getGlobal(VD)) 1677*fe013be4SDimitry Andric return true; 1678*fe013be4SDimitry Andric 1679*fe013be4SDimitry Andric std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init); 1680bdd1243dSDimitry Andric 1681bdd1243dSDimitry Andric if (!GlobalIndex) 1682bdd1243dSDimitry Andric return this->bail(VD); 1683bdd1243dSDimitry Andric 1684bdd1243dSDimitry Andric assert(Init); 1685bdd1243dSDimitry Andric { 1686bdd1243dSDimitry Andric DeclScope<Emitter> LocalScope(this, VD); 1687bdd1243dSDimitry Andric 1688bdd1243dSDimitry Andric if (VarT) { 1689bdd1243dSDimitry Andric if (!this->visit(Init)) 1690bdd1243dSDimitry Andric return false; 1691bdd1243dSDimitry Andric return this->emitInitGlobal(*VarT, *GlobalIndex, VD); 1692bdd1243dSDimitry Andric } 1693bdd1243dSDimitry Andric return this->visitGlobalInitializer(Init, *GlobalIndex); 1694bdd1243dSDimitry Andric } 1695bdd1243dSDimitry Andric } else { 1696bdd1243dSDimitry Andric VariableScope<Emitter> LocalScope(this); 1697bdd1243dSDimitry Andric if (VarT) { 1698bdd1243dSDimitry Andric unsigned Offset = this->allocateLocalPrimitive( 1699bdd1243dSDimitry Andric VD, *VarT, VD->getType().isConstQualified()); 1700bdd1243dSDimitry Andric if (Init) { 1701bdd1243dSDimitry Andric // Compile the initializer in its own scope. 1702bdd1243dSDimitry Andric ExprScope<Emitter> Scope(this); 1703bdd1243dSDimitry Andric if (!this->visit(Init)) 1704bdd1243dSDimitry Andric return false; 1705bdd1243dSDimitry Andric 1706bdd1243dSDimitry Andric return this->emitSetLocal(*VarT, Offset, VD); 1707bdd1243dSDimitry Andric } 1708bdd1243dSDimitry Andric } else { 1709bdd1243dSDimitry Andric if (std::optional<unsigned> Offset = this->allocateLocal(VD)) { 1710bdd1243dSDimitry Andric if (Init) 1711bdd1243dSDimitry Andric return this->visitLocalInitializer(Init, *Offset); 1712bdd1243dSDimitry Andric } 1713bdd1243dSDimitry Andric } 1714bdd1243dSDimitry Andric return true; 1715a7dea167SDimitry Andric } 1716a7dea167SDimitry Andric 1717bdd1243dSDimitry Andric return false; 1718bdd1243dSDimitry Andric } 1719bdd1243dSDimitry Andric 1720bdd1243dSDimitry Andric template <class Emitter> 1721*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) { 1722*fe013be4SDimitry Andric const Function *Func = getFunction(E->getDirectCallee()); 1723bdd1243dSDimitry Andric if (!Func) 1724bdd1243dSDimitry Andric return false; 1725*fe013be4SDimitry Andric 1726*fe013be4SDimitry Andric // Put arguments on the stack. 1727*fe013be4SDimitry Andric for (const auto *Arg : E->arguments()) { 1728*fe013be4SDimitry Andric if (!this->visit(Arg)) 1729*fe013be4SDimitry Andric return false; 1730*fe013be4SDimitry Andric } 1731*fe013be4SDimitry Andric 1732*fe013be4SDimitry Andric if (!this->emitCallBI(Func, E)) 1733bdd1243dSDimitry Andric return false; 1734bdd1243dSDimitry Andric 1735bdd1243dSDimitry Andric QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); 1736*fe013be4SDimitry Andric if (DiscardResult && !ReturnType->isVoidType()) { 1737*fe013be4SDimitry Andric PrimType T = classifyPrim(ReturnType); 1738*fe013be4SDimitry Andric return this->emitPop(T, E); 1739*fe013be4SDimitry Andric } 1740bdd1243dSDimitry Andric 1741*fe013be4SDimitry Andric return true; 1742*fe013be4SDimitry Andric } 1743*fe013be4SDimitry Andric 1744*fe013be4SDimitry Andric template <class Emitter> 1745*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) { 1746*fe013be4SDimitry Andric if (E->getBuiltinCallee()) 1747*fe013be4SDimitry Andric return VisitBuiltinCallExpr(E); 1748*fe013be4SDimitry Andric 1749*fe013be4SDimitry Andric QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); 1750*fe013be4SDimitry Andric std::optional<PrimType> T = classify(ReturnType); 1751*fe013be4SDimitry Andric bool HasRVO = !ReturnType->isVoidType() && !T; 1752*fe013be4SDimitry Andric 1753*fe013be4SDimitry Andric if (HasRVO && DiscardResult) { 1754bdd1243dSDimitry Andric // If we need to discard the return value but the function returns its 1755bdd1243dSDimitry Andric // value via an RVO pointer, we need to create one such pointer just 1756bdd1243dSDimitry Andric // for this call. 1757bdd1243dSDimitry Andric if (std::optional<unsigned> LocalIndex = allocateLocal(E)) { 1758bdd1243dSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E)) 1759bdd1243dSDimitry Andric return false; 1760bdd1243dSDimitry Andric } 1761bdd1243dSDimitry Andric } 1762bdd1243dSDimitry Andric 1763bdd1243dSDimitry Andric // Put arguments on the stack. 1764bdd1243dSDimitry Andric for (const auto *Arg : E->arguments()) { 1765bdd1243dSDimitry Andric if (!this->visit(Arg)) 1766bdd1243dSDimitry Andric return false; 1767bdd1243dSDimitry Andric } 1768bdd1243dSDimitry Andric 1769*fe013be4SDimitry Andric if (const FunctionDecl *FuncDecl = E->getDirectCallee()) { 1770*fe013be4SDimitry Andric const Function *Func = getFunction(FuncDecl); 1771*fe013be4SDimitry Andric if (!Func) 1772*fe013be4SDimitry Andric return false; 1773*fe013be4SDimitry Andric // If the function is being compiled right now, this is a recursive call. 1774*fe013be4SDimitry Andric // In that case, the function can't be valid yet, even though it will be 1775*fe013be4SDimitry Andric // later. 1776*fe013be4SDimitry Andric // If the function is already fully compiled but not constexpr, it was 1777*fe013be4SDimitry Andric // found to be faulty earlier on, so bail out. 1778*fe013be4SDimitry Andric if (Func->isFullyCompiled() && !Func->isConstexpr()) 1779bdd1243dSDimitry Andric return false; 1780bdd1243dSDimitry Andric 1781*fe013be4SDimitry Andric assert(HasRVO == Func->hasRVO()); 1782*fe013be4SDimitry Andric 1783*fe013be4SDimitry Andric bool HasQualifier = false; 1784*fe013be4SDimitry Andric if (const auto *ME = dyn_cast<MemberExpr>(E->getCallee())) 1785*fe013be4SDimitry Andric HasQualifier = ME->hasQualifier(); 1786*fe013be4SDimitry Andric 1787*fe013be4SDimitry Andric bool IsVirtual = false; 1788*fe013be4SDimitry Andric if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) 1789*fe013be4SDimitry Andric IsVirtual = MD->isVirtual(); 1790*fe013be4SDimitry Andric 1791*fe013be4SDimitry Andric // In any case call the function. The return value will end up on the stack 1792*fe013be4SDimitry Andric // and if the function has RVO, we already have the pointer on the stack to 1793*fe013be4SDimitry Andric // write the result into. 1794*fe013be4SDimitry Andric if (IsVirtual && !HasQualifier) { 1795*fe013be4SDimitry Andric if (!this->emitCallVirt(Func, E)) 1796*fe013be4SDimitry Andric return false; 1797*fe013be4SDimitry Andric } else { 1798*fe013be4SDimitry Andric if (!this->emitCall(Func, E)) 1799*fe013be4SDimitry Andric return false; 1800*fe013be4SDimitry Andric } 1801*fe013be4SDimitry Andric } else { 1802*fe013be4SDimitry Andric // Indirect call. Visit the callee, which will leave a FunctionPointer on 1803*fe013be4SDimitry Andric // the stack. Cleanup of the returned value if necessary will be done after 1804*fe013be4SDimitry Andric // the function call completed. 1805*fe013be4SDimitry Andric if (!this->visit(E->getCallee())) 1806*fe013be4SDimitry Andric return false; 1807*fe013be4SDimitry Andric 1808*fe013be4SDimitry Andric if (!this->emitCallPtr(E)) 1809*fe013be4SDimitry Andric return false; 1810*fe013be4SDimitry Andric } 1811*fe013be4SDimitry Andric 1812*fe013be4SDimitry Andric // Cleanup for discarded return values. 1813bdd1243dSDimitry Andric if (DiscardResult && !ReturnType->isVoidType() && T) 1814bdd1243dSDimitry Andric return this->emitPop(*T, E); 1815bdd1243dSDimitry Andric 1816bdd1243dSDimitry Andric return true; 1817bdd1243dSDimitry Andric } 1818bdd1243dSDimitry Andric 1819bdd1243dSDimitry Andric template <class Emitter> 1820bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXMemberCallExpr( 1821bdd1243dSDimitry Andric const CXXMemberCallExpr *E) { 1822bdd1243dSDimitry Andric // Get a This pointer on the stack. 1823bdd1243dSDimitry Andric if (!this->visit(E->getImplicitObjectArgument())) 1824bdd1243dSDimitry Andric return false; 1825bdd1243dSDimitry Andric 1826bdd1243dSDimitry Andric return VisitCallExpr(E); 1827bdd1243dSDimitry Andric } 1828bdd1243dSDimitry Andric 1829bdd1243dSDimitry Andric template <class Emitter> 1830bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultInitExpr( 1831bdd1243dSDimitry Andric const CXXDefaultInitExpr *E) { 1832*fe013be4SDimitry Andric assert(classify(E->getType())); 1833bdd1243dSDimitry Andric return this->visit(E->getExpr()); 1834bdd1243dSDimitry Andric } 1835bdd1243dSDimitry Andric 1836bdd1243dSDimitry Andric template <class Emitter> 1837bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultArgExpr( 1838bdd1243dSDimitry Andric const CXXDefaultArgExpr *E) { 1839bdd1243dSDimitry Andric return this->visit(E->getExpr()); 1840bdd1243dSDimitry Andric } 1841bdd1243dSDimitry Andric 1842bdd1243dSDimitry Andric template <class Emitter> 1843bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXBoolLiteralExpr( 1844bdd1243dSDimitry Andric const CXXBoolLiteralExpr *E) { 1845bdd1243dSDimitry Andric if (DiscardResult) 1846bdd1243dSDimitry Andric return true; 1847bdd1243dSDimitry Andric 1848bdd1243dSDimitry Andric return this->emitConstBool(E->getValue(), E); 1849bdd1243dSDimitry Andric } 1850bdd1243dSDimitry Andric 1851bdd1243dSDimitry Andric template <class Emitter> 1852bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr( 1853bdd1243dSDimitry Andric const CXXNullPtrLiteralExpr *E) { 1854bdd1243dSDimitry Andric if (DiscardResult) 1855bdd1243dSDimitry Andric return true; 1856bdd1243dSDimitry Andric 1857bdd1243dSDimitry Andric return this->emitNullPtr(E); 1858bdd1243dSDimitry Andric } 1859bdd1243dSDimitry Andric 1860bdd1243dSDimitry Andric template <class Emitter> 1861bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) { 1862bdd1243dSDimitry Andric if (DiscardResult) 1863bdd1243dSDimitry Andric return true; 1864bdd1243dSDimitry Andric return this->emitThis(E); 1865bdd1243dSDimitry Andric } 1866bdd1243dSDimitry Andric 1867bdd1243dSDimitry Andric template <class Emitter> 1868bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) { 1869bdd1243dSDimitry Andric const Expr *SubExpr = E->getSubExpr(); 1870bdd1243dSDimitry Andric std::optional<PrimType> T = classify(SubExpr->getType()); 1871bdd1243dSDimitry Andric 1872bdd1243dSDimitry Andric switch (E->getOpcode()) { 1873bdd1243dSDimitry Andric case UO_PostInc: { // x++ 1874bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1875bdd1243dSDimitry Andric return false; 1876bdd1243dSDimitry Andric 1877*fe013be4SDimitry Andric if (T == PT_Ptr) { 1878*fe013be4SDimitry Andric if (!this->emitIncPtr(E)) 1879*fe013be4SDimitry Andric return false; 1880*fe013be4SDimitry Andric 1881*fe013be4SDimitry Andric return DiscardResult ? this->emitPopPtr(E) : true; 1882*fe013be4SDimitry Andric } 1883*fe013be4SDimitry Andric 1884*fe013be4SDimitry Andric if (T == PT_Float) { 1885*fe013be4SDimitry Andric return DiscardResult ? this->emitIncfPop(getRoundingMode(E), E) 1886*fe013be4SDimitry Andric : this->emitIncf(getRoundingMode(E), E); 1887*fe013be4SDimitry Andric } 1888*fe013be4SDimitry Andric 1889bdd1243dSDimitry Andric return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E); 1890bdd1243dSDimitry Andric } 1891bdd1243dSDimitry Andric case UO_PostDec: { // x-- 1892bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1893bdd1243dSDimitry Andric return false; 1894bdd1243dSDimitry Andric 1895*fe013be4SDimitry Andric if (T == PT_Ptr) { 1896*fe013be4SDimitry Andric if (!this->emitDecPtr(E)) 1897*fe013be4SDimitry Andric return false; 1898*fe013be4SDimitry Andric 1899*fe013be4SDimitry Andric return DiscardResult ? this->emitPopPtr(E) : true; 1900*fe013be4SDimitry Andric } 1901*fe013be4SDimitry Andric 1902*fe013be4SDimitry Andric if (T == PT_Float) { 1903*fe013be4SDimitry Andric return DiscardResult ? this->emitDecfPop(getRoundingMode(E), E) 1904*fe013be4SDimitry Andric : this->emitDecf(getRoundingMode(E), E); 1905*fe013be4SDimitry Andric } 1906*fe013be4SDimitry Andric 1907bdd1243dSDimitry Andric return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E); 1908bdd1243dSDimitry Andric } 1909bdd1243dSDimitry Andric case UO_PreInc: { // ++x 1910bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1911bdd1243dSDimitry Andric return false; 1912bdd1243dSDimitry Andric 1913*fe013be4SDimitry Andric if (T == PT_Ptr) { 1914*fe013be4SDimitry Andric this->emitLoadPtr(E); 1915*fe013be4SDimitry Andric this->emitConstUint8(1, E); 1916*fe013be4SDimitry Andric this->emitAddOffsetUint8(E); 1917*fe013be4SDimitry Andric return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E); 1918*fe013be4SDimitry Andric } 1919bdd1243dSDimitry Andric 1920*fe013be4SDimitry Andric // Post-inc and pre-inc are the same if the value is to be discarded. 1921*fe013be4SDimitry Andric if (DiscardResult) { 1922*fe013be4SDimitry Andric if (T == PT_Float) 1923*fe013be4SDimitry Andric return this->emitIncfPop(getRoundingMode(E), E); 1924*fe013be4SDimitry Andric return this->emitIncPop(*T, E); 1925*fe013be4SDimitry Andric } 1926*fe013be4SDimitry Andric 1927*fe013be4SDimitry Andric if (T == PT_Float) { 1928*fe013be4SDimitry Andric const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType()); 1929*fe013be4SDimitry Andric this->emitLoadFloat(E); 1930*fe013be4SDimitry Andric this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E); 1931*fe013be4SDimitry Andric this->emitAddf(getRoundingMode(E), E); 1932*fe013be4SDimitry Andric return this->emitStoreFloat(E); 1933*fe013be4SDimitry Andric } 1934bdd1243dSDimitry Andric this->emitLoad(*T, E); 1935bdd1243dSDimitry Andric this->emitConst(1, E); 1936bdd1243dSDimitry Andric this->emitAdd(*T, E); 1937bdd1243dSDimitry Andric return this->emitStore(*T, E); 1938bdd1243dSDimitry Andric } 1939bdd1243dSDimitry Andric case UO_PreDec: { // --x 1940bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1941bdd1243dSDimitry Andric return false; 1942bdd1243dSDimitry Andric 1943*fe013be4SDimitry Andric if (T == PT_Ptr) { 1944*fe013be4SDimitry Andric this->emitLoadPtr(E); 1945*fe013be4SDimitry Andric this->emitConstUint8(1, E); 1946*fe013be4SDimitry Andric this->emitSubOffsetUint8(E); 1947*fe013be4SDimitry Andric return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E); 1948*fe013be4SDimitry Andric } 1949bdd1243dSDimitry Andric 1950*fe013be4SDimitry Andric // Post-dec and pre-dec are the same if the value is to be discarded. 1951*fe013be4SDimitry Andric if (DiscardResult) { 1952*fe013be4SDimitry Andric if (T == PT_Float) 1953*fe013be4SDimitry Andric return this->emitDecfPop(getRoundingMode(E), E); 1954*fe013be4SDimitry Andric return this->emitDecPop(*T, E); 1955*fe013be4SDimitry Andric } 1956*fe013be4SDimitry Andric 1957*fe013be4SDimitry Andric if (T == PT_Float) { 1958*fe013be4SDimitry Andric const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType()); 1959*fe013be4SDimitry Andric this->emitLoadFloat(E); 1960*fe013be4SDimitry Andric this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E); 1961*fe013be4SDimitry Andric this->emitSubf(getRoundingMode(E), E); 1962*fe013be4SDimitry Andric return this->emitStoreFloat(E); 1963*fe013be4SDimitry Andric } 1964bdd1243dSDimitry Andric this->emitLoad(*T, E); 1965bdd1243dSDimitry Andric this->emitConst(1, E); 1966bdd1243dSDimitry Andric this->emitSub(*T, E); 1967bdd1243dSDimitry Andric return this->emitStore(*T, E); 1968bdd1243dSDimitry Andric } 1969bdd1243dSDimitry Andric case UO_LNot: // !x 1970bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1971bdd1243dSDimitry Andric return false; 1972bdd1243dSDimitry Andric // The Inv doesn't change anything, so skip it if we don't need the result. 1973bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : this->emitInvBool(E); 1974bdd1243dSDimitry Andric case UO_Minus: // -x 1975bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1976bdd1243dSDimitry Andric return false; 1977bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E); 1978bdd1243dSDimitry Andric case UO_Plus: // +x 1979bdd1243dSDimitry Andric if (!this->visit(SubExpr)) // noop 1980bdd1243dSDimitry Andric return false; 1981bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : true; 1982bdd1243dSDimitry Andric case UO_AddrOf: // &x 1983bdd1243dSDimitry Andric // We should already have a pointer when we get here. 1984bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1985bdd1243dSDimitry Andric return false; 1986bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : true; 1987bdd1243dSDimitry Andric case UO_Deref: // *x 1988bdd1243dSDimitry Andric return dereference( 1989bdd1243dSDimitry Andric SubExpr, DerefKind::Read, 1990bdd1243dSDimitry Andric [](PrimType) { 1991bdd1243dSDimitry Andric llvm_unreachable("Dereferencing requires a pointer"); 1992bdd1243dSDimitry Andric return false; 1993bdd1243dSDimitry Andric }, 1994bdd1243dSDimitry Andric [this, E](PrimType T) { 1995bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(T, E) : true; 1996bdd1243dSDimitry Andric }); 1997bdd1243dSDimitry Andric case UO_Not: // ~x 1998bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 1999bdd1243dSDimitry Andric return false; 2000bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E); 2001bdd1243dSDimitry Andric case UO_Real: // __real x 2002bdd1243dSDimitry Andric case UO_Imag: // __imag x 2003bdd1243dSDimitry Andric case UO_Extension: 2004bdd1243dSDimitry Andric case UO_Coawait: 2005bdd1243dSDimitry Andric assert(false && "Unhandled opcode"); 2006bdd1243dSDimitry Andric } 2007bdd1243dSDimitry Andric 2008bdd1243dSDimitry Andric return false; 2009bdd1243dSDimitry Andric } 2010bdd1243dSDimitry Andric 2011bdd1243dSDimitry Andric template <class Emitter> 2012bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) { 2013*fe013be4SDimitry Andric if (DiscardResult) 2014*fe013be4SDimitry Andric return true; 2015*fe013be4SDimitry Andric 2016*fe013be4SDimitry Andric const auto *D = E->getDecl(); 2017*fe013be4SDimitry Andric 2018*fe013be4SDimitry Andric if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) { 2019*fe013be4SDimitry Andric return this->emitConst(ECD->getInitVal(), E); 2020*fe013be4SDimitry Andric } else if (const auto *BD = dyn_cast<BindingDecl>(D)) { 2021*fe013be4SDimitry Andric return this->visit(BD->getBinding()); 2022*fe013be4SDimitry Andric } else if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) { 2023*fe013be4SDimitry Andric const Function *F = getFunction(FuncDecl); 2024*fe013be4SDimitry Andric return F && this->emitGetFnPtr(F, E); 2025*fe013be4SDimitry Andric } 2026*fe013be4SDimitry Andric 2027bdd1243dSDimitry Andric // References are implemented via pointers, so when we see a DeclRefExpr 2028bdd1243dSDimitry Andric // pointing to a reference, we need to get its value directly (i.e. the 2029bdd1243dSDimitry Andric // pointer to the actual value) instead of a pointer to the pointer to the 2030bdd1243dSDimitry Andric // value. 2031*fe013be4SDimitry Andric bool IsReference = D->getType()->isReferenceType(); 2032bdd1243dSDimitry Andric 2033*fe013be4SDimitry Andric // Check for local/global variables and parameters. 2034*fe013be4SDimitry Andric if (auto It = Locals.find(D); It != Locals.end()) { 2035bdd1243dSDimitry Andric const unsigned Offset = It->second.Offset; 2036bdd1243dSDimitry Andric 2037bdd1243dSDimitry Andric if (IsReference) 2038bdd1243dSDimitry Andric return this->emitGetLocal(PT_Ptr, Offset, E); 2039bdd1243dSDimitry Andric return this->emitGetPtrLocal(Offset, E); 2040*fe013be4SDimitry Andric } else if (auto GlobalIndex = P.getGlobal(D)) { 2041bdd1243dSDimitry Andric if (IsReference) 2042*fe013be4SDimitry Andric return this->emitGetGlobalPtr(*GlobalIndex, E); 2043bdd1243dSDimitry Andric 2044bdd1243dSDimitry Andric return this->emitGetPtrGlobal(*GlobalIndex, E); 2045*fe013be4SDimitry Andric } else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) { 2046bdd1243dSDimitry Andric if (auto It = this->Params.find(PVD); It != this->Params.end()) { 2047bdd1243dSDimitry Andric if (IsReference) 2048*fe013be4SDimitry Andric return this->emitGetParamPtr(It->second, E); 2049bdd1243dSDimitry Andric return this->emitGetPtrParam(It->second, E); 2050bdd1243dSDimitry Andric } 2051*fe013be4SDimitry Andric } 2052*fe013be4SDimitry Andric 2053*fe013be4SDimitry Andric // Handle lambda captures. 2054*fe013be4SDimitry Andric if (auto It = this->LambdaCaptures.find(D); 2055*fe013be4SDimitry Andric It != this->LambdaCaptures.end()) { 2056*fe013be4SDimitry Andric auto [Offset, IsReference] = It->second; 2057*fe013be4SDimitry Andric 2058*fe013be4SDimitry Andric if (IsReference) 2059*fe013be4SDimitry Andric return this->emitGetThisFieldPtr(Offset, E); 2060*fe013be4SDimitry Andric return this->emitGetPtrThisField(Offset, E); 2061bdd1243dSDimitry Andric } 2062bdd1243dSDimitry Andric 2063bdd1243dSDimitry Andric return false; 2064a7dea167SDimitry Andric } 2065a7dea167SDimitry Andric 2066a7dea167SDimitry Andric template <class Emitter> 2067a7dea167SDimitry Andric void ByteCodeExprGen<Emitter>::emitCleanup() { 2068a7dea167SDimitry Andric for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent()) 2069a7dea167SDimitry Andric C->emitDestruction(); 2070a7dea167SDimitry Andric } 2071a7dea167SDimitry Andric 2072*fe013be4SDimitry Andric template <class Emitter> 2073*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::emitDerivedToBaseCasts( 2074*fe013be4SDimitry Andric const RecordType *DerivedType, const RecordType *BaseType, const Expr *E) { 2075*fe013be4SDimitry Andric // Pointer of derived type is already on the stack. 2076*fe013be4SDimitry Andric const auto *FinalDecl = cast<CXXRecordDecl>(BaseType->getDecl()); 2077*fe013be4SDimitry Andric const RecordDecl *CurDecl = DerivedType->getDecl(); 2078*fe013be4SDimitry Andric const Record *CurRecord = getRecord(CurDecl); 2079*fe013be4SDimitry Andric assert(CurDecl && FinalDecl); 2080*fe013be4SDimitry Andric for (;;) { 2081*fe013be4SDimitry Andric assert(CurRecord->getNumBases() > 0); 2082*fe013be4SDimitry Andric // One level up 2083*fe013be4SDimitry Andric for (const Record::Base &B : CurRecord->bases()) { 2084*fe013be4SDimitry Andric const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl); 2085*fe013be4SDimitry Andric 2086*fe013be4SDimitry Andric if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) { 2087*fe013be4SDimitry Andric // This decl will lead us to the final decl, so emit a base cast. 2088*fe013be4SDimitry Andric if (!this->emitGetPtrBasePop(B.Offset, E)) 2089*fe013be4SDimitry Andric return false; 2090*fe013be4SDimitry Andric 2091*fe013be4SDimitry Andric CurRecord = B.R; 2092*fe013be4SDimitry Andric CurDecl = BaseDecl; 2093*fe013be4SDimitry Andric break; 2094*fe013be4SDimitry Andric } 2095*fe013be4SDimitry Andric } 2096*fe013be4SDimitry Andric if (CurDecl == FinalDecl) 2097*fe013be4SDimitry Andric return true; 2098*fe013be4SDimitry Andric } 2099*fe013be4SDimitry Andric 2100*fe013be4SDimitry Andric llvm_unreachable("Couldn't find the base class?"); 2101*fe013be4SDimitry Andric return false; 2102*fe013be4SDimitry Andric } 2103*fe013be4SDimitry Andric 2104*fe013be4SDimitry Andric /// When calling this, we have a pointer of the local-to-destroy 2105*fe013be4SDimitry Andric /// on the stack. 2106*fe013be4SDimitry Andric /// Emit destruction of record types (or arrays of record types). 2107*fe013be4SDimitry Andric /// FIXME: Handle virtual destructors. 2108*fe013be4SDimitry Andric template <class Emitter> 2109*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Descriptor *Desc) { 2110*fe013be4SDimitry Andric assert(Desc); 2111*fe013be4SDimitry Andric assert(!Desc->isPrimitive()); 2112*fe013be4SDimitry Andric assert(!Desc->isPrimitiveArray()); 2113*fe013be4SDimitry Andric 2114*fe013be4SDimitry Andric // Arrays. 2115*fe013be4SDimitry Andric if (Desc->isArray()) { 2116*fe013be4SDimitry Andric const Descriptor *ElemDesc = Desc->ElemDesc; 2117*fe013be4SDimitry Andric const Record *ElemRecord = ElemDesc->ElemRecord; 2118*fe013be4SDimitry Andric assert(ElemRecord); // This is not a primitive array. 2119*fe013be4SDimitry Andric 2120*fe013be4SDimitry Andric if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor(); 2121*fe013be4SDimitry Andric Dtor && !Dtor->isTrivial()) { 2122*fe013be4SDimitry Andric for (ssize_t I = Desc->getNumElems() - 1; I >= 0; --I) { 2123*fe013be4SDimitry Andric if (!this->emitConstUint64(I, SourceInfo{})) 2124*fe013be4SDimitry Andric return false; 2125*fe013be4SDimitry Andric if (!this->emitArrayElemPtrUint64(SourceInfo{})) 2126*fe013be4SDimitry Andric return false; 2127*fe013be4SDimitry Andric if (!this->emitRecordDestruction(Desc->ElemDesc)) 2128*fe013be4SDimitry Andric return false; 2129*fe013be4SDimitry Andric } 2130*fe013be4SDimitry Andric } 2131*fe013be4SDimitry Andric return this->emitPopPtr(SourceInfo{}); 2132*fe013be4SDimitry Andric } 2133*fe013be4SDimitry Andric 2134*fe013be4SDimitry Andric const Record *R = Desc->ElemRecord; 2135*fe013be4SDimitry Andric assert(R); 2136*fe013be4SDimitry Andric // First, destroy all fields. 2137*fe013be4SDimitry Andric for (const Record::Field &Field : llvm::reverse(R->fields())) { 2138*fe013be4SDimitry Andric const Descriptor *D = Field.Desc; 2139*fe013be4SDimitry Andric if (!D->isPrimitive() && !D->isPrimitiveArray()) { 2140*fe013be4SDimitry Andric if (!this->emitDupPtr(SourceInfo{})) 2141*fe013be4SDimitry Andric return false; 2142*fe013be4SDimitry Andric if (!this->emitGetPtrField(Field.Offset, SourceInfo{})) 2143*fe013be4SDimitry Andric return false; 2144*fe013be4SDimitry Andric if (!this->emitRecordDestruction(D)) 2145*fe013be4SDimitry Andric return false; 2146*fe013be4SDimitry Andric } 2147*fe013be4SDimitry Andric } 2148*fe013be4SDimitry Andric 2149*fe013be4SDimitry Andric // FIXME: Unions need to be handled differently here. We don't want to 2150*fe013be4SDimitry Andric // call the destructor of its members. 2151*fe013be4SDimitry Andric 2152*fe013be4SDimitry Andric // Now emit the destructor and recurse into base classes. 2153*fe013be4SDimitry Andric if (const CXXDestructorDecl *Dtor = R->getDestructor(); 2154*fe013be4SDimitry Andric Dtor && !Dtor->isTrivial()) { 2155*fe013be4SDimitry Andric const Function *DtorFunc = getFunction(Dtor); 2156*fe013be4SDimitry Andric if (DtorFunc && DtorFunc->isConstexpr()) { 2157*fe013be4SDimitry Andric assert(DtorFunc->hasThisPointer()); 2158*fe013be4SDimitry Andric assert(DtorFunc->getNumParams() == 1); 2159*fe013be4SDimitry Andric if (!this->emitDupPtr(SourceInfo{})) 2160*fe013be4SDimitry Andric return false; 2161*fe013be4SDimitry Andric if (!this->emitCall(DtorFunc, SourceInfo{})) 2162*fe013be4SDimitry Andric return false; 2163*fe013be4SDimitry Andric } 2164*fe013be4SDimitry Andric } 2165*fe013be4SDimitry Andric 2166*fe013be4SDimitry Andric for (const Record::Base &Base : llvm::reverse(R->bases())) { 2167*fe013be4SDimitry Andric if (!this->emitGetPtrBase(Base.Offset, SourceInfo{})) 2168*fe013be4SDimitry Andric return false; 2169*fe013be4SDimitry Andric if (!this->emitRecordDestruction(Base.Desc)) 2170*fe013be4SDimitry Andric return false; 2171*fe013be4SDimitry Andric } 2172*fe013be4SDimitry Andric // FIXME: Virtual bases. 2173*fe013be4SDimitry Andric 2174*fe013be4SDimitry Andric // Remove the instance pointer. 2175*fe013be4SDimitry Andric return this->emitPopPtr(SourceInfo{}); 2176*fe013be4SDimitry Andric } 2177*fe013be4SDimitry Andric 2178a7dea167SDimitry Andric namespace clang { 2179a7dea167SDimitry Andric namespace interp { 2180a7dea167SDimitry Andric 2181a7dea167SDimitry Andric template class ByteCodeExprGen<ByteCodeEmitter>; 2182a7dea167SDimitry Andric template class ByteCodeExprGen<EvalEmitter>; 2183a7dea167SDimitry Andric 2184a7dea167SDimitry Andric } // namespace interp 2185a7dea167SDimitry Andric } // namespace clang 2186