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