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" 14fe013be4SDimitry Andric #include "Floating.h" 15a7dea167SDimitry Andric #include "Function.h" 16a7dea167SDimitry Andric #include "PrimType.h" 17a7dea167SDimitry Andric #include "Program.h" 18a7dea167SDimitry Andric 19a7dea167SDimitry Andric using namespace clang; 20a7dea167SDimitry Andric using namespace clang::interp; 21a7dea167SDimitry Andric 22a7dea167SDimitry Andric using APSInt = llvm::APSInt; 23a7dea167SDimitry Andric 24a7dea167SDimitry Andric namespace clang { 25a7dea167SDimitry Andric namespace interp { 26a7dea167SDimitry Andric 27a7dea167SDimitry Andric /// Scope used to handle temporaries in toplevel variable declarations. 28fe013be4SDimitry Andric template <class Emitter> class DeclScope final : public VariableScope<Emitter> { 29a7dea167SDimitry Andric public: 30fe013be4SDimitry Andric DeclScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD) 31*c9157d92SDimitry Andric : VariableScope<Emitter>(Ctx), Scope(Ctx->P, VD), 32*c9157d92SDimitry Andric OldGlobalDecl(Ctx->GlobalDecl) { 33*c9157d92SDimitry Andric Ctx->GlobalDecl = Context::shouldBeGloballyIndexed(VD); 34*c9157d92SDimitry Andric } 35a7dea167SDimitry Andric 36a7dea167SDimitry Andric void addExtended(const Scope::Local &Local) override { 37a7dea167SDimitry Andric return this->addLocal(Local); 38a7dea167SDimitry Andric } 39a7dea167SDimitry Andric 40*c9157d92SDimitry Andric ~DeclScope() { this->Ctx->GlobalDecl = OldGlobalDecl; } 41*c9157d92SDimitry Andric 42a7dea167SDimitry Andric private: 43a7dea167SDimitry Andric Program::DeclScope Scope; 44*c9157d92SDimitry Andric bool OldGlobalDecl; 45a7dea167SDimitry Andric }; 46a7dea167SDimitry Andric 47a7dea167SDimitry Andric /// Scope used to handle initialization methods. 48fe013be4SDimitry Andric template <class Emitter> class OptionScope final { 49a7dea167SDimitry Andric public: 50a7dea167SDimitry Andric /// Root constructor, compiling or discarding primitives. 51*c9157d92SDimitry Andric OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult, 52*c9157d92SDimitry Andric bool NewInitializing) 53*c9157d92SDimitry Andric : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult), 54*c9157d92SDimitry Andric OldInitializing(Ctx->Initializing) { 55a7dea167SDimitry Andric Ctx->DiscardResult = NewDiscardResult; 56*c9157d92SDimitry Andric Ctx->Initializing = NewInitializing; 57a7dea167SDimitry Andric } 58a7dea167SDimitry Andric 59*c9157d92SDimitry Andric ~OptionScope() { 60*c9157d92SDimitry Andric Ctx->DiscardResult = OldDiscardResult; 61*c9157d92SDimitry Andric Ctx->Initializing = OldInitializing; 62*c9157d92SDimitry Andric } 63a7dea167SDimitry Andric 64a7dea167SDimitry Andric private: 65a7dea167SDimitry Andric /// Parent context. 66a7dea167SDimitry Andric ByteCodeExprGen<Emitter> *Ctx; 67a7dea167SDimitry Andric /// Old discard flag to restore. 68a7dea167SDimitry Andric bool OldDiscardResult; 69*c9157d92SDimitry Andric bool OldInitializing; 70a7dea167SDimitry Andric }; 71a7dea167SDimitry Andric 72a7dea167SDimitry Andric } // namespace interp 73a7dea167SDimitry Andric } // namespace clang 74a7dea167SDimitry Andric 75a7dea167SDimitry Andric template <class Emitter> 76a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) { 77*c9157d92SDimitry Andric const Expr *SubExpr = CE->getSubExpr(); 78a7dea167SDimitry Andric switch (CE->getCastKind()) { 79a7dea167SDimitry Andric 80a7dea167SDimitry Andric case CK_LValueToRValue: { 81a7dea167SDimitry Andric return dereference( 82fe013be4SDimitry Andric SubExpr, DerefKind::Read, 83a7dea167SDimitry Andric [](PrimType) { 84a7dea167SDimitry Andric // Value loaded - nothing to do here. 85a7dea167SDimitry Andric return true; 86a7dea167SDimitry Andric }, 87a7dea167SDimitry Andric [this, CE](PrimType T) { 88a7dea167SDimitry Andric // Pointer on stack - dereference it. 89a7dea167SDimitry Andric if (!this->emitLoadPop(T, CE)) 90a7dea167SDimitry Andric return false; 91a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, CE) : true; 92a7dea167SDimitry Andric }); 93a7dea167SDimitry Andric } 94a7dea167SDimitry Andric 95bdd1243dSDimitry Andric case CK_UncheckedDerivedToBase: 96bdd1243dSDimitry Andric case CK_DerivedToBase: { 97bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 98bdd1243dSDimitry Andric return false; 99bdd1243dSDimitry Andric 100*c9157d92SDimitry Andric unsigned DerivedOffset = collectBaseOffset(getRecordTy(CE->getType()), 101*c9157d92SDimitry Andric getRecordTy(SubExpr->getType())); 102*c9157d92SDimitry Andric 103*c9157d92SDimitry Andric return this->emitGetPtrBasePop(DerivedOffset, CE); 104*c9157d92SDimitry Andric } 105*c9157d92SDimitry Andric 106*c9157d92SDimitry Andric case CK_BaseToDerived: { 107*c9157d92SDimitry Andric if (!this->visit(SubExpr)) 108*c9157d92SDimitry Andric return false; 109*c9157d92SDimitry Andric 110*c9157d92SDimitry Andric unsigned DerivedOffset = collectBaseOffset(getRecordTy(SubExpr->getType()), 111*c9157d92SDimitry Andric getRecordTy(CE->getType())); 112*c9157d92SDimitry Andric 113*c9157d92SDimitry Andric return this->emitGetPtrDerivedPop(DerivedOffset, CE); 114bdd1243dSDimitry Andric } 115bdd1243dSDimitry Andric 116fe013be4SDimitry Andric case CK_FloatingCast: { 117fe013be4SDimitry Andric if (!this->visit(SubExpr)) 118fe013be4SDimitry Andric return false; 119fe013be4SDimitry Andric const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType()); 120fe013be4SDimitry Andric return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE); 121fe013be4SDimitry Andric } 122fe013be4SDimitry Andric 123fe013be4SDimitry Andric case CK_IntegralToFloating: { 124fe013be4SDimitry Andric std::optional<PrimType> FromT = classify(SubExpr->getType()); 125fe013be4SDimitry Andric if (!FromT) 126fe013be4SDimitry Andric return false; 127fe013be4SDimitry Andric 128fe013be4SDimitry Andric if (!this->visit(SubExpr)) 129fe013be4SDimitry Andric return false; 130fe013be4SDimitry Andric 131fe013be4SDimitry Andric const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType()); 132fe013be4SDimitry Andric llvm::RoundingMode RM = getRoundingMode(CE); 133fe013be4SDimitry Andric return this->emitCastIntegralFloating(*FromT, TargetSemantics, RM, CE); 134fe013be4SDimitry Andric } 135fe013be4SDimitry Andric 136fe013be4SDimitry Andric case CK_FloatingToBoolean: 137fe013be4SDimitry Andric case CK_FloatingToIntegral: { 138fe013be4SDimitry Andric std::optional<PrimType> ToT = classify(CE->getType()); 139fe013be4SDimitry Andric 140fe013be4SDimitry Andric if (!ToT) 141fe013be4SDimitry Andric return false; 142fe013be4SDimitry Andric 143fe013be4SDimitry Andric if (!this->visit(SubExpr)) 144fe013be4SDimitry Andric return false; 145fe013be4SDimitry Andric 146*c9157d92SDimitry Andric if (ToT == PT_IntAP) 147*c9157d92SDimitry Andric return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(CE->getType()), 148*c9157d92SDimitry Andric CE); 149*c9157d92SDimitry Andric if (ToT == PT_IntAPS) 150*c9157d92SDimitry Andric return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(CE->getType()), 151*c9157d92SDimitry Andric CE); 152*c9157d92SDimitry Andric 153fe013be4SDimitry Andric return this->emitCastFloatingIntegral(*ToT, CE); 154fe013be4SDimitry Andric } 155fe013be4SDimitry Andric 156fe013be4SDimitry Andric case CK_NullToPointer: 157fe013be4SDimitry Andric if (DiscardResult) 158fe013be4SDimitry Andric return true; 159fe013be4SDimitry Andric return this->emitNull(classifyPrim(CE->getType()), CE); 160fe013be4SDimitry Andric 161*c9157d92SDimitry Andric case CK_PointerToIntegral: { 162*c9157d92SDimitry Andric // TODO: Discard handling. 163*c9157d92SDimitry Andric if (!this->visit(SubExpr)) 164*c9157d92SDimitry Andric return false; 165*c9157d92SDimitry Andric 166*c9157d92SDimitry Andric PrimType T = classifyPrim(CE->getType()); 167*c9157d92SDimitry Andric return this->emitCastPointerIntegral(T, CE); 168*c9157d92SDimitry Andric } 169*c9157d92SDimitry Andric 170*c9157d92SDimitry Andric case CK_ArrayToPointerDecay: { 171*c9157d92SDimitry Andric if (!this->visit(SubExpr)) 172*c9157d92SDimitry Andric return false; 173*c9157d92SDimitry Andric if (!this->emitArrayDecay(CE)) 174*c9157d92SDimitry Andric return false; 175*c9157d92SDimitry Andric if (DiscardResult) 176*c9157d92SDimitry Andric return this->emitPopPtr(CE); 177*c9157d92SDimitry Andric return true; 178*c9157d92SDimitry Andric } 179*c9157d92SDimitry Andric 180a7dea167SDimitry Andric case CK_AtomicToNonAtomic: 181a7dea167SDimitry Andric case CK_ConstructorConversion: 182a7dea167SDimitry Andric case CK_FunctionToPointerDecay: 183a7dea167SDimitry Andric case CK_NonAtomicToAtomic: 184a7dea167SDimitry Andric case CK_NoOp: 185a7dea167SDimitry Andric case CK_UserDefinedConversion: 186*c9157d92SDimitry Andric case CK_BitCast: 187*c9157d92SDimitry Andric return this->delegate(SubExpr); 188bdd1243dSDimitry Andric 189bdd1243dSDimitry Andric case CK_IntegralToBoolean: 190bdd1243dSDimitry Andric case CK_IntegralCast: { 191*c9157d92SDimitry Andric if (DiscardResult) 192*c9157d92SDimitry Andric return this->discard(SubExpr); 193bdd1243dSDimitry Andric std::optional<PrimType> FromT = classify(SubExpr->getType()); 194bdd1243dSDimitry Andric std::optional<PrimType> ToT = classify(CE->getType()); 195*c9157d92SDimitry Andric 196bdd1243dSDimitry Andric if (!FromT || !ToT) 197bdd1243dSDimitry Andric return false; 198bdd1243dSDimitry Andric 199bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 200bdd1243dSDimitry Andric return false; 201bdd1243dSDimitry Andric 202*c9157d92SDimitry Andric if (ToT == PT_IntAP) 203*c9157d92SDimitry Andric return this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE); 204*c9157d92SDimitry Andric if (ToT == PT_IntAPS) 205*c9157d92SDimitry Andric return this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE); 206*c9157d92SDimitry Andric 207fe013be4SDimitry Andric if (FromT == ToT) 208fe013be4SDimitry Andric return true; 209bdd1243dSDimitry Andric return this->emitCast(*FromT, *ToT, CE); 210bdd1243dSDimitry Andric } 211a7dea167SDimitry Andric 212fe013be4SDimitry Andric case CK_PointerToBoolean: { 213*c9157d92SDimitry Andric PrimType PtrT = classifyPrim(SubExpr->getType()); 214*c9157d92SDimitry Andric 215fe013be4SDimitry Andric // Just emit p != nullptr for this. 216fe013be4SDimitry Andric if (!this->visit(SubExpr)) 217fe013be4SDimitry Andric return false; 218fe013be4SDimitry Andric 219*c9157d92SDimitry Andric if (!this->emitNull(PtrT, CE)) 220fe013be4SDimitry Andric return false; 221fe013be4SDimitry Andric 222*c9157d92SDimitry Andric return this->emitNE(PtrT, CE); 223*c9157d92SDimitry Andric } 224*c9157d92SDimitry Andric 225*c9157d92SDimitry Andric case CK_IntegralComplexToBoolean: 226*c9157d92SDimitry Andric case CK_FloatingComplexToBoolean: { 227*c9157d92SDimitry Andric std::optional<PrimType> ElemT = 228*c9157d92SDimitry Andric classifyComplexElementType(SubExpr->getType()); 229*c9157d92SDimitry Andric if (!ElemT) 230*c9157d92SDimitry Andric return false; 231*c9157d92SDimitry Andric // We emit the expression (__real(E) != 0 || __imag(E) != 0) 232*c9157d92SDimitry Andric // for us, that means (bool)E[0] || (bool)E[1] 233*c9157d92SDimitry Andric if (!this->visit(SubExpr)) 234*c9157d92SDimitry Andric return false; 235*c9157d92SDimitry Andric if (!this->emitConstUint8(0, CE)) 236*c9157d92SDimitry Andric return false; 237*c9157d92SDimitry Andric if (!this->emitArrayElemPtrUint8(CE)) 238*c9157d92SDimitry Andric return false; 239*c9157d92SDimitry Andric if (!this->emitLoadPop(*ElemT, CE)) 240*c9157d92SDimitry Andric return false; 241*c9157d92SDimitry Andric if (*ElemT == PT_Float) { 242*c9157d92SDimitry Andric if (!this->emitCastFloatingIntegral(PT_Bool, CE)) 243*c9157d92SDimitry Andric return false; 244*c9157d92SDimitry Andric } else { 245*c9157d92SDimitry Andric if (!this->emitCast(*ElemT, PT_Bool, CE)) 246*c9157d92SDimitry Andric return false; 247*c9157d92SDimitry Andric } 248*c9157d92SDimitry Andric 249*c9157d92SDimitry Andric // We now have the bool value of E[0] on the stack. 250*c9157d92SDimitry Andric LabelTy LabelTrue = this->getLabel(); 251*c9157d92SDimitry Andric if (!this->jumpTrue(LabelTrue)) 252*c9157d92SDimitry Andric return false; 253*c9157d92SDimitry Andric 254*c9157d92SDimitry Andric if (!this->emitConstUint8(1, CE)) 255*c9157d92SDimitry Andric return false; 256*c9157d92SDimitry Andric if (!this->emitArrayElemPtrPopUint8(CE)) 257*c9157d92SDimitry Andric return false; 258*c9157d92SDimitry Andric if (!this->emitLoadPop(*ElemT, CE)) 259*c9157d92SDimitry Andric return false; 260*c9157d92SDimitry Andric if (*ElemT == PT_Float) { 261*c9157d92SDimitry Andric if (!this->emitCastFloatingIntegral(PT_Bool, CE)) 262*c9157d92SDimitry Andric return false; 263*c9157d92SDimitry Andric } else { 264*c9157d92SDimitry Andric if (!this->emitCast(*ElemT, PT_Bool, CE)) 265*c9157d92SDimitry Andric return false; 266*c9157d92SDimitry Andric } 267*c9157d92SDimitry Andric // Leave the boolean value of E[1] on the stack. 268*c9157d92SDimitry Andric LabelTy EndLabel = this->getLabel(); 269*c9157d92SDimitry Andric this->jump(EndLabel); 270*c9157d92SDimitry Andric 271*c9157d92SDimitry Andric this->emitLabel(LabelTrue); 272*c9157d92SDimitry Andric if (!this->emitPopPtr(CE)) 273*c9157d92SDimitry Andric return false; 274*c9157d92SDimitry Andric if (!this->emitConstBool(true, CE)) 275*c9157d92SDimitry Andric return false; 276*c9157d92SDimitry Andric 277*c9157d92SDimitry Andric this->fallthrough(EndLabel); 278*c9157d92SDimitry Andric this->emitLabel(EndLabel); 279*c9157d92SDimitry Andric 280*c9157d92SDimitry Andric return true; 281fe013be4SDimitry Andric } 282fe013be4SDimitry Andric 283a7dea167SDimitry Andric case CK_ToVoid: 284a7dea167SDimitry Andric return discard(SubExpr); 285a7dea167SDimitry Andric 286bdd1243dSDimitry Andric default: 287bdd1243dSDimitry Andric assert(false && "Cast not implemented"); 288a7dea167SDimitry Andric } 289bdd1243dSDimitry Andric llvm_unreachable("Unhandled clang::CastKind enum"); 290a7dea167SDimitry Andric } 291a7dea167SDimitry Andric 292a7dea167SDimitry Andric template <class Emitter> 293a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) { 294a7dea167SDimitry Andric if (DiscardResult) 295a7dea167SDimitry Andric return true; 296a7dea167SDimitry Andric 297bdd1243dSDimitry Andric return this->emitConst(LE->getValue(), LE); 298a7dea167SDimitry Andric } 299a7dea167SDimitry Andric 300a7dea167SDimitry Andric template <class Emitter> 301fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) { 302fe013be4SDimitry Andric if (DiscardResult) 303fe013be4SDimitry Andric return true; 304fe013be4SDimitry Andric 305fe013be4SDimitry Andric return this->emitConstFloat(E->getValue(), E); 306fe013be4SDimitry Andric } 307fe013be4SDimitry Andric 308fe013be4SDimitry Andric template <class Emitter> 309*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *E) { 310*c9157d92SDimitry Andric return this->delegate(E->getSubExpr()); 311a7dea167SDimitry Andric } 312a7dea167SDimitry Andric 313a7dea167SDimitry Andric template <class Emitter> 314a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) { 315fe013be4SDimitry Andric // Need short-circuiting for these. 316fe013be4SDimitry Andric if (BO->isLogicalOp()) 317fe013be4SDimitry Andric return this->VisitLogicalBinOp(BO); 318fe013be4SDimitry Andric 319*c9157d92SDimitry Andric if (BO->getType()->isAnyComplexType()) 320*c9157d92SDimitry Andric return this->VisitComplexBinOp(BO); 321*c9157d92SDimitry Andric 322a7dea167SDimitry Andric const Expr *LHS = BO->getLHS(); 323a7dea167SDimitry Andric const Expr *RHS = BO->getRHS(); 324a7dea167SDimitry Andric 325*c9157d92SDimitry Andric if (BO->isPtrMemOp()) 326*c9157d92SDimitry Andric return this->visit(RHS); 327*c9157d92SDimitry Andric 328a7dea167SDimitry Andric // Typecheck the args. 329bdd1243dSDimitry Andric std::optional<PrimType> LT = classify(LHS->getType()); 330bdd1243dSDimitry Andric std::optional<PrimType> RT = classify(RHS->getType()); 331bdd1243dSDimitry Andric std::optional<PrimType> T = classify(BO->getType()); 332a7dea167SDimitry Andric 333fe013be4SDimitry Andric // Deal with operations which have composite or void types. 334fe013be4SDimitry Andric if (BO->isCommaOp()) { 335*c9157d92SDimitry Andric if (!this->discard(LHS)) 336fe013be4SDimitry Andric return false; 337*c9157d92SDimitry Andric if (RHS->getType()->isVoidType()) 338*c9157d92SDimitry Andric return this->discard(RHS); 339*c9157d92SDimitry Andric 340*c9157d92SDimitry Andric return this->delegate(RHS); 341fe013be4SDimitry Andric } 342fe013be4SDimitry Andric 343*c9157d92SDimitry Andric // Special case for C++'s three-way/spaceship operator <=>, which 344*c9157d92SDimitry Andric // returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't 345*c9157d92SDimitry Andric // have a PrimType). 346*c9157d92SDimitry Andric if (!T) { 347*c9157d92SDimitry Andric if (DiscardResult) 348*c9157d92SDimitry Andric return true; 349*c9157d92SDimitry Andric const ComparisonCategoryInfo *CmpInfo = 350*c9157d92SDimitry Andric Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType()); 351*c9157d92SDimitry Andric assert(CmpInfo); 352*c9157d92SDimitry Andric 353*c9157d92SDimitry Andric // We need a temporary variable holding our return value. 354*c9157d92SDimitry Andric if (!Initializing) { 355*c9157d92SDimitry Andric std::optional<unsigned> ResultIndex = this->allocateLocal(BO, false); 356*c9157d92SDimitry Andric if (!this->emitGetPtrLocal(*ResultIndex, BO)) 357*c9157d92SDimitry Andric return false; 358*c9157d92SDimitry Andric } 359*c9157d92SDimitry Andric 360*c9157d92SDimitry Andric if (!visit(LHS) || !visit(RHS)) 361*c9157d92SDimitry Andric return false; 362*c9157d92SDimitry Andric 363*c9157d92SDimitry Andric return this->emitCMP3(*LT, CmpInfo, BO); 364*c9157d92SDimitry Andric } 365*c9157d92SDimitry Andric 366*c9157d92SDimitry Andric if (!LT || !RT || !T) 367*c9157d92SDimitry Andric return this->bail(BO); 368*c9157d92SDimitry Andric 369bdd1243dSDimitry Andric // Pointer arithmetic special case. 370bdd1243dSDimitry Andric if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) { 371fe013be4SDimitry Andric if (T == PT_Ptr || (LT == PT_Ptr && RT == PT_Ptr)) 372bdd1243dSDimitry Andric return this->VisitPointerArithBinOp(BO); 373bdd1243dSDimitry Andric } 374bdd1243dSDimitry Andric 375bdd1243dSDimitry Andric if (!visit(LHS) || !visit(RHS)) 376bdd1243dSDimitry Andric return false; 377bdd1243dSDimitry Andric 378fe013be4SDimitry Andric // For languages such as C, cast the result of one 379fe013be4SDimitry Andric // of our comparision opcodes to T (which is usually int). 380fe013be4SDimitry Andric auto MaybeCastToBool = [this, T, BO](bool Result) { 381fe013be4SDimitry Andric if (!Result) 382fe013be4SDimitry Andric return false; 383fe013be4SDimitry Andric if (DiscardResult) 384fe013be4SDimitry Andric return this->emitPop(*T, BO); 385fe013be4SDimitry Andric if (T != PT_Bool) 386fe013be4SDimitry Andric return this->emitCast(PT_Bool, *T, BO); 387fe013be4SDimitry Andric return true; 388fe013be4SDimitry Andric }; 389fe013be4SDimitry Andric 390*c9157d92SDimitry Andric auto Discard = [this, T, BO](bool Result) { 391*c9157d92SDimitry Andric if (!Result) 392*c9157d92SDimitry Andric return false; 393*c9157d92SDimitry Andric return DiscardResult ? this->emitPop(*T, BO) : true; 394*c9157d92SDimitry Andric }; 395*c9157d92SDimitry Andric 396a7dea167SDimitry Andric switch (BO->getOpcode()) { 397a7dea167SDimitry Andric case BO_EQ: 398fe013be4SDimitry Andric return MaybeCastToBool(this->emitEQ(*LT, BO)); 399a7dea167SDimitry Andric case BO_NE: 400fe013be4SDimitry Andric return MaybeCastToBool(this->emitNE(*LT, BO)); 401a7dea167SDimitry Andric case BO_LT: 402fe013be4SDimitry Andric return MaybeCastToBool(this->emitLT(*LT, BO)); 403a7dea167SDimitry Andric case BO_LE: 404fe013be4SDimitry Andric return MaybeCastToBool(this->emitLE(*LT, BO)); 405a7dea167SDimitry Andric case BO_GT: 406fe013be4SDimitry Andric return MaybeCastToBool(this->emitGT(*LT, BO)); 407a7dea167SDimitry Andric case BO_GE: 408fe013be4SDimitry Andric return MaybeCastToBool(this->emitGE(*LT, BO)); 409a7dea167SDimitry Andric case BO_Sub: 410fe013be4SDimitry Andric if (BO->getType()->isFloatingType()) 411fe013be4SDimitry Andric return Discard(this->emitSubf(getRoundingMode(BO), BO)); 412a7dea167SDimitry Andric return Discard(this->emitSub(*T, BO)); 413a7dea167SDimitry Andric case BO_Add: 414fe013be4SDimitry Andric if (BO->getType()->isFloatingType()) 415fe013be4SDimitry Andric return Discard(this->emitAddf(getRoundingMode(BO), BO)); 416a7dea167SDimitry Andric return Discard(this->emitAdd(*T, BO)); 417a7dea167SDimitry Andric case BO_Mul: 418fe013be4SDimitry Andric if (BO->getType()->isFloatingType()) 419fe013be4SDimitry Andric return Discard(this->emitMulf(getRoundingMode(BO), BO)); 420a7dea167SDimitry Andric return Discard(this->emitMul(*T, BO)); 421bdd1243dSDimitry Andric case BO_Rem: 422bdd1243dSDimitry Andric return Discard(this->emitRem(*T, BO)); 423bdd1243dSDimitry Andric case BO_Div: 424fe013be4SDimitry Andric if (BO->getType()->isFloatingType()) 425fe013be4SDimitry Andric return Discard(this->emitDivf(getRoundingMode(BO), BO)); 426bdd1243dSDimitry Andric return Discard(this->emitDiv(*T, BO)); 427bdd1243dSDimitry Andric case BO_Assign: 428bdd1243dSDimitry Andric if (DiscardResult) 429*c9157d92SDimitry Andric return LHS->refersToBitField() ? this->emitStoreBitFieldPop(*T, BO) 430*c9157d92SDimitry Andric : this->emitStorePop(*T, BO); 431*c9157d92SDimitry Andric return LHS->refersToBitField() ? this->emitStoreBitField(*T, BO) 432*c9157d92SDimitry Andric : this->emitStore(*T, BO); 433bdd1243dSDimitry Andric case BO_And: 434bdd1243dSDimitry Andric return Discard(this->emitBitAnd(*T, BO)); 435bdd1243dSDimitry Andric case BO_Or: 436bdd1243dSDimitry Andric return Discard(this->emitBitOr(*T, BO)); 437bdd1243dSDimitry Andric case BO_Shl: 438bdd1243dSDimitry Andric return Discard(this->emitShl(*LT, *RT, BO)); 439bdd1243dSDimitry Andric case BO_Shr: 440bdd1243dSDimitry Andric return Discard(this->emitShr(*LT, *RT, BO)); 441bdd1243dSDimitry Andric case BO_Xor: 442bdd1243dSDimitry Andric return Discard(this->emitBitXor(*T, BO)); 443bdd1243dSDimitry Andric case BO_LOr: 444fe013be4SDimitry Andric case BO_LAnd: 445fe013be4SDimitry Andric llvm_unreachable("Already handled earlier"); 446a7dea167SDimitry Andric default: 447a7dea167SDimitry Andric return this->bail(BO); 448a7dea167SDimitry Andric } 449bdd1243dSDimitry Andric 450bdd1243dSDimitry Andric llvm_unreachable("Unhandled binary op"); 451a7dea167SDimitry Andric } 452a7dea167SDimitry Andric 453bdd1243dSDimitry Andric /// Perform addition/subtraction of a pointer and an integer or 454bdd1243dSDimitry Andric /// subtraction of two pointers. 455bdd1243dSDimitry Andric template <class Emitter> 456bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) { 457bdd1243dSDimitry Andric BinaryOperatorKind Op = E->getOpcode(); 458bdd1243dSDimitry Andric const Expr *LHS = E->getLHS(); 459bdd1243dSDimitry Andric const Expr *RHS = E->getRHS(); 460bdd1243dSDimitry Andric 461bdd1243dSDimitry Andric if ((Op != BO_Add && Op != BO_Sub) || 462bdd1243dSDimitry Andric (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType())) 463bdd1243dSDimitry Andric return false; 464bdd1243dSDimitry Andric 465bdd1243dSDimitry Andric std::optional<PrimType> LT = classify(LHS); 466bdd1243dSDimitry Andric std::optional<PrimType> RT = classify(RHS); 467bdd1243dSDimitry Andric 468bdd1243dSDimitry Andric if (!LT || !RT) 469bdd1243dSDimitry Andric return false; 470bdd1243dSDimitry Andric 471bdd1243dSDimitry Andric if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) { 472bdd1243dSDimitry Andric if (Op != BO_Sub) 473bdd1243dSDimitry Andric return false; 474bdd1243dSDimitry Andric 475bdd1243dSDimitry Andric assert(E->getType()->isIntegerType()); 476bdd1243dSDimitry Andric if (!visit(RHS) || !visit(LHS)) 477bdd1243dSDimitry Andric return false; 478bdd1243dSDimitry Andric 479bdd1243dSDimitry Andric return this->emitSubPtr(classifyPrim(E->getType()), E); 480bdd1243dSDimitry Andric } 481bdd1243dSDimitry Andric 482bdd1243dSDimitry Andric PrimType OffsetType; 483bdd1243dSDimitry Andric if (LHS->getType()->isIntegerType()) { 484bdd1243dSDimitry Andric if (!visit(RHS) || !visit(LHS)) 485bdd1243dSDimitry Andric return false; 486bdd1243dSDimitry Andric OffsetType = *LT; 487bdd1243dSDimitry Andric } else if (RHS->getType()->isIntegerType()) { 488bdd1243dSDimitry Andric if (!visit(LHS) || !visit(RHS)) 489bdd1243dSDimitry Andric return false; 490bdd1243dSDimitry Andric OffsetType = *RT; 491bdd1243dSDimitry Andric } else { 492bdd1243dSDimitry Andric return false; 493bdd1243dSDimitry Andric } 494bdd1243dSDimitry Andric 495bdd1243dSDimitry Andric if (Op == BO_Add) 496bdd1243dSDimitry Andric return this->emitAddOffset(OffsetType, E); 497bdd1243dSDimitry Andric else if (Op == BO_Sub) 498bdd1243dSDimitry Andric return this->emitSubOffset(OffsetType, E); 499bdd1243dSDimitry Andric 500bdd1243dSDimitry Andric return this->bail(E); 501a7dea167SDimitry Andric } 502a7dea167SDimitry Andric 503a7dea167SDimitry Andric template <class Emitter> 504fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) { 505fe013be4SDimitry Andric assert(E->isLogicalOp()); 506fe013be4SDimitry Andric BinaryOperatorKind Op = E->getOpcode(); 507fe013be4SDimitry Andric const Expr *LHS = E->getLHS(); 508fe013be4SDimitry Andric const Expr *RHS = E->getRHS(); 509*c9157d92SDimitry Andric std::optional<PrimType> T = classify(E->getType()); 510bdd1243dSDimitry Andric 511fe013be4SDimitry Andric if (Op == BO_LOr) { 512fe013be4SDimitry Andric // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE. 513fe013be4SDimitry Andric LabelTy LabelTrue = this->getLabel(); 514fe013be4SDimitry Andric LabelTy LabelEnd = this->getLabel(); 515fe013be4SDimitry Andric 516*c9157d92SDimitry Andric if (!this->visitBool(LHS)) 517bdd1243dSDimitry Andric return false; 518fe013be4SDimitry Andric if (!this->jumpTrue(LabelTrue)) 519fe013be4SDimitry Andric return false; 520fe013be4SDimitry Andric 521*c9157d92SDimitry Andric if (!this->visitBool(RHS)) 522fe013be4SDimitry Andric return false; 523fe013be4SDimitry Andric if (!this->jump(LabelEnd)) 524fe013be4SDimitry Andric return false; 525fe013be4SDimitry Andric 526fe013be4SDimitry Andric this->emitLabel(LabelTrue); 527fe013be4SDimitry Andric this->emitConstBool(true, E); 528fe013be4SDimitry Andric this->fallthrough(LabelEnd); 529fe013be4SDimitry Andric this->emitLabel(LabelEnd); 530fe013be4SDimitry Andric 531*c9157d92SDimitry Andric } else { 532*c9157d92SDimitry Andric assert(Op == BO_LAnd); 533fe013be4SDimitry Andric // Logical AND. 534fe013be4SDimitry Andric // Visit LHS. Only visit RHS if LHS was TRUE. 535fe013be4SDimitry Andric LabelTy LabelFalse = this->getLabel(); 536fe013be4SDimitry Andric LabelTy LabelEnd = this->getLabel(); 537fe013be4SDimitry Andric 538*c9157d92SDimitry Andric if (!this->visitBool(LHS)) 539fe013be4SDimitry Andric return false; 540fe013be4SDimitry Andric if (!this->jumpFalse(LabelFalse)) 541fe013be4SDimitry Andric return false; 542fe013be4SDimitry Andric 543*c9157d92SDimitry Andric if (!this->visitBool(RHS)) 544fe013be4SDimitry Andric return false; 545fe013be4SDimitry Andric if (!this->jump(LabelEnd)) 546fe013be4SDimitry Andric return false; 547fe013be4SDimitry Andric 548fe013be4SDimitry Andric this->emitLabel(LabelFalse); 549fe013be4SDimitry Andric this->emitConstBool(false, E); 550fe013be4SDimitry Andric this->fallthrough(LabelEnd); 551fe013be4SDimitry Andric this->emitLabel(LabelEnd); 552*c9157d92SDimitry Andric } 553fe013be4SDimitry Andric 554fe013be4SDimitry Andric if (DiscardResult) 555fe013be4SDimitry Andric return this->emitPopBool(E); 556fe013be4SDimitry Andric 557*c9157d92SDimitry Andric // For C, cast back to integer type. 558*c9157d92SDimitry Andric assert(T); 559*c9157d92SDimitry Andric if (T != PT_Bool) 560*c9157d92SDimitry Andric return this->emitCast(PT_Bool, *T, E); 561*c9157d92SDimitry Andric return true; 562*c9157d92SDimitry Andric } 563*c9157d92SDimitry Andric 564*c9157d92SDimitry Andric template <class Emitter> 565*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitComplexBinOp(const BinaryOperator *E) { 566*c9157d92SDimitry Andric assert(Initializing); 567*c9157d92SDimitry Andric 568*c9157d92SDimitry Andric const Expr *LHS = E->getLHS(); 569*c9157d92SDimitry Andric const Expr *RHS = E->getRHS(); 570*c9157d92SDimitry Andric PrimType LHSElemT = *this->classifyComplexElementType(LHS->getType()); 571*c9157d92SDimitry Andric PrimType RHSElemT = *this->classifyComplexElementType(RHS->getType()); 572*c9157d92SDimitry Andric 573*c9157d92SDimitry Andric unsigned LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, true, false); 574*c9157d92SDimitry Andric unsigned RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, true, false); 575*c9157d92SDimitry Andric unsigned ResultOffset = ~0u; 576*c9157d92SDimitry Andric if (!this->DiscardResult) 577*c9157d92SDimitry Andric ResultOffset = this->allocateLocalPrimitive(E, PT_Ptr, true, false); 578*c9157d92SDimitry Andric 579*c9157d92SDimitry Andric assert(LHSElemT == RHSElemT); 580*c9157d92SDimitry Andric 581*c9157d92SDimitry Andric // Save result pointer in ResultOffset 582*c9157d92SDimitry Andric if (!this->DiscardResult) { 583*c9157d92SDimitry Andric if (!this->emitDupPtr(E)) 584*c9157d92SDimitry Andric return false; 585*c9157d92SDimitry Andric if (!this->emitSetLocal(PT_Ptr, ResultOffset, E)) 586*c9157d92SDimitry Andric return false; 587*c9157d92SDimitry Andric } 588*c9157d92SDimitry Andric 589*c9157d92SDimitry Andric // Evaluate LHS and save value to LHSOffset. 590*c9157d92SDimitry Andric if (!this->visit(LHS)) 591*c9157d92SDimitry Andric return false; 592*c9157d92SDimitry Andric if (!this->emitSetLocal(PT_Ptr, LHSOffset, E)) 593*c9157d92SDimitry Andric return false; 594*c9157d92SDimitry Andric 595*c9157d92SDimitry Andric // Same with RHS. 596*c9157d92SDimitry Andric if (!this->visit(RHS)) 597*c9157d92SDimitry Andric return false; 598*c9157d92SDimitry Andric if (!this->emitSetLocal(PT_Ptr, RHSOffset, E)) 599*c9157d92SDimitry Andric return false; 600*c9157d92SDimitry Andric 601*c9157d92SDimitry Andric // Now we can get pointers to the LHS and RHS from the offsets above. 602*c9157d92SDimitry Andric BinaryOperatorKind Op = E->getOpcode(); 603*c9157d92SDimitry Andric for (unsigned ElemIndex = 0; ElemIndex != 2; ++ElemIndex) { 604*c9157d92SDimitry Andric // Result pointer for the store later. 605*c9157d92SDimitry Andric if (!this->DiscardResult) { 606*c9157d92SDimitry Andric if (!this->emitGetLocal(PT_Ptr, ResultOffset, E)) 607*c9157d92SDimitry Andric return false; 608*c9157d92SDimitry Andric } 609*c9157d92SDimitry Andric 610*c9157d92SDimitry Andric if (!this->emitGetLocal(PT_Ptr, LHSOffset, E)) 611*c9157d92SDimitry Andric return false; 612*c9157d92SDimitry Andric if (!this->emitConstUint8(ElemIndex, E)) 613*c9157d92SDimitry Andric return false; 614*c9157d92SDimitry Andric if (!this->emitArrayElemPtrPopUint8(E)) 615*c9157d92SDimitry Andric return false; 616*c9157d92SDimitry Andric if (!this->emitLoadPop(LHSElemT, E)) 617*c9157d92SDimitry Andric return false; 618*c9157d92SDimitry Andric 619*c9157d92SDimitry Andric if (!this->emitGetLocal(PT_Ptr, RHSOffset, E)) 620*c9157d92SDimitry Andric return false; 621*c9157d92SDimitry Andric if (!this->emitConstUint8(ElemIndex, E)) 622*c9157d92SDimitry Andric return false; 623*c9157d92SDimitry Andric if (!this->emitArrayElemPtrPopUint8(E)) 624*c9157d92SDimitry Andric return false; 625*c9157d92SDimitry Andric if (!this->emitLoadPop(RHSElemT, E)) 626*c9157d92SDimitry Andric return false; 627*c9157d92SDimitry Andric 628*c9157d92SDimitry Andric // The actual operation. 629*c9157d92SDimitry Andric switch (Op) { 630*c9157d92SDimitry Andric case BO_Add: 631*c9157d92SDimitry Andric if (LHSElemT == PT_Float) { 632*c9157d92SDimitry Andric if (!this->emitAddf(getRoundingMode(E), E)) 633*c9157d92SDimitry Andric return false; 634*c9157d92SDimitry Andric } else { 635*c9157d92SDimitry Andric if (!this->emitAdd(LHSElemT, E)) 636*c9157d92SDimitry Andric return false; 637*c9157d92SDimitry Andric } 638*c9157d92SDimitry Andric break; 639*c9157d92SDimitry Andric case BO_Sub: 640*c9157d92SDimitry Andric if (LHSElemT == PT_Float) { 641*c9157d92SDimitry Andric if (!this->emitSubf(getRoundingMode(E), E)) 642*c9157d92SDimitry Andric return false; 643*c9157d92SDimitry Andric } else { 644*c9157d92SDimitry Andric if (!this->emitSub(LHSElemT, E)) 645*c9157d92SDimitry Andric return false; 646*c9157d92SDimitry Andric } 647*c9157d92SDimitry Andric break; 648*c9157d92SDimitry Andric 649*c9157d92SDimitry Andric default: 650*c9157d92SDimitry Andric return false; 651*c9157d92SDimitry Andric } 652*c9157d92SDimitry Andric 653*c9157d92SDimitry Andric if (!this->DiscardResult) { 654*c9157d92SDimitry Andric // Initialize array element with the value we just computed. 655*c9157d92SDimitry Andric if (!this->emitInitElemPop(LHSElemT, ElemIndex, E)) 656*c9157d92SDimitry Andric return false; 657*c9157d92SDimitry Andric } else { 658*c9157d92SDimitry Andric if (!this->emitPop(LHSElemT, E)) 659*c9157d92SDimitry Andric return false; 660*c9157d92SDimitry Andric } 661*c9157d92SDimitry Andric } 662fe013be4SDimitry Andric return true; 663fe013be4SDimitry Andric } 664fe013be4SDimitry Andric 665fe013be4SDimitry Andric template <class Emitter> 666fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) { 667*c9157d92SDimitry Andric QualType QT = E->getType(); 668fe013be4SDimitry Andric 669*c9157d92SDimitry Andric if (std::optional<PrimType> T = classify(QT)) 670*c9157d92SDimitry Andric return this->visitZeroInitializer(*T, QT, E); 671*c9157d92SDimitry Andric 672*c9157d92SDimitry Andric if (QT->isRecordType()) 673fe013be4SDimitry Andric return false; 674fe013be4SDimitry Andric 675*c9157d92SDimitry Andric if (QT->isIncompleteArrayType()) 676*c9157d92SDimitry Andric return true; 677*c9157d92SDimitry Andric 678*c9157d92SDimitry Andric if (QT->isArrayType()) { 679*c9157d92SDimitry Andric const ArrayType *AT = QT->getAsArrayTypeUnsafe(); 680*c9157d92SDimitry Andric assert(AT); 681*c9157d92SDimitry Andric const auto *CAT = cast<ConstantArrayType>(AT); 682*c9157d92SDimitry Andric size_t NumElems = CAT->getSize().getZExtValue(); 683*c9157d92SDimitry Andric PrimType ElemT = classifyPrim(CAT->getElementType()); 684*c9157d92SDimitry Andric 685*c9157d92SDimitry Andric for (size_t I = 0; I != NumElems; ++I) { 686*c9157d92SDimitry Andric if (!this->visitZeroInitializer(ElemT, CAT->getElementType(), E)) 687*c9157d92SDimitry Andric return false; 688*c9157d92SDimitry Andric if (!this->emitInitElem(ElemT, I, E)) 689*c9157d92SDimitry Andric return false; 690*c9157d92SDimitry Andric } 691*c9157d92SDimitry Andric 692*c9157d92SDimitry Andric return true; 693*c9157d92SDimitry Andric } 694*c9157d92SDimitry Andric 695*c9157d92SDimitry Andric return false; 696bdd1243dSDimitry Andric } 697bdd1243dSDimitry Andric 698bdd1243dSDimitry Andric template <class Emitter> 699bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr( 700bdd1243dSDimitry Andric const ArraySubscriptExpr *E) { 701bdd1243dSDimitry Andric const Expr *Base = E->getBase(); 702bdd1243dSDimitry Andric const Expr *Index = E->getIdx(); 703*c9157d92SDimitry Andric 704*c9157d92SDimitry Andric if (DiscardResult) 705*c9157d92SDimitry Andric return this->discard(Base) && this->discard(Index); 706bdd1243dSDimitry Andric 707fe013be4SDimitry Andric // Take pointer of LHS, add offset from RHS. 708bdd1243dSDimitry Andric // What's left on the stack after this is a pointer. 709bdd1243dSDimitry Andric if (!this->visit(Base)) 710bdd1243dSDimitry Andric return false; 711bdd1243dSDimitry Andric 712bdd1243dSDimitry Andric if (!this->visit(Index)) 713bdd1243dSDimitry Andric return false; 714bdd1243dSDimitry Andric 715*c9157d92SDimitry Andric PrimType IndexT = classifyPrim(Index->getType()); 716*c9157d92SDimitry Andric return this->emitArrayElemPtrPop(IndexT, E); 717*c9157d92SDimitry Andric } 718*c9157d92SDimitry Andric 719*c9157d92SDimitry Andric template <class Emitter> 720*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, 721*c9157d92SDimitry Andric const Expr *E) { 722*c9157d92SDimitry Andric assert(E->getType()->isRecordType()); 723*c9157d92SDimitry Andric const Record *R = getRecord(E->getType()); 724*c9157d92SDimitry Andric 725*c9157d92SDimitry Andric unsigned InitIndex = 0; 726*c9157d92SDimitry Andric for (const Expr *Init : Inits) { 727*c9157d92SDimitry Andric if (!this->emitDupPtr(E)) 728bdd1243dSDimitry Andric return false; 729bdd1243dSDimitry Andric 730*c9157d92SDimitry Andric if (std::optional<PrimType> T = classify(Init)) { 731*c9157d92SDimitry Andric const Record::Field *FieldToInit = R->getField(InitIndex); 732*c9157d92SDimitry Andric if (!this->visit(Init)) 733*c9157d92SDimitry Andric return false; 734bdd1243dSDimitry Andric 735*c9157d92SDimitry Andric if (FieldToInit->isBitField()) { 736*c9157d92SDimitry Andric if (!this->emitInitBitField(*T, FieldToInit, E)) 737*c9157d92SDimitry Andric return false; 738*c9157d92SDimitry Andric } else { 739*c9157d92SDimitry Andric if (!this->emitInitField(*T, FieldToInit->Offset, E)) 740*c9157d92SDimitry Andric return false; 741*c9157d92SDimitry Andric } 742*c9157d92SDimitry Andric 743*c9157d92SDimitry Andric if (!this->emitPopPtr(E)) 744*c9157d92SDimitry Andric return false; 745*c9157d92SDimitry Andric ++InitIndex; 746*c9157d92SDimitry Andric } else { 747*c9157d92SDimitry Andric // Initializer for a direct base class. 748*c9157d92SDimitry Andric if (const Record::Base *B = R->getBase(Init->getType())) { 749*c9157d92SDimitry Andric if (!this->emitGetPtrBasePop(B->Offset, Init)) 750*c9157d92SDimitry Andric return false; 751*c9157d92SDimitry Andric 752*c9157d92SDimitry Andric if (!this->visitInitializer(Init)) 753*c9157d92SDimitry Andric return false; 754*c9157d92SDimitry Andric 755*c9157d92SDimitry Andric if (!this->emitInitPtrPop(E)) 756*c9157d92SDimitry Andric return false; 757*c9157d92SDimitry Andric // Base initializers don't increase InitIndex, since they don't count 758*c9157d92SDimitry Andric // into the Record's fields. 759*c9157d92SDimitry Andric } else { 760*c9157d92SDimitry Andric const Record::Field *FieldToInit = R->getField(InitIndex); 761*c9157d92SDimitry Andric // Non-primitive case. Get a pointer to the field-to-initialize 762*c9157d92SDimitry Andric // on the stack and recurse into visitInitializer(). 763*c9157d92SDimitry Andric if (!this->emitGetPtrField(FieldToInit->Offset, Init)) 764*c9157d92SDimitry Andric return false; 765*c9157d92SDimitry Andric 766*c9157d92SDimitry Andric if (!this->visitInitializer(Init)) 767*c9157d92SDimitry Andric return false; 768*c9157d92SDimitry Andric 769*c9157d92SDimitry Andric if (!this->emitPopPtr(E)) 770*c9157d92SDimitry Andric return false; 771*c9157d92SDimitry Andric ++InitIndex; 772*c9157d92SDimitry Andric } 773*c9157d92SDimitry Andric } 774*c9157d92SDimitry Andric } 775bdd1243dSDimitry Andric return true; 776bdd1243dSDimitry Andric } 777bdd1243dSDimitry Andric 778*c9157d92SDimitry Andric /// Pointer to the array(not the element!) must be on the stack when calling 779*c9157d92SDimitry Andric /// this. 780*c9157d92SDimitry Andric template <class Emitter> 781*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitArrayElemInit(unsigned ElemIndex, 782*c9157d92SDimitry Andric const Expr *Init) { 783*c9157d92SDimitry Andric if (std::optional<PrimType> T = classify(Init->getType())) { 784*c9157d92SDimitry Andric // Visit the primitive element like normal. 785*c9157d92SDimitry Andric if (!this->visit(Init)) 786*c9157d92SDimitry Andric return false; 787*c9157d92SDimitry Andric return this->emitInitElem(*T, ElemIndex, Init); 788*c9157d92SDimitry Andric } 789*c9157d92SDimitry Andric 790*c9157d92SDimitry Andric // Advance the pointer currently on the stack to the given 791*c9157d92SDimitry Andric // dimension. 792*c9157d92SDimitry Andric if (!this->emitConstUint32(ElemIndex, Init)) 793*c9157d92SDimitry Andric return false; 794*c9157d92SDimitry Andric if (!this->emitArrayElemPtrUint32(Init)) 795*c9157d92SDimitry Andric return false; 796*c9157d92SDimitry Andric if (!this->visitInitializer(Init)) 797*c9157d92SDimitry Andric return false; 798*c9157d92SDimitry Andric return this->emitPopPtr(Init); 799*c9157d92SDimitry Andric } 800*c9157d92SDimitry Andric 801bdd1243dSDimitry Andric template <class Emitter> 802bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) { 803*c9157d92SDimitry Andric // Handle discarding first. 804*c9157d92SDimitry Andric if (DiscardResult) { 805bdd1243dSDimitry Andric for (const Expr *Init : E->inits()) { 806*c9157d92SDimitry Andric if (!this->discard(Init)) 807bdd1243dSDimitry Andric return false; 808bdd1243dSDimitry Andric } 809bdd1243dSDimitry Andric return true; 810bdd1243dSDimitry Andric } 811bdd1243dSDimitry Andric 812*c9157d92SDimitry Andric // Primitive values. 813*c9157d92SDimitry Andric if (std::optional<PrimType> T = classify(E->getType())) { 814*c9157d92SDimitry Andric assert(!DiscardResult); 815*c9157d92SDimitry Andric if (E->getNumInits() == 0) 816*c9157d92SDimitry Andric return this->visitZeroInitializer(*T, E->getType(), E); 817*c9157d92SDimitry Andric assert(E->getNumInits() == 1); 818*c9157d92SDimitry Andric return this->delegate(E->inits()[0]); 819*c9157d92SDimitry Andric } 820*c9157d92SDimitry Andric 821*c9157d92SDimitry Andric QualType T = E->getType(); 822*c9157d92SDimitry Andric if (T->isRecordType()) 823*c9157d92SDimitry Andric return this->visitInitList(E->inits(), E); 824*c9157d92SDimitry Andric 825*c9157d92SDimitry Andric if (T->isArrayType()) { 826*c9157d92SDimitry Andric // FIXME: Array fillers. 827*c9157d92SDimitry Andric unsigned ElementIndex = 0; 828*c9157d92SDimitry Andric for (const Expr *Init : E->inits()) { 829*c9157d92SDimitry Andric if (!this->visitArrayElemInit(ElementIndex, Init)) 830*c9157d92SDimitry Andric return false; 831*c9157d92SDimitry Andric ++ElementIndex; 832*c9157d92SDimitry Andric } 833*c9157d92SDimitry Andric return true; 834*c9157d92SDimitry Andric } 835*c9157d92SDimitry Andric 836*c9157d92SDimitry Andric if (T->isAnyComplexType()) { 837*c9157d92SDimitry Andric unsigned NumInits = E->getNumInits(); 838*c9157d92SDimitry Andric QualType ElemQT = E->getType()->getAs<ComplexType>()->getElementType(); 839*c9157d92SDimitry Andric PrimType ElemT = classifyPrim(ElemQT); 840*c9157d92SDimitry Andric if (NumInits == 0) { 841*c9157d92SDimitry Andric // Zero-initialize both elements. 842*c9157d92SDimitry Andric for (unsigned I = 0; I < 2; ++I) { 843*c9157d92SDimitry Andric if (!this->visitZeroInitializer(ElemT, ElemQT, E)) 844*c9157d92SDimitry Andric return false; 845*c9157d92SDimitry Andric if (!this->emitInitElem(ElemT, I, E)) 846*c9157d92SDimitry Andric return false; 847*c9157d92SDimitry Andric } 848*c9157d92SDimitry Andric } else if (NumInits == 2) { 849*c9157d92SDimitry Andric unsigned InitIndex = 0; 850*c9157d92SDimitry Andric for (const Expr *Init : E->inits()) { 851*c9157d92SDimitry Andric if (!this->visit(Init)) 852*c9157d92SDimitry Andric return false; 853*c9157d92SDimitry Andric 854*c9157d92SDimitry Andric if (!this->emitInitElem(ElemT, InitIndex, E)) 855*c9157d92SDimitry Andric return false; 856*c9157d92SDimitry Andric ++InitIndex; 857*c9157d92SDimitry Andric } 858*c9157d92SDimitry Andric } 859*c9157d92SDimitry Andric return true; 860*c9157d92SDimitry Andric } 861*c9157d92SDimitry Andric 862*c9157d92SDimitry Andric return false; 863*c9157d92SDimitry Andric } 864*c9157d92SDimitry Andric 865*c9157d92SDimitry Andric template <class Emitter> 866*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXParenListInitExpr( 867*c9157d92SDimitry Andric const CXXParenListInitExpr *E) { 868*c9157d92SDimitry Andric if (DiscardResult) { 869*c9157d92SDimitry Andric for (const Expr *Init : E->getInitExprs()) { 870*c9157d92SDimitry Andric if (!this->discard(Init)) 871*c9157d92SDimitry Andric return false; 872*c9157d92SDimitry Andric } 873*c9157d92SDimitry Andric return true; 874*c9157d92SDimitry Andric } 875*c9157d92SDimitry Andric 876*c9157d92SDimitry Andric assert(E->getType()->isRecordType()); 877*c9157d92SDimitry Andric return this->visitInitList(E->getInitExprs(), E); 878*c9157d92SDimitry Andric } 879*c9157d92SDimitry Andric 880bdd1243dSDimitry Andric template <class Emitter> 881bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitSubstNonTypeTemplateParmExpr( 882bdd1243dSDimitry Andric const SubstNonTypeTemplateParmExpr *E) { 883*c9157d92SDimitry Andric return this->delegate(E->getReplacement()); 884bdd1243dSDimitry Andric } 885bdd1243dSDimitry Andric 886bdd1243dSDimitry Andric template <class Emitter> 887bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitConstantExpr(const ConstantExpr *E) { 888*c9157d92SDimitry Andric // Try to emit the APValue directly, without visiting the subexpr. 889*c9157d92SDimitry Andric // This will only fail if we can't emit the APValue, so won't emit any 890*c9157d92SDimitry Andric // diagnostics or any double values. 891*c9157d92SDimitry Andric std::optional<PrimType> T = classify(E->getType()); 892*c9157d92SDimitry Andric if (T && E->hasAPValueResult() && 893*c9157d92SDimitry Andric this->visitAPValue(E->getAPValueResult(), *T, E)) 894*c9157d92SDimitry Andric return true; 895*c9157d92SDimitry Andric 896*c9157d92SDimitry Andric return this->delegate(E->getSubExpr()); 897bdd1243dSDimitry Andric } 898bdd1243dSDimitry Andric 899bdd1243dSDimitry Andric static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx, 900bdd1243dSDimitry Andric UnaryExprOrTypeTrait Kind) { 901bdd1243dSDimitry Andric bool AlignOfReturnsPreferred = 902bdd1243dSDimitry Andric ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7; 903bdd1243dSDimitry Andric 904bdd1243dSDimitry Andric // C++ [expr.alignof]p3: 905bdd1243dSDimitry Andric // When alignof is applied to a reference type, the result is the 906bdd1243dSDimitry Andric // alignment of the referenced type. 907bdd1243dSDimitry Andric if (const auto *Ref = T->getAs<ReferenceType>()) 908bdd1243dSDimitry Andric T = Ref->getPointeeType(); 909bdd1243dSDimitry Andric 910bdd1243dSDimitry Andric // __alignof is defined to return the preferred alignment. 911bdd1243dSDimitry Andric // Before 8, clang returned the preferred alignment for alignof and 912bdd1243dSDimitry Andric // _Alignof as well. 913bdd1243dSDimitry Andric if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred) 914bdd1243dSDimitry Andric return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T)); 915bdd1243dSDimitry Andric 916bdd1243dSDimitry Andric return ASTCtx.getTypeAlignInChars(T); 917bdd1243dSDimitry Andric } 918bdd1243dSDimitry Andric 919bdd1243dSDimitry Andric template <class Emitter> 920bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryExprOrTypeTraitExpr( 921bdd1243dSDimitry Andric const UnaryExprOrTypeTraitExpr *E) { 922bdd1243dSDimitry Andric UnaryExprOrTypeTrait Kind = E->getKind(); 923bdd1243dSDimitry Andric ASTContext &ASTCtx = Ctx.getASTContext(); 924bdd1243dSDimitry Andric 925bdd1243dSDimitry Andric if (Kind == UETT_SizeOf) { 926bdd1243dSDimitry Andric QualType ArgType = E->getTypeOfArgument(); 927bdd1243dSDimitry Andric CharUnits Size; 928bdd1243dSDimitry Andric if (ArgType->isVoidType() || ArgType->isFunctionType()) 929bdd1243dSDimitry Andric Size = CharUnits::One(); 930bdd1243dSDimitry Andric else { 931bdd1243dSDimitry Andric if (ArgType->isDependentType() || !ArgType->isConstantSizeType()) 932bdd1243dSDimitry Andric return false; 933bdd1243dSDimitry Andric 934bdd1243dSDimitry Andric Size = ASTCtx.getTypeSizeInChars(ArgType); 935bdd1243dSDimitry Andric } 936bdd1243dSDimitry Andric 937*c9157d92SDimitry Andric if (DiscardResult) 938*c9157d92SDimitry Andric return true; 939*c9157d92SDimitry Andric 940bdd1243dSDimitry Andric return this->emitConst(Size.getQuantity(), E); 941bdd1243dSDimitry Andric } 942bdd1243dSDimitry Andric 943bdd1243dSDimitry Andric if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) { 944bdd1243dSDimitry Andric CharUnits Size; 945bdd1243dSDimitry Andric 946bdd1243dSDimitry Andric if (E->isArgumentType()) { 947bdd1243dSDimitry Andric QualType ArgType = E->getTypeOfArgument(); 948bdd1243dSDimitry Andric 949bdd1243dSDimitry Andric Size = AlignOfType(ArgType, ASTCtx, Kind); 950bdd1243dSDimitry Andric } else { 951bdd1243dSDimitry Andric // Argument is an expression, not a type. 952bdd1243dSDimitry Andric const Expr *Arg = E->getArgumentExpr()->IgnoreParens(); 953bdd1243dSDimitry Andric 954bdd1243dSDimitry Andric // The kinds of expressions that we have special-case logic here for 955bdd1243dSDimitry Andric // should be kept up to date with the special checks for those 956bdd1243dSDimitry Andric // expressions in Sema. 957bdd1243dSDimitry Andric 958bdd1243dSDimitry Andric // alignof decl is always accepted, even if it doesn't make sense: we 959bdd1243dSDimitry Andric // default to 1 in those cases. 960bdd1243dSDimitry Andric if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg)) 961bdd1243dSDimitry Andric Size = ASTCtx.getDeclAlign(DRE->getDecl(), 962bdd1243dSDimitry Andric /*RefAsPointee*/ true); 963bdd1243dSDimitry Andric else if (const auto *ME = dyn_cast<MemberExpr>(Arg)) 964bdd1243dSDimitry Andric Size = ASTCtx.getDeclAlign(ME->getMemberDecl(), 965bdd1243dSDimitry Andric /*RefAsPointee*/ true); 966bdd1243dSDimitry Andric else 967bdd1243dSDimitry Andric Size = AlignOfType(Arg->getType(), ASTCtx, Kind); 968bdd1243dSDimitry Andric } 969bdd1243dSDimitry Andric 970*c9157d92SDimitry Andric if (DiscardResult) 971*c9157d92SDimitry Andric return true; 972*c9157d92SDimitry Andric 973bdd1243dSDimitry Andric return this->emitConst(Size.getQuantity(), E); 974bdd1243dSDimitry Andric } 975bdd1243dSDimitry Andric 976bdd1243dSDimitry Andric return false; 977bdd1243dSDimitry Andric } 978bdd1243dSDimitry Andric 979bdd1243dSDimitry Andric template <class Emitter> 980bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) { 981bdd1243dSDimitry Andric // 'Base.Member' 982bdd1243dSDimitry Andric const Expr *Base = E->getBase(); 983*c9157d92SDimitry Andric 984*c9157d92SDimitry Andric if (DiscardResult) 985*c9157d92SDimitry Andric return this->discard(Base); 986bdd1243dSDimitry Andric 987bdd1243dSDimitry Andric if (!this->visit(Base)) 988bdd1243dSDimitry Andric return false; 989bdd1243dSDimitry Andric 990bdd1243dSDimitry Andric // Base above gives us a pointer on the stack. 991bdd1243dSDimitry Andric // TODO: Implement non-FieldDecl members. 992*c9157d92SDimitry Andric const ValueDecl *Member = E->getMemberDecl(); 993bdd1243dSDimitry Andric if (const auto *FD = dyn_cast<FieldDecl>(Member)) { 994bdd1243dSDimitry Andric const RecordDecl *RD = FD->getParent(); 995bdd1243dSDimitry Andric const Record *R = getRecord(RD); 996bdd1243dSDimitry Andric const Record::Field *F = R->getField(FD); 997bdd1243dSDimitry Andric // Leave a pointer to the field on the stack. 998bdd1243dSDimitry Andric if (F->Decl->getType()->isReferenceType()) 999bdd1243dSDimitry Andric return this->emitGetFieldPop(PT_Ptr, F->Offset, E); 1000bdd1243dSDimitry Andric return this->emitGetPtrField(F->Offset, E); 1001bdd1243dSDimitry Andric } 1002bdd1243dSDimitry Andric 1003bdd1243dSDimitry Andric return false; 1004bdd1243dSDimitry Andric } 1005bdd1243dSDimitry Andric 1006bdd1243dSDimitry Andric template <class Emitter> 1007bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArrayInitIndexExpr( 1008bdd1243dSDimitry Andric const ArrayInitIndexExpr *E) { 1009bdd1243dSDimitry Andric // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated 1010bdd1243dSDimitry Andric // stand-alone, e.g. via EvaluateAsInt(). 1011bdd1243dSDimitry Andric if (!ArrayIndex) 1012bdd1243dSDimitry Andric return false; 1013bdd1243dSDimitry Andric return this->emitConst(*ArrayIndex, E); 1014bdd1243dSDimitry Andric } 1015bdd1243dSDimitry Andric 1016bdd1243dSDimitry Andric template <class Emitter> 1017*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArrayInitLoopExpr( 1018*c9157d92SDimitry Andric const ArrayInitLoopExpr *E) { 1019*c9157d92SDimitry Andric assert(Initializing); 1020*c9157d92SDimitry Andric assert(!DiscardResult); 1021*c9157d92SDimitry Andric // TODO: This compiles to quite a lot of bytecode if the array is larger. 1022*c9157d92SDimitry Andric // Investigate compiling this to a loop. 1023*c9157d92SDimitry Andric 1024*c9157d92SDimitry Andric const Expr *SubExpr = E->getSubExpr(); 1025*c9157d92SDimitry Andric const Expr *CommonExpr = E->getCommonExpr(); 1026*c9157d92SDimitry Andric size_t Size = E->getArraySize().getZExtValue(); 1027*c9157d92SDimitry Andric 1028*c9157d92SDimitry Andric // If the common expression is an opaque expression, we visit it 1029*c9157d92SDimitry Andric // here once so we have its value cached. 1030*c9157d92SDimitry Andric // FIXME: This might be necessary (or useful) for all expressions. 1031*c9157d92SDimitry Andric if (isa<OpaqueValueExpr>(CommonExpr)) { 1032*c9157d92SDimitry Andric if (!this->discard(CommonExpr)) 1033*c9157d92SDimitry Andric return false; 1034*c9157d92SDimitry Andric } 1035*c9157d92SDimitry Andric 1036*c9157d92SDimitry Andric // So, every iteration, we execute an assignment here 1037*c9157d92SDimitry Andric // where the LHS is on the stack (the target array) 1038*c9157d92SDimitry Andric // and the RHS is our SubExpr. 1039*c9157d92SDimitry Andric for (size_t I = 0; I != Size; ++I) { 1040*c9157d92SDimitry Andric ArrayIndexScope<Emitter> IndexScope(this, I); 1041*c9157d92SDimitry Andric BlockScope<Emitter> BS(this); 1042*c9157d92SDimitry Andric 1043*c9157d92SDimitry Andric if (!this->visitArrayElemInit(I, SubExpr)) 1044*c9157d92SDimitry Andric return false; 1045*c9157d92SDimitry Andric } 1046*c9157d92SDimitry Andric return true; 1047*c9157d92SDimitry Andric } 1048*c9157d92SDimitry Andric 1049*c9157d92SDimitry Andric template <class Emitter> 1050bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) { 1051*c9157d92SDimitry Andric if (Initializing) 1052*c9157d92SDimitry Andric return this->visitInitializer(E->getSourceExpr()); 1053*c9157d92SDimitry Andric 1054*c9157d92SDimitry Andric PrimType SubExprT = classify(E->getSourceExpr()).value_or(PT_Ptr); 1055*c9157d92SDimitry Andric if (auto It = OpaqueExprs.find(E); It != OpaqueExprs.end()) 1056*c9157d92SDimitry Andric return this->emitGetLocal(SubExprT, It->second, E); 1057*c9157d92SDimitry Andric 1058*c9157d92SDimitry Andric if (!this->visit(E->getSourceExpr())) 1059*c9157d92SDimitry Andric return false; 1060*c9157d92SDimitry Andric 1061*c9157d92SDimitry Andric // At this point we either have the evaluated source expression or a pointer 1062*c9157d92SDimitry Andric // to an object on the stack. We want to create a local variable that stores 1063*c9157d92SDimitry Andric // this value. 1064*c9157d92SDimitry Andric std::optional<unsigned> LocalIndex = 1065*c9157d92SDimitry Andric allocateLocalPrimitive(E, SubExprT, /*IsConst=*/true); 1066*c9157d92SDimitry Andric if (!LocalIndex) 1067*c9157d92SDimitry Andric return false; 1068*c9157d92SDimitry Andric if (!this->emitSetLocal(SubExprT, *LocalIndex, E)) 1069*c9157d92SDimitry Andric return false; 1070*c9157d92SDimitry Andric 1071*c9157d92SDimitry Andric // Here the local variable is created but the value is removed from the stack, 1072*c9157d92SDimitry Andric // so we put it back, because the caller might need it. 1073*c9157d92SDimitry Andric if (!DiscardResult) { 1074*c9157d92SDimitry Andric if (!this->emitGetLocal(SubExprT, *LocalIndex, E)) 1075*c9157d92SDimitry Andric return false; 1076*c9157d92SDimitry Andric } 1077*c9157d92SDimitry Andric 1078*c9157d92SDimitry Andric // FIXME: Ideally the cached value should be cleaned up later. 1079*c9157d92SDimitry Andric OpaqueExprs.insert({E, *LocalIndex}); 1080*c9157d92SDimitry Andric 1081*c9157d92SDimitry Andric return true; 1082bdd1243dSDimitry Andric } 1083bdd1243dSDimitry Andric 1084bdd1243dSDimitry Andric template <class Emitter> 1085bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitAbstractConditionalOperator( 1086bdd1243dSDimitry Andric const AbstractConditionalOperator *E) { 1087*c9157d92SDimitry Andric const Expr *Condition = E->getCond(); 1088*c9157d92SDimitry Andric const Expr *TrueExpr = E->getTrueExpr(); 1089*c9157d92SDimitry Andric const Expr *FalseExpr = E->getFalseExpr(); 1090*c9157d92SDimitry Andric 1091*c9157d92SDimitry Andric LabelTy LabelEnd = this->getLabel(); // Label after the operator. 1092*c9157d92SDimitry Andric LabelTy LabelFalse = this->getLabel(); // Label for the false expr. 1093*c9157d92SDimitry Andric 1094*c9157d92SDimitry Andric if (!this->visitBool(Condition)) 1095*c9157d92SDimitry Andric return false; 1096*c9157d92SDimitry Andric 1097*c9157d92SDimitry Andric if (!this->jumpFalse(LabelFalse)) 1098*c9157d92SDimitry Andric return false; 1099*c9157d92SDimitry Andric 1100*c9157d92SDimitry Andric if (!this->delegate(TrueExpr)) 1101*c9157d92SDimitry Andric return false; 1102*c9157d92SDimitry Andric if (!this->jump(LabelEnd)) 1103*c9157d92SDimitry Andric return false; 1104*c9157d92SDimitry Andric 1105*c9157d92SDimitry Andric this->emitLabel(LabelFalse); 1106*c9157d92SDimitry Andric 1107*c9157d92SDimitry Andric if (!this->delegate(FalseExpr)) 1108*c9157d92SDimitry Andric return false; 1109*c9157d92SDimitry Andric 1110*c9157d92SDimitry Andric this->fallthrough(LabelEnd); 1111*c9157d92SDimitry Andric this->emitLabel(LabelEnd); 1112*c9157d92SDimitry Andric 1113*c9157d92SDimitry Andric return true; 1114bdd1243dSDimitry Andric } 1115bdd1243dSDimitry Andric 1116bdd1243dSDimitry Andric template <class Emitter> 1117bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitStringLiteral(const StringLiteral *E) { 1118*c9157d92SDimitry Andric if (DiscardResult) 1119*c9157d92SDimitry Andric return true; 1120*c9157d92SDimitry Andric 1121*c9157d92SDimitry Andric if (!Initializing) { 1122bdd1243dSDimitry Andric unsigned StringIndex = P.createGlobalString(E); 1123bdd1243dSDimitry Andric return this->emitGetPtrGlobal(StringIndex, E); 1124bdd1243dSDimitry Andric } 1125bdd1243dSDimitry Andric 1126*c9157d92SDimitry Andric // We are initializing an array on the stack. 1127*c9157d92SDimitry Andric const ConstantArrayType *CAT = 1128*c9157d92SDimitry Andric Ctx.getASTContext().getAsConstantArrayType(E->getType()); 1129*c9157d92SDimitry Andric assert(CAT && "a string literal that's not a constant array?"); 1130*c9157d92SDimitry Andric 1131*c9157d92SDimitry Andric // If the initializer string is too long, a diagnostic has already been 1132*c9157d92SDimitry Andric // emitted. Read only the array length from the string literal. 1133*c9157d92SDimitry Andric unsigned ArraySize = CAT->getSize().getZExtValue(); 1134*c9157d92SDimitry Andric unsigned N = std::min(ArraySize, E->getLength()); 1135*c9157d92SDimitry Andric size_t CharWidth = E->getCharByteWidth(); 1136*c9157d92SDimitry Andric 1137*c9157d92SDimitry Andric for (unsigned I = 0; I != N; ++I) { 1138*c9157d92SDimitry Andric uint32_t CodeUnit = E->getCodeUnit(I); 1139*c9157d92SDimitry Andric 1140*c9157d92SDimitry Andric if (CharWidth == 1) { 1141*c9157d92SDimitry Andric this->emitConstSint8(CodeUnit, E); 1142*c9157d92SDimitry Andric this->emitInitElemSint8(I, E); 1143*c9157d92SDimitry Andric } else if (CharWidth == 2) { 1144*c9157d92SDimitry Andric this->emitConstUint16(CodeUnit, E); 1145*c9157d92SDimitry Andric this->emitInitElemUint16(I, E); 1146*c9157d92SDimitry Andric } else if (CharWidth == 4) { 1147*c9157d92SDimitry Andric this->emitConstUint32(CodeUnit, E); 1148*c9157d92SDimitry Andric this->emitInitElemUint32(I, E); 1149*c9157d92SDimitry Andric } else { 1150*c9157d92SDimitry Andric llvm_unreachable("unsupported character width"); 1151*c9157d92SDimitry Andric } 1152*c9157d92SDimitry Andric } 1153*c9157d92SDimitry Andric 1154*c9157d92SDimitry Andric // Fill up the rest of the char array with NUL bytes. 1155*c9157d92SDimitry Andric for (unsigned I = N; I != ArraySize; ++I) { 1156*c9157d92SDimitry Andric if (CharWidth == 1) { 1157*c9157d92SDimitry Andric this->emitConstSint8(0, E); 1158*c9157d92SDimitry Andric this->emitInitElemSint8(I, E); 1159*c9157d92SDimitry Andric } else if (CharWidth == 2) { 1160*c9157d92SDimitry Andric this->emitConstUint16(0, E); 1161*c9157d92SDimitry Andric this->emitInitElemUint16(I, E); 1162*c9157d92SDimitry Andric } else if (CharWidth == 4) { 1163*c9157d92SDimitry Andric this->emitConstUint32(0, E); 1164*c9157d92SDimitry Andric this->emitInitElemUint32(I, E); 1165*c9157d92SDimitry Andric } else { 1166*c9157d92SDimitry Andric llvm_unreachable("unsupported character width"); 1167*c9157d92SDimitry Andric } 1168*c9157d92SDimitry Andric } 1169*c9157d92SDimitry Andric 1170*c9157d92SDimitry Andric return true; 1171*c9157d92SDimitry Andric } 1172*c9157d92SDimitry Andric 1173bdd1243dSDimitry Andric template <class Emitter> 1174bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral( 1175bdd1243dSDimitry Andric const CharacterLiteral *E) { 1176*c9157d92SDimitry Andric if (DiscardResult) 1177*c9157d92SDimitry Andric return true; 1178bdd1243dSDimitry Andric return this->emitConst(E->getValue(), E); 1179bdd1243dSDimitry Andric } 1180bdd1243dSDimitry Andric 1181bdd1243dSDimitry Andric template <class Emitter> 1182fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitFloatCompoundAssignOperator( 1183bdd1243dSDimitry Andric const CompoundAssignOperator *E) { 1184fe013be4SDimitry Andric 1185bdd1243dSDimitry Andric const Expr *LHS = E->getLHS(); 1186bdd1243dSDimitry Andric const Expr *RHS = E->getRHS(); 1187*c9157d92SDimitry Andric QualType LHSType = LHS->getType(); 1188fe013be4SDimitry Andric QualType LHSComputationType = E->getComputationLHSType(); 1189fe013be4SDimitry Andric QualType ResultType = E->getComputationResultType(); 1190fe013be4SDimitry Andric std::optional<PrimType> LT = classify(LHSComputationType); 1191fe013be4SDimitry Andric std::optional<PrimType> RT = classify(ResultType); 1192bdd1243dSDimitry Andric 1193*c9157d92SDimitry Andric assert(ResultType->isFloatingType()); 1194*c9157d92SDimitry Andric 1195bdd1243dSDimitry Andric if (!LT || !RT) 1196bdd1243dSDimitry Andric return false; 1197bdd1243dSDimitry Andric 1198*c9157d92SDimitry Andric PrimType LHST = classifyPrim(LHSType); 1199*c9157d92SDimitry Andric 1200fe013be4SDimitry Andric // C++17 onwards require that we evaluate the RHS first. 1201fe013be4SDimitry Andric // Compute RHS and save it in a temporary variable so we can 1202fe013be4SDimitry Andric // load it again later. 1203fe013be4SDimitry Andric if (!visit(RHS)) 1204fe013be4SDimitry Andric return false; 1205bdd1243dSDimitry Andric 1206fe013be4SDimitry Andric unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true); 1207fe013be4SDimitry Andric if (!this->emitSetLocal(*RT, TempOffset, E)) 1208fe013be4SDimitry Andric return false; 1209fe013be4SDimitry Andric 1210fe013be4SDimitry Andric // First, visit LHS. 1211bdd1243dSDimitry Andric if (!visit(LHS)) 1212bdd1243dSDimitry Andric return false; 1213*c9157d92SDimitry Andric if (!this->emitLoad(LHST, E)) 1214bdd1243dSDimitry Andric return false; 1215fe013be4SDimitry Andric 1216fe013be4SDimitry Andric // If necessary, convert LHS to its computation type. 1217*c9157d92SDimitry Andric if (!this->emitPrimCast(LHST, classifyPrim(LHSComputationType), 1218*c9157d92SDimitry Andric LHSComputationType, E)) 1219fe013be4SDimitry Andric return false; 1220fe013be4SDimitry Andric 1221fe013be4SDimitry Andric // Now load RHS. 1222fe013be4SDimitry Andric if (!this->emitGetLocal(*RT, TempOffset, E)) 1223bdd1243dSDimitry Andric return false; 1224bdd1243dSDimitry Andric 1225*c9157d92SDimitry Andric llvm::RoundingMode RM = getRoundingMode(E); 1226bdd1243dSDimitry Andric switch (E->getOpcode()) { 1227bdd1243dSDimitry Andric case BO_AddAssign: 1228fe013be4SDimitry Andric if (!this->emitAddf(RM, E)) 1229bdd1243dSDimitry Andric return false; 1230bdd1243dSDimitry Andric break; 1231bdd1243dSDimitry Andric case BO_SubAssign: 1232fe013be4SDimitry Andric if (!this->emitSubf(RM, E)) 1233bdd1243dSDimitry Andric return false; 1234bdd1243dSDimitry Andric break; 1235bdd1243dSDimitry Andric case BO_MulAssign: 1236fe013be4SDimitry Andric if (!this->emitMulf(RM, E)) 1237fe013be4SDimitry Andric return false; 1238fe013be4SDimitry Andric break; 1239bdd1243dSDimitry Andric case BO_DivAssign: 1240fe013be4SDimitry Andric if (!this->emitDivf(RM, E)) 1241bdd1243dSDimitry Andric return false; 1242bdd1243dSDimitry Andric break; 1243bdd1243dSDimitry Andric default: 1244fe013be4SDimitry Andric return false; 1245bdd1243dSDimitry Andric } 1246bdd1243dSDimitry Andric 1247*c9157d92SDimitry Andric if (!this->emitPrimCast(classifyPrim(ResultType), LHST, LHS->getType(), E)) 1248fe013be4SDimitry Andric return false; 1249fe013be4SDimitry Andric 1250bdd1243dSDimitry Andric if (DiscardResult) 1251*c9157d92SDimitry Andric return this->emitStorePop(LHST, E); 1252*c9157d92SDimitry Andric return this->emitStore(LHST, E); 1253bdd1243dSDimitry Andric } 1254bdd1243dSDimitry Andric 1255fe013be4SDimitry Andric template <class Emitter> 1256fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPointerCompoundAssignOperator( 1257fe013be4SDimitry Andric const CompoundAssignOperator *E) { 1258fe013be4SDimitry Andric BinaryOperatorKind Op = E->getOpcode(); 1259fe013be4SDimitry Andric const Expr *LHS = E->getLHS(); 1260fe013be4SDimitry Andric const Expr *RHS = E->getRHS(); 1261fe013be4SDimitry Andric std::optional<PrimType> LT = classify(LHS->getType()); 1262fe013be4SDimitry Andric std::optional<PrimType> RT = classify(RHS->getType()); 1263fe013be4SDimitry Andric 1264fe013be4SDimitry Andric if (Op != BO_AddAssign && Op != BO_SubAssign) 1265fe013be4SDimitry Andric return false; 1266fe013be4SDimitry Andric 1267fe013be4SDimitry Andric if (!LT || !RT) 1268fe013be4SDimitry Andric return false; 1269fe013be4SDimitry Andric assert(*LT == PT_Ptr); 1270fe013be4SDimitry Andric 1271fe013be4SDimitry Andric if (!visit(LHS)) 1272fe013be4SDimitry Andric return false; 1273fe013be4SDimitry Andric 1274fe013be4SDimitry Andric if (!this->emitLoadPtr(LHS)) 1275fe013be4SDimitry Andric return false; 1276fe013be4SDimitry Andric 1277fe013be4SDimitry Andric if (!visit(RHS)) 1278fe013be4SDimitry Andric return false; 1279fe013be4SDimitry Andric 1280fe013be4SDimitry Andric if (Op == BO_AddAssign) 1281fe013be4SDimitry Andric this->emitAddOffset(*RT, E); 1282fe013be4SDimitry Andric else 1283fe013be4SDimitry Andric this->emitSubOffset(*RT, E); 1284fe013be4SDimitry Andric 1285fe013be4SDimitry Andric if (DiscardResult) 1286fe013be4SDimitry Andric return this->emitStorePopPtr(E); 1287fe013be4SDimitry Andric return this->emitStorePtr(E); 1288fe013be4SDimitry Andric } 1289fe013be4SDimitry Andric 1290fe013be4SDimitry Andric template <class Emitter> 1291fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator( 1292fe013be4SDimitry Andric const CompoundAssignOperator *E) { 1293fe013be4SDimitry Andric 1294fe013be4SDimitry Andric const Expr *LHS = E->getLHS(); 1295fe013be4SDimitry Andric const Expr *RHS = E->getRHS(); 1296fe013be4SDimitry Andric std::optional<PrimType> LHSComputationT = 1297fe013be4SDimitry Andric classify(E->getComputationLHSType()); 1298fe013be4SDimitry Andric std::optional<PrimType> LT = classify(LHS->getType()); 1299fe013be4SDimitry Andric std::optional<PrimType> RT = classify(E->getComputationResultType()); 1300fe013be4SDimitry Andric std::optional<PrimType> ResultT = classify(E->getType()); 1301fe013be4SDimitry Andric 1302fe013be4SDimitry Andric if (!LT || !RT || !ResultT || !LHSComputationT) 1303fe013be4SDimitry Andric return false; 1304fe013be4SDimitry Andric 1305*c9157d92SDimitry Andric // Handle floating point operations separately here, since they 1306*c9157d92SDimitry Andric // require special care. 1307*c9157d92SDimitry Andric 1308*c9157d92SDimitry Andric if (ResultT == PT_Float || RT == PT_Float) 1309*c9157d92SDimitry Andric return VisitFloatCompoundAssignOperator(E); 1310*c9157d92SDimitry Andric 1311*c9157d92SDimitry Andric if (E->getType()->isPointerType()) 1312*c9157d92SDimitry Andric return VisitPointerCompoundAssignOperator(E); 1313*c9157d92SDimitry Andric 1314fe013be4SDimitry Andric assert(!E->getType()->isPointerType() && "Handled above"); 1315fe013be4SDimitry Andric assert(!E->getType()->isFloatingType() && "Handled above"); 1316fe013be4SDimitry Andric 1317fe013be4SDimitry Andric // C++17 onwards require that we evaluate the RHS first. 1318fe013be4SDimitry Andric // Compute RHS and save it in a temporary variable so we can 1319fe013be4SDimitry Andric // load it again later. 1320fe013be4SDimitry Andric // FIXME: Compound assignments are unsequenced in C, so we might 1321fe013be4SDimitry Andric // have to figure out how to reject them. 1322fe013be4SDimitry Andric if (!visit(RHS)) 1323fe013be4SDimitry Andric return false; 1324fe013be4SDimitry Andric 1325fe013be4SDimitry Andric unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true); 1326fe013be4SDimitry Andric 1327fe013be4SDimitry Andric if (!this->emitSetLocal(*RT, TempOffset, E)) 1328fe013be4SDimitry Andric return false; 1329fe013be4SDimitry Andric 1330fe013be4SDimitry Andric // Get LHS pointer, load its value and cast it to the 1331fe013be4SDimitry Andric // computation type if necessary. 1332fe013be4SDimitry Andric if (!visit(LHS)) 1333fe013be4SDimitry Andric return false; 1334fe013be4SDimitry Andric if (!this->emitLoad(*LT, E)) 1335fe013be4SDimitry Andric return false; 1336fe013be4SDimitry Andric if (*LT != *LHSComputationT) { 1337fe013be4SDimitry Andric if (!this->emitCast(*LT, *LHSComputationT, E)) 1338fe013be4SDimitry Andric return false; 1339fe013be4SDimitry Andric } 1340fe013be4SDimitry Andric 1341fe013be4SDimitry Andric // Get the RHS value on the stack. 1342fe013be4SDimitry Andric if (!this->emitGetLocal(*RT, TempOffset, E)) 1343fe013be4SDimitry Andric return false; 1344fe013be4SDimitry Andric 1345fe013be4SDimitry Andric // Perform operation. 1346fe013be4SDimitry Andric switch (E->getOpcode()) { 1347fe013be4SDimitry Andric case BO_AddAssign: 1348fe013be4SDimitry Andric if (!this->emitAdd(*LHSComputationT, E)) 1349fe013be4SDimitry Andric return false; 1350fe013be4SDimitry Andric break; 1351fe013be4SDimitry Andric case BO_SubAssign: 1352fe013be4SDimitry Andric if (!this->emitSub(*LHSComputationT, E)) 1353fe013be4SDimitry Andric return false; 1354fe013be4SDimitry Andric break; 1355fe013be4SDimitry Andric case BO_MulAssign: 1356fe013be4SDimitry Andric if (!this->emitMul(*LHSComputationT, E)) 1357fe013be4SDimitry Andric return false; 1358fe013be4SDimitry Andric break; 1359fe013be4SDimitry Andric case BO_DivAssign: 1360fe013be4SDimitry Andric if (!this->emitDiv(*LHSComputationT, E)) 1361fe013be4SDimitry Andric return false; 1362fe013be4SDimitry Andric break; 1363fe013be4SDimitry Andric case BO_RemAssign: 1364fe013be4SDimitry Andric if (!this->emitRem(*LHSComputationT, E)) 1365fe013be4SDimitry Andric return false; 1366fe013be4SDimitry Andric break; 1367fe013be4SDimitry Andric case BO_ShlAssign: 1368fe013be4SDimitry Andric if (!this->emitShl(*LHSComputationT, *RT, E)) 1369fe013be4SDimitry Andric return false; 1370fe013be4SDimitry Andric break; 1371fe013be4SDimitry Andric case BO_ShrAssign: 1372fe013be4SDimitry Andric if (!this->emitShr(*LHSComputationT, *RT, E)) 1373fe013be4SDimitry Andric return false; 1374fe013be4SDimitry Andric break; 1375fe013be4SDimitry Andric case BO_AndAssign: 1376fe013be4SDimitry Andric if (!this->emitBitAnd(*LHSComputationT, E)) 1377fe013be4SDimitry Andric return false; 1378fe013be4SDimitry Andric break; 1379fe013be4SDimitry Andric case BO_XorAssign: 1380fe013be4SDimitry Andric if (!this->emitBitXor(*LHSComputationT, E)) 1381fe013be4SDimitry Andric return false; 1382fe013be4SDimitry Andric break; 1383fe013be4SDimitry Andric case BO_OrAssign: 1384fe013be4SDimitry Andric if (!this->emitBitOr(*LHSComputationT, E)) 1385fe013be4SDimitry Andric return false; 1386fe013be4SDimitry Andric break; 1387fe013be4SDimitry Andric default: 1388fe013be4SDimitry Andric llvm_unreachable("Unimplemented compound assign operator"); 1389fe013be4SDimitry Andric } 1390fe013be4SDimitry Andric 1391fe013be4SDimitry Andric // And now cast from LHSComputationT to ResultT. 1392fe013be4SDimitry Andric if (*ResultT != *LHSComputationT) { 1393fe013be4SDimitry Andric if (!this->emitCast(*LHSComputationT, *ResultT, E)) 1394fe013be4SDimitry Andric return false; 1395fe013be4SDimitry Andric } 1396fe013be4SDimitry Andric 1397fe013be4SDimitry Andric // And store the result in LHS. 1398*c9157d92SDimitry Andric if (DiscardResult) { 1399*c9157d92SDimitry Andric if (LHS->refersToBitField()) 1400*c9157d92SDimitry Andric return this->emitStoreBitFieldPop(*ResultT, E); 1401fe013be4SDimitry Andric return this->emitStorePop(*ResultT, E); 1402*c9157d92SDimitry Andric } 1403*c9157d92SDimitry Andric if (LHS->refersToBitField()) 1404*c9157d92SDimitry Andric return this->emitStoreBitField(*ResultT, E); 1405fe013be4SDimitry Andric return this->emitStore(*ResultT, E); 1406fe013be4SDimitry Andric } 1407fe013be4SDimitry Andric 1408fe013be4SDimitry Andric template <class Emitter> 1409fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitExprWithCleanups( 1410fe013be4SDimitry Andric const ExprWithCleanups *E) { 1411fe013be4SDimitry Andric const Expr *SubExpr = E->getSubExpr(); 1412fe013be4SDimitry Andric 1413fe013be4SDimitry Andric assert(E->getNumObjects() == 0 && "TODO: Implement cleanups"); 1414fe013be4SDimitry Andric 1415*c9157d92SDimitry Andric return this->delegate(SubExpr); 1416fe013be4SDimitry Andric } 1417fe013be4SDimitry Andric 1418fe013be4SDimitry Andric template <class Emitter> 1419fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr( 1420fe013be4SDimitry Andric const MaterializeTemporaryExpr *E) { 1421fe013be4SDimitry Andric const Expr *SubExpr = E->getSubExpr(); 1422fe013be4SDimitry Andric 1423*c9157d92SDimitry Andric if (Initializing) { 1424*c9157d92SDimitry Andric // We already have a value, just initialize that. 1425*c9157d92SDimitry Andric return this->visitInitializer(SubExpr); 1426*c9157d92SDimitry Andric } 1427*c9157d92SDimitry Andric // If we don't end up using the materialized temporary anyway, don't 1428*c9157d92SDimitry Andric // bother creating it. 1429*c9157d92SDimitry Andric if (DiscardResult) 1430*c9157d92SDimitry Andric return this->discard(SubExpr); 1431*c9157d92SDimitry Andric 1432*c9157d92SDimitry Andric // When we're initializing a global variable *or* the storage duration of 1433*c9157d92SDimitry Andric // the temporary is explicitly static, create a global variable. 1434*c9157d92SDimitry Andric std::optional<PrimType> SubExprT = classify(SubExpr); 1435*c9157d92SDimitry Andric bool IsStatic = E->getStorageDuration() == SD_Static; 1436*c9157d92SDimitry Andric if (GlobalDecl || IsStatic) { 1437*c9157d92SDimitry Andric std::optional<unsigned> GlobalIndex = P.createGlobal(E); 1438*c9157d92SDimitry Andric if (!GlobalIndex) 1439*c9157d92SDimitry Andric return false; 1440*c9157d92SDimitry Andric 1441fe013be4SDimitry Andric const LifetimeExtendedTemporaryDecl *TempDecl = 1442fe013be4SDimitry Andric E->getLifetimeExtendedTemporaryDecl(); 1443*c9157d92SDimitry Andric if (IsStatic) 1444*c9157d92SDimitry Andric assert(TempDecl); 1445fe013be4SDimitry Andric 1446*c9157d92SDimitry Andric if (SubExprT) { 1447*c9157d92SDimitry Andric if (!this->visit(SubExpr)) 1448fe013be4SDimitry Andric return false; 1449*c9157d92SDimitry Andric if (IsStatic) { 1450fe013be4SDimitry Andric if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E)) 1451fe013be4SDimitry Andric return false; 1452*c9157d92SDimitry Andric } else { 1453*c9157d92SDimitry Andric if (!this->emitInitGlobal(*SubExprT, *GlobalIndex, E)) 1454*c9157d92SDimitry Andric return false; 1455*c9157d92SDimitry Andric } 1456fe013be4SDimitry Andric return this->emitGetPtrGlobal(*GlobalIndex, E); 1457fe013be4SDimitry Andric } 1458fe013be4SDimitry Andric 1459*c9157d92SDimitry Andric // Non-primitive values. 1460*c9157d92SDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, E)) 1461fe013be4SDimitry Andric return false; 1462*c9157d92SDimitry Andric if (!this->visitInitializer(SubExpr)) 1463*c9157d92SDimitry Andric return false; 1464*c9157d92SDimitry Andric if (IsStatic) 1465*c9157d92SDimitry Andric return this->emitInitGlobalTempComp(TempDecl, E); 1466*c9157d92SDimitry Andric return true; 1467fe013be4SDimitry Andric } 1468fe013be4SDimitry Andric 1469fe013be4SDimitry Andric // For everyhing else, use local variables. 1470fe013be4SDimitry Andric if (SubExprT) { 1471fe013be4SDimitry Andric if (std::optional<unsigned> LocalIndex = allocateLocalPrimitive( 1472fe013be4SDimitry Andric SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true)) { 1473*c9157d92SDimitry Andric if (!this->visit(SubExpr)) 1474fe013be4SDimitry Andric return false; 1475fe013be4SDimitry Andric this->emitSetLocal(*SubExprT, *LocalIndex, E); 1476fe013be4SDimitry Andric return this->emitGetPtrLocal(*LocalIndex, E); 1477fe013be4SDimitry Andric } 1478fe013be4SDimitry Andric } else { 1479fe013be4SDimitry Andric if (std::optional<unsigned> LocalIndex = 1480fe013be4SDimitry Andric allocateLocal(SubExpr, /*IsExtended=*/true)) { 1481fe013be4SDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E)) 1482fe013be4SDimitry Andric return false; 1483fe013be4SDimitry Andric return this->visitInitializer(SubExpr); 1484fe013be4SDimitry Andric } 1485fe013be4SDimitry Andric } 1486fe013be4SDimitry Andric return false; 1487fe013be4SDimitry Andric } 1488fe013be4SDimitry Andric 1489fe013be4SDimitry Andric template <class Emitter> 1490*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXBindTemporaryExpr( 1491*c9157d92SDimitry Andric const CXXBindTemporaryExpr *E) { 1492*c9157d92SDimitry Andric return this->delegate(E->getSubExpr()); 1493*c9157d92SDimitry Andric } 1494*c9157d92SDimitry Andric 1495*c9157d92SDimitry Andric template <class Emitter> 1496fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr( 1497fe013be4SDimitry Andric const CompoundLiteralExpr *E) { 1498fe013be4SDimitry Andric const Expr *Init = E->getInitializer(); 1499*c9157d92SDimitry Andric if (Initializing) { 1500*c9157d92SDimitry Andric // We already have a value, just initialize that. 1501*c9157d92SDimitry Andric return this->visitInitializer(Init); 1502*c9157d92SDimitry Andric } 1503*c9157d92SDimitry Andric 1504*c9157d92SDimitry Andric std::optional<PrimType> T = classify(E->getType()); 1505fe013be4SDimitry Andric if (E->isFileScope()) { 1506fe013be4SDimitry Andric if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) { 1507fe013be4SDimitry Andric if (classify(E->getType())) 1508fe013be4SDimitry Andric return this->visit(Init); 1509fe013be4SDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, E)) 1510fe013be4SDimitry Andric return false; 1511fe013be4SDimitry Andric return this->visitInitializer(Init); 1512fe013be4SDimitry Andric } 1513fe013be4SDimitry Andric } 1514fe013be4SDimitry Andric 1515fe013be4SDimitry Andric // Otherwise, use a local variable. 1516fe013be4SDimitry Andric if (T) { 1517fe013be4SDimitry Andric // For primitive types, we just visit the initializer. 1518*c9157d92SDimitry Andric return this->delegate(Init); 1519fe013be4SDimitry Andric } else { 1520fe013be4SDimitry Andric if (std::optional<unsigned> LocalIndex = allocateLocal(Init)) { 1521fe013be4SDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E)) 1522fe013be4SDimitry Andric return false; 1523*c9157d92SDimitry Andric if (!this->visitInitializer(Init)) 1524*c9157d92SDimitry Andric return false; 1525*c9157d92SDimitry Andric if (DiscardResult) 1526*c9157d92SDimitry Andric return this->emitPopPtr(E); 1527*c9157d92SDimitry Andric return true; 1528fe013be4SDimitry Andric } 1529fe013be4SDimitry Andric } 1530fe013be4SDimitry Andric 1531fe013be4SDimitry Andric return false; 1532fe013be4SDimitry Andric } 1533fe013be4SDimitry Andric 1534fe013be4SDimitry Andric template <class Emitter> 1535fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) { 1536*c9157d92SDimitry Andric if (DiscardResult) 1537*c9157d92SDimitry Andric return true; 1538fe013be4SDimitry Andric return this->emitConstBool(E->getValue(), E); 1539fe013be4SDimitry Andric } 1540fe013be4SDimitry Andric 1541fe013be4SDimitry Andric template <class Emitter> 1542fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) { 1543*c9157d92SDimitry Andric assert(Initializing); 1544fe013be4SDimitry Andric const Record *R = P.getOrCreateRecord(E->getLambdaClass()); 1545fe013be4SDimitry Andric 1546fe013be4SDimitry Andric auto *CaptureInitIt = E->capture_init_begin(); 1547fe013be4SDimitry Andric // Initialize all fields (which represent lambda captures) of the 1548fe013be4SDimitry Andric // record with their initializers. 1549fe013be4SDimitry Andric for (const Record::Field &F : R->fields()) { 1550fe013be4SDimitry Andric const Expr *Init = *CaptureInitIt; 1551fe013be4SDimitry Andric ++CaptureInitIt; 1552fe013be4SDimitry Andric 1553fe013be4SDimitry Andric if (std::optional<PrimType> T = classify(Init)) { 1554fe013be4SDimitry Andric if (!this->visit(Init)) 1555fe013be4SDimitry Andric return false; 1556fe013be4SDimitry Andric 1557fe013be4SDimitry Andric if (!this->emitSetField(*T, F.Offset, E)) 1558fe013be4SDimitry Andric return false; 1559fe013be4SDimitry Andric } else { 1560fe013be4SDimitry Andric if (!this->emitDupPtr(E)) 1561fe013be4SDimitry Andric return false; 1562fe013be4SDimitry Andric 1563fe013be4SDimitry Andric if (!this->emitGetPtrField(F.Offset, E)) 1564fe013be4SDimitry Andric return false; 1565fe013be4SDimitry Andric 1566fe013be4SDimitry Andric if (!this->visitInitializer(Init)) 1567fe013be4SDimitry Andric return false; 1568fe013be4SDimitry Andric 1569fe013be4SDimitry Andric if (!this->emitPopPtr(E)) 1570fe013be4SDimitry Andric return false; 1571fe013be4SDimitry Andric } 1572fe013be4SDimitry Andric } 1573fe013be4SDimitry Andric 1574fe013be4SDimitry Andric return true; 1575fe013be4SDimitry Andric } 1576fe013be4SDimitry Andric 1577fe013be4SDimitry Andric template <class Emitter> 1578fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) { 1579fe013be4SDimitry Andric if (DiscardResult) 1580fe013be4SDimitry Andric return true; 1581fe013be4SDimitry Andric 1582*c9157d92SDimitry Andric assert(!Initializing); 1583fe013be4SDimitry Andric return this->visit(E->getFunctionName()); 1584fe013be4SDimitry Andric } 1585fe013be4SDimitry Andric 1586*c9157d92SDimitry Andric template <class Emitter> 1587*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) { 1588*c9157d92SDimitry Andric if (E->getSubExpr() && !this->discard(E->getSubExpr())) 1589*c9157d92SDimitry Andric return false; 1590*c9157d92SDimitry Andric 1591*c9157d92SDimitry Andric return this->emitInvalid(E); 1592*c9157d92SDimitry Andric } 1593*c9157d92SDimitry Andric 1594*c9157d92SDimitry Andric template <class Emitter> 1595*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXReinterpretCastExpr( 1596*c9157d92SDimitry Andric const CXXReinterpretCastExpr *E) { 1597*c9157d92SDimitry Andric if (!this->discard(E->getSubExpr())) 1598*c9157d92SDimitry Andric return false; 1599*c9157d92SDimitry Andric 1600*c9157d92SDimitry Andric return this->emitInvalidCast(CastKind::Reinterpret, E); 1601*c9157d92SDimitry Andric } 1602*c9157d92SDimitry Andric 1603*c9157d92SDimitry Andric template <class Emitter> 1604*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) { 1605*c9157d92SDimitry Andric assert(E->getType()->isBooleanType()); 1606*c9157d92SDimitry Andric 1607*c9157d92SDimitry Andric if (DiscardResult) 1608*c9157d92SDimitry Andric return true; 1609*c9157d92SDimitry Andric return this->emitConstBool(E->getValue(), E); 1610*c9157d92SDimitry Andric } 1611*c9157d92SDimitry Andric 1612*c9157d92SDimitry Andric template <class Emitter> 1613*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXConstructExpr( 1614*c9157d92SDimitry Andric const CXXConstructExpr *E) { 1615*c9157d92SDimitry Andric QualType T = E->getType(); 1616*c9157d92SDimitry Andric assert(!classify(T)); 1617*c9157d92SDimitry Andric 1618*c9157d92SDimitry Andric if (T->isRecordType()) { 1619*c9157d92SDimitry Andric const CXXConstructorDecl *Ctor = E->getConstructor(); 1620*c9157d92SDimitry Andric 1621*c9157d92SDimitry Andric // Trivial zero initialization. 1622*c9157d92SDimitry Andric if (E->requiresZeroInitialization() && Ctor->isTrivial()) { 1623*c9157d92SDimitry Andric const Record *R = getRecord(E->getType()); 1624*c9157d92SDimitry Andric return this->visitZeroRecordInitializer(R, E); 1625*c9157d92SDimitry Andric } 1626*c9157d92SDimitry Andric 1627*c9157d92SDimitry Andric const Function *Func = getFunction(Ctor); 1628*c9157d92SDimitry Andric 1629*c9157d92SDimitry Andric if (!Func) 1630*c9157d92SDimitry Andric return false; 1631*c9157d92SDimitry Andric 1632*c9157d92SDimitry Andric assert(Func->hasThisPointer()); 1633*c9157d92SDimitry Andric assert(!Func->hasRVO()); 1634*c9157d92SDimitry Andric 1635*c9157d92SDimitry Andric // If we're discarding a construct expression, we still need 1636*c9157d92SDimitry Andric // to allocate a variable and call the constructor and destructor. 1637*c9157d92SDimitry Andric if (DiscardResult) { 1638*c9157d92SDimitry Andric assert(!Initializing); 1639*c9157d92SDimitry Andric std::optional<unsigned> LocalIndex = 1640*c9157d92SDimitry Andric allocateLocal(E, /*IsExtended=*/true); 1641*c9157d92SDimitry Andric 1642*c9157d92SDimitry Andric if (!LocalIndex) 1643*c9157d92SDimitry Andric return false; 1644*c9157d92SDimitry Andric 1645*c9157d92SDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E)) 1646*c9157d92SDimitry Andric return false; 1647*c9157d92SDimitry Andric } 1648*c9157d92SDimitry Andric 1649*c9157d92SDimitry Andric // The This pointer is already on the stack because this is an initializer, 1650*c9157d92SDimitry Andric // but we need to dup() so the call() below has its own copy. 1651*c9157d92SDimitry Andric if (!this->emitDupPtr(E)) 1652*c9157d92SDimitry Andric return false; 1653*c9157d92SDimitry Andric 1654*c9157d92SDimitry Andric // Constructor arguments. 1655*c9157d92SDimitry Andric for (const auto *Arg : E->arguments()) { 1656*c9157d92SDimitry Andric if (!this->visit(Arg)) 1657*c9157d92SDimitry Andric return false; 1658*c9157d92SDimitry Andric } 1659*c9157d92SDimitry Andric 1660*c9157d92SDimitry Andric if (!this->emitCall(Func, E)) 1661*c9157d92SDimitry Andric return false; 1662*c9157d92SDimitry Andric 1663*c9157d92SDimitry Andric // Immediately call the destructor if we have to. 1664*c9157d92SDimitry Andric if (DiscardResult) { 1665*c9157d92SDimitry Andric if (!this->emitPopPtr(E)) 1666*c9157d92SDimitry Andric return false; 1667*c9157d92SDimitry Andric } 1668*c9157d92SDimitry Andric return true; 1669*c9157d92SDimitry Andric } 1670*c9157d92SDimitry Andric 1671*c9157d92SDimitry Andric if (T->isArrayType()) { 1672*c9157d92SDimitry Andric const ConstantArrayType *CAT = 1673*c9157d92SDimitry Andric Ctx.getASTContext().getAsConstantArrayType(E->getType()); 1674*c9157d92SDimitry Andric assert(CAT); 1675*c9157d92SDimitry Andric size_t NumElems = CAT->getSize().getZExtValue(); 1676*c9157d92SDimitry Andric const Function *Func = getFunction(E->getConstructor()); 1677*c9157d92SDimitry Andric if (!Func || !Func->isConstexpr()) 1678*c9157d92SDimitry Andric return false; 1679*c9157d92SDimitry Andric 1680*c9157d92SDimitry Andric // FIXME(perf): We're calling the constructor once per array element here, 1681*c9157d92SDimitry Andric // in the old intepreter we had a special-case for trivial constructors. 1682*c9157d92SDimitry Andric for (size_t I = 0; I != NumElems; ++I) { 1683*c9157d92SDimitry Andric if (!this->emitConstUint64(I, E)) 1684*c9157d92SDimitry Andric return false; 1685*c9157d92SDimitry Andric if (!this->emitArrayElemPtrUint64(E)) 1686*c9157d92SDimitry Andric return false; 1687*c9157d92SDimitry Andric 1688*c9157d92SDimitry Andric // Constructor arguments. 1689*c9157d92SDimitry Andric for (const auto *Arg : E->arguments()) { 1690*c9157d92SDimitry Andric if (!this->visit(Arg)) 1691*c9157d92SDimitry Andric return false; 1692*c9157d92SDimitry Andric } 1693*c9157d92SDimitry Andric 1694*c9157d92SDimitry Andric if (!this->emitCall(Func, E)) 1695*c9157d92SDimitry Andric return false; 1696*c9157d92SDimitry Andric } 1697*c9157d92SDimitry Andric return true; 1698*c9157d92SDimitry Andric } 1699*c9157d92SDimitry Andric 1700*c9157d92SDimitry Andric return false; 1701*c9157d92SDimitry Andric } 1702*c9157d92SDimitry Andric 1703*c9157d92SDimitry Andric template <class Emitter> 1704*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitSourceLocExpr(const SourceLocExpr *E) { 1705*c9157d92SDimitry Andric if (DiscardResult) 1706*c9157d92SDimitry Andric return true; 1707*c9157d92SDimitry Andric 1708*c9157d92SDimitry Andric const APValue Val = 1709*c9157d92SDimitry Andric E->EvaluateInContext(Ctx.getASTContext(), SourceLocDefaultExpr); 1710*c9157d92SDimitry Andric 1711*c9157d92SDimitry Andric // Things like __builtin_LINE(). 1712*c9157d92SDimitry Andric if (E->getType()->isIntegerType()) { 1713*c9157d92SDimitry Andric assert(Val.isInt()); 1714*c9157d92SDimitry Andric const APSInt &I = Val.getInt(); 1715*c9157d92SDimitry Andric return this->emitConst(I, E); 1716*c9157d92SDimitry Andric } 1717*c9157d92SDimitry Andric // Otherwise, the APValue is an LValue, with only one element. 1718*c9157d92SDimitry Andric // Theoretically, we don't need the APValue at all of course. 1719*c9157d92SDimitry Andric assert(E->getType()->isPointerType()); 1720*c9157d92SDimitry Andric assert(Val.isLValue()); 1721*c9157d92SDimitry Andric const APValue::LValueBase &Base = Val.getLValueBase(); 1722*c9157d92SDimitry Andric if (const Expr *LValueExpr = Base.dyn_cast<const Expr *>()) 1723*c9157d92SDimitry Andric return this->visit(LValueExpr); 1724*c9157d92SDimitry Andric 1725*c9157d92SDimitry Andric // Otherwise, we have a decl (which is the case for 1726*c9157d92SDimitry Andric // __builtin_source_location). 1727*c9157d92SDimitry Andric assert(Base.is<const ValueDecl *>()); 1728*c9157d92SDimitry Andric assert(Val.getLValuePath().size() == 0); 1729*c9157d92SDimitry Andric const auto *BaseDecl = Base.dyn_cast<const ValueDecl *>(); 1730*c9157d92SDimitry Andric assert(BaseDecl); 1731*c9157d92SDimitry Andric 1732*c9157d92SDimitry Andric auto *UGCD = cast<UnnamedGlobalConstantDecl>(BaseDecl); 1733*c9157d92SDimitry Andric 1734*c9157d92SDimitry Andric std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(UGCD); 1735*c9157d92SDimitry Andric if (!GlobalIndex) 1736*c9157d92SDimitry Andric return false; 1737*c9157d92SDimitry Andric 1738*c9157d92SDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, E)) 1739*c9157d92SDimitry Andric return false; 1740*c9157d92SDimitry Andric 1741*c9157d92SDimitry Andric const Record *R = getRecord(E->getType()); 1742*c9157d92SDimitry Andric const APValue &V = UGCD->getValue(); 1743*c9157d92SDimitry Andric for (unsigned I = 0, N = R->getNumFields(); I != N; ++I) { 1744*c9157d92SDimitry Andric const Record::Field *F = R->getField(I); 1745*c9157d92SDimitry Andric const APValue &FieldValue = V.getStructField(I); 1746*c9157d92SDimitry Andric 1747*c9157d92SDimitry Andric PrimType FieldT = classifyPrim(F->Decl->getType()); 1748*c9157d92SDimitry Andric 1749*c9157d92SDimitry Andric if (!this->visitAPValue(FieldValue, FieldT, E)) 1750*c9157d92SDimitry Andric return false; 1751*c9157d92SDimitry Andric if (!this->emitInitField(FieldT, F->Offset, E)) 1752*c9157d92SDimitry Andric return false; 1753*c9157d92SDimitry Andric } 1754*c9157d92SDimitry Andric 1755*c9157d92SDimitry Andric // Leave the pointer to the global on the stack. 1756*c9157d92SDimitry Andric return true; 1757*c9157d92SDimitry Andric } 1758*c9157d92SDimitry Andric 1759*c9157d92SDimitry Andric template <class Emitter> 1760*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) { 1761*c9157d92SDimitry Andric unsigned N = E->getNumComponents(); 1762*c9157d92SDimitry Andric if (N == 0) 1763*c9157d92SDimitry Andric return false; 1764*c9157d92SDimitry Andric 1765*c9157d92SDimitry Andric for (unsigned I = 0; I != N; ++I) { 1766*c9157d92SDimitry Andric const OffsetOfNode &Node = E->getComponent(I); 1767*c9157d92SDimitry Andric if (Node.getKind() == OffsetOfNode::Array) { 1768*c9157d92SDimitry Andric const Expr *ArrayIndexExpr = E->getIndexExpr(Node.getArrayExprIndex()); 1769*c9157d92SDimitry Andric PrimType IndexT = classifyPrim(ArrayIndexExpr->getType()); 1770*c9157d92SDimitry Andric 1771*c9157d92SDimitry Andric if (DiscardResult) { 1772*c9157d92SDimitry Andric if (!this->discard(ArrayIndexExpr)) 1773*c9157d92SDimitry Andric return false; 1774*c9157d92SDimitry Andric continue; 1775*c9157d92SDimitry Andric } 1776*c9157d92SDimitry Andric 1777*c9157d92SDimitry Andric if (!this->visit(ArrayIndexExpr)) 1778*c9157d92SDimitry Andric return false; 1779*c9157d92SDimitry Andric // Cast to Sint64. 1780*c9157d92SDimitry Andric if (IndexT != PT_Sint64) { 1781*c9157d92SDimitry Andric if (!this->emitCast(IndexT, PT_Sint64, E)) 1782*c9157d92SDimitry Andric return false; 1783*c9157d92SDimitry Andric } 1784*c9157d92SDimitry Andric } 1785*c9157d92SDimitry Andric } 1786*c9157d92SDimitry Andric 1787*c9157d92SDimitry Andric if (DiscardResult) 1788*c9157d92SDimitry Andric return true; 1789*c9157d92SDimitry Andric 1790*c9157d92SDimitry Andric PrimType T = classifyPrim(E->getType()); 1791*c9157d92SDimitry Andric return this->emitOffsetOf(T, E, E); 1792*c9157d92SDimitry Andric } 1793*c9157d92SDimitry Andric 1794*c9157d92SDimitry Andric template <class Emitter> 1795*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXScalarValueInitExpr( 1796*c9157d92SDimitry Andric const CXXScalarValueInitExpr *E) { 1797*c9157d92SDimitry Andric QualType Ty = E->getType(); 1798*c9157d92SDimitry Andric 1799*c9157d92SDimitry Andric if (Ty->isVoidType()) 1800*c9157d92SDimitry Andric return true; 1801*c9157d92SDimitry Andric 1802*c9157d92SDimitry Andric return this->visitZeroInitializer(classifyPrim(Ty), Ty, E); 1803*c9157d92SDimitry Andric } 1804*c9157d92SDimitry Andric 1805*c9157d92SDimitry Andric template <class Emitter> 1806*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitSizeOfPackExpr(const SizeOfPackExpr *E) { 1807*c9157d92SDimitry Andric return this->emitConst(E->getPackLength(), E); 1808*c9157d92SDimitry Andric } 1809*c9157d92SDimitry Andric 1810bdd1243dSDimitry Andric template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) { 1811fe013be4SDimitry Andric if (E->containsErrors()) 1812fe013be4SDimitry Andric return false; 1813fe013be4SDimitry Andric 1814*c9157d92SDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true, 1815*c9157d92SDimitry Andric /*NewInitializing=*/false); 1816a7dea167SDimitry Andric return this->Visit(E); 1817a7dea167SDimitry Andric } 1818a7dea167SDimitry Andric 1819a7dea167SDimitry Andric template <class Emitter> 1820*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::delegate(const Expr *E) { 1821fe013be4SDimitry Andric if (E->containsErrors()) 1822fe013be4SDimitry Andric return false; 1823fe013be4SDimitry Andric 1824*c9157d92SDimitry Andric // We're basically doing: 1825*c9157d92SDimitry Andric // OptionScope<Emitter> Scope(this, DicardResult, Initializing); 1826*c9157d92SDimitry Andric // but that's unnecessary of course. 1827*c9157d92SDimitry Andric return this->Visit(E); 1828*c9157d92SDimitry Andric } 1829*c9157d92SDimitry Andric 1830*c9157d92SDimitry Andric template <class Emitter> bool ByteCodeExprGen<Emitter>::visit(const Expr *E) { 1831*c9157d92SDimitry Andric if (E->containsErrors()) 1832*c9157d92SDimitry Andric return false; 1833*c9157d92SDimitry Andric 1834*c9157d92SDimitry Andric if (E->getType()->isVoidType()) 1835*c9157d92SDimitry Andric return this->discard(E); 1836*c9157d92SDimitry Andric 1837*c9157d92SDimitry Andric // Create local variable to hold the return value. 1838*c9157d92SDimitry Andric if (!E->isGLValue() && !E->getType()->isAnyComplexType() && 1839*c9157d92SDimitry Andric !classify(E->getType())) { 1840*c9157d92SDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/true); 1841*c9157d92SDimitry Andric if (!LocalIndex) 1842*c9157d92SDimitry Andric return false; 1843*c9157d92SDimitry Andric 1844*c9157d92SDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E)) 1845*c9157d92SDimitry Andric return false; 1846*c9157d92SDimitry Andric return this->visitInitializer(E); 1847*c9157d92SDimitry Andric } 1848*c9157d92SDimitry Andric 1849*c9157d92SDimitry Andric // Otherwise,we have a primitive return value, produce the value directly 1850*c9157d92SDimitry Andric // and push it on the stack. 1851*c9157d92SDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false, 1852*c9157d92SDimitry Andric /*NewInitializing=*/false); 1853*c9157d92SDimitry Andric return this->Visit(E); 1854*c9157d92SDimitry Andric } 1855*c9157d92SDimitry Andric 1856*c9157d92SDimitry Andric template <class Emitter> 1857*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *E) { 1858*c9157d92SDimitry Andric assert(!classify(E->getType())); 1859*c9157d92SDimitry Andric 1860*c9157d92SDimitry Andric if (E->containsErrors()) 1861*c9157d92SDimitry Andric return false; 1862*c9157d92SDimitry Andric 1863*c9157d92SDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false, 1864*c9157d92SDimitry Andric /*NewInitializing=*/true); 1865a7dea167SDimitry Andric return this->Visit(E); 1866a7dea167SDimitry Andric } 1867a7dea167SDimitry Andric 1868a7dea167SDimitry Andric template <class Emitter> 1869a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) { 1870*c9157d92SDimitry Andric std::optional<PrimType> T = classify(E->getType()); 1871*c9157d92SDimitry Andric if (!T) 1872fe013be4SDimitry Andric return false; 1873fe013be4SDimitry Andric 1874*c9157d92SDimitry Andric if (!this->visit(E)) 1875fe013be4SDimitry Andric return false; 1876fe013be4SDimitry Andric 1877*c9157d92SDimitry Andric if (T == PT_Bool) 1878fe013be4SDimitry Andric return true; 1879*c9157d92SDimitry Andric 1880*c9157d92SDimitry Andric // Convert pointers to bool. 1881*c9157d92SDimitry Andric if (T == PT_Ptr || T == PT_FnPtr) { 1882*c9157d92SDimitry Andric if (!this->emitNull(*T, E)) 1883*c9157d92SDimitry Andric return false; 1884*c9157d92SDimitry Andric return this->emitNE(*T, E); 1885*c9157d92SDimitry Andric } 1886*c9157d92SDimitry Andric 1887*c9157d92SDimitry Andric // Or Floats. 1888*c9157d92SDimitry Andric if (T == PT_Float) 1889*c9157d92SDimitry Andric return this->emitCastFloatingIntegralBool(E); 1890*c9157d92SDimitry Andric 1891*c9157d92SDimitry Andric // Or anything else we can. 1892*c9157d92SDimitry Andric return this->emitCast(*T, PT_Bool, E); 1893fe013be4SDimitry Andric } 1894fe013be4SDimitry Andric 1895fe013be4SDimitry Andric template <class Emitter> 1896*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, QualType QT, 1897fe013be4SDimitry Andric const Expr *E) { 1898a7dea167SDimitry Andric switch (T) { 1899a7dea167SDimitry Andric case PT_Bool: 1900a7dea167SDimitry Andric return this->emitZeroBool(E); 1901a7dea167SDimitry Andric case PT_Sint8: 1902a7dea167SDimitry Andric return this->emitZeroSint8(E); 1903a7dea167SDimitry Andric case PT_Uint8: 1904a7dea167SDimitry Andric return this->emitZeroUint8(E); 1905a7dea167SDimitry Andric case PT_Sint16: 1906a7dea167SDimitry Andric return this->emitZeroSint16(E); 1907a7dea167SDimitry Andric case PT_Uint16: 1908a7dea167SDimitry Andric return this->emitZeroUint16(E); 1909a7dea167SDimitry Andric case PT_Sint32: 1910a7dea167SDimitry Andric return this->emitZeroSint32(E); 1911a7dea167SDimitry Andric case PT_Uint32: 1912a7dea167SDimitry Andric return this->emitZeroUint32(E); 1913a7dea167SDimitry Andric case PT_Sint64: 1914a7dea167SDimitry Andric return this->emitZeroSint64(E); 1915a7dea167SDimitry Andric case PT_Uint64: 1916a7dea167SDimitry Andric return this->emitZeroUint64(E); 1917*c9157d92SDimitry Andric case PT_IntAP: 1918*c9157d92SDimitry Andric return this->emitZeroIntAP(Ctx.getBitWidth(QT), E); 1919*c9157d92SDimitry Andric case PT_IntAPS: 1920*c9157d92SDimitry Andric return this->emitZeroIntAPS(Ctx.getBitWidth(QT), E); 1921a7dea167SDimitry Andric case PT_Ptr: 1922a7dea167SDimitry Andric return this->emitNullPtr(E); 1923fe013be4SDimitry Andric case PT_FnPtr: 1924fe013be4SDimitry Andric return this->emitNullFnPtr(E); 1925fe013be4SDimitry Andric case PT_Float: { 1926fe013be4SDimitry Andric return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E); 1927fe013be4SDimitry Andric } 1928a7dea167SDimitry Andric } 1929a7dea167SDimitry Andric llvm_unreachable("unknown primitive type"); 1930a7dea167SDimitry Andric } 1931a7dea167SDimitry Andric 1932a7dea167SDimitry Andric template <class Emitter> 1933*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitZeroRecordInitializer(const Record *R, 1934*c9157d92SDimitry Andric const Expr *E) { 1935*c9157d92SDimitry Andric assert(E); 1936*c9157d92SDimitry Andric assert(R); 1937*c9157d92SDimitry Andric // Fields 1938*c9157d92SDimitry Andric for (const Record::Field &Field : R->fields()) { 1939*c9157d92SDimitry Andric const Descriptor *D = Field.Desc; 1940*c9157d92SDimitry Andric if (D->isPrimitive()) { 1941*c9157d92SDimitry Andric QualType QT = D->getType(); 1942*c9157d92SDimitry Andric PrimType T = classifyPrim(D->getType()); 1943*c9157d92SDimitry Andric if (!this->visitZeroInitializer(T, QT, E)) 1944*c9157d92SDimitry Andric return false; 1945*c9157d92SDimitry Andric if (!this->emitInitField(T, Field.Offset, E)) 1946*c9157d92SDimitry Andric return false; 1947*c9157d92SDimitry Andric continue; 1948*c9157d92SDimitry Andric } 1949*c9157d92SDimitry Andric 1950*c9157d92SDimitry Andric // TODO: Add GetPtrFieldPop and get rid of this dup. 1951*c9157d92SDimitry Andric if (!this->emitDupPtr(E)) 1952*c9157d92SDimitry Andric return false; 1953*c9157d92SDimitry Andric if (!this->emitGetPtrField(Field.Offset, E)) 1954*c9157d92SDimitry Andric return false; 1955*c9157d92SDimitry Andric 1956*c9157d92SDimitry Andric if (D->isPrimitiveArray()) { 1957*c9157d92SDimitry Andric QualType ET = D->getElemQualType(); 1958*c9157d92SDimitry Andric PrimType T = classifyPrim(ET); 1959*c9157d92SDimitry Andric for (uint32_t I = 0, N = D->getNumElems(); I != N; ++I) { 1960*c9157d92SDimitry Andric if (!this->visitZeroInitializer(T, ET, E)) 1961*c9157d92SDimitry Andric return false; 1962*c9157d92SDimitry Andric if (!this->emitInitElem(T, I, E)) 1963*c9157d92SDimitry Andric return false; 1964*c9157d92SDimitry Andric } 1965*c9157d92SDimitry Andric } else if (D->isCompositeArray()) { 1966*c9157d92SDimitry Andric const Record *ElemRecord = D->ElemDesc->ElemRecord; 1967*c9157d92SDimitry Andric assert(D->ElemDesc->ElemRecord); 1968*c9157d92SDimitry Andric for (uint32_t I = 0, N = D->getNumElems(); I != N; ++I) { 1969*c9157d92SDimitry Andric if (!this->emitConstUint32(I, E)) 1970*c9157d92SDimitry Andric return false; 1971*c9157d92SDimitry Andric if (!this->emitArrayElemPtr(PT_Uint32, E)) 1972*c9157d92SDimitry Andric return false; 1973*c9157d92SDimitry Andric if (!this->visitZeroRecordInitializer(ElemRecord, E)) 1974*c9157d92SDimitry Andric return false; 1975*c9157d92SDimitry Andric if (!this->emitPopPtr(E)) 1976*c9157d92SDimitry Andric return false; 1977*c9157d92SDimitry Andric } 1978*c9157d92SDimitry Andric } else if (D->isRecord()) { 1979*c9157d92SDimitry Andric if (!this->visitZeroRecordInitializer(D->ElemRecord, E)) 1980*c9157d92SDimitry Andric return false; 1981*c9157d92SDimitry Andric } else { 1982*c9157d92SDimitry Andric assert(false); 1983*c9157d92SDimitry Andric } 1984*c9157d92SDimitry Andric 1985*c9157d92SDimitry Andric if (!this->emitPopPtr(E)) 1986*c9157d92SDimitry Andric return false; 1987*c9157d92SDimitry Andric } 1988*c9157d92SDimitry Andric 1989*c9157d92SDimitry Andric for (const Record::Base &B : R->bases()) { 1990*c9157d92SDimitry Andric if (!this->emitGetPtrBase(B.Offset, E)) 1991*c9157d92SDimitry Andric return false; 1992*c9157d92SDimitry Andric if (!this->visitZeroRecordInitializer(B.R, E)) 1993*c9157d92SDimitry Andric return false; 1994*c9157d92SDimitry Andric if (!this->emitInitPtrPop(E)) 1995*c9157d92SDimitry Andric return false; 1996*c9157d92SDimitry Andric } 1997*c9157d92SDimitry Andric 1998*c9157d92SDimitry Andric // FIXME: Virtual bases. 1999*c9157d92SDimitry Andric 2000*c9157d92SDimitry Andric return true; 2001*c9157d92SDimitry Andric } 2002*c9157d92SDimitry Andric 2003*c9157d92SDimitry Andric template <class Emitter> 2004a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereference( 2005a7dea167SDimitry Andric const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct, 2006a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 2007bdd1243dSDimitry Andric if (std::optional<PrimType> T = classify(LV->getType())) { 2008a7dea167SDimitry Andric if (!LV->refersToBitField()) { 2009a7dea167SDimitry Andric // Only primitive, non bit-field types can be dereferenced directly. 2010fe013be4SDimitry Andric if (const auto *DE = dyn_cast<DeclRefExpr>(LV)) { 2011a7dea167SDimitry Andric if (!DE->getDecl()->getType()->isReferenceType()) { 2012fe013be4SDimitry Andric if (const auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl())) 2013a7dea167SDimitry Andric return dereferenceParam(LV, *T, PD, AK, Direct, Indirect); 2014fe013be4SDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(DE->getDecl())) 2015a7dea167SDimitry Andric return dereferenceVar(LV, *T, VD, AK, Direct, Indirect); 2016a7dea167SDimitry Andric } 2017a7dea167SDimitry Andric } 2018a7dea167SDimitry Andric } 2019a7dea167SDimitry Andric 2020a7dea167SDimitry Andric if (!visit(LV)) 2021a7dea167SDimitry Andric return false; 2022a7dea167SDimitry Andric return Indirect(*T); 2023a7dea167SDimitry Andric } 2024a7dea167SDimitry Andric 2025*c9157d92SDimitry Andric if (LV->getType()->isAnyComplexType()) 2026*c9157d92SDimitry Andric return visit(LV); 2027*c9157d92SDimitry Andric 2028a7dea167SDimitry Andric return false; 2029a7dea167SDimitry Andric } 2030a7dea167SDimitry Andric 2031a7dea167SDimitry Andric template <class Emitter> 2032a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceParam( 2033a7dea167SDimitry Andric const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK, 2034a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Direct, 2035a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 2036a7dea167SDimitry Andric auto It = this->Params.find(PD); 2037a7dea167SDimitry Andric if (It != this->Params.end()) { 2038*c9157d92SDimitry Andric unsigned Idx = It->second.Offset; 2039a7dea167SDimitry Andric switch (AK) { 2040a7dea167SDimitry Andric case DerefKind::Read: 2041a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetParam(T, Idx, LV); 2042a7dea167SDimitry Andric 2043a7dea167SDimitry Andric case DerefKind::Write: 2044a7dea167SDimitry Andric if (!Direct(T)) 2045a7dea167SDimitry Andric return false; 2046a7dea167SDimitry Andric if (!this->emitSetParam(T, Idx, LV)) 2047a7dea167SDimitry Andric return false; 2048a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 2049a7dea167SDimitry Andric 2050a7dea167SDimitry Andric case DerefKind::ReadWrite: 2051a7dea167SDimitry Andric if (!this->emitGetParam(T, Idx, LV)) 2052a7dea167SDimitry Andric return false; 2053a7dea167SDimitry Andric if (!Direct(T)) 2054a7dea167SDimitry Andric return false; 2055a7dea167SDimitry Andric if (!this->emitSetParam(T, Idx, LV)) 2056a7dea167SDimitry Andric return false; 2057a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrParam(Idx, LV); 2058a7dea167SDimitry Andric } 2059a7dea167SDimitry Andric return true; 2060a7dea167SDimitry Andric } 2061a7dea167SDimitry Andric 2062a7dea167SDimitry Andric // If the param is a pointer, we can dereference a dummy value. 2063a7dea167SDimitry Andric if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) { 2064a7dea167SDimitry Andric if (auto Idx = P.getOrCreateDummy(PD)) 2065a7dea167SDimitry Andric return this->emitGetPtrGlobal(*Idx, PD); 2066a7dea167SDimitry Andric return false; 2067a7dea167SDimitry Andric } 2068a7dea167SDimitry Andric 2069a7dea167SDimitry Andric // Value cannot be produced - try to emit pointer and do stuff with it. 2070a7dea167SDimitry Andric return visit(LV) && Indirect(T); 2071a7dea167SDimitry Andric } 2072a7dea167SDimitry Andric 2073a7dea167SDimitry Andric template <class Emitter> 2074a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceVar( 2075a7dea167SDimitry Andric const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK, 2076a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Direct, 2077a7dea167SDimitry Andric llvm::function_ref<bool(PrimType)> Indirect) { 2078a7dea167SDimitry Andric auto It = Locals.find(VD); 2079a7dea167SDimitry Andric if (It != Locals.end()) { 2080a7dea167SDimitry Andric const auto &L = It->second; 2081a7dea167SDimitry Andric switch (AK) { 2082a7dea167SDimitry Andric case DerefKind::Read: 2083a7dea167SDimitry Andric if (!this->emitGetLocal(T, L.Offset, LV)) 2084a7dea167SDimitry Andric return false; 2085a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, LV) : true; 2086a7dea167SDimitry Andric 2087a7dea167SDimitry Andric case DerefKind::Write: 2088a7dea167SDimitry Andric if (!Direct(T)) 2089a7dea167SDimitry Andric return false; 2090a7dea167SDimitry Andric if (!this->emitSetLocal(T, L.Offset, LV)) 2091a7dea167SDimitry Andric return false; 2092a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 2093a7dea167SDimitry Andric 2094a7dea167SDimitry Andric case DerefKind::ReadWrite: 2095a7dea167SDimitry Andric if (!this->emitGetLocal(T, L.Offset, LV)) 2096a7dea167SDimitry Andric return false; 2097a7dea167SDimitry Andric if (!Direct(T)) 2098a7dea167SDimitry Andric return false; 2099a7dea167SDimitry Andric if (!this->emitSetLocal(T, L.Offset, LV)) 2100a7dea167SDimitry Andric return false; 2101a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV); 2102a7dea167SDimitry Andric } 2103bdd1243dSDimitry Andric } else if (auto Idx = P.getGlobal(VD)) { 2104a7dea167SDimitry Andric switch (AK) { 2105a7dea167SDimitry Andric case DerefKind::Read: 2106a7dea167SDimitry Andric if (!this->emitGetGlobal(T, *Idx, LV)) 2107a7dea167SDimitry Andric return false; 2108a7dea167SDimitry Andric return DiscardResult ? this->emitPop(T, LV) : true; 2109a7dea167SDimitry Andric 2110a7dea167SDimitry Andric case DerefKind::Write: 2111a7dea167SDimitry Andric if (!Direct(T)) 2112a7dea167SDimitry Andric return false; 2113a7dea167SDimitry Andric if (!this->emitSetGlobal(T, *Idx, LV)) 2114a7dea167SDimitry Andric return false; 2115a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 2116a7dea167SDimitry Andric 2117a7dea167SDimitry Andric case DerefKind::ReadWrite: 2118a7dea167SDimitry Andric if (!this->emitGetGlobal(T, *Idx, LV)) 2119a7dea167SDimitry Andric return false; 2120a7dea167SDimitry Andric if (!Direct(T)) 2121a7dea167SDimitry Andric return false; 2122a7dea167SDimitry Andric if (!this->emitSetGlobal(T, *Idx, LV)) 2123a7dea167SDimitry Andric return false; 2124a7dea167SDimitry Andric return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV); 2125a7dea167SDimitry Andric } 2126a7dea167SDimitry Andric } 2127a7dea167SDimitry Andric 2128a7dea167SDimitry Andric // If the declaration is a constant value, emit it here even 2129a7dea167SDimitry Andric // though the declaration was not evaluated in the current scope. 2130a7dea167SDimitry Andric // The access mode can only be read in this case. 2131a7dea167SDimitry Andric if (!DiscardResult && AK == DerefKind::Read) { 2132a7dea167SDimitry Andric if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) { 2133a7dea167SDimitry Andric QualType VT = VD->getType(); 2134a7dea167SDimitry Andric if (VT.isConstQualified() && VT->isFundamentalType()) 2135bdd1243dSDimitry Andric return this->visit(VD->getInit()); 2136a7dea167SDimitry Andric } 2137a7dea167SDimitry Andric } 2138a7dea167SDimitry Andric 2139a7dea167SDimitry Andric // Value cannot be produced - try to emit pointer. 2140a7dea167SDimitry Andric return visit(LV) && Indirect(T); 2141a7dea167SDimitry Andric } 2142a7dea167SDimitry Andric 2143a7dea167SDimitry Andric template <class Emitter> 2144bdd1243dSDimitry Andric template <typename T> 2145*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) { 2146*c9157d92SDimitry Andric switch (Ty) { 2147a7dea167SDimitry Andric case PT_Sint8: 2148bdd1243dSDimitry Andric return this->emitConstSint8(Value, E); 2149a7dea167SDimitry Andric case PT_Uint8: 2150bdd1243dSDimitry Andric return this->emitConstUint8(Value, E); 2151a7dea167SDimitry Andric case PT_Sint16: 2152bdd1243dSDimitry Andric return this->emitConstSint16(Value, E); 2153a7dea167SDimitry Andric case PT_Uint16: 2154bdd1243dSDimitry Andric return this->emitConstUint16(Value, E); 2155a7dea167SDimitry Andric case PT_Sint32: 2156bdd1243dSDimitry Andric return this->emitConstSint32(Value, E); 2157a7dea167SDimitry Andric case PT_Uint32: 2158bdd1243dSDimitry Andric return this->emitConstUint32(Value, E); 2159a7dea167SDimitry Andric case PT_Sint64: 2160bdd1243dSDimitry Andric return this->emitConstSint64(Value, E); 2161a7dea167SDimitry Andric case PT_Uint64: 2162bdd1243dSDimitry Andric return this->emitConstUint64(Value, E); 2163*c9157d92SDimitry Andric case PT_IntAP: 2164*c9157d92SDimitry Andric case PT_IntAPS: 2165*c9157d92SDimitry Andric assert(false); 2166*c9157d92SDimitry Andric return false; 2167a7dea167SDimitry Andric case PT_Bool: 2168bdd1243dSDimitry Andric return this->emitConstBool(Value, E); 2169a7dea167SDimitry Andric case PT_Ptr: 2170fe013be4SDimitry Andric case PT_FnPtr: 2171fe013be4SDimitry Andric case PT_Float: 2172a7dea167SDimitry Andric llvm_unreachable("Invalid integral type"); 2173a7dea167SDimitry Andric break; 2174a7dea167SDimitry Andric } 2175a7dea167SDimitry Andric llvm_unreachable("unknown primitive type"); 2176a7dea167SDimitry Andric } 2177a7dea167SDimitry Andric 2178a7dea167SDimitry Andric template <class Emitter> 2179*c9157d92SDimitry Andric template <typename T> 2180*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(T Value, const Expr *E) { 2181*c9157d92SDimitry Andric return this->emitConst(Value, classifyPrim(E->getType()), E); 2182*c9157d92SDimitry Andric } 2183*c9157d92SDimitry Andric 2184*c9157d92SDimitry Andric template <class Emitter> 2185*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, PrimType Ty, 2186*c9157d92SDimitry Andric const Expr *E) { 2187bdd1243dSDimitry Andric if (Value.isSigned()) 2188*c9157d92SDimitry Andric return this->emitConst(Value.getSExtValue(), Ty, E); 2189*c9157d92SDimitry Andric return this->emitConst(Value.getZExtValue(), Ty, E); 2190*c9157d92SDimitry Andric } 2191*c9157d92SDimitry Andric 2192*c9157d92SDimitry Andric template <class Emitter> 2193*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, const Expr *E) { 2194*c9157d92SDimitry Andric return this->emitConst(Value, classifyPrim(E->getType()), E); 2195bdd1243dSDimitry Andric } 2196bdd1243dSDimitry Andric 2197bdd1243dSDimitry Andric template <class Emitter> 2198a7dea167SDimitry Andric unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src, 2199a7dea167SDimitry Andric PrimType Ty, 2200a7dea167SDimitry Andric bool IsConst, 2201a7dea167SDimitry Andric bool IsExtended) { 2202bdd1243dSDimitry Andric // Make sure we don't accidentally register the same decl twice. 2203bdd1243dSDimitry Andric if (const auto *VD = 2204bdd1243dSDimitry Andric dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { 2205bdd1243dSDimitry Andric assert(!P.getGlobal(VD)); 2206fe013be4SDimitry Andric assert(!Locals.contains(VD)); 2207bdd1243dSDimitry Andric } 2208bdd1243dSDimitry Andric 2209bdd1243dSDimitry Andric // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g. 2210bdd1243dSDimitry Andric // (int){12} in C. Consider using Expr::isTemporaryObject() instead 2211bdd1243dSDimitry Andric // or isa<MaterializeTemporaryExpr>(). 2212bdd1243dSDimitry Andric Descriptor *D = P.createDescriptor(Src, Ty, Descriptor::InlineDescMD, IsConst, 2213bdd1243dSDimitry Andric Src.is<const Expr *>()); 2214a7dea167SDimitry Andric Scope::Local Local = this->createLocal(D); 2215fe013be4SDimitry Andric if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) 2216a7dea167SDimitry Andric Locals.insert({VD, Local}); 2217a7dea167SDimitry Andric VarScope->add(Local, IsExtended); 2218a7dea167SDimitry Andric return Local.Offset; 2219a7dea167SDimitry Andric } 2220a7dea167SDimitry Andric 2221a7dea167SDimitry Andric template <class Emitter> 2222bdd1243dSDimitry Andric std::optional<unsigned> 2223a7dea167SDimitry Andric ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) { 2224bdd1243dSDimitry Andric // Make sure we don't accidentally register the same decl twice. 2225*c9157d92SDimitry Andric if ([[maybe_unused]] const auto *VD = 2226bdd1243dSDimitry Andric dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { 2227bdd1243dSDimitry Andric assert(!P.getGlobal(VD)); 2228fe013be4SDimitry Andric assert(!Locals.contains(VD)); 2229bdd1243dSDimitry Andric } 2230a7dea167SDimitry Andric 2231bdd1243dSDimitry Andric QualType Ty; 2232a7dea167SDimitry Andric const ValueDecl *Key = nullptr; 2233bdd1243dSDimitry Andric const Expr *Init = nullptr; 2234a7dea167SDimitry Andric bool IsTemporary = false; 2235bdd1243dSDimitry Andric if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) { 2236a7dea167SDimitry Andric Key = VD; 2237a7dea167SDimitry Andric Ty = VD->getType(); 2238bdd1243dSDimitry Andric 2239bdd1243dSDimitry Andric if (const auto *VarD = dyn_cast<VarDecl>(VD)) 2240bdd1243dSDimitry Andric Init = VarD->getInit(); 2241a7dea167SDimitry Andric } 2242a7dea167SDimitry Andric if (auto *E = Src.dyn_cast<const Expr *>()) { 2243a7dea167SDimitry Andric IsTemporary = true; 2244a7dea167SDimitry Andric Ty = E->getType(); 2245a7dea167SDimitry Andric } 2246a7dea167SDimitry Andric 2247bdd1243dSDimitry Andric Descriptor *D = P.createDescriptor( 2248bdd1243dSDimitry Andric Src, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(), 2249bdd1243dSDimitry Andric IsTemporary, /*IsMutable=*/false, Init); 2250a7dea167SDimitry Andric if (!D) 2251a7dea167SDimitry Andric return {}; 2252a7dea167SDimitry Andric 2253a7dea167SDimitry Andric Scope::Local Local = this->createLocal(D); 2254a7dea167SDimitry Andric if (Key) 2255a7dea167SDimitry Andric Locals.insert({Key, Local}); 2256a7dea167SDimitry Andric VarScope->add(Local, IsExtended); 2257a7dea167SDimitry Andric return Local.Offset; 2258a7dea167SDimitry Andric } 2259a7dea167SDimitry Andric 2260a7dea167SDimitry Andric template <class Emitter> 2261a7dea167SDimitry Andric const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) { 2262753f127fSDimitry Andric if (const PointerType *PT = dyn_cast<PointerType>(Ty)) 2263a7dea167SDimitry Andric return PT->getPointeeType()->getAs<RecordType>(); 2264a7dea167SDimitry Andric return Ty->getAs<RecordType>(); 2265a7dea167SDimitry Andric } 2266a7dea167SDimitry Andric 2267a7dea167SDimitry Andric template <class Emitter> 2268a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) { 2269*c9157d92SDimitry Andric if (const auto *RecordTy = getRecordTy(Ty)) 2270a7dea167SDimitry Andric return getRecord(RecordTy->getDecl()); 2271a7dea167SDimitry Andric return nullptr; 2272a7dea167SDimitry Andric } 2273a7dea167SDimitry Andric 2274a7dea167SDimitry Andric template <class Emitter> 2275a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) { 2276a7dea167SDimitry Andric return P.getOrCreateRecord(RD); 2277a7dea167SDimitry Andric } 2278a7dea167SDimitry Andric 2279a7dea167SDimitry Andric template <class Emitter> 2280bdd1243dSDimitry Andric const Function *ByteCodeExprGen<Emitter>::getFunction(const FunctionDecl *FD) { 2281*c9157d92SDimitry Andric return Ctx.getOrCreateFunction(FD); 2282bdd1243dSDimitry Andric } 2283bdd1243dSDimitry Andric 2284bdd1243dSDimitry Andric template <class Emitter> 2285*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *E) { 2286a7dea167SDimitry Andric ExprScope<Emitter> RootScope(this); 2287*c9157d92SDimitry Andric // Void expressions. 2288*c9157d92SDimitry Andric if (E->getType()->isVoidType()) { 2289*c9157d92SDimitry Andric if (!visit(E)) 2290*c9157d92SDimitry Andric return false; 2291*c9157d92SDimitry Andric return this->emitRetVoid(E); 2292*c9157d92SDimitry Andric } 2293*c9157d92SDimitry Andric 2294*c9157d92SDimitry Andric // Expressions with a primitive return type. 2295*c9157d92SDimitry Andric if (std::optional<PrimType> T = classify(E)) { 2296*c9157d92SDimitry Andric if (!visit(E)) 2297*c9157d92SDimitry Andric return false; 2298*c9157d92SDimitry Andric return this->emitRet(*T, E); 2299*c9157d92SDimitry Andric } 2300*c9157d92SDimitry Andric 2301*c9157d92SDimitry Andric // Expressions with a composite return type. 2302*c9157d92SDimitry Andric // For us, that means everything we don't 2303*c9157d92SDimitry Andric // have a PrimType for. 2304*c9157d92SDimitry Andric if (std::optional<unsigned> LocalOffset = this->allocateLocal(E)) { 2305*c9157d92SDimitry Andric if (!this->visitLocalInitializer(E, *LocalOffset)) 2306a7dea167SDimitry Andric return false; 2307a7dea167SDimitry Andric 2308*c9157d92SDimitry Andric if (!this->emitGetPtrLocal(*LocalOffset, E)) 2309*c9157d92SDimitry Andric return false; 2310*c9157d92SDimitry Andric return this->emitRetValue(E); 2311*c9157d92SDimitry Andric } 2312*c9157d92SDimitry Andric 2313*c9157d92SDimitry Andric return false; 2314a7dea167SDimitry Andric } 2315a7dea167SDimitry Andric 2316bdd1243dSDimitry Andric /// Toplevel visitDecl(). 2317bdd1243dSDimitry Andric /// We get here from evaluateAsInitializer(). 2318bdd1243dSDimitry Andric /// We need to evaluate the initializer and return its value. 2319a7dea167SDimitry Andric template <class Emitter> 2320a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) { 2321fe013be4SDimitry Andric assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl"); 2322a7dea167SDimitry Andric 2323bdd1243dSDimitry Andric // Create and initialize the variable. 2324bdd1243dSDimitry Andric if (!this->visitVarDecl(VD)) 2325a7dea167SDimitry Andric return false; 2326a7dea167SDimitry Andric 2327*c9157d92SDimitry Andric std::optional<PrimType> VarT = classify(VD->getType()); 2328bdd1243dSDimitry Andric // Get a pointer to the variable 2329fe013be4SDimitry Andric if (Context::shouldBeGloballyIndexed(VD)) { 2330bdd1243dSDimitry Andric auto GlobalIndex = P.getGlobal(VD); 2331bdd1243dSDimitry Andric assert(GlobalIndex); // visitVarDecl() didn't return false. 2332*c9157d92SDimitry Andric if (VarT) { 2333*c9157d92SDimitry Andric if (!this->emitGetGlobal(*VarT, *GlobalIndex, VD)) 2334*c9157d92SDimitry Andric return false; 2335*c9157d92SDimitry Andric } else { 2336bdd1243dSDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, VD)) 2337a7dea167SDimitry Andric return false; 2338*c9157d92SDimitry Andric } 2339a7dea167SDimitry Andric } else { 2340bdd1243dSDimitry Andric auto Local = Locals.find(VD); 2341bdd1243dSDimitry Andric assert(Local != Locals.end()); // Same here. 2342*c9157d92SDimitry Andric if (VarT) { 2343*c9157d92SDimitry Andric if (!this->emitGetLocal(*VarT, Local->second.Offset, VD)) 2344*c9157d92SDimitry Andric return false; 2345*c9157d92SDimitry Andric } else { 2346bdd1243dSDimitry Andric if (!this->emitGetPtrLocal(Local->second.Offset, VD)) 2347a7dea167SDimitry Andric return false; 2348a7dea167SDimitry Andric } 2349bdd1243dSDimitry Andric } 2350bdd1243dSDimitry Andric 2351*c9157d92SDimitry Andric // Return the value 2352*c9157d92SDimitry Andric if (VarT) 2353*c9157d92SDimitry Andric return this->emitRet(*VarT, VD); 2354a7dea167SDimitry Andric return this->emitRetValue(VD); 2355a7dea167SDimitry Andric } 2356bdd1243dSDimitry Andric 2357bdd1243dSDimitry Andric template <class Emitter> 2358bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) { 2359fe013be4SDimitry Andric // We don't know what to do with these, so just return false. 2360fe013be4SDimitry Andric if (VD->getType().isNull()) 2361fe013be4SDimitry Andric return false; 2362fe013be4SDimitry Andric 2363bdd1243dSDimitry Andric const Expr *Init = VD->getInit(); 2364bdd1243dSDimitry Andric std::optional<PrimType> VarT = classify(VD->getType()); 2365bdd1243dSDimitry Andric 2366fe013be4SDimitry Andric if (Context::shouldBeGloballyIndexed(VD)) { 2367fe013be4SDimitry Andric // We've already seen and initialized this global. 2368fe013be4SDimitry Andric if (P.getGlobal(VD)) 2369fe013be4SDimitry Andric return true; 2370fe013be4SDimitry Andric 2371fe013be4SDimitry Andric std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init); 2372bdd1243dSDimitry Andric 2373bdd1243dSDimitry Andric if (!GlobalIndex) 2374bdd1243dSDimitry Andric return this->bail(VD); 2375bdd1243dSDimitry Andric 2376bdd1243dSDimitry Andric assert(Init); 2377bdd1243dSDimitry Andric { 2378bdd1243dSDimitry Andric DeclScope<Emitter> LocalScope(this, VD); 2379bdd1243dSDimitry Andric 2380bdd1243dSDimitry Andric if (VarT) { 2381bdd1243dSDimitry Andric if (!this->visit(Init)) 2382bdd1243dSDimitry Andric return false; 2383bdd1243dSDimitry Andric return this->emitInitGlobal(*VarT, *GlobalIndex, VD); 2384bdd1243dSDimitry Andric } 2385bdd1243dSDimitry Andric return this->visitGlobalInitializer(Init, *GlobalIndex); 2386bdd1243dSDimitry Andric } 2387bdd1243dSDimitry Andric } else { 2388bdd1243dSDimitry Andric VariableScope<Emitter> LocalScope(this); 2389bdd1243dSDimitry Andric if (VarT) { 2390bdd1243dSDimitry Andric unsigned Offset = this->allocateLocalPrimitive( 2391bdd1243dSDimitry Andric VD, *VarT, VD->getType().isConstQualified()); 2392bdd1243dSDimitry Andric if (Init) { 2393bdd1243dSDimitry Andric // Compile the initializer in its own scope. 2394bdd1243dSDimitry Andric ExprScope<Emitter> Scope(this); 2395bdd1243dSDimitry Andric if (!this->visit(Init)) 2396bdd1243dSDimitry Andric return false; 2397bdd1243dSDimitry Andric 2398bdd1243dSDimitry Andric return this->emitSetLocal(*VarT, Offset, VD); 2399bdd1243dSDimitry Andric } 2400bdd1243dSDimitry Andric } else { 2401bdd1243dSDimitry Andric if (std::optional<unsigned> Offset = this->allocateLocal(VD)) { 2402bdd1243dSDimitry Andric if (Init) 2403bdd1243dSDimitry Andric return this->visitLocalInitializer(Init, *Offset); 2404bdd1243dSDimitry Andric } 2405bdd1243dSDimitry Andric } 2406bdd1243dSDimitry Andric return true; 2407a7dea167SDimitry Andric } 2408a7dea167SDimitry Andric 2409bdd1243dSDimitry Andric return false; 2410bdd1243dSDimitry Andric } 2411bdd1243dSDimitry Andric 2412bdd1243dSDimitry Andric template <class Emitter> 2413*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val, 2414*c9157d92SDimitry Andric PrimType ValType, const Expr *E) { 2415*c9157d92SDimitry Andric assert(!DiscardResult); 2416*c9157d92SDimitry Andric if (Val.isInt()) 2417*c9157d92SDimitry Andric return this->emitConst(Val.getInt(), ValType, E); 2418*c9157d92SDimitry Andric 2419*c9157d92SDimitry Andric if (Val.isLValue()) { 2420*c9157d92SDimitry Andric APValue::LValueBase Base = Val.getLValueBase(); 2421*c9157d92SDimitry Andric if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>()) 2422*c9157d92SDimitry Andric return this->visit(BaseExpr); 2423*c9157d92SDimitry Andric } 2424*c9157d92SDimitry Andric 2425*c9157d92SDimitry Andric return false; 2426*c9157d92SDimitry Andric } 2427*c9157d92SDimitry Andric 2428*c9157d92SDimitry Andric template <class Emitter> 2429fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) { 2430fe013be4SDimitry Andric const Function *Func = getFunction(E->getDirectCallee()); 2431bdd1243dSDimitry Andric if (!Func) 2432bdd1243dSDimitry Andric return false; 2433fe013be4SDimitry Andric 2434*c9157d92SDimitry Andric if (!Func->isUnevaluatedBuiltin()) { 2435fe013be4SDimitry Andric // Put arguments on the stack. 2436fe013be4SDimitry Andric for (const auto *Arg : E->arguments()) { 2437fe013be4SDimitry Andric if (!this->visit(Arg)) 2438fe013be4SDimitry Andric return false; 2439fe013be4SDimitry Andric } 2440*c9157d92SDimitry Andric } 2441fe013be4SDimitry Andric 2442*c9157d92SDimitry Andric if (!this->emitCallBI(Func, E, E)) 2443bdd1243dSDimitry Andric return false; 2444bdd1243dSDimitry Andric 2445bdd1243dSDimitry Andric QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); 2446fe013be4SDimitry Andric if (DiscardResult && !ReturnType->isVoidType()) { 2447fe013be4SDimitry Andric PrimType T = classifyPrim(ReturnType); 2448fe013be4SDimitry Andric return this->emitPop(T, E); 2449fe013be4SDimitry Andric } 2450bdd1243dSDimitry Andric 2451fe013be4SDimitry Andric return true; 2452fe013be4SDimitry Andric } 2453fe013be4SDimitry Andric 2454fe013be4SDimitry Andric template <class Emitter> 2455fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) { 2456fe013be4SDimitry Andric if (E->getBuiltinCallee()) 2457fe013be4SDimitry Andric return VisitBuiltinCallExpr(E); 2458fe013be4SDimitry Andric 2459fe013be4SDimitry Andric QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); 2460fe013be4SDimitry Andric std::optional<PrimType> T = classify(ReturnType); 2461fe013be4SDimitry Andric bool HasRVO = !ReturnType->isVoidType() && !T; 2462fe013be4SDimitry Andric 2463*c9157d92SDimitry Andric if (HasRVO) { 2464*c9157d92SDimitry Andric if (DiscardResult) { 2465bdd1243dSDimitry Andric // If we need to discard the return value but the function returns its 2466bdd1243dSDimitry Andric // value via an RVO pointer, we need to create one such pointer just 2467bdd1243dSDimitry Andric // for this call. 2468bdd1243dSDimitry Andric if (std::optional<unsigned> LocalIndex = allocateLocal(E)) { 2469bdd1243dSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E)) 2470bdd1243dSDimitry Andric return false; 2471bdd1243dSDimitry Andric } 2472*c9157d92SDimitry Andric } else { 2473*c9157d92SDimitry Andric assert(Initializing); 2474*c9157d92SDimitry Andric if (!this->emitDupPtr(E)) 2475*c9157d92SDimitry Andric return false; 2476*c9157d92SDimitry Andric } 2477*c9157d92SDimitry Andric } 2478*c9157d92SDimitry Andric 2479*c9157d92SDimitry Andric // Add the (optional, implicit) This pointer. 2480*c9157d92SDimitry Andric if (const auto *MC = dyn_cast<CXXMemberCallExpr>(E)) { 2481*c9157d92SDimitry Andric if (!this->visit(MC->getImplicitObjectArgument())) 2482*c9157d92SDimitry Andric return false; 2483bdd1243dSDimitry Andric } 2484bdd1243dSDimitry Andric 2485bdd1243dSDimitry Andric // Put arguments on the stack. 2486bdd1243dSDimitry Andric for (const auto *Arg : E->arguments()) { 2487bdd1243dSDimitry Andric if (!this->visit(Arg)) 2488bdd1243dSDimitry Andric return false; 2489bdd1243dSDimitry Andric } 2490bdd1243dSDimitry Andric 2491fe013be4SDimitry Andric if (const FunctionDecl *FuncDecl = E->getDirectCallee()) { 2492fe013be4SDimitry Andric const Function *Func = getFunction(FuncDecl); 2493fe013be4SDimitry Andric if (!Func) 2494fe013be4SDimitry Andric return false; 2495fe013be4SDimitry Andric // If the function is being compiled right now, this is a recursive call. 2496fe013be4SDimitry Andric // In that case, the function can't be valid yet, even though it will be 2497fe013be4SDimitry Andric // later. 2498fe013be4SDimitry Andric // If the function is already fully compiled but not constexpr, it was 2499fe013be4SDimitry Andric // found to be faulty earlier on, so bail out. 2500fe013be4SDimitry Andric if (Func->isFullyCompiled() && !Func->isConstexpr()) 2501bdd1243dSDimitry Andric return false; 2502bdd1243dSDimitry Andric 2503fe013be4SDimitry Andric assert(HasRVO == Func->hasRVO()); 2504fe013be4SDimitry Andric 2505fe013be4SDimitry Andric bool HasQualifier = false; 2506fe013be4SDimitry Andric if (const auto *ME = dyn_cast<MemberExpr>(E->getCallee())) 2507fe013be4SDimitry Andric HasQualifier = ME->hasQualifier(); 2508fe013be4SDimitry Andric 2509fe013be4SDimitry Andric bool IsVirtual = false; 2510fe013be4SDimitry Andric if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl)) 2511fe013be4SDimitry Andric IsVirtual = MD->isVirtual(); 2512fe013be4SDimitry Andric 2513fe013be4SDimitry Andric // In any case call the function. The return value will end up on the stack 2514fe013be4SDimitry Andric // and if the function has RVO, we already have the pointer on the stack to 2515fe013be4SDimitry Andric // write the result into. 2516fe013be4SDimitry Andric if (IsVirtual && !HasQualifier) { 2517fe013be4SDimitry Andric if (!this->emitCallVirt(Func, E)) 2518fe013be4SDimitry Andric return false; 2519fe013be4SDimitry Andric } else { 2520fe013be4SDimitry Andric if (!this->emitCall(Func, E)) 2521fe013be4SDimitry Andric return false; 2522fe013be4SDimitry Andric } 2523fe013be4SDimitry Andric } else { 2524fe013be4SDimitry Andric // Indirect call. Visit the callee, which will leave a FunctionPointer on 2525fe013be4SDimitry Andric // the stack. Cleanup of the returned value if necessary will be done after 2526fe013be4SDimitry Andric // the function call completed. 2527fe013be4SDimitry Andric if (!this->visit(E->getCallee())) 2528fe013be4SDimitry Andric return false; 2529fe013be4SDimitry Andric 2530fe013be4SDimitry Andric if (!this->emitCallPtr(E)) 2531fe013be4SDimitry Andric return false; 2532fe013be4SDimitry Andric } 2533fe013be4SDimitry Andric 2534fe013be4SDimitry Andric // Cleanup for discarded return values. 2535bdd1243dSDimitry Andric if (DiscardResult && !ReturnType->isVoidType() && T) 2536bdd1243dSDimitry Andric return this->emitPop(*T, E); 2537bdd1243dSDimitry Andric 2538bdd1243dSDimitry Andric return true; 2539bdd1243dSDimitry Andric } 2540bdd1243dSDimitry Andric 2541bdd1243dSDimitry Andric template <class Emitter> 2542bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultInitExpr( 2543bdd1243dSDimitry Andric const CXXDefaultInitExpr *E) { 2544*c9157d92SDimitry Andric SourceLocScope<Emitter> SLS(this, E); 2545*c9157d92SDimitry Andric if (Initializing) 2546*c9157d92SDimitry Andric return this->visitInitializer(E->getExpr()); 2547*c9157d92SDimitry Andric 2548fe013be4SDimitry Andric assert(classify(E->getType())); 2549bdd1243dSDimitry Andric return this->visit(E->getExpr()); 2550bdd1243dSDimitry Andric } 2551bdd1243dSDimitry Andric 2552bdd1243dSDimitry Andric template <class Emitter> 2553bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultArgExpr( 2554bdd1243dSDimitry Andric const CXXDefaultArgExpr *E) { 2555*c9157d92SDimitry Andric SourceLocScope<Emitter> SLS(this, E); 2556*c9157d92SDimitry Andric 2557*c9157d92SDimitry Andric const Expr *SubExpr = E->getExpr(); 2558*c9157d92SDimitry Andric if (std::optional<PrimType> T = classify(E->getExpr())) 2559*c9157d92SDimitry Andric return this->visit(SubExpr); 2560*c9157d92SDimitry Andric 2561*c9157d92SDimitry Andric assert(Initializing); 2562*c9157d92SDimitry Andric return this->visitInitializer(SubExpr); 2563bdd1243dSDimitry Andric } 2564bdd1243dSDimitry Andric 2565bdd1243dSDimitry Andric template <class Emitter> 2566bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXBoolLiteralExpr( 2567bdd1243dSDimitry Andric const CXXBoolLiteralExpr *E) { 2568bdd1243dSDimitry Andric if (DiscardResult) 2569bdd1243dSDimitry Andric return true; 2570bdd1243dSDimitry Andric 2571bdd1243dSDimitry Andric return this->emitConstBool(E->getValue(), E); 2572bdd1243dSDimitry Andric } 2573bdd1243dSDimitry Andric 2574bdd1243dSDimitry Andric template <class Emitter> 2575bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr( 2576bdd1243dSDimitry Andric const CXXNullPtrLiteralExpr *E) { 2577bdd1243dSDimitry Andric if (DiscardResult) 2578bdd1243dSDimitry Andric return true; 2579bdd1243dSDimitry Andric 2580bdd1243dSDimitry Andric return this->emitNullPtr(E); 2581bdd1243dSDimitry Andric } 2582bdd1243dSDimitry Andric 2583bdd1243dSDimitry Andric template <class Emitter> 2584*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitGNUNullExpr(const GNUNullExpr *E) { 2585*c9157d92SDimitry Andric if (DiscardResult) 2586*c9157d92SDimitry Andric return true; 2587*c9157d92SDimitry Andric 2588*c9157d92SDimitry Andric assert(E->getType()->isIntegerType()); 2589*c9157d92SDimitry Andric 2590*c9157d92SDimitry Andric PrimType T = classifyPrim(E->getType()); 2591*c9157d92SDimitry Andric return this->emitZero(T, E); 2592*c9157d92SDimitry Andric } 2593*c9157d92SDimitry Andric 2594*c9157d92SDimitry Andric template <class Emitter> 2595bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) { 2596bdd1243dSDimitry Andric if (DiscardResult) 2597bdd1243dSDimitry Andric return true; 2598*c9157d92SDimitry Andric 2599*c9157d92SDimitry Andric if (this->LambdaThisCapture > 0) 2600*c9157d92SDimitry Andric return this->emitGetThisFieldPtr(this->LambdaThisCapture, E); 2601*c9157d92SDimitry Andric 2602bdd1243dSDimitry Andric return this->emitThis(E); 2603bdd1243dSDimitry Andric } 2604bdd1243dSDimitry Andric 2605bdd1243dSDimitry Andric template <class Emitter> 2606bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) { 2607bdd1243dSDimitry Andric const Expr *SubExpr = E->getSubExpr(); 2608bdd1243dSDimitry Andric std::optional<PrimType> T = classify(SubExpr->getType()); 2609bdd1243dSDimitry Andric 2610bdd1243dSDimitry Andric switch (E->getOpcode()) { 2611bdd1243dSDimitry Andric case UO_PostInc: { // x++ 2612bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 2613bdd1243dSDimitry Andric return false; 2614bdd1243dSDimitry Andric 2615fe013be4SDimitry Andric if (T == PT_Ptr) { 2616fe013be4SDimitry Andric if (!this->emitIncPtr(E)) 2617fe013be4SDimitry Andric return false; 2618fe013be4SDimitry Andric 2619fe013be4SDimitry Andric return DiscardResult ? this->emitPopPtr(E) : true; 2620fe013be4SDimitry Andric } 2621fe013be4SDimitry Andric 2622fe013be4SDimitry Andric if (T == PT_Float) { 2623fe013be4SDimitry Andric return DiscardResult ? this->emitIncfPop(getRoundingMode(E), E) 2624fe013be4SDimitry Andric : this->emitIncf(getRoundingMode(E), E); 2625fe013be4SDimitry Andric } 2626fe013be4SDimitry Andric 2627bdd1243dSDimitry Andric return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E); 2628bdd1243dSDimitry Andric } 2629bdd1243dSDimitry Andric case UO_PostDec: { // x-- 2630bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 2631bdd1243dSDimitry Andric return false; 2632bdd1243dSDimitry Andric 2633fe013be4SDimitry Andric if (T == PT_Ptr) { 2634fe013be4SDimitry Andric if (!this->emitDecPtr(E)) 2635fe013be4SDimitry Andric return false; 2636fe013be4SDimitry Andric 2637fe013be4SDimitry Andric return DiscardResult ? this->emitPopPtr(E) : true; 2638fe013be4SDimitry Andric } 2639fe013be4SDimitry Andric 2640fe013be4SDimitry Andric if (T == PT_Float) { 2641fe013be4SDimitry Andric return DiscardResult ? this->emitDecfPop(getRoundingMode(E), E) 2642fe013be4SDimitry Andric : this->emitDecf(getRoundingMode(E), E); 2643fe013be4SDimitry Andric } 2644fe013be4SDimitry Andric 2645bdd1243dSDimitry Andric return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E); 2646bdd1243dSDimitry Andric } 2647bdd1243dSDimitry Andric case UO_PreInc: { // ++x 2648bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 2649bdd1243dSDimitry Andric return false; 2650bdd1243dSDimitry Andric 2651fe013be4SDimitry Andric if (T == PT_Ptr) { 2652*c9157d92SDimitry Andric if (!this->emitLoadPtr(E)) 2653*c9157d92SDimitry Andric return false; 2654*c9157d92SDimitry Andric if (!this->emitConstUint8(1, E)) 2655*c9157d92SDimitry Andric return false; 2656*c9157d92SDimitry Andric if (!this->emitAddOffsetUint8(E)) 2657*c9157d92SDimitry Andric return false; 2658fe013be4SDimitry Andric return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E); 2659fe013be4SDimitry Andric } 2660bdd1243dSDimitry Andric 2661fe013be4SDimitry Andric // Post-inc and pre-inc are the same if the value is to be discarded. 2662fe013be4SDimitry Andric if (DiscardResult) { 2663fe013be4SDimitry Andric if (T == PT_Float) 2664fe013be4SDimitry Andric return this->emitIncfPop(getRoundingMode(E), E); 2665fe013be4SDimitry Andric return this->emitIncPop(*T, E); 2666fe013be4SDimitry Andric } 2667fe013be4SDimitry Andric 2668fe013be4SDimitry Andric if (T == PT_Float) { 2669fe013be4SDimitry Andric const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType()); 2670*c9157d92SDimitry Andric if (!this->emitLoadFloat(E)) 2671*c9157d92SDimitry Andric return false; 2672*c9157d92SDimitry Andric if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E)) 2673*c9157d92SDimitry Andric return false; 2674*c9157d92SDimitry Andric if (!this->emitAddf(getRoundingMode(E), E)) 2675*c9157d92SDimitry Andric return false; 2676fe013be4SDimitry Andric return this->emitStoreFloat(E); 2677fe013be4SDimitry Andric } 2678*c9157d92SDimitry Andric if (!this->emitLoad(*T, E)) 2679*c9157d92SDimitry Andric return false; 2680*c9157d92SDimitry Andric if (!this->emitConst(1, E)) 2681*c9157d92SDimitry Andric return false; 2682*c9157d92SDimitry Andric if (!this->emitAdd(*T, E)) 2683*c9157d92SDimitry Andric return false; 2684bdd1243dSDimitry Andric return this->emitStore(*T, E); 2685bdd1243dSDimitry Andric } 2686bdd1243dSDimitry Andric case UO_PreDec: { // --x 2687bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 2688bdd1243dSDimitry Andric return false; 2689bdd1243dSDimitry Andric 2690fe013be4SDimitry Andric if (T == PT_Ptr) { 2691*c9157d92SDimitry Andric if (!this->emitLoadPtr(E)) 2692*c9157d92SDimitry Andric return false; 2693*c9157d92SDimitry Andric if (!this->emitConstUint8(1, E)) 2694*c9157d92SDimitry Andric return false; 2695*c9157d92SDimitry Andric if (!this->emitSubOffsetUint8(E)) 2696*c9157d92SDimitry Andric return false; 2697fe013be4SDimitry Andric return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E); 2698fe013be4SDimitry Andric } 2699bdd1243dSDimitry Andric 2700fe013be4SDimitry Andric // Post-dec and pre-dec are the same if the value is to be discarded. 2701fe013be4SDimitry Andric if (DiscardResult) { 2702fe013be4SDimitry Andric if (T == PT_Float) 2703fe013be4SDimitry Andric return this->emitDecfPop(getRoundingMode(E), E); 2704fe013be4SDimitry Andric return this->emitDecPop(*T, E); 2705fe013be4SDimitry Andric } 2706fe013be4SDimitry Andric 2707fe013be4SDimitry Andric if (T == PT_Float) { 2708fe013be4SDimitry Andric const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType()); 2709*c9157d92SDimitry Andric if (!this->emitLoadFloat(E)) 2710*c9157d92SDimitry Andric return false; 2711*c9157d92SDimitry Andric if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E)) 2712*c9157d92SDimitry Andric return false; 2713*c9157d92SDimitry Andric if (!this->emitSubf(getRoundingMode(E), E)) 2714*c9157d92SDimitry Andric return false; 2715fe013be4SDimitry Andric return this->emitStoreFloat(E); 2716fe013be4SDimitry Andric } 2717*c9157d92SDimitry Andric if (!this->emitLoad(*T, E)) 2718*c9157d92SDimitry Andric return false; 2719*c9157d92SDimitry Andric if (!this->emitConst(1, E)) 2720*c9157d92SDimitry Andric return false; 2721*c9157d92SDimitry Andric if (!this->emitSub(*T, E)) 2722*c9157d92SDimitry Andric return false; 2723bdd1243dSDimitry Andric return this->emitStore(*T, E); 2724bdd1243dSDimitry Andric } 2725bdd1243dSDimitry Andric case UO_LNot: // !x 2726*c9157d92SDimitry Andric if (DiscardResult) 2727*c9157d92SDimitry Andric return this->discard(SubExpr); 2728*c9157d92SDimitry Andric 2729*c9157d92SDimitry Andric if (!this->visitBool(SubExpr)) 2730bdd1243dSDimitry Andric return false; 2731*c9157d92SDimitry Andric 2732*c9157d92SDimitry Andric if (!this->emitInvBool(E)) 2733*c9157d92SDimitry Andric return false; 2734*c9157d92SDimitry Andric 2735*c9157d92SDimitry Andric if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool) 2736*c9157d92SDimitry Andric return this->emitCast(PT_Bool, ET, E); 2737*c9157d92SDimitry Andric return true; 2738bdd1243dSDimitry Andric case UO_Minus: // -x 2739bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 2740bdd1243dSDimitry Andric return false; 2741bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E); 2742bdd1243dSDimitry Andric case UO_Plus: // +x 2743bdd1243dSDimitry Andric if (!this->visit(SubExpr)) // noop 2744bdd1243dSDimitry Andric return false; 2745bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : true; 2746bdd1243dSDimitry Andric case UO_AddrOf: // &x 2747bdd1243dSDimitry Andric // We should already have a pointer when we get here. 2748*c9157d92SDimitry Andric return this->delegate(SubExpr); 2749bdd1243dSDimitry Andric case UO_Deref: // *x 2750bdd1243dSDimitry Andric return dereference( 2751bdd1243dSDimitry Andric SubExpr, DerefKind::Read, 2752bdd1243dSDimitry Andric [](PrimType) { 2753bdd1243dSDimitry Andric llvm_unreachable("Dereferencing requires a pointer"); 2754bdd1243dSDimitry Andric return false; 2755bdd1243dSDimitry Andric }, 2756bdd1243dSDimitry Andric [this, E](PrimType T) { 2757bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(T, E) : true; 2758bdd1243dSDimitry Andric }); 2759bdd1243dSDimitry Andric case UO_Not: // ~x 2760bdd1243dSDimitry Andric if (!this->visit(SubExpr)) 2761bdd1243dSDimitry Andric return false; 2762bdd1243dSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E); 2763*c9157d92SDimitry Andric case UO_Real: { // __real x 2764*c9157d92SDimitry Andric assert(!T); 2765*c9157d92SDimitry Andric if (!this->visit(SubExpr)) 2766*c9157d92SDimitry Andric return false; 2767*c9157d92SDimitry Andric if (!this->emitConstUint8(0, E)) 2768*c9157d92SDimitry Andric return false; 2769*c9157d92SDimitry Andric if (!this->emitArrayElemPtrPopUint8(E)) 2770*c9157d92SDimitry Andric return false; 2771*c9157d92SDimitry Andric 2772*c9157d92SDimitry Andric // Since our _Complex implementation does not map to a primitive type, 2773*c9157d92SDimitry Andric // we sometimes have to do the lvalue-to-rvalue conversion here manually. 2774*c9157d92SDimitry Andric if (!SubExpr->isLValue()) 2775*c9157d92SDimitry Andric return this->emitLoadPop(classifyPrim(E->getType()), E); 2776*c9157d92SDimitry Andric return true; 2777*c9157d92SDimitry Andric } 2778*c9157d92SDimitry Andric case UO_Imag: { // __imag x 2779*c9157d92SDimitry Andric assert(!T); 2780*c9157d92SDimitry Andric if (!this->visit(SubExpr)) 2781*c9157d92SDimitry Andric return false; 2782*c9157d92SDimitry Andric if (!this->emitConstUint8(1, E)) 2783*c9157d92SDimitry Andric return false; 2784*c9157d92SDimitry Andric if (!this->emitArrayElemPtrPopUint8(E)) 2785*c9157d92SDimitry Andric return false; 2786*c9157d92SDimitry Andric 2787*c9157d92SDimitry Andric // Since our _Complex implementation does not map to a primitive type, 2788*c9157d92SDimitry Andric // we sometimes have to do the lvalue-to-rvalue conversion here manually. 2789*c9157d92SDimitry Andric if (!SubExpr->isLValue()) 2790*c9157d92SDimitry Andric return this->emitLoadPop(classifyPrim(E->getType()), E); 2791*c9157d92SDimitry Andric return true; 2792*c9157d92SDimitry Andric } 2793bdd1243dSDimitry Andric case UO_Extension: 2794*c9157d92SDimitry Andric return this->delegate(SubExpr); 2795bdd1243dSDimitry Andric case UO_Coawait: 2796bdd1243dSDimitry Andric assert(false && "Unhandled opcode"); 2797bdd1243dSDimitry Andric } 2798bdd1243dSDimitry Andric 2799bdd1243dSDimitry Andric return false; 2800bdd1243dSDimitry Andric } 2801bdd1243dSDimitry Andric 2802bdd1243dSDimitry Andric template <class Emitter> 2803bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) { 2804fe013be4SDimitry Andric if (DiscardResult) 2805fe013be4SDimitry Andric return true; 2806fe013be4SDimitry Andric 2807fe013be4SDimitry Andric const auto *D = E->getDecl(); 2808fe013be4SDimitry Andric 2809fe013be4SDimitry Andric if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) { 2810fe013be4SDimitry Andric return this->emitConst(ECD->getInitVal(), E); 2811fe013be4SDimitry Andric } else if (const auto *BD = dyn_cast<BindingDecl>(D)) { 2812fe013be4SDimitry Andric return this->visit(BD->getBinding()); 2813fe013be4SDimitry Andric } else if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) { 2814fe013be4SDimitry Andric const Function *F = getFunction(FuncDecl); 2815fe013be4SDimitry Andric return F && this->emitGetFnPtr(F, E); 2816fe013be4SDimitry Andric } 2817fe013be4SDimitry Andric 2818bdd1243dSDimitry Andric // References are implemented via pointers, so when we see a DeclRefExpr 2819bdd1243dSDimitry Andric // pointing to a reference, we need to get its value directly (i.e. the 2820bdd1243dSDimitry Andric // pointer to the actual value) instead of a pointer to the pointer to the 2821bdd1243dSDimitry Andric // value. 2822fe013be4SDimitry Andric bool IsReference = D->getType()->isReferenceType(); 2823bdd1243dSDimitry Andric 2824fe013be4SDimitry Andric // Check for local/global variables and parameters. 2825fe013be4SDimitry Andric if (auto It = Locals.find(D); It != Locals.end()) { 2826bdd1243dSDimitry Andric const unsigned Offset = It->second.Offset; 2827bdd1243dSDimitry Andric 2828bdd1243dSDimitry Andric if (IsReference) 2829bdd1243dSDimitry Andric return this->emitGetLocal(PT_Ptr, Offset, E); 2830bdd1243dSDimitry Andric return this->emitGetPtrLocal(Offset, E); 2831fe013be4SDimitry Andric } else if (auto GlobalIndex = P.getGlobal(D)) { 2832bdd1243dSDimitry Andric if (IsReference) 2833fe013be4SDimitry Andric return this->emitGetGlobalPtr(*GlobalIndex, E); 2834bdd1243dSDimitry Andric 2835bdd1243dSDimitry Andric return this->emitGetPtrGlobal(*GlobalIndex, E); 2836fe013be4SDimitry Andric } else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) { 2837bdd1243dSDimitry Andric if (auto It = this->Params.find(PVD); It != this->Params.end()) { 2838*c9157d92SDimitry Andric if (IsReference || !It->second.IsPtr) 2839*c9157d92SDimitry Andric return this->emitGetParamPtr(It->second.Offset, E); 2840*c9157d92SDimitry Andric 2841*c9157d92SDimitry Andric return this->emitGetPtrParam(It->second.Offset, E); 2842bdd1243dSDimitry Andric } 2843fe013be4SDimitry Andric } 2844fe013be4SDimitry Andric 2845fe013be4SDimitry Andric // Handle lambda captures. 2846fe013be4SDimitry Andric if (auto It = this->LambdaCaptures.find(D); 2847fe013be4SDimitry Andric It != this->LambdaCaptures.end()) { 2848*c9157d92SDimitry Andric auto [Offset, IsPtr] = It->second; 2849fe013be4SDimitry Andric 2850*c9157d92SDimitry Andric if (IsPtr) 2851fe013be4SDimitry Andric return this->emitGetThisFieldPtr(Offset, E); 2852fe013be4SDimitry Andric return this->emitGetPtrThisField(Offset, E); 2853bdd1243dSDimitry Andric } 2854bdd1243dSDimitry Andric 2855*c9157d92SDimitry Andric // Lazily visit global declarations we haven't seen yet. 2856*c9157d92SDimitry Andric // This happens in C. 2857*c9157d92SDimitry Andric if (!Ctx.getLangOpts().CPlusPlus) { 2858*c9157d92SDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(D); 2859*c9157d92SDimitry Andric VD && VD->hasGlobalStorage() && VD->getAnyInitializer() && 2860*c9157d92SDimitry Andric VD->getType().isConstQualified()) { 2861*c9157d92SDimitry Andric if (!this->visitVarDecl(VD)) 2862bdd1243dSDimitry Andric return false; 2863*c9157d92SDimitry Andric // Retry. 2864*c9157d92SDimitry Andric return this->VisitDeclRefExpr(E); 2865*c9157d92SDimitry Andric } 2866*c9157d92SDimitry Andric 2867*c9157d92SDimitry Andric if (std::optional<unsigned> I = P.getOrCreateDummy(D)) 2868*c9157d92SDimitry Andric return this->emitGetPtrGlobal(*I, E); 2869*c9157d92SDimitry Andric } 2870*c9157d92SDimitry Andric 2871*c9157d92SDimitry Andric return this->emitInvalidDeclRef(E, E); 2872a7dea167SDimitry Andric } 2873a7dea167SDimitry Andric 2874a7dea167SDimitry Andric template <class Emitter> 2875a7dea167SDimitry Andric void ByteCodeExprGen<Emitter>::emitCleanup() { 2876a7dea167SDimitry Andric for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent()) 2877a7dea167SDimitry Andric C->emitDestruction(); 2878a7dea167SDimitry Andric } 2879a7dea167SDimitry Andric 2880fe013be4SDimitry Andric template <class Emitter> 2881*c9157d92SDimitry Andric unsigned 2882*c9157d92SDimitry Andric ByteCodeExprGen<Emitter>::collectBaseOffset(const RecordType *BaseType, 2883*c9157d92SDimitry Andric const RecordType *DerivedType) { 2884fe013be4SDimitry Andric const auto *FinalDecl = cast<CXXRecordDecl>(BaseType->getDecl()); 2885fe013be4SDimitry Andric const RecordDecl *CurDecl = DerivedType->getDecl(); 2886fe013be4SDimitry Andric const Record *CurRecord = getRecord(CurDecl); 2887fe013be4SDimitry Andric assert(CurDecl && FinalDecl); 2888*c9157d92SDimitry Andric 2889*c9157d92SDimitry Andric unsigned OffsetSum = 0; 2890fe013be4SDimitry Andric for (;;) { 2891fe013be4SDimitry Andric assert(CurRecord->getNumBases() > 0); 2892fe013be4SDimitry Andric // One level up 2893fe013be4SDimitry Andric for (const Record::Base &B : CurRecord->bases()) { 2894fe013be4SDimitry Andric const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl); 2895fe013be4SDimitry Andric 2896fe013be4SDimitry Andric if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) { 2897*c9157d92SDimitry Andric OffsetSum += B.Offset; 2898fe013be4SDimitry Andric CurRecord = B.R; 2899fe013be4SDimitry Andric CurDecl = BaseDecl; 2900fe013be4SDimitry Andric break; 2901fe013be4SDimitry Andric } 2902fe013be4SDimitry Andric } 2903fe013be4SDimitry Andric if (CurDecl == FinalDecl) 2904*c9157d92SDimitry Andric break; 2905fe013be4SDimitry Andric } 2906fe013be4SDimitry Andric 2907*c9157d92SDimitry Andric assert(OffsetSum > 0); 2908*c9157d92SDimitry Andric return OffsetSum; 2909*c9157d92SDimitry Andric } 2910*c9157d92SDimitry Andric 2911*c9157d92SDimitry Andric /// Emit casts from a PrimType to another PrimType. 2912*c9157d92SDimitry Andric template <class Emitter> 2913*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT, 2914*c9157d92SDimitry Andric QualType ToQT, const Expr *E) { 2915*c9157d92SDimitry Andric 2916*c9157d92SDimitry Andric if (FromT == PT_Float) { 2917*c9157d92SDimitry Andric // Floating to floating. 2918*c9157d92SDimitry Andric if (ToT == PT_Float) { 2919*c9157d92SDimitry Andric const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT); 2920*c9157d92SDimitry Andric return this->emitCastFP(ToSem, getRoundingMode(E), E); 2921*c9157d92SDimitry Andric } 2922*c9157d92SDimitry Andric 2923*c9157d92SDimitry Andric // Float to integral. 2924*c9157d92SDimitry Andric if (isIntegralType(ToT) || ToT == PT_Bool) 2925*c9157d92SDimitry Andric return this->emitCastFloatingIntegral(ToT, E); 2926*c9157d92SDimitry Andric } 2927*c9157d92SDimitry Andric 2928*c9157d92SDimitry Andric if (isIntegralType(FromT) || FromT == PT_Bool) { 2929*c9157d92SDimitry Andric // Integral to integral. 2930*c9157d92SDimitry Andric if (isIntegralType(ToT) || ToT == PT_Bool) 2931*c9157d92SDimitry Andric return FromT != ToT ? this->emitCast(FromT, ToT, E) : true; 2932*c9157d92SDimitry Andric 2933*c9157d92SDimitry Andric if (ToT == PT_Float) { 2934*c9157d92SDimitry Andric // Integral to floating. 2935*c9157d92SDimitry Andric const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT); 2936*c9157d92SDimitry Andric return this->emitCastIntegralFloating(FromT, ToSem, getRoundingMode(E), 2937*c9157d92SDimitry Andric E); 2938*c9157d92SDimitry Andric } 2939*c9157d92SDimitry Andric } 2940*c9157d92SDimitry Andric 2941fe013be4SDimitry Andric return false; 2942fe013be4SDimitry Andric } 2943fe013be4SDimitry Andric 2944fe013be4SDimitry Andric /// When calling this, we have a pointer of the local-to-destroy 2945fe013be4SDimitry Andric /// on the stack. 2946fe013be4SDimitry Andric /// Emit destruction of record types (or arrays of record types). 2947fe013be4SDimitry Andric /// FIXME: Handle virtual destructors. 2948fe013be4SDimitry Andric template <class Emitter> 2949fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Descriptor *Desc) { 2950fe013be4SDimitry Andric assert(Desc); 2951fe013be4SDimitry Andric assert(!Desc->isPrimitive()); 2952fe013be4SDimitry Andric assert(!Desc->isPrimitiveArray()); 2953fe013be4SDimitry Andric 2954fe013be4SDimitry Andric // Arrays. 2955fe013be4SDimitry Andric if (Desc->isArray()) { 2956fe013be4SDimitry Andric const Descriptor *ElemDesc = Desc->ElemDesc; 2957*c9157d92SDimitry Andric assert(ElemDesc); 2958fe013be4SDimitry Andric 2959*c9157d92SDimitry Andric // Don't need to do anything for these. 2960*c9157d92SDimitry Andric if (ElemDesc->isPrimitiveArray()) 2961*c9157d92SDimitry Andric return this->emitPopPtr(SourceInfo{}); 2962*c9157d92SDimitry Andric 2963*c9157d92SDimitry Andric // If this is an array of record types, check if we need 2964*c9157d92SDimitry Andric // to call the element destructors at all. If not, try 2965*c9157d92SDimitry Andric // to save the work. 2966*c9157d92SDimitry Andric if (const Record *ElemRecord = ElemDesc->ElemRecord) { 2967fe013be4SDimitry Andric if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor(); 2968*c9157d92SDimitry Andric !Dtor || Dtor->isTrivial()) 2969*c9157d92SDimitry Andric return this->emitPopPtr(SourceInfo{}); 2970*c9157d92SDimitry Andric } 2971*c9157d92SDimitry Andric 2972fe013be4SDimitry Andric for (ssize_t I = Desc->getNumElems() - 1; I >= 0; --I) { 2973fe013be4SDimitry Andric if (!this->emitConstUint64(I, SourceInfo{})) 2974fe013be4SDimitry Andric return false; 2975fe013be4SDimitry Andric if (!this->emitArrayElemPtrUint64(SourceInfo{})) 2976fe013be4SDimitry Andric return false; 2977*c9157d92SDimitry Andric if (!this->emitRecordDestruction(ElemDesc)) 2978fe013be4SDimitry Andric return false; 2979fe013be4SDimitry Andric } 2980fe013be4SDimitry Andric return this->emitPopPtr(SourceInfo{}); 2981fe013be4SDimitry Andric } 2982fe013be4SDimitry Andric 2983fe013be4SDimitry Andric const Record *R = Desc->ElemRecord; 2984fe013be4SDimitry Andric assert(R); 2985fe013be4SDimitry Andric // First, destroy all fields. 2986fe013be4SDimitry Andric for (const Record::Field &Field : llvm::reverse(R->fields())) { 2987fe013be4SDimitry Andric const Descriptor *D = Field.Desc; 2988fe013be4SDimitry Andric if (!D->isPrimitive() && !D->isPrimitiveArray()) { 2989fe013be4SDimitry Andric if (!this->emitDupPtr(SourceInfo{})) 2990fe013be4SDimitry Andric return false; 2991fe013be4SDimitry Andric if (!this->emitGetPtrField(Field.Offset, SourceInfo{})) 2992fe013be4SDimitry Andric return false; 2993fe013be4SDimitry Andric if (!this->emitRecordDestruction(D)) 2994fe013be4SDimitry Andric return false; 2995fe013be4SDimitry Andric } 2996fe013be4SDimitry Andric } 2997fe013be4SDimitry Andric 2998fe013be4SDimitry Andric // FIXME: Unions need to be handled differently here. We don't want to 2999fe013be4SDimitry Andric // call the destructor of its members. 3000fe013be4SDimitry Andric 3001fe013be4SDimitry Andric // Now emit the destructor and recurse into base classes. 3002fe013be4SDimitry Andric if (const CXXDestructorDecl *Dtor = R->getDestructor(); 3003fe013be4SDimitry Andric Dtor && !Dtor->isTrivial()) { 3004*c9157d92SDimitry Andric if (const Function *DtorFunc = getFunction(Dtor)) { 3005fe013be4SDimitry Andric assert(DtorFunc->hasThisPointer()); 3006fe013be4SDimitry Andric assert(DtorFunc->getNumParams() == 1); 3007fe013be4SDimitry Andric if (!this->emitDupPtr(SourceInfo{})) 3008fe013be4SDimitry Andric return false; 3009fe013be4SDimitry Andric if (!this->emitCall(DtorFunc, SourceInfo{})) 3010fe013be4SDimitry Andric return false; 3011fe013be4SDimitry Andric } 3012fe013be4SDimitry Andric } 3013fe013be4SDimitry Andric 3014fe013be4SDimitry Andric for (const Record::Base &Base : llvm::reverse(R->bases())) { 3015fe013be4SDimitry Andric if (!this->emitGetPtrBase(Base.Offset, SourceInfo{})) 3016fe013be4SDimitry Andric return false; 3017fe013be4SDimitry Andric if (!this->emitRecordDestruction(Base.Desc)) 3018fe013be4SDimitry Andric return false; 3019fe013be4SDimitry Andric } 3020fe013be4SDimitry Andric // FIXME: Virtual bases. 3021fe013be4SDimitry Andric 3022fe013be4SDimitry Andric // Remove the instance pointer. 3023fe013be4SDimitry Andric return this->emitPopPtr(SourceInfo{}); 3024fe013be4SDimitry Andric } 3025fe013be4SDimitry Andric 3026a7dea167SDimitry Andric namespace clang { 3027a7dea167SDimitry Andric namespace interp { 3028a7dea167SDimitry Andric 3029a7dea167SDimitry Andric template class ByteCodeExprGen<ByteCodeEmitter>; 3030a7dea167SDimitry Andric template class ByteCodeExprGen<EvalEmitter>; 3031a7dea167SDimitry Andric 3032a7dea167SDimitry Andric } // namespace interp 3033a7dea167SDimitry Andric } // namespace clang 3034